diff --git a/modules/rwallet/lib/price-feed.ts b/modules/rwallet/lib/price-feed.ts index 3f5ead9..df1a8b1 100644 --- a/modules/rwallet/lib/price-feed.ts +++ b/modules/rwallet/lib/price-feed.ts @@ -74,7 +74,7 @@ export async function getNativePrice(chainId: string): Promise { return data?.[coinId]?.usd ?? 0; } -/** Fetch token prices for a batch of contract addresses on a chain */ +/** Fetch token prices for contract addresses on a chain (1 per request for free tier) */ export async function getTokenPrices( chainId: string, addresses: string[], @@ -82,16 +82,22 @@ export async function getTokenPrices( const platform = CHAIN_PLATFORM[chainId]; if (!platform || addresses.length === 0) return new Map(); - const lower = addresses.map((a) => a.toLowerCase()); - const data = await cgFetch( - `https://api.coingecko.com/api/v3/simple/token_price/${platform}?contract_addresses=${lower.join(",")}&vs_currencies=usd`, - ); - + const lower = [...new Set(addresses.map((a) => a.toLowerCase()))]; const result = new Map(); - if (data) { - for (const addr of lower) { - if (data[addr]?.usd) result.set(addr, data[addr].usd); - } + + // CoinGecko free tier: 1 contract address per request, ~30 req/min + // Process in batches of 3 with a short delay between batches + const BATCH = 3; + for (let i = 0; i < lower.length; i += BATCH) { + const batch = lower.slice(i, i + BATCH); + const fetches = batch.map(async (addr) => { + const data = await cgFetch( + `https://api.coingecko.com/api/v3/simple/token_price/${platform}?contract_addresses=${addr}&vs_currencies=usd`, + ); + if (data?.[addr]?.usd) result.set(addr, data[addr].usd); + }); + await Promise.allSettled(fetches); + if (i + BATCH < lower.length) await new Promise((r) => setTimeout(r, 1500)); } return result; }