Route CoinGecko via Pro endpoint with proxy support and add health watchdogs#31
Merged
Merged
Conversation
…tchdogs The price service was sending Pro keys to api.coingecko.com with the demo header, so CoinGecko counted the calls against the anonymous IP-shared quota and routinely returned 429 (~47% of BTC fetches per day). WCBTC suspicious-liq-price detection silently degraded whenever the BTC spot cache went stale. - COINGECKO_BASE_URL env var lets a service be pointed at a caching pricing proxy that injects the upstream key itself; otherwise a Pro key in COINGECKO_API_KEY now correctly routes to pro-api.coingecko.com with x-cg-pro-api-key. - @Cron hourly staleness watchdog: if BTC spot has not refreshed for 60 min, raise a critical Telegram alert (re-arms every 6 h while the condition persists, clears on the next successful fetch). - @Cron daily quota probe of /api/v3/key: alert when the Pro account's monthly remaining call credit drops below 25k, so the account does not silently run dry.
- btcLastSuccessMs now seeds with Date.now() at construction. With the earlier `null` default, a container that started while CoinGecko was down would never raise the staleness alert: the cron returned early on `null` and the gate could only open after a first success that wasn't arriving. - checkCoingeckoQuota now routes through resolveCoingeckoEndpoint(), so a proxy-mode deployment (no local API key, key held by the proxy) is still covered. The previous `if (!apiKey) return` silently skipped the daily probe in exactly the configuration this PR was meant to roll out, leaving no signal when the Pro account approaches exhaustion. - Single Date.now() per success path on the BTC fetch so the cache timestamp and the staleness anchor stay aligned.
The resolver previously returned \`https://api.coingecko.com\` (anonymous public host) when neither COINGECKO_BASE_URL nor COINGECKO_API_KEY was set. That is a silent fallback and exactly the shape \"no fallbacks\" is meant to prevent: a misconfigured service would happily come up, route every call through the IP-shared anonymous quota, and surface only later as sporadic 429s. The constructor now throws when both env vars are empty, and the resolver no longer carries an unauthenticated branch. The only two remaining paths are the explicit proxy origin and direct Pro.
COINGECKO_API_KEY is no longer read by this service. The proxy stack holds the upstream key. The resolver now has a single path (`COINGECKO_BASE_URL` only) and the constructor refuses to start without it. No more two-branch logic, no more dead code.
Operators without a pricing-proxy can now point COINGECKO_BASE_URL at pro-api.coingecko.com directly and supply COINGECKO_API_KEY — the key is attached as the x-cg-pro-api-key header on every request when set, no two-branch logic, no fallback. In the DFX setup COINGECKO_API_KEY stays unset because the proxy injects its own key. README documents the pattern and links the proxy reference implementation at github.com/DFXswiss/pricing-proxy.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
api.coingecko.comwith the demo header, so calls counted against the anonymous IP-shared quota and ~47% of BTC fetches per day returned 429. WCBTC suspicious-liq-price detection silently degraded whenever the BTC spot cache went stale.COINGECKO_BASE_URLenv var: when set, requests go to that origin (typically a caching pricing proxy that injects the upstream key itself) and no auth header is added. When unset, a Pro key inCOINGECKO_API_KEYcorrectly routes topro-api.coingecko.comwithx-cg-pro-api-key. Anonymous public host stays as the no-key fallback./api/v3/keyprobe: critical Telegram alert when the Pro account's monthly remaining call credit drops below 25k.Resolution priority
COINGECKO_BASE_URLset → proxy mode, no key sent from this service.COINGECKO_API_KEYset →pro-api.coingecko.com+x-cg-pro-api-key.api.coingecko.comunauthenticated.Hardening (follow-up commits in this PR)
btcLastSuccessMsnow seeds withDate.now()at construction. With the earliernulldefault, a container that started while CoinGecko was down would never raise the staleness alert: the cron returned early onnulland the gate could only open after a first success that wasn't arriving.checkCoingeckoQuotanow routes throughresolveCoingeckoEndpoint(), so a proxy-mode deployment (no local API key, key held by the proxy) is still covered. The previousif (!apiKey) returnsilently skipped the daily probe in exactly the configuration this PR was meant to roll out.Test plan
npm run build) passes locally.COINGECKO_BASE_URL=http://pricing-proxy:8080/coingeckoand noCOINGECKO_API_KEY— confirm BTC fetch logs show success and no 429 in the next 24 h.CoinGecko quota: ... remainingafter deploy.COINGECKO_API_KEYset (no base URL), confirm calls go topro-api.coingecko.com.