Skip to content

Add pro/frontend-jwt-auth Next.js example for Pyth Pro JWT flow#131

Open
aditya520 wants to merge 1 commit into
mainfrom
sw-djpmrwuj
Open

Add pro/frontend-jwt-auth Next.js example for Pyth Pro JWT flow#131
aditya520 wants to merge 1 commit into
mainfrom
sw-djpmrwuj

Conversation

@aditya520

Copy link
Copy Markdown
Member

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

  • Server-side mint route (src/app/api/pyth-token/route.ts): POST /api/pyth-token forwards to POST https://pyth.dourolabs.app/auth/token with Authorization: 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_KEY is read from process.env in a server-only file — never referenced from NEXT_PUBLIC_* or client code.
  • Browser token cache (src/lib/pythToken.ts): matches the caching pattern in the docs — reuses the JWT until it's within 30s of expiry, then re-mints via POST /api/pyth-token.
  • History client (src/lib/pythClient.ts): fetchHistory({ symbol, from, to, resolution })GET https://pyth.dourolabs.app/v1/fixed_rate@200ms/history?… with Authorization: Bearer <jwt>, invalidates the cache and retries once on 401.
  • Chart UI: main page renders three lightweight-charts candlestick charts (BTC/USD, ETH/USD, SOL/USD), last 24h at 1-minute resolution, refreshed every 30s.
  • README + .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.
  • CI: .github/workflows/ci-pro-frontend-jwt-auth.yml — pnpm 9 / Node 18, runs test: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/symbols catalog on https://pyth.dourolabs.app exposes crypto spots as Crypto.BTC/USD (fully-qualified symbol) — passing the bare BTC/USD returns HTTP 404 symbol not found. The example uses Crypto.{BTC,ETH,SOL}/USD for API calls and displays the shorter form (BTC/USD, …) as the card label.

Test plan

  • pnpm install --frozen-lockfile
  • pnpm run test:format
  • pnpm run test:types
  • pnpm run build (without PRO_API_KEY — succeeds)
  • grep -rn PRO_API_KEY .next/static → no matches
  • POST /api/pyth-token with no PRO_API_KEY → 500 with setup message
  • POST /api/pyth-token with a bogus PRO_API_KEY → mirrors upstream 401 + body
  • Live GET /v1/fixed_rate@200ms/history matches the HistoryResponse shape used in src/lib/pythClient.ts
  • End-to-end browser render with a real PRO_API_KEY — not verified (no key available in this environment); see validation comment on the tracking issue

Out of scope

  • No wallet integration, on-chain posting, or trading UI.
  • No production hardening of /api/pyth-token (auth, rate limit) — called out in the README instead.
  • No test suite beyond typecheck + build.

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).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge 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 👍 / 👎.

Comment on lines +15 to +16
const PYTH_API_BASE_URL =
process.env.NEXT_PUBLIC_PYTH_API_BASE_URL ?? DEFAULT_PYTH_API_BASE_URL;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant