Skip to content

fix(market): support CoinGecko free Demo API keys#4313

Open
guhyun9454 wants to merge 1 commit into
koala73:mainfrom
guhyun9454:fix/coingecko-demo-api-key
Open

fix(market): support CoinGecko free Demo API keys#4313
guhyun9454 wants to merge 1 commit into
koala73:mainfrom
guhyun9454:fix/coingecko-demo-api-key

Conversation

@guhyun9454

@guhyun9454 guhyun9454 commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Summary

CoinGecko's free Demo plan and paid Pro plan share the CG- key prefix but require different hosts and auth headers:

Tier Base URL Auth header
Demo (free) api.coingecko.com/api/v3 x-cg-demo-api-key
Pro (paid) pro-api.coingecko.com/api/v3 x-cg-pro-api-key

The current code assumes any COINGECKO_API_KEY is a Pro key and unconditionally calls pro-api.coingecko.com with x-cg-pro-api-key. So a free Demo key fails with HTTP 400 (error_code: 10011"change your root URL from pro-api.coingecko.com to api.coingecko.com"). Since the CG- prefix is identical, the tier can't be auto-detected from the key string.

This affects 5 call sites (4 seeders + the server market RPC fetcher):

  • scripts/seed-crypto-quotes.mjs
  • scripts/seed-crypto-sectors.mjs
  • scripts/seed-stablecoin-markets.mjs
  • scripts/seed-token-panels.mjs
  • server/worldmonitor/market/v1/_shared.tsfetchCoinGeckoMarkets()

Fix

Add an explicit COINGECKO_DEMO_API_KEY env var that routes to api.coingecko.com with x-cg-demo-api-key. Tier resolution is extracted into a shared coingeckoEndpoint() helper (scripts/_seed-utils.mjs) and a typed local helper (server _shared.ts):

  • COINGECKO_API_KEY set → Pro (unchanged — existing Pro deployments unaffected)
  • only COINGECKO_DEMO_API_KEY set → Demo
  • neither → keyless public endpoint (unchanged)
  • both → Pro wins

Fully backward compatible — no behavior change for existing Pro or keyless setups.

Type of change

  • Bug fix

Affected areas

  • Market Radar / Crypto
  • API endpoints (/api/*)
  • Config / Settings

Verification

Tested against the live CoinGecko API with a real free Demo key (key redacted in all logs).

1. Tier resolution (unit) — all 4 cases route correctly:

pro only         tier=pro      base=https://pro-api.coingecko.com/api/v3   header=x-cg-pro-api-key: CG-P***xKEY
demo only        tier=demo     base=https://api.coingecko.com/api/v3       header=x-cg-demo-api-key: CG-D***xKEY
both (pro wins)  tier=pro      base=https://pro-api.coingecko.com/api/v3   header=x-cg-pro-api-key: CG-P***xKEY
keyless          tier=keyless  base=https://api.coingecko.com/api/v3       header=(none)

2. Before / after (same free Demo key, one endpoint):

BEFORE: demo key in COINGECKO_API_KEY        tier=pro   host=pro-api.coingecko.com   HTTP 400  (error_code 10011)
AFTER:  demo key in COINGECKO_DEMO_API_KEY   tier=demo  host=api.coingecko.com       HTTP 200

3. Live demo-tier call for the exact query each of the 5 call sites builds (real Demo key):

resolved tier = demo  base = https://api.coingecko.com/api/v3
auth header   = x-cg-demo-api-key = [REDACTED]

OK | seed-crypto-quotes                   | HTTP 200 | 10 ids -> 10 records | bitcoin=$64072
OK | seed-crypto-sectors                  | HTTP 200 | 40 ids -> 40 records | bitcoin=$64070
OK | seed-stablecoin-markets              | HTTP 200 |  5 ids ->  5 records | tether=$0.999453
OK | seed-token-panels                    | HTTP 200 | 30 ids -> 30 records | hyperliquid=$60.32
OK | server _shared.fetchCoinGeckoMarkets | HTTP 200 | 10 ids -> 10 records | bitcoin=$64072

ALL DEMO-TIER CALLS PASSED

Checklist

  • No API keys or secrets committed (keys redacted in logs; .env.example placeholders are empty)
  • TypeScript compiles without errors (npm run typecheck)
  • biome lint passes on changed files
  • Tested on worldmonitor.app variant — N/A (server/seeder data-fetch tier fix; verified directly against live CoinGecko API)

@vercel

vercel Bot commented Jun 14, 2026

Copy link
Copy Markdown

@guhyun9454 is attempting to deploy a commit to the World Monitor Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added the trust:safe Brin: contributor trust score safe label Jun 14, 2026
CoinGecko's free Demo plan and paid Pro plan share the CG- key prefix
but require different hosts and auth headers. The code assumed any key
was a Pro key and always called pro-api.coingecko.com with
x-cg-pro-api-key, so a free Demo key failed with HTTP 400 (error 10011)
across all 4 crypto seeders and the server market RPC fetcher.

Add an explicit COINGECKO_DEMO_API_KEY env var that routes to
api.coingecko.com with x-cg-demo-api-key. Pro takes precedence when both
are set, so existing Pro deployments are unaffected; no key still falls
back to the public endpoint. Extracted the tier resolution into a shared
coingeckoEndpoint() helper (scripts) and a typed local helper (server).
@guhyun9454 guhyun9454 force-pushed the fix/coingecko-demo-api-key branch from 8b5dfda to 4d8f078 Compare June 14, 2026 15:08
@greptile-apps

greptile-apps Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes CoinGecko API routing so that free Demo keys (COINGECKO_DEMO_API_KEY) are sent to api.coingecko.com with x-cg-demo-api-key, while paid Pro keys (COINGECKO_API_KEY) continue to use pro-api.coingecko.com with x-cg-pro-api-key. The change is fully backward-compatible — existing Pro and keyless setups are unaffected.

  • A shared coingeckoEndpoint() helper is extracted into scripts/_seed-utils.mjs (returning { baseUrl, headers, tier }) and a private equivalent is inlined in server/worldmonitor/market/v1/_shared.ts; both implement Pro-wins precedence with a keyless fallback.
  • All five affected call sites (four seeders + fetchCoinGeckoMarkets) are migrated to the helper, removing duplicated inline URL/key logic.
  • The PR accidentally includes 33+ internal agent state files (.omc/ directory) and .codegraph/daemon.pid that expose a local machine path and should not be committed; .omc/ is also missing from the root .gitignore.

Confidence Score: 3/5

The functional fix is correct and well-tested, but the PR brings along 33+ internal agent state files and a runtime PID file that must be removed before merging — they permanently enter git history if merged as-is.

The CoinGecko tier-routing logic is sound and the .env.example documentation is clear. The concern is the large number of unrelated files accidentally staged from the .omc/ and .codegraph/ directories: they expose the author's local filesystem path and will clutter git history permanently once merged. The root .gitignore also needs entries for these directories to prevent recurrence. The fix itself is ready; the commit just needs to be cleaned up first.

All files under .omc/ (33 files) and .codegraph/daemon.pid should be dropped from the PR and added to .gitignore.

Important Files Changed

Filename Overview
scripts/_seed-utils.mjs Adds shared coingeckoEndpoint() helper exporting { baseUrl, headers, tier } with correct Pro-wins precedence and keyless fallback.
server/worldmonitor/market/v1/_shared.ts Adds private coingeckoEndpoint() helper; logic is correct, Demo and keyless cases cleanly fall through to the same return with the header conditionally set.
.env.example Adds COINGECKO_DEMO_API_KEY with clear documentation on tier routing and precedence rules; no secrets committed.
.omc/project-memory.json Internal Claude Code agent state file accidentally committed; exposes local machine path. Should be in .gitignore and excluded from this PR.
.codegraph/daemon.pid Runtime process file with local socket path accidentally committed; not covered by .codegraph/.gitignore added in this PR.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["coingeckoEndpoint() called"] --> B{COINGECKO_API_KEY set?}
    B -- Yes --> C["tier = pro\nbaseUrl = pro-api.coingecko.com/api/v3\nheader: x-cg-pro-api-key"]
    B -- No --> D{COINGECKO_DEMO_API_KEY set?}
    D -- Yes --> E["tier = demo\nbaseUrl = api.coingecko.com/api/v3\nheader: x-cg-demo-api-key"]
    D -- No --> F["tier = keyless\nbaseUrl = api.coingecko.com/api/v3\nno auth header"]
    C --> G["fetch /coins/markets"]
    E --> G
    F --> G
Loading

Comments Outside Diff (2)

  1. .omc/project-memory.json, line 1-7 (link)

    P1 Internal agent state files accidentally committed

    This PR includes 33 files from the .omc/ directory (Claude Code agent session state — hud-state.json, agent-replay-*.jsonl, session-started.json, pre-tool-advisory-throttle.json, etc.) and .codegraph/daemon.pid, none of which belong in version control. These files expose the author's local machine path (/home/guhyun/projects/github-playground/worldmonitor) and runtime process info, and if merged will permanently clutter git history with untracked tooling artifacts. The root .gitignore has no entry for .omc/ or .codegraph/daemon.pid. All of these files should be removed from the PR, and .omc/ (and daemon.pid) added to .gitignore to prevent recurrence.

  2. .codegraph/.gitignore, line 15-16 (link)

    P2 The .codegraph/.gitignore doesn't cover daemon.pid, which is a runtime file that records the local process ID and socket path and was accidentally committed in this PR. Add an exclusion for it here. The .omc/ directory at the repo root also needs a top-level .gitignore entry.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "fix(market): support CoinGecko free Demo..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trust:safe Brin: contributor trust score safe

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant