/**
 * Canonical token list for GRU base money, W-tokens, asset (ac*), and debt (vdc* / sdc*) tokens.
 * Used for CMC/CoinGecko reporting and token-aggregation indexing.
 * Addresses can be overridden via env (e.g. CUSDC_ADDRESS_138) or filled by indexer.
 */

export type TokenType = 'base' | 'w' | 'asset' | 'debt';

export interface CanonicalTokenSpec {
  symbol: string;
  name: string;
  type: TokenType;
  decimals: number;
  currencyCode?: string; // ISO-4217 for base/w
  /** ChainId -> contract address (placeholder or from env) */
  addresses: Partial<Record<number, string>>;
  description?: string;
  websiteUrl?: string;
  logoUrl?: string;
  /** v1 matrix symbol for origin reference only (e.g. cXUSDC when bridged); on Chain 138 symbol is v0 only (no X) */
  v1Symbol?: string;
  /** v0 symbol alias; on ChainID 138 tokens use v0 only (cUSDC, cUSDT), no chain designator */
  v0Alias?: string;
}

const CHAIN_138 = 138;
const CHAIN_25 = 25; // Cronos
const CHAIN_651940 = 651940;
/** L2/mainnet chain IDs for cUSDT/cUSDC multichain (env: CUSDT_ADDRESS_56, CUSDC_ADDRESS_137, etc.) */
const L2_CHAIN_IDS = [1, 56, 137, 10, 42161, 8453, 43114, 25, 100, 42220, 1111] as const;

/** Verified addresses from CHAIN138_TOKEN_ADDRESSES, .env, and deployment summaries */
const FALLBACK_ADDRESSES: Record<string, Partial<Record<number, string>>> = {
  USDC: {
    [CHAIN_138]: '0x71D6687F38b93CCad569Fa6352c876eea967201b',
  },
  USDT: {
    [CHAIN_138]: '0x004b63A7B5b0E06f6bB6adb4a5F9f590BF3182D1',
  },
  cUSDC: {
    [CHAIN_138]: '0xf22258f57794CC8E06237084b353Ab30fFfa640b',
    [CHAIN_651940]: '0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881', // AUSDC on ALL Mainnet
    [1]: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // Ethereum USDC
    [56]: '0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d', // BSC USDC
    [137]: '0x3c499c542cEF5E3811e1192ce70d8cC03d5c1369', // Polygon USDC
    [100]: '0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83', // Gnosis USDC
    [10]: '0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85', // Optimism USDC
    [42161]: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // Arbitrum USDC
    [8453]: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // Base USDC
    [43114]: '0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E', // Avalanche USDC
    [CHAIN_25]: '0xc21223249CA28397B4B6541dfFaEcC539BfF0c59', // Cronos USDC
    [42220]: '0xcebA9300f2b948710d2653dD7B07f33A8B32118C', // Celo USDC
    [1111]: '0xE3F5a90F9cb311505cd691a46596599aA1A0AD7D', // Wemix USDC
  },
  cUSDT: {
    [CHAIN_138]: '0x93E66202A11B1772E55407B32B44e5Cd8eda7f22',
    [CHAIN_651940]: '0x015B1897Ed5279930bC2Be46F661894d219292A6', // AUSDT primary on ALL Mainnet
    [1]: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // Ethereum USDT
    [56]: '0x55d398326f99059fF775485246999027B3197955', // BSC USDT
    [137]: '0xc2132D05D31c914a87C6611C10748AEb04B58e8F', // Polygon USDT
    [100]: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6', // Gnosis USDT
    [10]: '0x94b008aA00579c1307B0EF2c499aD98a8ce58e58', // Optimism USDT
    [42161]: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', // Arbitrum USDT
    [8453]: '0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2', // Base USDT
    [43114]: '0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7', // Avalanche USDT
    [CHAIN_25]: '0x66e4286603D22FF153A6547700f37C7Eae42F8E2', // Cronos USDT
    [42220]: '0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e', // Celo USDT
    [1111]: '0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F', // Wemix USDT
  },
  // Compliant Fiat on Chain 138 — from DeployCompliantFiatTokens (2026-02-27)
  cEURC: { [CHAIN_138]: '0x8085961F9cF02b4d800A3c6d386D31da4B34266a' },
  cEURT: { [CHAIN_138]: '0xdf4b71c61E5912712C1Bdd451416B9aC26949d72' },
  cGBPC: { [CHAIN_138]: '0x003960f16D9d34F2e98d62723B6721Fb92074aD2' },
  cGBPT: { [CHAIN_138]: '0x350f54e4D23795f86A9c03988c7135357CCaD97c' },
  cAUDC: { [CHAIN_138]: '0xD51482e567c03899eecE3CAe8a058161FD56069D' },
  cJPYC: { [CHAIN_138]: '0xEe269e1226a334182aace90056EE4ee5Cc8A6770' },
  cCHFC: { [CHAIN_138]: '0x873990849DDa5117d7C644f0aF24370797C03885' },
  cCADC: { [CHAIN_138]: '0x54dBd40cF05e15906A2C21f600937e96787f5679' },
  cXAUC: { [CHAIN_138]: '0x290E52a8819A4fbD0714E517225429aA2B70EC6b' },
  cXAUT: { [CHAIN_138]: '0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E' },
  // ISO-4217W on Cronos (25) — from DeployISO4217WSystem
  USDW: { [CHAIN_25]: '0x948690147D2e50ffe50C5d38C14125aD6a9FA036' },
  EURW: { [CHAIN_25]: '0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd' },
  GBPW: { [CHAIN_25]: '0xFb4B6Cc81211F7d886950158294A44C312abCA29' },
  AUDW: { [CHAIN_25]: '0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68' },
  JPYW: { [CHAIN_25]: '0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B' },
  CHFW: { [CHAIN_25]: '0xc9750828124D4c10e7a6f4B655cA8487bD3842EB' },
  CADW: { [CHAIN_25]: '0x328Cd365Bb35524297E68ED28c6fF2C9557d1363' },
};

function addr(symbol: string, chainId: number): string | undefined {
  if (chainId === CHAIN_138 && symbol === 'USDT') {
    return process.env.USDT_ADDRESS_138 || process.env.OFFICIAL_USDT_ADDRESS || FALLBACK_ADDRESSES[symbol]?.[chainId];
  }
  if (chainId === CHAIN_138 && symbol === 'USDC') {
    return process.env.USDC_ADDRESS_138 || process.env.OFFICIAL_USDC_ADDRESS || FALLBACK_ADDRESSES[symbol]?.[chainId];
  }
  const key = `${symbol.replace(/-/g, '_').toUpperCase()}_ADDRESS_${chainId}`;
  const envVal = process.env[key];
  if (envVal && envVal.trim() !== '') return envVal;
  return FALLBACK_ADDRESSES[symbol]?.[chainId];
}

export const CANONICAL_TOKENS: CanonicalTokenSpec[] = [
  // --- Base (GRU-M1) ---
  // Local Chain 138 quote-side mirror stables used by PMM pools.
  { symbol: 'USDC', name: 'USD Coin (Official Mirror)', type: 'base', decimals: 6, currencyCode: 'USD', addresses: { [CHAIN_138]: addr('USDC', CHAIN_138) || '' } },
  { symbol: 'USDT', name: 'Tether USD (Official Mirror)', type: 'base', decimals: 6, currencyCode: 'USD', addresses: { [CHAIN_138]: addr('USDT', CHAIN_138) || '' } },
  // Chain 138 v0 only (no X): cUSDC on 138; cXUSDC used only for bridged/origin reference elsewhere. See ISO4217_COMPLIANT_TOKEN_MATRIX.md
  { symbol: 'cUSDC', name: 'USD Coin (Compliant)', type: 'base', decimals: 6, currencyCode: 'USD', v0Alias: 'cUSDC', addresses: { [CHAIN_138]: addr('cUSDC', CHAIN_138) || '', [CHAIN_651940]: addr('cUSDC', CHAIN_651940) || '', ...Object.fromEntries(L2_CHAIN_IDS.map((id) => [id, addr('cUSDC', id)])) } },
  // Chain 138 v0 only (no X): cUSDT on 138; cXUSDT used only for bridged/origin reference elsewhere. See ISO4217_COMPLIANT_TOKEN_MATRIX.md
  { symbol: 'cUSDT', name: 'Tether USD (Compliant)', type: 'base', decimals: 6, currencyCode: 'USD', v0Alias: 'cUSDT', addresses: { [CHAIN_138]: addr('cUSDT', CHAIN_138) || '', [CHAIN_651940]: addr('cUSDT', CHAIN_651940) || '', ...Object.fromEntries(L2_CHAIN_IDS.map((id) => [id, addr('cUSDT', id)])) } },
  { symbol: 'cEURC', name: 'Euro Coin (Compliant)', type: 'base', decimals: 6, currencyCode: 'EUR', addresses: { [CHAIN_138]: addr('cEURC', CHAIN_138), [CHAIN_651940]: addr('cEURC', CHAIN_651940) } },
  { symbol: 'cEURT', name: 'Tether EUR (Compliant)', type: 'base', decimals: 6, currencyCode: 'EUR', addresses: { [CHAIN_138]: addr('cEURT', CHAIN_138), [CHAIN_651940]: addr('cEURT', CHAIN_651940) } },
  { symbol: 'cGBPC', name: 'Pound Sterling (Compliant)', type: 'base', decimals: 6, currencyCode: 'GBP', addresses: { [CHAIN_138]: addr('cGBPC', CHAIN_138), [CHAIN_651940]: addr('cGBPC', CHAIN_651940) } },
  { symbol: 'cGBPT', name: 'Tether GBP (Compliant)', type: 'base', decimals: 6, currencyCode: 'GBP', addresses: { [CHAIN_138]: addr('cGBPT', CHAIN_138), [CHAIN_651940]: addr('cGBPT', CHAIN_651940) } },
  { symbol: 'cAUDC', name: 'Australian Dollar (Compliant)', type: 'base', decimals: 6, currencyCode: 'AUD', addresses: { [CHAIN_138]: addr('cAUDC', CHAIN_138), [CHAIN_651940]: addr('cAUDC', CHAIN_651940) } },
  { symbol: 'cJPYC', name: 'Japanese Yen (Compliant)', type: 'base', decimals: 6, currencyCode: 'JPY', addresses: { [CHAIN_138]: addr('cJPYC', CHAIN_138), [CHAIN_651940]: addr('cJPYC', CHAIN_651940) } },
  { symbol: 'cCHFC', name: 'Swiss Franc (Compliant)', type: 'base', decimals: 6, currencyCode: 'CHF', addresses: { [CHAIN_138]: addr('cCHFC', CHAIN_138), [CHAIN_651940]: addr('cCHFC', CHAIN_651940) } },
  { symbol: 'cCADC', name: 'Canadian Dollar (Compliant)', type: 'base', decimals: 6, currencyCode: 'CAD', addresses: { [CHAIN_138]: addr('cCADC', CHAIN_138), [CHAIN_651940]: addr('cCADC', CHAIN_651940) } },
  {
    symbol: 'cXAUC',
    name: 'Gold (Compliant)',
    type: 'base',
    decimals: 6,
    currencyCode: 'XAU',
    description: '1 full token = 1 troy ounce fine gold (10^6 base units = 1 oz).',
    addresses: { [CHAIN_138]: addr('cXAUC', CHAIN_138), [CHAIN_651940]: addr('cXAUC', CHAIN_651940) },
  },
  {
    symbol: 'cXAUT',
    name: 'Tether XAU (Compliant)',
    type: 'base',
    decimals: 6,
    currencyCode: 'XAU',
    description: '1 full token = 1 troy ounce fine gold (10^6 base units = 1 oz).',
    addresses: { [CHAIN_138]: addr('cXAUT', CHAIN_138), [CHAIN_651940]: addr('cXAUT', CHAIN_651940) },
  },
  { symbol: 'LiXAU', name: 'XAU Liquidity-adjusted', type: 'base', decimals: 6, currencyCode: 'XAU', addresses: { [CHAIN_138]: addr('LiXAU', CHAIN_138), [CHAIN_651940]: addr('LiXAU', CHAIN_651940) } },
  // --- ISO-4217 W ---
  { symbol: 'USDW', name: 'USD W Token', type: 'w', decimals: 2, currencyCode: 'USD', addresses: { [CHAIN_138]: addr('USDW', CHAIN_138), [CHAIN_25]: addr('USDW', CHAIN_25), [CHAIN_651940]: addr('USDW', CHAIN_651940) } },
  { symbol: 'EURW', name: 'EUR W Token', type: 'w', decimals: 2, currencyCode: 'EUR', addresses: { [CHAIN_138]: addr('EURW', CHAIN_138), [CHAIN_25]: addr('EURW', CHAIN_25), [CHAIN_651940]: addr('EURW', CHAIN_651940) } },
  { symbol: 'GBPW', name: 'GBP W Token', type: 'w', decimals: 2, currencyCode: 'GBP', addresses: { [CHAIN_138]: addr('GBPW', CHAIN_138), [CHAIN_25]: addr('GBPW', CHAIN_25), [CHAIN_651940]: addr('GBPW', CHAIN_651940) } },
  { symbol: 'AUDW', name: 'AUD W Token', type: 'w', decimals: 2, currencyCode: 'AUD', addresses: { [CHAIN_138]: addr('AUDW', CHAIN_138), [CHAIN_25]: addr('AUDW', CHAIN_25), [CHAIN_651940]: addr('AUDW', CHAIN_651940) } },
  { symbol: 'JPYW', name: 'JPY W Token', type: 'w', decimals: 2, currencyCode: 'JPY', addresses: { [CHAIN_138]: addr('JPYW', CHAIN_138), [CHAIN_25]: addr('JPYW', CHAIN_25), [CHAIN_651940]: addr('JPYW', CHAIN_651940) } },
  { symbol: 'CHFW', name: 'CHF W Token', type: 'w', decimals: 2, currencyCode: 'CHF', addresses: { [CHAIN_138]: addr('CHFW', CHAIN_138), [CHAIN_25]: addr('CHFW', CHAIN_25), [CHAIN_651940]: addr('CHFW', CHAIN_651940) } },
  { symbol: 'CADW', name: 'CAD W Token', type: 'w', decimals: 2, currencyCode: 'CAD', addresses: { [CHAIN_138]: addr('CADW', CHAIN_138), [CHAIN_25]: addr('CADW', CHAIN_25), [CHAIN_651940]: addr('CADW', CHAIN_651940) } },
  // --- Asset (ac*) ---
  { symbol: 'acUSDC', name: 'Deposit cUSDC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acUSDC', CHAIN_138), [CHAIN_651940]: addr('acUSDC', CHAIN_651940) } },
  { symbol: 'acUSDT', name: 'Deposit cUSDT', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acUSDT', CHAIN_138), [CHAIN_651940]: addr('acUSDT', CHAIN_651940) } },
  { symbol: 'acEURC', name: 'Deposit cEURC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acEURC', CHAIN_138), [CHAIN_651940]: addr('acEURC', CHAIN_651940) } },
  { symbol: 'acGBPC', name: 'Deposit cGBPC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acGBPC', CHAIN_138), [CHAIN_651940]: addr('acGBPC', CHAIN_651940) } },
  { symbol: 'acAUDC', name: 'Deposit cAUDC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acAUDC', CHAIN_138), [CHAIN_651940]: addr('acAUDC', CHAIN_651940) } },
  { symbol: 'acJPYC', name: 'Deposit cJPYC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acJPYC', CHAIN_138), [CHAIN_651940]: addr('acJPYC', CHAIN_651940) } },
  { symbol: 'acCHFC', name: 'Deposit cCHFC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acCHFC', CHAIN_138), [CHAIN_651940]: addr('acCHFC', CHAIN_651940) } },
  { symbol: 'acCADC', name: 'Deposit cCADC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acCADC', CHAIN_138), [CHAIN_651940]: addr('acCADC', CHAIN_651940) } },
  { symbol: 'acXAUC', name: 'Deposit cXAUC', type: 'asset', decimals: 6, addresses: { [CHAIN_138]: addr('acXAUC', CHAIN_138), [CHAIN_651940]: addr('acXAUC', CHAIN_651940) } },
  // --- Debt (vdc* / sdc*) ---
  { symbol: 'vdcUSDC', name: 'Debt cUSDC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcUSDC', CHAIN_138), [CHAIN_651940]: addr('vdcUSDC', CHAIN_651940) } },
  { symbol: 'sdcUSDC', name: 'Debt cUSDC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcUSDC', CHAIN_138), [CHAIN_651940]: addr('sdcUSDC', CHAIN_651940) } },
  { symbol: 'vdcUSDT', name: 'Debt cUSDT (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcUSDT', CHAIN_138), [CHAIN_651940]: addr('vdcUSDT', CHAIN_651940) } },
  { symbol: 'sdcUSDT', name: 'Debt cUSDT (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcUSDT', CHAIN_138), [CHAIN_651940]: addr('sdcUSDT', CHAIN_651940) } },
  { symbol: 'vdcEURC', name: 'Debt cEURC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcEURC', CHAIN_138), [CHAIN_651940]: addr('vdcEURC', CHAIN_651940) } },
  { symbol: 'sdcEURC', name: 'Debt cEURC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcEURC', CHAIN_138), [CHAIN_651940]: addr('sdcEURC', CHAIN_651940) } },
  { symbol: 'vdcGBPC', name: 'Debt cGBPC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcGBPC', CHAIN_138), [CHAIN_651940]: addr('vdcGBPC', CHAIN_651940) } },
  { symbol: 'sdcGBPC', name: 'Debt cGBPC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcGBPC', CHAIN_138), [CHAIN_651940]: addr('sdcGBPC', CHAIN_651940) } },
  { symbol: 'vdcAUDC', name: 'Debt cAUDC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcAUDC', CHAIN_138), [CHAIN_651940]: addr('vdcAUDC', CHAIN_651940) } },
  { symbol: 'sdcAUDC', name: 'Debt cAUDC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcAUDC', CHAIN_138), [CHAIN_651940]: addr('sdcAUDC', CHAIN_651940) } },
  { symbol: 'vdcJPYC', name: 'Debt cJPYC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcJPYC', CHAIN_138), [CHAIN_651940]: addr('vdcJPYC', CHAIN_651940) } },
  { symbol: 'sdcJPYC', name: 'Debt cJPYC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcJPYC', CHAIN_138), [CHAIN_651940]: addr('sdcJPYC', CHAIN_651940) } },
  { symbol: 'vdcCHFC', name: 'Debt cCHFC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcCHFC', CHAIN_138), [CHAIN_651940]: addr('vdcCHFC', CHAIN_651940) } },
  { symbol: 'sdcCHFC', name: 'Debt cCHFC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcCHFC', CHAIN_138), [CHAIN_651940]: addr('sdcCHFC', CHAIN_651940) } },
  { symbol: 'vdcCADC', name: 'Debt cCADC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcCADC', CHAIN_138), [CHAIN_651940]: addr('vdcCADC', CHAIN_651940) } },
  { symbol: 'sdcCADC', name: 'Debt cCADC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcCADC', CHAIN_138), [CHAIN_651940]: addr('sdcCADC', CHAIN_651940) } },
  { symbol: 'vdcXAUC', name: 'Debt cXAUC (variable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('vdcXAUC', CHAIN_138), [CHAIN_651940]: addr('vdcXAUC', CHAIN_651940) } },
  { symbol: 'sdcXAUC', name: 'Debt cXAUC (stable)', type: 'debt', decimals: 6, addresses: { [CHAIN_138]: addr('sdcXAUC', CHAIN_138), [CHAIN_651940]: addr('sdcXAUC', CHAIN_651940) } },
];

export function getCanonicalTokensByChain(chainId: number): CanonicalTokenSpec[] {
  return CANONICAL_TOKENS.filter(
    (t) => t.addresses[chainId] && String(t.addresses[chainId]).trim() !== ''
  );
}

export function getCanonicalTokenByAddress(chainId: number, address: string): CanonicalTokenSpec | undefined {
  const lower = address.toLowerCase();
  return CANONICAL_TOKENS.find((t) => t.addresses[chainId]?.toLowerCase() === lower);
}

export function getCanonicalTokenBySymbol(chainId: number, symbol: string): CanonicalTokenSpec | undefined {
  const normalized = symbol.trim().toLowerCase();
  return CANONICAL_TOKENS.find(
    (t) => t.symbol.toLowerCase() === normalized && t.addresses[chainId] && String(t.addresses[chainId]).trim() !== ''
  );
}

/** IPFS-hosted logo URLs (Pinata) for Uniswap token list (logoURI).
 * 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';
const ETH_LOGO = `${IPFS_GATEWAY}/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong`;
const USDC_LOGO = `${IPFS_GATEWAY}/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm`;
const USDT_LOGO = `${IPFS_GATEWAY}/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP`;

const LOGO_BY_SYMBOL: Record<string, string> = {
  USDC: USDC_LOGO,
  USDT: USDT_LOGO,
  cUSDC: USDC_LOGO,
  cUSDT: USDT_LOGO,
  cEURC: USDC_LOGO,
  cEURT: USDT_LOGO,
  cGBPC: `${IPFS_GATEWAY}/QmNQF73WjxU6FwTXNH8PXoDRFaSFKTYQWL7d4Q1kdRVJ4o`,
  cGBPT: `${IPFS_GATEWAY}/QmV4frsJmDTWzLdxdj1z81uMqVXcbGpHZLzwkpj6GvEX4k`,
  cAUDC: `${IPFS_GATEWAY}/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS`,
  cJPYC: `${IPFS_GATEWAY}/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K`,
  cCHFC: `${IPFS_GATEWAY}/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS`,
  cCADC: `${IPFS_GATEWAY}/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS`,
  cXAUC: ETH_LOGO,
  cXAUT: ETH_LOGO,
  LiXAU: `${IPFS_GATEWAY}/QmUVY5trUM5N1UnS4abReb66fNzGw7kenjU9AjL7TgR3M1`,
  USDW: USDC_LOGO,
  EURW: `${IPFS_GATEWAY}/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS`,
  GBPW: `${IPFS_GATEWAY}/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF`,
  AUDW: `${IPFS_GATEWAY}/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K`,
  JPYW: `${IPFS_GATEWAY}/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K`,
  CHFW: `${IPFS_GATEWAY}/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K`,
  CADW: `${IPFS_GATEWAY}/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K`,
};

/** Resolve logo URI for a canonical token (Uniswap token list format). */
export function getLogoUriForSpec(spec: CanonicalTokenSpec): string {
  if (spec.logoUrl) return spec.logoUrl;
  const bySymbol = LOGO_BY_SYMBOL[spec.symbol];
  if (bySymbol) return bySymbol;
  if (spec.symbol.startsWith('ac')) return getLogoUriForSpec(CANONICAL_TOKENS.find((t) => t.symbol === spec.symbol.replace('ac', 'c')) || spec);
  if (spec.symbol.startsWith('vdc') || spec.symbol.startsWith('sdc')) {
    const base = spec.symbol.replace(/^(vd|sd)c/, 'c');
    return getLogoUriForSpec(CANONICAL_TOKENS.find((t) => t.symbol === base) || spec);
  }
  return ETH_LOGO;
}
