-
Notifications
You must be signed in to change notification settings - Fork 590
[SDK] added settlePayment() utility for x402 payments #8105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SDK] added settlePayment() utility for x402 payments #8105
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Name | Type |
---|---|
thirdweb | Minor |
@thirdweb-dev/nebula | Patch |
@thirdweb-dev/wagmi-adapter | Patch |
Click here to learn what changesets are, and how to add one.
Click here if you're a maintainer who wants to add a changeset to this PR
WalkthroughSplit X402 into verification and settlement: add shared types and common decoding/price logic, introduce a new settlePayment flow, refactor verifyPayment to verification-only, update exports/docs, and migrate middleware and example call sites to use settlePayment. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Client
participant Middleware as App/Middleware
participant X402 as thirdweb/x402
participant Fac as Facilitator
participant Net as Network
Client->>Middleware: Request protected resource
Middleware->>X402: settlePayment({resourceUrl, method, paymentData, payTo, network, price, facilitator})
X402->>X402: decodePaymentRequest() / processPriceToAtomicAmount()
X402->>Fac: submit settlement request
Fac->>Net: perform payment/verify proof
Net-->>Fac: success or error
Fac-->>X402: receipt or error
alt Success (200)
X402-->>Middleware: 200 + paymentReceipt + X-PAYMENT-RESPONSE header
Middleware-->>Client: Serve resource with settlement headers
else Payment Required (402)
X402-->>Middleware: 402 + { x402Version, error, accepts, optional payer }
Middleware-->>Client: 402 with accepted requirements
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Warning Review ran into problems🔥 ProblemsErrors were encountered while retrieving linked issues. Errors (1)
Comment |
How to use the Graphite Merge QueueAdd either label to this PR to merge it via the merge queue:
You must have a Graphite account in order to use the merge queue. Sign up using this link. An organization admin has enabled the Graphite Merge Queue in this repository. Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue. This stack of pull requests is managed by Graphite. Learn more about stacking. |
2c42ac2
to
7e3341b
Compare
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
packages/thirdweb/src/x402/facilitator.ts (1)
104-116
: Add timeouts to all facilitator fetch callsNetwork calls lack timeouts; a stalled upstream can hang request threads. Use AbortController with a sensible default (e.g., 10s) and make it configurable.
- const res = await fetch(`${url}/verify`, { + const ac = new AbortController(); + const to = setTimeout(() => ac.abort(), 10_000); + const res = await fetch(`${url}/verify`, { method: "POST", - headers, + headers, + signal: ac.signal, body: stringify({ x402Version: payload.x402Version, paymentPayload: payload, paymentRequirements: paymentRequirements, }), }); + clearTimeout(to);- const res = await fetch(`${url}/settle`, { + const ac = new AbortController(); + const to = setTimeout(() => ac.abort(), 10_000); + const res = await fetch(`${url}/settle`, { method: "POST", - headers, - body: JSON.stringify({ + headers, + signal: ac.signal, + body: stringify({ x402Version: payload.x402Version, paymentPayload: payload, paymentRequirements: paymentRequirements, }), }); + clearTimeout(to);- const res = await fetch(`${url}/supported`, { headers }); + const ac = new AbortController(); + const to = setTimeout(() => ac.abort(), 10_000); + const res = await fetch(`${url}/supported`, { headers, signal: ac.signal }); + clearTimeout(to);Also applies to: 140-152, 175-181
packages/thirdweb/src/x402/types.ts (1)
59-75
: Add @beta and an @example to ProcessPaymentResultSame doc requirements apply to this exported type.
/** * The result of a payment verification or processing operation. * - * @public + * @public + * @beta + * @example + * ```ts + * import { type ProcessPaymentResult } from "thirdweb/x402"; + * function handle(r: ProcessPaymentResult) { + * if (r.status === 200) { + * console.log(r.paymentReceipt.success); + * } else { + * console.warn(r.responseBody.error); + * } + * } + * ``` */apps/playground-web/src/middleware.ts (1)
11-21
: Validate required env vars and avoid unsafe type assertionsFail fast if secrets are missing; avoid
as string
on possibly undefined envs.-const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET as string; -const ENGINE_VAULT_ACCESS_TOKEN = process.env - .ENGINE_VAULT_ACCESS_TOKEN as string; -const API_URL = `https://${process.env.NEXT_PUBLIC_API_URL || "api.thirdweb.com"}`; +const BACKEND_WALLET_ADDRESS = process.env.ENGINE_BACKEND_WALLET; +if (!BACKEND_WALLET_ADDRESS) throw new Error("ENGINE_BACKEND_WALLET is required"); +const ENGINE_VAULT_ACCESS_TOKEN = process.env.ENGINE_VAULT_ACCESS_TOKEN; +const rawApiHost = process.env.NEXT_PUBLIC_API_URL || "api.thirdweb.com"; +const API_URL = rawApiHost.startsWith("http") + ? rawApiHost + : `https://${rawApiHost}`;packages/thirdweb/src/x402/process-payment.ts (1)
340-357
: Avoid float math for money → atomic units conversionMultiplying JS floats by 10**decimals can produce incorrect non-integer strings (precision loss). Use exact decimal-to-units conversion.
- if (typeof price === "string" || typeof price === "number") { - // USDC amount in dollars - const parsedAmount = moneySchema.safeParse(price); - if (!parsedAmount.success) { - return { - error: `Invalid price (price: ${price}). Must be in the form "$3.10", 0.10, "0.001", ${parsedAmount.error}`, - }; - } - const parsedUsdAmount = parsedAmount.data; - const defaultAsset = await getDefaultAsset(network, facilitator); - if (!defaultAsset) { - return { - error: `Unable to get default asset on ${network}. Please specify an asset in the payment requirements.`, - }; - } - asset = defaultAsset; - maxAmountRequired = (parsedUsdAmount * 10 ** asset.decimals).toString(); - } else { + if (typeof price === "string" || typeof price === "number") { + const parsedAmount = moneySchema.safeParse(price); + if (!parsedAmount.success) { + return { + error: `Invalid price (price: ${price}). Must be in the form "$3.10", 0.10, "0.001", ${parsedAmount.error}`, + }; + } + const defaultAsset = await getDefaultAsset(network, facilitator); + if (!defaultAsset) { + return { + error: `Unable to get default asset on ${network}. Please specify an asset in the payment requirements.`, + }; + } + asset = defaultAsset; + // Convert a decimal string (e.g. "$0.01" | "0.01" | 0.01) to atomic units exactly + const raw = (typeof price === "string" ? price.replace(/^\$/,'') : String(price)).trim(); + maxAmountRequired = decimalToUnits(raw, asset.decimals); + } else {Add this helper in the same file (below) or a shared util:
+function decimalToUnits(value: string, decimals: number): string { + if (!/^\d*(\.\d*)?$/.test(value)) throw new Error(`Invalid decimal: ${value}`); + const [ints, frac = ""] = value.split("."); + const fracPadded = (frac + "0".repeat(decimals)).slice(0, decimals); + const intPart = BigInt(ints || "0"); + const fracPart = BigInt(fracPadded || "0"); + const base = 10n ** BigInt(decimals); + return (intPart * base + fracPart).toString(); +}
🧹 Nitpick comments (4)
packages/thirdweb/src/x402/facilitator.ts (1)
147-151
: Use a single JSON serializer consistentlyverify() uses stringify() while settle() uses JSON.stringify(). Prefer one (stringify) for consistency and stable formatting.
- body: JSON.stringify({ + body: stringify({ x402Version: payload.x402Version, paymentPayload: payload, paymentRequirements: paymentRequirements, }),apps/portal/src/app/payments/x402/page.mdx (1)
46-47
: Microcopy: fix grammar“Use the facilitator configuration function settle transactions…” → “to settle transactions…”
-Use the `facilitator` configuration function settle transactions with your thirdweb server wallet gaslessly and pass it to the `processPayment` function. +Use the `facilitator` configuration function to settle transactions with your thirdweb server wallet gaslessly and pass it to the `processPayment` function.apps/playground-web/src/middleware.ts (1)
26-27
: Include querystring in resourceUrlParity with other examples and clearer provenance.
- const resourceUrl = `${request.nextUrl.protocol}//${request.nextUrl.host}${pathname}`; + const resourceUrl = request.nextUrl.toString();packages/thirdweb/src/x402/process-payment.ts (1)
1-7
: Consider extracting helpers to satisfy “one function per file” guidanceprocessPriceToAtomicAmount and getDefaultAsset could live in a local utility (e.g., ./price.ts) to keep this file single‑responsibility.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (8)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(2 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/process-payment.ts
(6 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/process-payment.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/process-payment.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/facilitator.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/process-payment.ts
.changeset/*.md
📄 CodeRabbit inference engine (AGENTS.md)
.changeset/*.md
: Each change inpackages/*
must include a changeset for the appropriate package
Version bump rules: patch for non‑API changes; minor for new/modified public API
Files:
.changeset/some-moons-burn.md
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
packages/thirdweb/src/exports/**
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/exports/**
: Export everything viaexports/
directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one@example
block that compiles and custom annotation tags (@beta
,@internal
,@experimental
)
Files:
packages/thirdweb/src/exports/x402.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
🧠 Learnings (1)
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.
Applied to files:
apps/playground-web/src/app/payments/x402/page.tsx
🧬 Code graph analysis (3)
apps/playground-web/src/middleware.ts (2)
packages/thirdweb/src/exports/x402.ts (1)
processPayment
(7-7)packages/thirdweb/src/x402/process-payment.ts (1)
processPayment
(132-319)
packages/thirdweb/src/x402/types.ts (2)
packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (3)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)
packages/thirdweb/src/x402/process-payment.ts (1)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(22-39)ProcessPaymentResult
(64-74)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: Build Packages
- GitHub Check: Lint Packages
- GitHub Check: Unit Tests
- GitHub Check: Analyze (javascript)
🔇 Additional comments (9)
packages/thirdweb/src/x402/facilitator.ts (1)
22-22
: Docs alignment with new API name looks goodReference switched to processPayment. No runtime impact.
.changeset/some-moons-burn.md (1)
2-6
: Correct release note and bump levelMinor bump matches the public API rename and broader surface change.
apps/playground-web/src/app/payments/x402/page.tsx (1)
60-86
: Example updated to processPayment — looks goodImport and call-site changes align with the new API and arguments.
packages/thirdweb/src/x402/types.ts (1)
15-16
: Clarify visibility of x402VersionIf not intended for public consumption, mark as @internal to avoid surfacing it implicitly.
- export const x402Version = 1; + /** + * X402 protocol version used internally. + * @internal + */ + export const x402Version = 1;apps/portal/src/app/payments/x402/page.mdx (1)
65-76
: Docs example aligns with new APIGood coverage showing headers echo-back.
apps/playground-web/src/middleware.ts (2)
29-41
: Middleware usage matches new APIArgs and header propagation look correct.
1-61
: Sweep for stale verifyPayment references across the repoEnsure no dead imports/usages remain.
packages/thirdweb/src/x402/process-payment.ts (1)
24-79
: TSDoc is strong and includes examplesPublic API surface is well documented with @beta and @bridge tags.
packages/thirdweb/src/exports/x402.ts (1)
7-8
: Re-exports look correct; ensure public TSDoc originates at sourceprocessPayment and types are exposed via the exports barrel. Confirm that their declarations carry comprehensive TSDoc with a compiling @example and a custom tag (e.g., @beta), per packages/thirdweb guidelines.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8105 +/- ##
==========================================
- Coverage 56.32% 56.32% -0.01%
==========================================
Files 906 906
Lines 59197 59197
Branches 4176 4175 -1
==========================================
- Hits 33345 33340 -5
- Misses 25746 25751 +5
Partials 106 106
🚀 New features to boost your workflow:
|
7e3341b
to
b88919c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/thirdweb/src/x402/verify-payment.ts (1)
33-33
: Fix JSDoc import to include settlePayment.The example calls
settlePayment
but does not import it, causing a non-compiling example.Apply this diff:
- * import { verifyPayment, facilitator } from "thirdweb/x402"; + * import { verifyPayment, settlePayment, facilitator } from "thirdweb/x402";
🧹 Nitpick comments (5)
packages/thirdweb/src/x402/types.ts (1)
15-15
: Documentx402Version
and mark as internal.Public exports in packages/thirdweb require TSDoc with a custom tag. Add a brief doc and mark as
@internal
(or@beta
if intended for public use).Apply this diff:
+/** + * X402 protocol version used in requests and responses. + * @internal + */ export const x402Version = 1;packages/thirdweb/src/x402/verify-payment.ts (2)
85-88
: MarkverifyPayment
as deprecated in favor ofsettlePayment
.The public API has moved to settlement; deprecate this to guide consumers.
Apply this diff:
* @public * @beta * @bridge x402 + * @deprecated Use `settlePayment()` instead. This function will be removed in the next major version. */
280-334
: Deduplicate shared helpers withsettle-payment.ts
.
processPriceToAtomicAmount
andgetDefaultAsset
are duplicated. Extract to a shared module (e.g.,./helpers/price.ts
) and import from both files to satisfy “single‑responsibility” guidance and DRY.packages/thirdweb/src/x402/settle-payment.ts (2)
99-110
: Express example: fetch header viareq.get()
to satisfy types.
req.headers["x-payment"]
isstring | string[] | undefined
and may not type‑check forpaymentData
. Preferreq.get("x-payment")
.Apply this diff:
- * paymentData: req.headers["x-payment"], + * paymentData: req.get("x-payment") ?? undefined,
330-383
: Deduplicate helpers shared withverify-payment.ts
.Extract
processPriceToAtomicAmount
andgetDefaultAsset
to a shared helper to adhere to “single function per file” guidance and DRY.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (9)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(3 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/settle-payment.ts
(1 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)packages/thirdweb/src/x402/verify-payment.ts
(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- packages/thirdweb/src/exports/x402.ts
- packages/thirdweb/src/x402/facilitator.ts
- .changeset/some-moons-burn.md
- apps/playground-web/src/app/payments/x402/page.tsx
- apps/portal/src/app/payments/x402/page.mdx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/types.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/playground-web/src/middleware.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
🧠 Learnings (2)
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to packages/thirdweb/**/*.{ts,tsx} : Every public symbol must have comprehensive TSDoc with at least one compiling `example` and a custom tag (`beta`, `internal`, `experimental`, etc.)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Every public symbol must have comprehensive TSDoc with at least one `example` block that compiles and custom annotation tags (`beta`, `internal`, `experimental`)
Applied to files:
packages/thirdweb/src/x402/types.ts
🧬 Code graph analysis (4)
packages/thirdweb/src/x402/settle-payment.ts (5)
packages/thirdweb/src/x402/types.ts (3)
PaymentArgs
(22-39)SettlePaymentResult
(64-74)x402Version
(15-15)packages/thirdweb/src/x402/facilitator.ts (2)
facilitator
(58-195)supported
(168-191)packages/thirdweb/src/x402/schemas.ts (4)
RequestedPaymentRequirements
(47-49)RequestedPaymentPayload
(32-34)FacilitatorNetwork
(26-26)networkToChainId
(58-76)packages/thirdweb/src/exports/utils.ts (2)
getAddress
(147-147)stringify
(189-189)packages/thirdweb/src/x402/encode.ts (1)
safeBase64Encode
(57-65)
packages/thirdweb/src/x402/verify-payment.ts (2)
packages/thirdweb/src/x402/types.ts (1)
PaymentArgs
(22-39)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)
apps/playground-web/src/middleware.ts (2)
packages/thirdweb/src/exports/x402.ts (1)
settlePayment
(7-7)packages/thirdweb/src/x402/settle-payment.ts (1)
settlePayment
(134-321)
packages/thirdweb/src/x402/types.ts (2)
packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (3)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
apps/playground-web/src/middleware.ts (1)
29-41
: LGTM: middleware uses the new settlement flow correctly.Args match
PaymentArgs
, and response headers are forwarded.packages/thirdweb/src/x402/types.ts (1)
17-21
: Add @beta and a compiling @example to PaymentArgs.Required per packages/thirdweb guidelines; include a minimal compiling example.
Apply this diff:
/** * Configuration object for verifying or processing X402 payments. * * @public + * @beta + * @example + * ```ts + * import { type PaymentArgs, facilitator } from "thirdweb/x402"; + * import { createThirdwebClient } from "thirdweb"; + * + * const client = createThirdwebClient({ secretKey: "sk_test_..." }); + * const thirdwebFacilitator = facilitator({ + * client, + * serverWalletAddress: "0x1234567890123456789012345678901234567890", + * }); + * + * const args: PaymentArgs = { + * resourceUrl: "https://api.example.com/paid", + * method: "GET", + * paymentData: null, + * payTo: "0x1234567890123456789012345678901234567890", + * network: "eip155:8453", + * price: "$0.01", + * facilitator: thirdwebFacilitator, + * }; + * ``` */packages/thirdweb/src/x402/verify-payment.ts (1)
23-29
: Incorrect — codebase usessettlePayment
; update PR title/description if it referencesprocessPayment
No occurrences ofprocessPayment
;settlePayment
is exported at packages/thirdweb/src/exports/x402.ts and implemented/used in packages/thirdweb/src/x402/settle-payment.ts, packages/thirdweb/src/x402/verify-payment.ts and example apps. No code changes required.Likely an incorrect or invalid review comment.
b88919c
to
4014c4a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (6)
packages/thirdweb/src/x402/types.ts (2)
42-58
: Document internal PaymentRequiredResult or gate it.If not intended for the public surface (not re-exported), annotate as internal to discourage direct consumption.
+/** + * Shape for HTTP 402 Payment Required responses used internally by the X402 flow. + * @internal + */ export type PaymentRequiredResult = {
16-16
: Narrow type of x402Version to a literal.Use const assertion to keep it as 1 at the type level.
-export const x402Version = 1; +export const x402Version = 1 as const;packages/thirdweb/src/x402/common.ts (3)
205-207
: Sanitize validation error message.Interpolating the zod error object can leak noisy internals; return a concise, predictable message.
- return { - error: `Invalid price (price: ${price}). Must be in the form "$3.10", 0.10, "0.001", ${parsedAmount.error}`, - }; + return { + error: `Invalid price (price: ${price}). Must be "$3.10" or a decimal number like 0.10`, + };
153-158
: Tighten requirement matching beyond scheme/network.Also match resource, payTo, method, and asset to prevent mismatched verification.
- const selectedPaymentRequirements = paymentRequirements.find( - (value) => - value.scheme === decodedPayment.scheme && - value.network === decodedPayment.network, - ); + const selectedPaymentRequirements = paymentRequirements.find((value) => { + const input = value.outputSchema?.input as { method?: string } | undefined; + return ( + value.scheme === decodedPayment.scheme && + value.network === decodedPayment.network && + value.resource === resourceUrl && + value.payTo === getAddress(payTo) && + value.asset === getAddress(asset.address) && + (!input?.method || input.method === method) + ); + });
101-102
: Remove redundant type cast.asset is already typed; access eip712 directly.
- extra: (asset as ERC20TokenAmount["asset"]).eip712, + extra: asset.eip712,packages/thirdweb/src/x402/verify-payment.ts (1)
8-69
: Fix the example to compile: add settlePayment import and avoid shadowing.The example uses settlePayment without importing it and shadows result.
- * import { verifyPayment, facilitator } from "thirdweb/x402"; + * import { verifyPayment, settlePayment, facilitator } from "thirdweb/x402"; @@ - * // you can do the work that requires payment first - * const result = await doSomething(); + * // you can do the work that requires payment first + * const data = await doSomething(); @@ - * // then return the result - * return Response.json(result); + * // then return the result + * return Response.json(data);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(3 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/common.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/settle-payment.ts
(1 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)packages/thirdweb/src/x402/verify-payment.ts
(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- apps/playground-web/src/middleware.ts
- .changeset/some-moons-burn.md
- packages/thirdweb/src/x402/facilitator.ts
- apps/portal/src/app/payments/x402/page.mdx
- apps/playground-web/src/app/payments/x402/page.tsx
- packages/thirdweb/src/x402/settle-payment.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/verify-payment.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/verify-payment.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/exports/**
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/exports/**
: Export everything viaexports/
directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one@example
block that compiles and custom annotation tags (@beta
,@internal
,@experimental
)
Files:
packages/thirdweb/src/exports/x402.ts
🧠 Learnings (2)
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to packages/thirdweb/**/*.{ts,tsx} : Every public symbol must have comprehensive TSDoc with at least one compiling `example` and a custom tag (`beta`, `internal`, `experimental`, etc.)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Every public symbol must have comprehensive TSDoc with at least one `example` block that compiles and custom annotation tags (`beta`, `internal`, `experimental`)
Applied to files:
packages/thirdweb/src/x402/types.ts
🧬 Code graph analysis (3)
packages/thirdweb/src/x402/types.ts (3)
packages/thirdweb/src/exports/x402.ts (3)
PaymentArgs
(9-9)SettlePaymentResult
(10-10)VerifyPaymentResult
(11-11)packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (4)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)RequestedPaymentPayload
(32-34)
packages/thirdweb/src/x402/common.ts (4)
packages/thirdweb/src/x402/schemas.ts (4)
RequestedPaymentRequirements
(47-49)RequestedPaymentPayload
(32-34)FacilitatorNetwork
(26-26)networkToChainId
(58-76)packages/thirdweb/src/x402/types.ts (3)
PaymentArgs
(23-40)PaymentRequiredResult
(42-58)x402Version
(16-16)packages/thirdweb/src/x402/facilitator.ts (2)
facilitator
(58-195)supported
(168-191)packages/thirdweb/src/exports/utils.ts (1)
getAddress
(147-147)
packages/thirdweb/src/x402/verify-payment.ts (3)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)VerifyPaymentResult
(82-90)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (6)
packages/thirdweb/src/x402/types.ts (3)
18-22
: Add @beta and a compiling @example to PaymentArgs.Public symbols under packages/thirdweb require a custom tag and a compiling example.
Apply this diff to the JSDoc:
/** * Configuration object for verifying or processing X402 payments. * * @public + * @beta + * @example + * ```ts + * import { type PaymentArgs, facilitator } from "thirdweb/x402"; + * + * const args: PaymentArgs = { + * resourceUrl: "https://api.example.com/paid", + * method: "GET", + * paymentData: null, + * payTo: "0x1234567890123456789012345678901234567890", + * network: "eip155:8453", + * price: "$0.01", + * // In real usage, call facilitator({...}); here we satisfy types for the example. + * facilitator: {} as ReturnType<typeof facilitator>, + * }; + * ``` */
60-65
: Add @beta and a compiling @example to SettlePaymentResult.Include both union branches in the example.
/** * The result of a payment settlement operation. * * @public + * @beta + * @example + * ```ts + * import type { SettlePaymentResult } from "thirdweb/x402"; + * + * const ok: SettlePaymentResult = { + * status: 200, + * responseHeaders: {}, + * paymentReceipt: {} as any, + * }; + * + * const needPayment: SettlePaymentResult = { + * status: 402, + * responseHeaders: { "Content-Type": "application/json" }, + * responseBody: { x402Version: 1, error: "Payment required", accepts: [] }, + * }; + * ``` */
77-82
: Add @beta and a compiling @example to VerifyPaymentResult.Match documentation quality across public types.
/** * The result of a payment verification operation. * * @public + * @beta + * @example + * ```ts + * import type { VerifyPaymentResult } from "thirdweb/x402"; + * + * const ok: VerifyPaymentResult = { status: 200, decodedPayment: {} as any, selectedPaymentRequirements: {} as any }; + * const notOk: VerifyPaymentResult = { + * status: 402, + * responseHeaders: { "Content-Type": "application/json" }, + * responseBody: { x402Version: 1, error: "Invalid payment", accepts: [] }, + * }; + * ``` */packages/thirdweb/src/x402/verify-payment.ts (2)
80-84
: Early return path is correct.Propagating 402 from decodePaymentRequest preserves structured error shape.
96-116
: Good verification flow and error mapping.Clean 200/402 split, carries facilitator reason and x402Version correctly.
packages/thirdweb/src/exports/x402.ts (1)
7-13
: LGTM — re-exports clean; no legacy verifyPayment() imports remainrg search returned only the implementation at packages/thirdweb/src/x402/verify-payment.ts (no legacy imports in apps/examples/middleware). Verify docs for the shared types are updated (see types.ts comments).
30c10ca
to
dea4269
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (7)
packages/thirdweb/src/x402/types.ts (2)
42-58
: Document PaymentRequiredResult with @beta and a compiling @example.This is public and reused; add TSDoc with a small example.
-export type PaymentRequiredResult = { +/** + * 402 Payment Required envelope returned by verification/settlement on failure. + * + * @public + * @beta + * @example + * ```ts + * import type { PaymentRequiredResult } from "thirdweb/x402"; + * const res: PaymentRequiredResult = { + * status: 402, + * responseHeaders: { "Content-Type": "application/json" }, + * responseBody: { x402Version: 1, error: "Payment required", accepts: [] }, + * }; + * ``` + */ +export type PaymentRequiredResult = {
16-16
: Add TSDoc for x402Version.Public symbol; include tag and example.
-export const x402Version = 1; +/** + * X402 protocol version used in requests/responses. + * @public + * @beta + * @example + * ```ts + * import { x402Version } from "thirdweb/x402"; + * console.log(x402Version); // 1 + * ``` + */ +export const x402Version = 1;apps/playground-web/src/middleware.ts (1)
26-27
: Build resourceUrl using origin to avoid protocol formatting issues.NextURL.protocol may include a trailing colon; prefer origin.
- const resourceUrl = `${request.nextUrl.protocol}//${request.nextUrl.host}${pathname}`; + const origin = request.nextUrl.origin; + const resourceUrl = `${origin}${pathname}`;packages/thirdweb/src/exports/x402.ts (1)
7-13
: Export a public aliasprocessPayment
forsettlePayment
to match PR intent.Reduces confusion and eases migration for downstreams expecting
processPayment
.-export { settlePayment } from "../x402/settle-payment.js"; +export { settlePayment, settlePayment as processPayment } from "../x402/settle-payment.js";packages/thirdweb/src/x402/settle-payment.ts (1)
182-183
: Provide a public aliasprocessPayment
for compatibility with the PR title.Keeps API aligned with “processPayment” naming while retaining
settlePayment
.} + +export { settlePayment as processPayment };packages/thirdweb/src/x402/verify-payment.ts (1)
16-22
: ImportsettlePayment
in the example before using it.Prevents a non-compiling example.
- * import { verifyPayment, facilitator } from "thirdweb/x402"; + * import { verifyPayment, settlePayment, facilitator } from "thirdweb/x402";packages/thirdweb/src/x402/common.ts (1)
235-241
: Make getDefaultAsset resilient to invalid network strings.networkToChainId can throw, causing a 500 instead of a 402; catch and return undefined so callers can surface a proper error.
- const chainId = networkToChainId(network); + let chainId: number; + try { + chainId = networkToChainId(network); + } catch { + return undefined; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(3 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/common.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/settle-payment.ts
(1 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)packages/thirdweb/src/x402/verify-payment.ts
(6 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/thirdweb/src/x402/facilitator.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- .changeset/some-moons-burn.md
- apps/portal/src/app/payments/x402/page.mdx
- apps/playground-web/src/app/payments/x402/page.tsx
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/exports/x402.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/exports/x402.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/playground-web/src/middleware.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/exports/x402.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/exports/**
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/exports/**
: Export everything viaexports/
directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one@example
block that compiles and custom annotation tags (@beta
,@internal
,@experimental
)
Files:
packages/thirdweb/src/exports/x402.ts
🧠 Learnings (5)
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to packages/thirdweb/**/*.{ts,tsx} : Every public symbol must have comprehensive TSDoc with at least one compiling `example` and a custom tag (`beta`, `internal`, `experimental`, etc.)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Every public symbol must have comprehensive TSDoc with at least one `example` block that compiles and custom annotation tags (`beta`, `internal`, `experimental`)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-05-20T18:54:15.781Z
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:110-118
Timestamp: 2025-05-20T18:54:15.781Z
Learning: In the thirdweb dashboard's token asset creation flow, the `transferBatch` function from `thirdweb/extensions/erc20` accepts the raw quantity values from the form without requiring explicit conversion to wei using `toUnits()`. The function appears to handle this conversion internally or is designed to work with the values in the format they're already provided.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-06-06T23:47:55.122Z
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:255-277
Timestamp: 2025-06-06T23:47:55.122Z
Learning: The `transfer` function from `thirdweb/extensions/erc20` accepts human-readable amounts via the `amount` property and automatically handles conversion to base units (wei) by fetching the token decimals internally. Manual conversion using `toWei()` is not required when using the `amount` property.
Applied to files:
packages/thirdweb/src/x402/common.ts
🧬 Code graph analysis (5)
apps/playground-web/src/middleware.ts (2)
packages/thirdweb/src/exports/x402.ts (1)
settlePayment
(7-7)packages/thirdweb/src/x402/settle-payment.ts (1)
settlePayment
(120-182)
packages/thirdweb/src/x402/verify-payment.ts (3)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)VerifyPaymentResult
(82-90)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)
packages/thirdweb/src/x402/types.ts (2)
packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (4)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)RequestedPaymentPayload
(32-34)
packages/thirdweb/src/x402/common.ts (3)
packages/thirdweb/src/x402/schemas.ts (3)
RequestedPaymentRequirements
(47-49)FacilitatorNetwork
(26-26)networkToChainId
(58-76)packages/thirdweb/src/x402/types.ts (3)
PaymentArgs
(23-40)PaymentRequiredResult
(42-58)x402Version
(16-16)packages/thirdweb/src/x402/facilitator.ts (2)
facilitator
(58-195)supported
(168-191)
packages/thirdweb/src/x402/settle-payment.ts (4)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)SettlePaymentResult
(65-75)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)packages/thirdweb/src/x402/encode.ts (1)
safeBase64Encode
(57-65)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Unit Tests
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (5)
packages/thirdweb/src/x402/types.ts (3)
18-22
: Add @beta and a compiling @example to PaymentArgs.Public types require a custom tag and a compiling example. Add both.
/** * Configuration object for verifying or processing X402 payments. * * @public + * @beta + * @example + * ```ts + * import { type PaymentArgs, facilitator } from "thirdweb/x402"; + * import { createThirdwebClient } from "thirdweb"; + * + * const client = createThirdwebClient({ secretKey: "sk_test_..." }); + * const f = facilitator({ + * baseUrl: "https://api.thirdweb.com/v1/payments/x402", + * client, + * serverWalletAddress: "0x1234567890123456789012345678901234567890", + * }); + * + * const args: PaymentArgs = { + * resourceUrl: "https://api.example.com/paid", + * method: "GET", + * paymentData: null, + * payTo: "0x1234567890123456789012345678901234567890", + * network: "eip155:8453", + * price: "$0.01", + * facilitator: f, + * }; + * ``` */ export type PaymentArgs = {Also applies to: 23-40
60-76
: Add @beta and a compiling @example to SettlePaymentResult.Include minimal examples for both union branches.
/** * The result of a payment settlement operation. * * @public + * @beta + * @example + * ```ts + * import type { SettlePaymentResult } from "thirdweb/x402"; + * + * const ok: SettlePaymentResult = { + * status: 200, + * responseHeaders: {}, + * paymentReceipt: {} as any, + * }; + * + * const needPayment: SettlePaymentResult = { + * status: 402, + * responseHeaders: { "Content-Type": "application/json" }, + * responseBody: { x402Version: 1, error: "Payment required", accepts: [] }, + * }; + * ``` */ export type SettlePaymentResult = Prettify<
77-90
: Add @beta and a compiling @example to VerifyPaymentResult.Ensure consistency with other public types.
/** * The result of a payment verification operation. * * @public + * @beta + * @example + * ```ts + * import type { VerifyPaymentResult } from "thirdweb/x402"; + * + * const ok: VerifyPaymentResult = { + * status: 200, + * decodedPayment: {} as any, + * selectedPaymentRequirements: {} as any, + * }; + * + * const notOk: VerifyPaymentResult = { + * status: 402, + * responseHeaders: { "Content-Type": "application/json" }, + * responseBody: { x402Version: 1, error: "Invalid payment", accepts: [] }, + * }; + * ``` */ export type VerifyPaymentResult = Prettify<packages/thirdweb/src/x402/settle-payment.ts (1)
20-25
: Fix JSDoc import: usesettlePayment
, notsettle
.The example won’t compile otherwise.
- * import { settle, facilitator } from "thirdweb/x402"; + * import { settlePayment, facilitator } from "thirdweb/x402";packages/thirdweb/src/x402/common.ts (1)
201-218
: Avoid floating‑point math for atomic amounts; use integer‑safe parsing.Floating precision can misprice payments (e.g., $0.1 with 6+ decimals).
-import { getAddress } from "../utils/address.js"; +import { getAddress } from "../utils/address.js"; +import { parseUnits } from "viem"; @@ - asset = defaultAsset; - maxAmountRequired = (parsedUsdAmount * 10 ** asset.decimals).toString(); + asset = defaultAsset; + // Use integer-safe conversion + maxAmountRequired = parseUnits(String(parsedUsdAmount), asset.decimals).toString();
dea4269
to
86c308b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/thirdweb/src/x402/common.ts (1)
230-242
: Consider caching the default asset lookup.The
getDefaultAsset
function callsfacilitator.supported()
which makes an HTTP request (although it has internal caching). For high-frequency operations, consider additional caching at this layer.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(3 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/common.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/settle-payment.ts
(1 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)packages/thirdweb/src/x402/verify-payment.ts
(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- .changeset/some-moons-burn.md
- packages/thirdweb/src/x402/facilitator.ts
- packages/thirdweb/src/x402/settle-payment.ts
- apps/playground-web/src/app/payments/x402/page.tsx
- apps/playground-web/src/middleware.ts
- apps/portal/src/app/payments/x402/page.mdx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/common.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/exports/x402.ts
packages/thirdweb/src/x402/common.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/exports/**
📄 CodeRabbit inference engine (CLAUDE.md)
packages/thirdweb/src/exports/**
: Export everything viaexports/
directory, grouped by feature in the SDK public API
Every public symbol must have comprehensive TSDoc with at least one@example
block that compiles and custom annotation tags (@beta
,@internal
,@experimental
)
Files:
packages/thirdweb/src/exports/x402.ts
🧠 Learnings (5)
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to packages/thirdweb/**/*.{ts,tsx} : Every public symbol must have comprehensive TSDoc with at least one compiling `example` and a custom tag (`beta`, `internal`, `experimental`, etc.)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Every public symbol must have comprehensive TSDoc with at least one `example` block that compiles and custom annotation tags (`beta`, `internal`, `experimental`)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-05-20T18:54:15.781Z
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:110-118
Timestamp: 2025-05-20T18:54:15.781Z
Learning: In the thirdweb dashboard's token asset creation flow, the `transferBatch` function from `thirdweb/extensions/erc20` accepts the raw quantity values from the form without requiring explicit conversion to wei using `toUnits()`. The function appears to handle this conversion internally or is designed to work with the values in the format they're already provided.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-06-06T23:47:55.122Z
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:255-277
Timestamp: 2025-06-06T23:47:55.122Z
Learning: The `transfer` function from `thirdweb/extensions/erc20` accepts human-readable amounts via the `amount` property and automatically handles conversion to base units (wei) by fetching the token decimals internally. Manual conversion using `toWei()` is not required when using the `amount` property.
Applied to files:
packages/thirdweb/src/x402/common.ts
🧬 Code graph analysis (3)
packages/thirdweb/src/x402/verify-payment.ts (3)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)VerifyPaymentResult
(82-90)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)
packages/thirdweb/src/x402/types.ts (3)
packages/thirdweb/src/exports/x402.ts (3)
PaymentArgs
(9-9)SettlePaymentResult
(10-10)VerifyPaymentResult
(11-11)packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (4)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)RequestedPaymentPayload
(32-34)
packages/thirdweb/src/x402/common.ts (4)
packages/thirdweb/src/x402/schemas.ts (3)
RequestedPaymentRequirements
(47-49)FacilitatorNetwork
(26-26)networkToChainId
(58-76)packages/thirdweb/src/x402/types.ts (3)
PaymentArgs
(23-40)PaymentRequiredResult
(42-58)x402Version
(16-16)packages/thirdweb/src/x402/facilitator.ts (2)
facilitator
(58-195)supported
(168-191)packages/thirdweb/src/exports/utils.ts (1)
getAddress
(147-147)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
- GitHub Check: Lint Packages
- GitHub Check: Size
- GitHub Check: E2E Tests (pnpm, vite)
- GitHub Check: Unit Tests
- GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
packages/thirdweb/src/exports/x402.ts (1)
7-13
: Exports align with the new settle/verify separation.The export structure properly reflects the architectural refactoring to split verification and settlement. The shared types (
PaymentArgs
,SettlePaymentResult
,VerifyPaymentResult
) are now centralized intypes.js
.packages/thirdweb/src/x402/types.ts (3)
18-40
: Add the @beta tag to PaymentArgs for consistency.Based on previous reviewer feedback and team learnings, public types require custom tags for the SDK API surface.
Apply this diff:
/** * Configuration object for verifying or processing X402 payments. * * @public + * @beta */
60-75
: Add the @beta tag to SettlePaymentResult.For consistency with other public types in the SDK, add the custom tag.
Apply this diff:
/** * The result of a payment settlement operation. * * @public + * @beta */
77-90
: Add the @beta tag to VerifyPaymentResult.Maintain consistency with the SDK's documentation standards.
Apply this diff:
/** * The result of a payment verification operation. * * @public + * @beta */
packages/thirdweb/src/x402/verify-payment.ts (2)
8-73
: Documentation clearly explains the verify/settle separation.The TSDoc and example code effectively demonstrate the new workflow where verification and settlement are separate operations. This allows for important use cases like performing work between verification and settlement.
74-133
: Clean separation of concerns in the refactored verification logic.The function now correctly focuses solely on verification, delegating payment decoding to the shared
decodePaymentRequest
utility. The error handling maintains consistent structure with proper x402Version inclusion.packages/thirdweb/src/x402/common.ts (1)
201-218
: Replace floating-point math with integer-safe conversion.The current implementation risks precision loss when converting USD amounts to atomic units. For example,
0.1 * 10**6
in JavaScript produces100000.00000000001
instead of100000
.Apply this diff to use integer-safe conversion:
- maxAmountRequired = (parsedUsdAmount * 10 ** asset.decimals).toString(); + // Convert to atomic units using BigInt to avoid floating point precision issues + const [whole, fractional = "0"] = parsedUsdAmount.toString().split("."); + const paddedFractional = fractional.padEnd(asset.decimals, "0").slice(0, asset.decimals); + maxAmountRequired = BigInt(whole + paddedFractional).toString();
218edc3
to
5cead43
Compare
5cead43
to
e48a412
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/thirdweb/src/x402/settle-payment.ts (1)
124-186
: Consider exportingprocessPayment
as a temporary alias to avoid churn.
Branch name suggests “processPayment”; aliasing reduces breaking docs/usages during rollout.export async function settlePayment( args: PaymentArgs, ): Promise<SettlePaymentResult> { ... } + +// Temporary alias for smoother migration; remove in a future major. +export { settlePayment as processPayment };packages/thirdweb/src/x402/verify-payment.ts (2)
18-18
: Doc compile fix: import settlePayment in the example.
The example calls settlePayment but doesn’t import it.-import { verifyPayment, facilitator } from "thirdweb/x402"; +import { verifyPayment, settlePayment, facilitator } from "thirdweb/x402";
49-60
: Doc compile fix: avoid variable shadowing and unused vars.
Rename and drop the unused assignment to keep the example compiling.- // verify the payment - const result = await verifyPayment(paymentArgs); + // verify the payment + const verificationResult = await verifyPayment(paymentArgs); - if (result.status === 200) { + if (verificationResult.status === 200) { // Payment verified, but not settled yet // you can do the work that requires payment first - const result = await doSomething(); + const data = await doSomething(); // then settle the payment - const settleResult = await settlePayment(paymentArgs); + await settlePayment(paymentArgs); // then return the result - return Response.json(result); + return Response.json(data);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.changeset/some-moons-burn.md
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(2 hunks)apps/portal/src/app/payments/x402/page.mdx
(3 hunks)packages/thirdweb/src/exports/x402.ts
(1 hunks)packages/thirdweb/src/x402/common.ts
(1 hunks)packages/thirdweb/src/x402/facilitator.ts
(1 hunks)packages/thirdweb/src/x402/settle-payment.ts
(1 hunks)packages/thirdweb/src/x402/types.ts
(1 hunks)packages/thirdweb/src/x402/verify-payment.ts
(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- apps/portal/src/app/payments/x402/page.mdx
- apps/playground-web/src/middleware.ts
- .changeset/some-moons-burn.md
- packages/thirdweb/src/exports/x402.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}
: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from@/types
or localtypes.ts
barrels
Prefer type aliases over interface except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial
,Pick
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
**/*.{ts,tsx}
: Use explicit function declarations and explicit return types in TypeScript
Limit each file to one stateless, single‑responsibility function
Re‑use shared types from@/types
where applicable
Prefertype
aliases overinterface
except for nominal shapes
Avoidany
andunknown
unless unavoidable; narrow generics when possible
Prefer composition over inheritance; use utility types (Partial, Pick, etc.)
Lazy‑import optional features and avoid top‑level side‑effects to reduce bundle size
Files:
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/page.tsx
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (CLAUDE.md)
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)
Files:
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/page.tsx
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
packages/thirdweb/**/*.{ts,tsx}
: Every public symbol must have comprehensive TSDoc with at least one compiling@example
and a custom tag (@beta
,@internal
,@experimental
, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Lazy‑load heavy dependencies inside async paths (e.g.,const { jsPDF } = await import("jspdf")
)
Files:
packages/thirdweb/src/x402/facilitator.ts
packages/thirdweb/src/x402/settle-payment.ts
packages/thirdweb/src/x402/verify-payment.ts
packages/thirdweb/src/x402/types.ts
packages/thirdweb/src/x402/common.ts
apps/{dashboard,playground-web}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
apps/{dashboard,playground-web}/**/*.{ts,tsx}
: Import UI primitives from@/components/ui/*
(Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
UseNavLink
for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Usecn()
from@/lib/utils
for conditional class logic
Use design system tokens (e.g.,bg-card
,border-border
,text-muted-foreground
)
Server Components (Node edge): Start files withimport "server-only";
Client Components (browser): Begin files with'use client';
Always callgetAuthToken()
to retrieve JWT from cookies on server side
UseAuthorization: Bearer
header – never embed tokens in URLs
Return typed results (e.g.,Project[]
,User[]
) – avoidany
Wrap client-side data fetching calls in React Query (@tanstack/react-query
)
Use descriptive, stablequeryKeys
for React Query cache hits
ConfigurestaleTime
/cacheTime
in React Query based on freshness (default ≥ 60s)
Keep tokens secret via internal API routes or server actions
Never importposthog-js
in server components
Files:
apps/playground-web/src/app/payments/x402/page.tsx
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
packages/thirdweb/src/x402/types.ts
🧠 Learnings (6)
📚 Learning: 2025-08-20T10:35:18.543Z
Learnt from: jnsdls
PR: thirdweb-dev/js#7888
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/payments/page.tsx:77-81
Timestamp: 2025-08-20T10:35:18.543Z
Learning: The webhooks/payments route exists at apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/webhooks/payments/page.tsx and was added as part of the unified project layout changes.
Applied to files:
apps/playground-web/src/app/payments/x402/page.tsx
📚 Learning: 2025-08-29T15:37:38.513Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: AGENTS.md:0-0
Timestamp: 2025-08-29T15:37:38.513Z
Learning: Applies to packages/thirdweb/**/*.{ts,tsx} : Every public symbol must have comprehensive TSDoc with at least one compiling `example` and a custom tag (`beta`, `internal`, `experimental`, etc.)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-07-18T19:19:55.613Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-07-18T19:19:55.613Z
Learning: Applies to packages/thirdweb/src/exports/** : Every public symbol must have comprehensive TSDoc with at least one `example` block that compiles and custom annotation tags (`beta`, `internal`, `experimental`)
Applied to files:
packages/thirdweb/src/x402/types.ts
📚 Learning: 2025-06-26T19:46:04.024Z
Learnt from: gregfromstl
PR: thirdweb-dev/js#7450
File: packages/thirdweb/src/bridge/Webhook.ts:57-81
Timestamp: 2025-06-26T19:46:04.024Z
Learning: In the onramp webhook schema (`packages/thirdweb/src/bridge/Webhook.ts`), the `currencyAmount` field is intentionally typed as `z.number()` while other amount fields use `z.string()` because `currencyAmount` represents fiat currency amounts in decimals (like $10.50), whereas other amount fields represent token amounts in wei (very large integers that benefit from bigint representation). The different naming convention (`currencyAmount` vs `amount`) reflects this intentional distinction.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-05-20T18:54:15.781Z
Learnt from: MananTank
PR: thirdweb-dev/js#7081
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/assets/create/create-token-page-impl.tsx:110-118
Timestamp: 2025-05-20T18:54:15.781Z
Learning: In the thirdweb dashboard's token asset creation flow, the `transferBatch` function from `thirdweb/extensions/erc20` accepts the raw quantity values from the form without requiring explicit conversion to wei using `toUnits()`. The function appears to handle this conversion internally or is designed to work with the values in the format they're already provided.
Applied to files:
packages/thirdweb/src/x402/common.ts
📚 Learning: 2025-06-06T23:47:55.122Z
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:255-277
Timestamp: 2025-06-06T23:47:55.122Z
Learning: The `transfer` function from `thirdweb/extensions/erc20` accepts human-readable amounts via the `amount` property and automatically handles conversion to base units (wei) by fetching the token decimals internally. Manual conversion using `toWei()` is not required when using the `amount` property.
Applied to files:
packages/thirdweb/src/x402/common.ts
🧬 Code graph analysis (4)
packages/thirdweb/src/x402/settle-payment.ts (5)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)SettlePaymentResult
(65-75)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)packages/thirdweb/src/x402/encode.ts (1)
safeBase64Encode
(57-65)packages/thirdweb/src/exports/utils.ts (1)
stringify
(189-189)
packages/thirdweb/src/x402/verify-payment.ts (3)
packages/thirdweb/src/x402/types.ts (2)
PaymentArgs
(23-40)VerifyPaymentResult
(82-90)packages/thirdweb/src/x402/common.ts (1)
decodePaymentRequest
(35-180)packages/thirdweb/src/x402/facilitator.ts (1)
facilitator
(58-195)
packages/thirdweb/src/x402/types.ts (3)
packages/thirdweb/src/exports/x402.ts (3)
PaymentArgs
(9-9)SettlePaymentResult
(10-10)VerifyPaymentResult
(11-11)packages/thirdweb/src/exports/utils.ts (1)
Address
(144-144)packages/thirdweb/src/x402/schemas.ts (4)
FacilitatorNetwork
(26-26)RequestedPaymentRequirements
(47-49)FacilitatorSettleResponse
(54-56)RequestedPaymentPayload
(32-34)
packages/thirdweb/src/x402/common.ts (4)
packages/thirdweb/src/x402/schemas.ts (4)
RequestedPaymentRequirements
(47-49)RequestedPaymentPayload
(32-34)FacilitatorNetwork
(26-26)networkToChainId
(58-76)packages/thirdweb/src/x402/types.ts (3)
PaymentArgs
(23-40)PaymentRequiredResult
(42-58)x402Version
(16-16)packages/thirdweb/src/x402/facilitator.ts (2)
facilitator
(58-195)supported
(168-191)packages/thirdweb/src/exports/utils.ts (1)
getAddress
(147-147)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Size
- GitHub Check: Unit Tests
🔇 Additional comments (6)
packages/thirdweb/src/x402/facilitator.ts (1)
22-22
: Doc reference updated to settlePayment — looks good.apps/playground-web/src/app/payments/x402/page.tsx (1)
60-60
: Example now uses settlePayment correctly.
Imports and args align with the new API.Also applies to: 74-82
packages/thirdweb/src/x402/settle-payment.ts (1)
146-154
: Expose the receipt header without breaking other exposed headers.
If callers merge headers, fine; if not, consider appending, not replacing.packages/thirdweb/src/x402/types.ts (1)
18-40
: Public types read well and match usage.
No action; leaving out @example for types matches prior maintainer guidance.If you require a custom tag on public types (e.g., @beta) per internal docs, we can add it uniformly; otherwise we’ll keep functions-only examples/tags.
packages/thirdweb/src/x402/verify-payment.ts (1)
74-133
: Verification flow refactor looks solid.
Separation of concerns with shared decode step is clear and correct.packages/thirdweb/src/x402/common.ts (1)
201-218
: Fix precision bug: avoid float math for atomic amounts.
Using JS numbers can under/overcharge (e.g., 0.1 × 10^6). Use integer-safe parsing.Apply this diff:
@@ - asset = defaultAsset; - maxAmountRequired = (parsedUsdAmount * 10 ** asset.decimals).toString(); + asset = defaultAsset; + // Avoid floating‑point precision loss + maxAmountRequired = parseUnits(String(parsedUsdAmount), asset.decimals).toString();Add the import:
@@ -import { getAddress } from "../utils/address.js"; +import { getAddress } from "../utils/address.js"; +import { parseUnits } from "viem";
PR-Codex overview
This PR focuses on enhancing the
thirdweb
payment system by introducing a newsettlePayment()
function alongside the existingverifyPayment()
. This allows for better handling of payments within the x402 payment protocol.Detailed summary
settlePayment()
.settlePayment()
function to handle payment settlements.middleware.ts
andpage.tsx
to usesettlePayment()
instead ofverifyPayment()
.verifyPayment()
to only verify payments without settling.types.ts
for payment handling.verify-payment.ts
.Summary by CodeRabbit
New Features
Refactor
Documentation
Chores