#!/usr/bin/env node // Temporary script: fetch name + homepage URL for every token in tokenList.js // Phase 1: CoinGecko /coins/list (1 bulk call) for names — gets 100% // Phase 2: ethereum-lists GitHub repo for project URLs — gets ~15% import { readFileSync, writeFileSync } from "fs"; const src = readFileSync("src/shared/tokenList.js", "utf8"); const tokens = []; const re = /\{\s*address:\s*"(0x[a-fA-F0-9]{40})",\s*symbol:\s*"([^"]+)",\s*decimals:\s*(\d+)/g; let m; while ((m = re.exec(src)) !== null) { tokens.push({ address: m[1], symbol: m[2], decimals: parseInt(m[3]) }); } console.error(`Parsed ${tokens.length} tokens`); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); // --- Phase 1: bulk names from CoinGecko --- console.error("Fetching CoinGecko coins list..."); const listResp = await fetch( "https://api.coingecko.com/api/v3/coins/list?include_platform=true", ); if (!listResp.ok) throw new Error(`CoinGecko list HTTP ${listResp.status}`); const coins = await listResp.json(); const addrMap = new Map(); for (const coin of coins) { const eth = (coin.platforms?.ethereum || "").toLowerCase().trim(); if (eth && eth.startsWith("0x")) { addrMap.set(eth, { name: coin.name, id: coin.id }); } } console.error(`CoinGecko map: ${addrMap.size} Ethereum tokens`); const enriched = new Map(); for (const t of tokens) { const info = addrMap.get(t.address.toLowerCase()); enriched.set(t.address, { name: info?.name || t.symbol, url: "" }); } console.error( `Matched ${[...enriched.values()].filter((e) => e.name).length}/${tokens.length} names`, ); // --- Phase 2: ethereum-lists GitHub for URLs --- console.error("Fetching URLs from ethereum-lists GitHub..."); const CONCURRENT = 10; let urlsFound = 0; for (let i = 0; i < tokens.length; i += CONCURRENT) { const batch = tokens.slice(i, i + CONCURRENT); await Promise.allSettled( batch.map(async (t) => { try { const r = await fetch( `https://raw.githubusercontent.com/ethereum-lists/tokens/master/tokens/eth/${t.address}.json`, ); if (!r.ok) return; const data = await r.json(); const website = (data.website || "").trim(); if (website && website !== "https://") { enriched.get(t.address).url = website; urlsFound++; } } catch { // ignore } }), ); if (i % 100 === 0) { console.error( ` GitHub: ${Math.min(i + CONCURRENT, tokens.length)}/${tokens.length}, ${urlsFound} URLs`, ); } await sleep(200); } console.error(`Phase 2 done: ${urlsFound} URLs from ethereum-lists`); // --- Output --- const output = {}; for (const [addr, e] of enriched) { output[addr] = { name: e.name, url: e.url }; } writeFileSync("scripts/token-enrichment.json", JSON.stringify(output, null, 2)); console.error(`Done! ${tokens.length} names, ${urlsFound} URLs.`);