From 76a846cc362e9a0f3d0e6373f8b2e127349a3281 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 25 Mar 2026 16:31:44 -0700 Subject: [PATCH] fix(rwallet): handle CoinGecko free tier 1-address limit gracefully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single-token wallets get CoinGecko verification + spam filtering. Multi-token wallets attempt batch (works with Pro/Demo keys), degrade gracefully on free tier — Safe API trusted+exclude_spam handles most spam. Co-Authored-By: Claude Opus 4.6 --- modules/rwallet/lib/price-feed.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/modules/rwallet/lib/price-feed.ts b/modules/rwallet/lib/price-feed.ts index 86b9574..10f0d29 100644 --- a/modules/rwallet/lib/price-feed.ts +++ b/modules/rwallet/lib/price-feed.ts @@ -75,7 +75,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 */ export async function getTokenPrices( chainId: string, addresses: string[], @@ -86,6 +86,21 @@ export async function getTokenPrices( const lower = [...new Set(addresses.map((a) => a.toLowerCase()))]; const prices = new Map(); + // CoinGecko free tier limits to 1 address per request. + // For 1 token, do a single lookup. For multiple, try batch (works with Pro/Demo keys). + if (lower.length === 1) { + const addr = lower[0]; + const data = await cgFetch( + `https://api.coingecko.com/api/v3/simple/token_price/${platform}?contract_addresses=${addr}&vs_currencies=usd`, + ); + if (data && !data.error_code) { + if (data[addr]?.usd) prices.set(addr, data[addr].usd); + return { prices, available: true }; + } + return { prices, available: false }; + } + + // Multiple tokens: batch request (succeeds with CoinGecko Demo/Pro API key) const data = await cgFetch( `https://api.coingecko.com/api/v3/simple/token_price/${platform}?contract_addresses=${lower.join(",")}&vs_currencies=usd`, ); @@ -95,6 +110,7 @@ export async function getTokenPrices( } return { prices, available: true }; } + // Batch failed (free tier limit) — degrade gracefully, no spam filtering return { prices, available: false }; }