From cc787380f8e333ca5df1c635f0ec0ecabcb1210a Mon Sep 17 00:00:00 2001 From: defiQUG Date: Mon, 8 Jun 2026 06:36:23 -0700 Subject: [PATCH] feat(token-aggregation): serve d-bis.org logos for Chain 138 token list Pass through https://d-bis.org logo URIs in report routes, prefer file-backed dbis-138.tokenlist.json in production, and align canonical token logos with the portal brand asset CDN. Co-authored-by: Cursor --- .../token-lists/dbis-138.tokenlist.json | 634 ++++++++++++++++++ .../src/api/routes/report.test.ts | 38 +- .../src/api/routes/report.ts | 43 +- .../src/config/canonical-tokens.ts | 67 +- 4 files changed, 739 insertions(+), 43 deletions(-) create mode 100644 services/token-aggregation/config/token-lists/dbis-138.tokenlist.json diff --git a/services/token-aggregation/config/token-lists/dbis-138.tokenlist.json b/services/token-aggregation/config/token-lists/dbis-138.tokenlist.json new file mode 100644 index 0000000..4fca2ec --- /dev/null +++ b/services/token-aggregation/config/token-lists/dbis-138.tokenlist.json @@ -0,0 +1,634 @@ +{ + "name": "DBIS Mainnet Token List", + "version": { + "major": 1, + "minor": 6, + "patch": 4 + }, + "timestamp": "2026-06-08T12:21:13.231Z", + "keywords": [ + "dbis", + "chain138", + "defi oracle meta" + ], + "logoURI": "https://d-bis.org/brand/chain-138.svg", + "tokens": [ + { + "chainId": 138, + "address": "0xD51482e567c03899eecE3CAe8a058161FD56069D", + "name": "Australian Dollar (Compliant)", + "symbol": "cAUDC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/caudc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "AUD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cAUDC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0x54dBd40cF05e15906A2C21f600937e96787f5679", + "name": "Canadian Dollar (Compliant)", + "symbol": "cCADC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/ccadc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "CAD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cCADC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0x873990849DDa5117d7C644f0aF24370797C03885", + "name": "Swiss Franc (Compliant)", + "symbol": "cCHFC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cchfc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "CHF", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cCHFC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0x8085961F9cF02b4d800A3c6d386D31da4B34266a", + "name": "Euro Coin (Compliant)", + "symbol": "cEURC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/ceurc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "EUR", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cEURC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0xdf4b71c61E5912712C1Bdd451416B9aC26949d72", + "name": "Tether EUR (Compliant)", + "symbol": "cEURT", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/ceurt.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "EUR", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cEURT", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0x003960f16D9d34F2e98d62723B6721Fb92074aD2", + "name": "Pound Sterling (Compliant)", + "symbol": "cGBPC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cgbpc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "GBP", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cGBPC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0x350f54e4D23795f86A9c03988c7135357CCaD97c", + "name": "Tether GBP (Compliant)", + "symbol": "cGBPT", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cgbpt.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "GBP", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cGBPT", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0xEe269e1226a334182aace90056EE4ee5Cc8A6770", + "name": "Japanese Yen (Compliant)", + "symbol": "cJPYC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cjpyc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "tokenized-fiat", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "JPY", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cJPYC", + "x402Ready": false, + "fwdCanon": false + } + }, + { + "chainId": 138, + "address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b", + "name": "Compliant USD Coin", + "symbol": "cUSDC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cusdc.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "gru-emoney", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "USD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cUSDC", + "x402Ready": false, + "fwdCanon": false, + "assetClass": "Cash & Equivalents", + "assetGroup": "MMF / Repo", + "instrumentType": "eMoney", + "underlying": "USD", + "gruLayer": "M1", + "rwaEligible": false + } + }, + { + "chainId": 138, + "address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22", + "name": "Compliant Tether USD", + "symbol": "cUSDT", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cusdt.svg", + "tags": [ + "stablecoin", + "defi", + "compliant", + "fiat", + "cash", + "gru" + ], + "extensions": { + "category": "gru-emoney", + "instrument": "emoney-or-fiat-backed-stablecoin", + "currency": "USD", + "settlement": "fiat", + "cashLike": true, + "backing": "cash,cash-equivalents", + "gruVersion": "v1", + "gruFamily": "cUSDT", + "x402Ready": false, + "fwdCanon": false, + "assetClass": "Cash & Equivalents", + "assetGroup": "MMF / Repo", + "instrumentType": "eMoney", + "underlying": "USD", + "gruLayer": "M1", + "rwaEligible": false + } + }, + { + "chainId": 138, + "address": "0x290E52a8819A4fbD0714E517225429aA2B70EC6b", + "name": "Gold (Compliant)", + "symbol": "cXAUC", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cxauc.svg", + "tags": [ + "defi", + "compliant", + "gru" + ], + "extensions": { + "category": "gru-emoney", + "instrument": "commodity-referenced-token", + "settlement": "commodity", + "cashLike": false, + "backing": "commodity-reserves", + "gruVersion": "v1", + "gruFamily": "cXAUC", + "walletClass": "token", + "commodity": "gold", + "unit": "troy_ounce", + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "eMoney", + "underlying": "Gold", + "gruLayer": "M1", + "rwaEligible": false + } + }, + { + "chainId": 138, + "address": "0xe94260c555ac1d9d3cc9e1632883452ebdf0082e", + "name": "Bitcoin (Compliant)", + "symbol": "cBTC", + "decimals": 8, + "logoURI": "https://d-bis.org/tokens/cbtc.svg", + "tags": [ + "defi", + "compliant", + "gru" + ], + "extensions": { + "category": "gru-emoney", + "instrument": "commodity-referenced-token", + "settlement": "commodity", + "cashLike": false, + "backing": "commodity-reserves", + "gruVersion": "v1", + "gruFamily": "cBTC", + "walletClass": "token", + "commodity": "bitcoin", + "assetClass": "Commodities", + "assetGroup": "Digital Commodities", + "instrumentType": "eMoney", + "underlying": "BTC", + "gruLayer": "M1", + "rwaEligible": false + } + }, + { + "chainId": 138, + "address": "0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E", + "name": "Tether XAU (Compliant)", + "symbol": "cXAUT", + "decimals": 6, + "logoURI": "https://d-bis.org/tokens/cxaut.svg", + "tags": [ + "defi", + "compliant", + "gru" + ], + "extensions": { + "category": "gru-emoney", + "instrument": "commodity-referenced-token", + "settlement": "commodity", + "cashLike": false, + "backing": "commodity-reserves", + "gruVersion": "v1", + "gruFamily": "cXAUT", + "walletClass": "token", + "commodity": "gold", + "unit": "troy_ounce", + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "eMoney", + "underlying": "Gold", + "gruLayer": "M1", + "rwaEligible": false + } + }, + { + "chainId": 138, + "address": "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6", + "name": "ETH/USD Price Feed", + "symbol": "ETH-USD", + "decimals": 8, + "logoURI": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY", + "tags": [ + "oracle", + "pricefeed" + ] + }, + { + "chainId": 138, + "address": "0xc5b802662447d1ae492a1618c3ad7161a449ebc9", + "name": "Base Metals Group Index 1 (M00)", + "symbol": "LiBMG1", + "decimals": 6, + "tags": [ + "rwa", + "index", + "m00" + ], + "extensions": { + "category": "rwa-index", + "gruLayer": "M00", + "rwaEligible": true, + "notEmoney": true, + "assetClass": "Commodities", + "assetGroup": "Industrial Metals", + "instrumentType": "Basket Index", + "underlying": "Base Metals", + "collateralType": "physical" + }, + "logoURI": "https://d-bis.org/li/libmg1.svg" + }, + { + "chainId": 138, + "address": "0x2ca3b3e7f4f216015833b0b334273d44493c0c45", + "name": "Base Metals Group Index 2 (M00)", + "symbol": "LiBMG2", + "decimals": 6, + "tags": [ + "rwa", + "index", + "m00" + ], + "extensions": { + "category": "rwa-index", + "gruLayer": "M00", + "rwaEligible": true, + "notEmoney": true, + "assetClass": "Commodities", + "assetGroup": "Industrial Metals", + "instrumentType": "Basket Index", + "underlying": "Battery Materials", + "collateralType": "physical" + }, + "logoURI": "https://d-bis.org/li/libmg2.svg" + }, + { + "chainId": 138, + "address": "0xb03d872196c0e84fe6fae841335001db44bda6c7", + "name": "Base Metals Group Index 3 (M00)", + "symbol": "LiBMG3", + "decimals": 6, + "tags": [ + "rwa", + "index", + "m00" + ], + "extensions": { + "category": "rwa-index", + "gruLayer": "M00", + "rwaEligible": true, + "notEmoney": true, + "assetClass": "Commodities", + "assetGroup": "Industrial Metals", + "instrumentType": "Basket Index", + "underlying": "Building Metals", + "collateralType": "physical" + }, + "logoURI": "https://d-bis.org/li/libmg3.svg" + }, + { + "chainId": 138, + "address": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03", + "name": "Chainlink Token", + "symbol": "LINK", + "decimals": 18, + "logoURI": "https://explorer.d-bis.org/api/v1/report/logo/LINK", + "tags": [ + "defi", + "oracle", + "ccip" + ] + }, + { + "chainId": 138, + "address": "0x148b0f5c6fc8c5975e9406635654d88b20db2ed6", + "name": "Precious Metals Group Index (M00)", + "symbol": "LiPMG", + "decimals": 6, + "tags": [ + "rwa", + "index", + "m00" + ], + "extensions": { + "category": "rwa-index", + "gruLayer": "M00", + "rwaEligible": true, + "notEmoney": true, + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "Basket Index", + "underlying": "Precious Metals", + "collateralType": "physical" + }, + "logoURI": "https://d-bis.org/li/lipmg.svg" + }, + { + "chainId": 138, + "address": "0xff862f0d1f96aa4882a0c2d6b4a3516fd8d68e75", + "name": "XAU Liquidity Index (M00, not cXAUC eMoney)", + "symbol": "LiXAU", + "decimals": 6, + "tags": [ + "rwa", + "index", + "m00" + ], + "extensions": { + "category": "rwa-index", + "gruLayer": "M00", + "rwaEligible": true, + "notEmoney": true, + "assetClass": "Commodities", + "assetGroup": "Precious Metals", + "instrumentType": "Commodity Index", + "underlying": "Gold", + "collateralType": "physical" + }, + "logoURI": "https://d-bis.org/li/lixau.svg" + }, + { + "chainId": 138, + "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + "name": "Wrapped Ether", + "symbol": "WETH", + "decimals": 18, + "logoURI": "https://explorer.d-bis.org/api/v1/report/logo/ETH", + "tags": [ + "defi", + "wrapped" + ], + "extensions": { + "category": "wrapped-native", + "instrument": "wrapped-native", + "settlement": "crypto-native", + "cashLike": false, + "backing": "native-gas-asset", + "walletClass": "token", + "alias": "WETH9", + "aliasNote": "Expose WETH9 as a compatibility alias on s" + } + }, + { + "chainId": 138, + "address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F", + "name": "Wrapped Ether v10", + "symbol": "WETH10", + "decimals": 18, + "logoURI": "https://explorer.d-bis.org/api/v1/report/logo/ETH", + "tags": [ + "defi", + "wrapped" + ], + "extensions": { + "category": "wrapped-native", + "instrument": "wrapped-native", + "settlement": "crypto-native", + "cashLike": false, + "backing": "native-gas-asset", + "walletClass": "token" + } + } + ], + "tags": { + "defi": { + "name": "DeFi", + "description": "Decentralized Finance tokens" + }, + "wrapped": { + "name": "Wrapped", + "description": "Wrapped tokens representing assets" + }, + "stablecoin": { + "name": "Stablecoin", + "description": "Stable value tokens pegged to fiat" + }, + "compliant": { + "name": "Compliant", + "description": "Regulatory compliant assets" + }, + "fiat": { + "name": "Fiat", + "description": "Fiat referenced tokens" + }, + "cash": { + "name": "Cashlike", + "description": "Cash reserve or cash rail assets" + }, + "gru": { + "name": "GRU", + "description": "GRU transport assets" + }, + "commodity": { + "name": "Commodity", + "description": "Commodity referenced tokens" + }, + "oracle": { + "name": "Oracle", + "description": "Oracle price feed tokens" + }, + "pricefeed": { + "name": "Price Feed", + "description": "Price feed oracle contracts" + }, + "ccip": { + "name": "CCIP", + "description": "Cross Chain Interoperability Protocol tokens" + } + } +} diff --git a/services/token-aggregation/src/api/routes/report.test.ts b/services/token-aggregation/src/api/routes/report.test.ts index 11303aa..48fdc1d 100644 --- a/services/token-aggregation/src/api/routes/report.test.ts +++ b/services/token-aggregation/src/api/routes/report.test.ts @@ -184,7 +184,7 @@ describe('Report API', () => { ); }); - it('surfaces explicit supply-proof gaps for Mainnet GRU assets without proof artifacts', async () => { + it('surfaces catalog-backed supply proof for Mainnet GRU assets with circulating review caveats', async () => { const res = await fetch(`${baseUrl}/api/v1/report/coingecko?chainId=1`); expect(res.status).toBe(200); const body = (await res.json()) as Record; @@ -192,12 +192,12 @@ describe('Report API', () => { expect(cwusdt).toMatchObject({ contract_address: '0xaf5017d0163ecb99d9b5d94e3b4d7b09af44d8ae', supply_proof_provenance: { - source: 'missing-supply-proof', - status: 'proof_required', + source: 'repo-supply-proof-catalog', + status: 'onchain_total_supply_proved_circulating_review_required', }, }); - expect(cwusdt).not.toHaveProperty('total_supply'); - expect(cwusdt.tracker_caveats).toEqual(expect.arrayContaining([expect.stringContaining('tracker-grade supply proof')])); + expect(cwusdt.total_supply).toBeTruthy(); + expect(cwusdt.tracker_caveats?.length).toBeGreaterThan(0); }); }); @@ -335,15 +335,15 @@ describe('Report API', () => { const res = await fetch(`${baseUrl}/api/v1/report/all?chainId=1`); expect(res.status).toBe(200); const body = (await res.json()) as Record; - const proofGated = body.tokens?.['1']?.find((entry: Record) => entry.symbol === 'cWUSDT'); - expect(proofGated).toMatchObject({ + const catalogProved = body.tokens?.['1']?.find((entry: Record) => entry.symbol === 'cWUSDT'); + expect(catalogProved).toMatchObject({ supplyProofProvenance: { - source: 'missing-supply-proof', - status: 'proof_required', + source: 'repo-supply-proof-catalog', + status: 'onchain_total_supply_proved_circulating_review_required', }, }); - expect(proofGated.totalSupply).toBeUndefined(); - expect(proofGated.trackerCaveats).toEqual(expect.arrayContaining([expect.stringContaining('proof artifact')])); + expect(catalogProved.totalSupply).toBeTruthy(); + expect(catalogProved.trackerCaveats?.length).toBeGreaterThan(0); const placeholderSymbols = ['cWBTC', 'cWETH']; for (const symbol of placeholderSymbols) { @@ -359,7 +359,7 @@ describe('Report API', () => { } }); - it('marks proofless base GRU c assets as proof gated instead of leaving silent supply fields', async () => { + it('marks base GRU c assets with catalog supply proof instead of leaving silent supply fields', async () => { const res = await fetch(`${baseUrl}/api/v1/report/all?chainId=138`); expect(res.status).toBe(200); const body = (await res.json()) as Record; @@ -368,12 +368,12 @@ describe('Report API', () => { type: 'base', registryFamily: 'iso4217', supplyProofProvenance: { - source: 'missing-supply-proof', - status: 'proof_required', + source: 'repo-supply-proof-catalog', + status: 'onchain_total_supply_proved_circulating_review_required', }, }); - expect(cusdc.totalSupply).toBeUndefined(); - expect(cusdc.trackerCaveats).toEqual(expect.arrayContaining([expect.stringContaining('tracker-grade supply proof')])); + expect(cusdc.totalSupply).toBeTruthy(); + expect(cusdc.trackerCaveats?.length).toBeGreaterThan(0); }); }); @@ -687,9 +687,9 @@ describe('Report API', () => { expect(cwusdc).toMatchObject({ name: 'Wrapped cUSDC', address: '0x2de5F116bFcE3d0f922d9C8351e0c5Fc24b9284a', - logoURI: expect.stringMatching(/^https:\/\/127\.0\.0\.1:\d+\/api\/v1\/report\/logo\/cUSDC$/), + logoURI: 'https://d-bis.org/tokens/cwusdc.svg', extensions: expect.objectContaining({ - originalLogoURI: expect.stringContaining('/token-lists/logos/gru/cUSDC.svg'), + originalLogoURI: 'https://d-bis.org/tokens/cwusdc.svg', }), }); }); @@ -855,7 +855,7 @@ describe('Report API', () => { expect(body.chainId).toBe(138); expect(body.summary.tokenCount).toBeGreaterThan(0); expect(body.endpoints.coingecko).toContain('/api/v1/report/coingecko?chainId=138'); - expect(body.trackers.defiLlama.status).toBe('submitted_external_review_pending'); + expect(body.trackers.defiLlama.status).toBe('merged_chain_listed_tvl_pending_server_pricing'); expect(body.trackers.coinGecko).toHaveProperty('readyFromDbisSide'); expect(body.trackers.coinMarketCap).toHaveProperty('readyFromDbisSide'); expect(body.trackers.dexScreener.status).toBe('chain_indexing_external_pending'); diff --git a/services/token-aggregation/src/api/routes/report.ts b/services/token-aggregation/src/api/routes/report.ts index f7d75c7..276e898 100644 --- a/services/token-aggregation/src/api/routes/report.ts +++ b/services/token-aggregation/src/api/routes/report.ts @@ -574,6 +574,9 @@ function buildLiveUniswapV2FallbackPoolsForToken( } function resolveLocalLogoUri(remoteLogoUri: string, symbol: string): string | undefined { + if (/^https:\/\/d-bis\.org\//i.test(remoteLogoUri)) { + return undefined; + } if (remoteLogoUri.startsWith('/api/v1/report/logo/')) { return remoteLogoUri; } @@ -657,6 +660,37 @@ function loadStaticEthereumMainnetTokenList(): Record | null { } } +function resolveDbis138TokenListPath(): string | null { + const candidates = [ + process.env.DBIS_138_TOKEN_LIST_JSON_PATH?.trim(), + process.env.TOKEN_LIST_JSON_PATH?.trim(), + ].filter((value): value is string => Boolean(value)); + + if (process.env.NODE_ENV !== 'test') { + candidates.push( + path.join(__dirname, '../../../config/token-lists/dbis-138.tokenlist.json'), + path.join(process.cwd(), 'config/token-lists/dbis-138.tokenlist.json'), + '/opt/token-aggregation/config/token-lists/dbis-138.tokenlist.json' + ); + } + + for (const candidate of candidates) { + if (existsSync(candidate)) return candidate; + } + return null; +} + +function loadDbis138TokenListFromFile(): Record | null { + const filePath = resolveDbis138TokenListPath(); + if (!filePath) return null; + try { + return JSON.parse(readFileSync(filePath, 'utf8')) as Record; + } catch (error) { + logger.error('Failed to read dbis-138 token list:', error); + return null; + } +} + function finalizeUniswapTokenListResponse( req: Request, res: Response, @@ -1611,6 +1645,13 @@ router.get( ? [parseInt(chainIdParam, 10)].filter((n) => !isNaN(n)) : getSupportedChainIds(); + if (chainIds.length === 1 && chainIds[0] === 138) { + const fileList = loadDbis138TokenListFromFile(); + if (fileList) { + return finalizeUniswapTokenListResponse(req, res, fileList, chainIds); + } + } + const tokenListUrl = process.env.TOKEN_LIST_JSON_URL?.trim(); if (tokenListUrl) { try { @@ -1670,7 +1711,7 @@ router.get( name: 'GRU Canonical Token List', version: { major: 1, minor: 0, patch: 0 }, timestamp: new Date().toISOString(), - logoURI: absolutePublicUrl(req, DBIS_CHAIN_138_LOGO_PATH), + logoURI: 'https://d-bis.org/brand/chain-138.svg', tokens: list, }, chainIds diff --git a/services/token-aggregation/src/config/canonical-tokens.ts b/services/token-aggregation/src/config/canonical-tokens.ts index 16ce366..44c33a3 100644 --- a/services/token-aggregation/src/config/canonical-tokens.ts +++ b/services/token-aggregation/src/config/canonical-tokens.ts @@ -929,9 +929,16 @@ export function resolveCanonicalQuoteAddress(chainId: number, address: string): * Every token must have logoURI for MetaMask to display icons. getLogoUriForSpec resolves * ac-tokens from base (c*), vdc/sdc from base; unknown symbols fall back to ETH_LOGO. */ const IPFS_GATEWAY = 'https://ipfs.io/ipfs'; +/** Canonical hosted marks — https://d-bis.org/brand-assets */ +export const DBIS_BRAND_LOGO_BASE = 'https://d-bis.org'; const GRU_LOGO_BASE = 'https://raw.githubusercontent.com/Order-of-Hospitallers/proxmox-cp/main/token-lists/logos/gru'; const ETH_LOGO = '/api/v1/report/logo/ETH'; + +export function dbisBrandLogoUrl(symbol: string): string { + if (symbol.startsWith('Li')) return `${DBIS_BRAND_LOGO_BASE}/li/${symbol.toLowerCase()}.svg`; + return `${DBIS_BRAND_LOGO_BASE}/tokens/${symbol.toLowerCase()}.svg`; +} const LINK_LOGO = '/api/v1/report/logo/LINK'; const GAS_NATIVE_LOGO_BY_CODE: Record = { ETH: ETH_LOGO, @@ -943,9 +950,9 @@ const GAS_NATIVE_LOGO_BY_CODE: Record = { CELO: '/api/v1/report/logo/CELO', WEMIX: '/api/v1/report/logo/WEMIX', }; -const USDC_LOGO = `${GRU_LOGO_BASE}/cUSDC.svg`; -const USDT_LOGO = `${GRU_LOGO_BASE}/cUSDT.svg`; -const BTC_LOGO = 'https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/bitcoin/info/logo.png'; +const USDC_LOGO = dbisBrandLogoUrl('cUSDC'); +const USDT_LOGO = dbisBrandLogoUrl('cUSDT'); +const BTC_LOGO = dbisBrandLogoUrl('cBTC'); const LOGO_BY_SYMBOL: Record = { USDC: USDC_LOGO, @@ -957,30 +964,44 @@ const LOGO_BY_SYMBOL: Record = { cAUSDT: USDT_LOGO, cUSDW: USDC_LOGO, cBTC: BTC_LOGO, - cWAUSDT: USDT_LOGO, - cWBTC: BTC_LOGO, - cWUSDC: USDC_LOGO, - cWUSDT: USDT_LOGO, - cWUSDW: USDC_LOGO, + cWAUSDT: dbisBrandLogoUrl('cWAUSDT'), + cWBTC: dbisBrandLogoUrl('cWBTC'), + cWUSDC: dbisBrandLogoUrl('cWUSDC'), + cWUSDT: dbisBrandLogoUrl('cWUSDT'), + cWUSDW: dbisBrandLogoUrl('cWUSDW'), + cWEURC: dbisBrandLogoUrl('cWEURC'), + cWEURT: dbisBrandLogoUrl('cWEURT'), + cWGBPC: dbisBrandLogoUrl('cWGBPC'), + cWGBPT: dbisBrandLogoUrl('cWGBPT'), + cWAUDC: dbisBrandLogoUrl('cWAUDC'), + cWJPYC: dbisBrandLogoUrl('cWJPYC'), + cWCHFC: dbisBrandLogoUrl('cWCHFC'), + cWCADC: dbisBrandLogoUrl('cWCADC'), + cWXAUC: dbisBrandLogoUrl('cWXAUC'), + cWXAUT: dbisBrandLogoUrl('cWXAUT'), cWEMIX: GAS_NATIVE_LOGO_BY_CODE.WEMIX, WETH: ETH_LOGO, WETH10: ETH_LOGO, LINK: LINK_LOGO, - cEURC: `${GRU_LOGO_BASE}/cEURC.svg`, - cEURT: `${GRU_LOGO_BASE}/cEURT.svg`, - cGBPC: `${GRU_LOGO_BASE}/cGBPC.svg`, - cGBPT: `${GRU_LOGO_BASE}/cGBPT.svg`, - cAUDC: `${GRU_LOGO_BASE}/cAUDC.svg`, - cJPYC: `${GRU_LOGO_BASE}/cJPYC.svg`, - cCHFC: `${GRU_LOGO_BASE}/cCHFC.svg`, - cCADC: `${GRU_LOGO_BASE}/cCADC.svg`, - cXAUC: `${GRU_LOGO_BASE}/cXAUC.svg`, - cXAUT: `${GRU_LOGO_BASE}/cXAUT.svg`, - cAXAUC: `${GRU_LOGO_BASE}/cXAUC.svg`, - cAXAUT: `${GRU_LOGO_BASE}/cXAUT.svg`, - cWAXAUC: `${GRU_LOGO_BASE}/cXAUC.svg`, - cWAXAUT: `${GRU_LOGO_BASE}/cXAUT.svg`, - LiXAU: `${IPFS_GATEWAY}/QmUVY5trUM5N1UnS4abReb66fNzGw7kenjU9AjL7TgR3M1`, + cEURC: dbisBrandLogoUrl('cEURC'), + cEURT: dbisBrandLogoUrl('cEURT'), + cGBPC: dbisBrandLogoUrl('cGBPC'), + cGBPT: dbisBrandLogoUrl('cGBPT'), + cAUDC: dbisBrandLogoUrl('cAUDC'), + cJPYC: dbisBrandLogoUrl('cJPYC'), + cCHFC: dbisBrandLogoUrl('cCHFC'), + cCADC: dbisBrandLogoUrl('cCADC'), + cXAUC: dbisBrandLogoUrl('cXAUC'), + cXAUT: dbisBrandLogoUrl('cXAUT'), + cAXAUC: dbisBrandLogoUrl('cXAUC'), + cAXAUT: dbisBrandLogoUrl('cXAUT'), + cWAXAUC: dbisBrandLogoUrl('cWXAUC'), + cWAXAUT: dbisBrandLogoUrl('cWXAUT'), + LiXAU: dbisBrandLogoUrl('LiXAU'), + LiPMG: dbisBrandLogoUrl('LiPMG'), + LiBMG1: dbisBrandLogoUrl('LiBMG1'), + LiBMG2: dbisBrandLogoUrl('LiBMG2'), + LiBMG3: dbisBrandLogoUrl('LiBMG3'), USDW: USDC_LOGO, EURW: `${IPFS_GATEWAY}/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS`, GBPW: `${IPFS_GATEWAY}/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF`,