Add pro/frontend-jwt-auth Next.js example for Pyth Pro JWT flow#131
Add pro/frontend-jwt-auth Next.js example for Pyth Pro JWT flow#131aditya520 wants to merge 1 commit into
Conversation
New top-level `pro/frontend-jwt-auth/` example demonstrating the JWT auth flow required for the Pyth Pro History API. A Next.js App Router route (`POST /api/pyth-token`) mints short-lived JWTs on the server using `PRO_API_KEY`, the browser caches them 30s before `expires_at`, and a lightweight-charts UI renders 24h of 1m OHLC for BTC/USD, ETH/USD, and SOL/USD from the Pyth Pro History API, polling every 30s. Also adds `.github/workflows/ci-pro-frontend-jwt-auth.yml` — a paths-scoped CI job that runs prettier, tsc --noEmit, and next build (no secrets required).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ee6df77732
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (!series) return; | ||
| const latest = candlesFromHistory(history); | ||
| for (const candle of latest) { | ||
| series.update(toChartCandle(candle)); |
There was a problem hiding this comment.
Update only the newest candle during polling
After the initial setData, the series already ends at the newest candle, but each refresh requests two minutes of history and iterates from the older candle first. lightweight-charts rejects a normal series.update whose timestamp precedes the series' latest timestamp, so the first poll throws before applying any new data; the charts remain stale and display an error. Update only the latest candle or explicitly perform supported historical updates.
Useful? React with 👍 / 👎.
| const PYTH_API_BASE_URL = | ||
| process.env.NEXT_PUBLIC_PYTH_API_BASE_URL ?? DEFAULT_PYTH_API_BASE_URL; |
There was a problem hiding this comment.
Keep the browser and mint endpoints on the same base URL
When a user follows .env.example and sets only PYTH_API_BASE_URL for a non-production environment, the server mints the token there while this browser client still sends history requests to the production default. Consequently the override does not actually move the app's data requests to non-prod and may also use a token against the wrong environment. The configuration should set/document the corresponding public URL as part of the same override.
Useful? React with 👍 / 👎.
Summary
Adds a new top-level
pro/frontend-jwt-auth/example demonstrating the JWT auth flow required for the Pyth Pro History API since 2026-07-24. Also adds a paths-scoped GitHub Actions workflow that runs prettier + typecheck + build on changes to the example.What it does
src/app/api/pyth-token/route.ts):POST /api/pyth-tokenforwards toPOST https://pyth.dourolabs.app/auth/tokenwithAuthorization: Bearer $PRO_API_KEY, mirrors the upstream status + body on error, and returns the{ access_token, expires_at, token_type }JSON on success.PRO_API_KEYis read fromprocess.envin a server-only file — never referenced fromNEXT_PUBLIC_*or client code.src/lib/pythToken.ts): matches the caching pattern in the docs — reuses the JWT until it's within 30s of expiry, then re-mints viaPOST /api/pyth-token.src/lib/pythClient.ts):fetchHistory({ symbol, from, to, resolution })→GET https://pyth.dourolabs.app/v1/fixed_rate@200ms/history?…withAuthorization: Bearer <jwt>, invalidates the cache and retries once on401.lightweight-chartscandlestick charts (BTC/USD, ETH/USD, SOL/USD), last 24h at 1-minute resolution, refreshed every 30s..env.example: quick-start (Node 18+, pnpm, one env var), "how it works" section, security notes calling out that the example intentionally ships without request auth or a rate limit on/api/pyth-token..github/workflows/ci-pro-frontend-jwt-auth.yml— pnpm 9 / Node 18, runstest:format,test:types,build. Path-scoped so it only fires on changes to the example or the workflow itself. No secrets required to build.Discrepancy vs. docs
The docs table lists symbols like
BTC/USD, but the live/v1/symbolscatalog onhttps://pyth.dourolabs.appexposes crypto spots asCrypto.BTC/USD(fully-qualifiedsymbol) — passing the bareBTC/USDreturnsHTTP 404 symbol not found. The example usesCrypto.{BTC,ETH,SOL}/USDfor API calls and displays the shorter form (BTC/USD, …) as the card label.Test plan
pnpm install --frozen-lockfilepnpm run test:formatpnpm run test:typespnpm run build(withoutPRO_API_KEY— succeeds)grep -rn PRO_API_KEY .next/static→ no matchesPOST /api/pyth-tokenwith noPRO_API_KEY→ 500 with setup messagePOST /api/pyth-tokenwith a bogusPRO_API_KEY→ mirrors upstream 401 + bodyGET /v1/fixed_rate@200ms/historymatches theHistoryResponseshape used insrc/lib/pythClient.tsPRO_API_KEY— not verified (no key available in this environment); see validation comment on the tracking issueOut of scope
/api/pyth-token(auth, rate limit) — called out in the README instead.