-
Notifications
You must be signed in to change notification settings - Fork 590
Fix typo in facilitator configuration function #8093
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
base: main
Are you sure you want to change the base?
Conversation
Corrected a typo in the configuration function description. Signed-off-by: Eiman <[email protected]>
The latest updates on your projects. Learn more about Vercel for GitHub.
4 Skipped Deployments
|
|
WalkthroughComplete rewrite of the x402 payments doc renamed to "402 Gated Payments", expanding introduction, core concepts, payment protocol fundamentals, supported networks/tokens, detailed client and server implementations (including Next.js), middleware and env-based server wallet configuration, richer TypeScript examples, and per-endpoint pricing configuration. Changes
Sequence Diagram(s)sequenceDiagram
rect rgba(46,125,50,0.06)
participant Client
end
rect rgba(13,71,161,0.06)
participant Facilitator as "thirdweb Facilitator / Middleware"
end
rect rgba(236,64,122,0.06)
participant ServerWallet as "Server Wallet (env: SERVER_WALLET_ADDRESS)"
end
rect rgba(255,179,0,0.06)
participant Network as "Blockchain / Token Network"
end
Client->>Facilitator: Initial API request
Facilitator-->>Client: 402 Payment Required (payment params)
Client->>Client: User wallet signs payment intent
Client->>Facilitator: Retry request with Payment header + signed intent
Facilitator->>ServerWallet: Forward/aggregate payment intents (optional)
ServerWallet->>Network: On-chain settlement / token transfer
Network-->>ServerWallet: Transaction confirmation
ServerWallet-->>Facilitator: Settlement result
Facilitator-->>Client: Final API response (success / error)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 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. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8093 +/- ##
=======================================
Coverage 56.34% 56.34%
=======================================
Files 906 906
Lines 59187 59187
Branches 4181 4181
=======================================
Hits 33351 33351
Misses 25730 25730
Partials 106 106
🚀 New features to boost your workflow:
|
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: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/portal/src/app/payments/x402/page.mdx (1)
220-239
: Use a single source of truth for server wallet address.You hard‑code an address (Line 225) but also pass SERVER_WALLET_ADDRESS to facilitator (Line 237). This can drift and cause mis‑settlement.
-export const middleware = paymentMiddleware( - "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024", // Your server wallet address +const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +export const middleware = paymentMiddleware( + serverWalletAddress, // Your server wallet address @@ - facilitator({ - client, - serverWalletAddress: process.env.SERVER_WALLET_ADDRESS, - }), + facilitator({ client, serverWalletAddress }), );
🧹 Nitpick comments (7)
apps/portal/src/app/payments/x402/page.mdx (7)
6-6
: Hyphenate “on‑chain”.Change “onchain” to “on-chain” for correctness.
-Implement paid API calls using the x402 protocol. Every request is paid for by the user with a micro payment onchain. +Implement paid API calls using the x402 protocol. Every request is paid for by the user with a micro payment on-chain.
10-13
: Use “an x402” (article agreement).“x402” is pronounced “ex-…”, so use “an”.
- description="Try out a x402 payment in our live playground" + description="Try out an x402 payment in our live playground"
124-132
: Avoid top‑level await in generic snippets.Wrap in an async IIFE for portability across bundlers/runtimes.
-const client = createThirdwebClient({ clientId: "your-client-id" }); -const wallet = createWallet("io.metamask"); // or any other wallet -await wallet.connect({ client }) - -const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet); - -// Make a request that may require payment -const response = await fetchWithPay('https://api.example.com/paid-endpoint'); +(async () => { + const client = createThirdwebClient({ clientId: "your-client-id" }); + const wallet = createWallet("io.metamask"); // or any other wallet + await wallet.connect({ client }); + const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet); + const response = await fetchWithPay("https://api.example.com/paid-endpoint"); + // use response... +})();
139-146
: Prefer BigInt literals or utility for token units.Avoid Number→BigInt coercion; use BigInt math or a helper like parseUnits.
- BigInt(5 * 10 ** 6) // Maximum 5 USDC + 5n * 10n ** 6n // Maximum 5 USDC (6 decimals) + // or: parseUnits("5", 6) if available from your SDK
75-76
: “Automatically negotiate the best payment network” needs qualification.If negotiation requires explicit config or wallet capabilities, clarify to avoid misleading expectations.
-- **Network selection**: Client and server automatically negotiate the best payment network +- **Network selection**: Client and server select the configured payment network (auto‑prompting wallet switch when required)
91-93
: Clarify “Gasless transactions”.If the facilitator pays gas (sponsor) rather than transactions being gas‑free on-chain, reword to avoid confusion.
-- **Gasless transactions**: Handles all gas costs for payment settlement +- **Sponsored settlement**: Facilitator covers gas for payment settlement on your behalf
63-71
: Link supported networks list to thirdweb's canonical Chainlist / Pay Supported Chains
Replace the hardcoded list in apps/portal/src/app/payments/x402/page.mdx (lines 63–71) with a link to thirdweb’s maintained Chainlist / Pay Supported Chains page — or generate the list from the canonical config at build time to prevent drift.
📜 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 (1)
apps/portal/src/app/payments/x402/page.mdx
(5 hunks)
⏰ 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: Analyze (javascript)
🔇 Additional comments (1)
apps/portal/src/app/payments/x402/page.mdx (1)
209-212
: Package names verified — no change needed.
The middleware packages "x402-hono", "x402-next", and "x402-express" are the published npm package names and match the thirdweb x402 x402 facilitator docs.
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
apps/portal/src/app/payments/x402/page.mdx (2)
220-239
: Use one source of truth for server wallet; avoid hard‑coded addressYou hard‑code payTo while passing env in facilitator. Make both use the same env var and validate presence.
-import { facilitator } from "thirdweb/x402"; +import { facilitator } from "thirdweb/x402"; @@ -export const middleware = paymentMiddleware( - "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024", // Your server wallet address +const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +if (!serverWalletAddress) { + throw new Error("SERVER_WALLET_ADDRESS is not set"); +} +export const middleware = paymentMiddleware( + serverWalletAddress, // Your server wallet address @@ facilitator({ client, - serverWalletAddress: process.env.SERVER_WALLET_ADDRESS, + serverWalletAddress, }), // thirdweb payment processor configuration );
119-132
: Add required bigintmaxValue
to wrapFetchWithPayment callSignature is wrapFetchWithPayment(fetch, client, wallet, maxValue: bigint). The snippet passes only three args — update apps/portal/src/app/payments/x402/page.mdx (lines 119–132) to provide an appropriate bigint (e.g., 0n) or update the example to match the API.
🧹 Nitpick comments (3)
apps/portal/src/app/payments/x402/page.mdx (3)
55-59
: Clarify max‑amount units (token smallest unit vs. USD)Explicitly state that client max limits are specified in the payment token’s smallest unit (e.g., USDC 6 decimals) to avoid misconfiguration.
139-146
: Use bigint literals; avoid Number -> BigInt coercion and document decimalsPrefer bigint math to prevent accidental float/precision issues; also annotate 6‑decimals for USDC.
- BigInt(5 * 10 ** 6) // Maximum 5 USDC + 5n * 10n ** 6n // Maximum 5 USDC (USDC has 6 decimals)
294-298
: Add client‑side env var used in React snippetInclude NEXT_PUBLIC_THIRDWEB_CLIENT_ID to prevent confusion when instantiating the client on the web.
# .env.local THIRDWEB_SECRET_KEY=your_thirdweb_secret_key SERVER_WALLET_ADDRESS=0x1234567890123456789012345678901234567890 +NEXT_PUBLIC_THIRDWEB_CLIENT_ID=your_thirdweb_client_id
📜 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 (1)
apps/portal/src/app/payments/x402/page.mdx
(4 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
📚 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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
⏰ 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: Size
- GitHub Check: Lint Packages
- GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
apps/portal/src/app/payments/x402/page.mdx (7)
4-7
: Scope drift: doc rewrite vs. “Fix typo” PR titleThis is a substantial docs overhaul, not a typo fix. Please confirm scope and update the PR title/description accordingly or split changes.
8-13
: Verify playground link and title consistencyConfirm the playground URL resolves and matches the page’s “402 Gated Payments” terminology across nav/search.
153-171
: Don’t match on error.message; switch on structured codes/payload-} catch (error) { - if (error.message.includes("Payment amount exceeds maximum")) { +} catch (error: unknown) { + const err = error as { code?: string; name?: string; message?: string }; + switch (err?.code) { + case "X402_MAX_AMOUNT_EXCEEDED": // Handle payment too expensive - } else if (error.message.includes("Wallet not connected")) { + console.error("Payment required exceeds your limit"); + break; + case "WALLET_NOT_CONNECTED": // Handle wallet connection issues - console.error("Please connect your wallet"); - } else if (error.message.includes("Payment already attempted")) { + console.error("Please connect your wallet"); + break; + case "X402_ALREADY_ATTEMPTED": // Handle retry scenarios - console.error("Payment was already processed"); - } else { + console.error("Payment was already processed"); + break; + default: { // Handle other errors (user rejected, insufficient funds, etc.) - console.error("Payment failed:", error.message); - } + console.error("Payment failed:", err?.message ?? "Unknown error"); + } + } }
178-203
: React snippet missing client and wrapFetchWithPayment imports/definition-import { useActiveWallet } from "thirdweb/react"; +import { useActiveWallet } from "thirdweb/react"; +import { createThirdwebClient } from "thirdweb"; +import { wrapFetchWithPayment } from "thirdweb/x402"; +// If your app provides a client via context, prefer that (e.g., useThirdwebClient) +// import { useThirdwebClient } from "your/provider"; @@ function PayableAPICall() { const wallet = useActiveWallet(); + const client = createThirdwebClient({ clientId: process.env.NEXT_PUBLIC_THIRDWEB_CLIENT_ID! }); @@ if (!wallet) throw new Error("Wallet not connected"); const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet);
263-288
: Undefined serverWalletAddress in multi‑route snippet-export const middleware = paymentMiddleware( - serverWalletAddress, +const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +if (!serverWalletAddress) throw new Error("SERVER_WALLET_ADDRESS is not set"); +export const middleware = paymentMiddleware( + serverWalletAddress, { @@ }, facilitator({ client, serverWalletAddress }), // thirdweb payment processor );Also verify network identifiers (“base”, “base-sepolia”) match your x402-next version.
249-256
: Approve — config example matches thirdweb/x402 docsOption names client and serverWalletAddress are correct; optional baseUrl and vaultAccessToken are also supported. Keep the example synced with the package README.
60-71
: Network support list may be stale — mark as examples or link to the canonical README
x402 / x402-next READMEs use "base-sepolia" and the middleware is configurable for other networks (e.g., "sei"); do not present an exhaustive list — either prefix with "for example" or add a link to the package README/source-of-truth.
File: apps/portal/src/app/payments/x402/page.mdx (lines 60–71)
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/portal/src/app/payments/x402/page.mdx (1)
210-225
: Inconsistent server wallet source — hardcoded address vs env var.Using a literal address for payTo while passing a different env address to the facilitator risks funds going to the wrong place. Use a single env‑driven variable and fail fast if missing.
-import { createThirdwebClient } from "thirdweb"; +import { createThirdwebClient } from "thirdweb"; import { facilitator } from "thirdweb/x402"; import { paymentMiddleware } from "x402-next"; const client = createThirdwebClient({ secretKey: process.env.THIRDWEB_SECRET_KEY as string, }); +const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +if (!serverWalletAddress) { + throw new Error("SERVER_WALLET_ADDRESS is not set"); +} + export const middleware = paymentMiddleware( - "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024", // Your server wallet address + serverWalletAddress, { "/api/paid-endpoint": { price: "$0.01", network: "base-sepolia", config: { description: "Access to paid content", }, }, }, facilitator({ client, - serverWalletAddress: process.env.SERVER_WALLET_ADDRESS, + serverWalletAddress, }), // thirdweb payment processor configuration );
🧹 Nitpick comments (4)
apps/portal/src/app/payments/x402/page.mdx (4)
4-6
: PR scope/title/body mismatch — this is more than a typo fix.Large doc rewrites are included. Please update the PR title/description (or split the PR) so reviewers know the true scope.
74-75
: Auto chain switch claim — clarify user prompt.Most wallets require a user‑approved switch; don’t promise automatic switching.
-- **Chain switching**: Automatically switches to the required payment network +- **Chain switching**: Prompts the user to switch to the required payment network (or surfaces an actionable error)
49-59
: Supported networks/tokens list can drift — confirm and reduce maintenance risk.Verify the list matches the current processor release; consider replacing with “Examples include …” plus a link to a single source of truth or an include pulled from shared constants to avoid stale docs.
Also applies to: 61-63
87-92
: Over‑promising on “multi‑network”, “gasless”, “real‑time” — add constraints.Clarify that: same EVM address works across EVM chains; gasless depends on facilitator/network; “real‑time” may be subject to chain finality/queueing.
📜 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 (1)
apps/portal/src/app/payments/x402/page.mdx
(4 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
📚 Learning: 2025-07-18T19:20:32.530Z
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-07-18T19:20:32.530Z
Learning: Applies to dashboard/**/*client.tsx : Anything that consumes hooks from `tanstack/react-query` or thirdweb SDKs.
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
📚 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 apps/{dashboard,playground-web}/**/*.{ts,tsx} : Wrap client-side data fetching calls in React Query (`tanstack/react-query`)
Applied to files:
apps/portal/src/app/payments/x402/page.mdx
⏰ 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: Lint Packages
- GitHub Check: Size
- GitHub Check: Analyze (javascript)
🔇 Additional comments (7)
apps/portal/src/app/payments/x402/page.mdx (7)
61-64
: Network negotiation phrasing is misleading — server dictates the network.Replace “Client and server automatically negotiate the best payment network” with server‑led wording.
-**Network selection**: Client and server automatically negotiate the best payment network + - Network selection: Server advertises accepted network(s) in the 402 response; the client will build/send the payment on an advertised network if the connected wallet supports it.
83-84
: Unconditional “gasless” statements — make conditional and note limits.Gas sponsorship depends on the facilitator, token/network, and quotas. Soften both bullets.
-- **Automatic settlement**: Executes token transfers to your server wallet -- **Gasless transactions**: thirdweb covers all gas costs for payment processing +- **Automatic settlement**: Executes token transfers to your server wallet +- **Gasless transactions (when supported)**: Settlement can be sponsored by a facilitator so buyers pay no gas; availability depends on the facilitator, supported token/network, and any quotas/plan limits. @@ -- **Gasless payments**: Payment transfers are performed in gasless fashion to reduce friction +- **Gasless payments (when supported)**: Transfers may be sponsored by the facilitator; availability varies by facilitator and network/token.Also applies to: 90-91
125-131
: Max payment units — confirm default and denomination.You state default is 1 USDC and pass BigInt(5 * 10 ** 6) for 5 USDC (USDC 6 decimals). Verify the helper indeed expects 6‑decimals amount and that the default is 1 USDC in the current SDK version.
139-157
: Don’t match on error.message — use codes/payload.Switch to typed/narrow checks (error code/response payload) instead of substring matching.
-} catch (error) { - if (error.message.includes("Payment amount exceeds maximum")) { +} catch (error: unknown) { + const err = error as { code?: string; message?: string; response?: Response }; + // Try protocol/server payload first + let code: string | undefined = err?.code; + if (!code && err?.response) { + try { + const body = await err.response.clone().json(); + code = body?.code ?? body?.error?.code; + } catch {} + } + if (code === "X402_MAX_AMOUNT_EXCEEDED") { // Handle payment too expensive - } else if (error.message.includes("Wallet not connected")) { + } else if (code === "WALLET_NOT_CONNECTED") { // Handle wallet connection issues - } else if (error.message.includes("Payment already attempted")) { + } else if (code === "X402_ALREADY_ATTEMPTED") { // Handle retry scenarios - } else { + } else if (err?.message) { // Handle other errors (user rejected, insufficient funds, etc.) - console.error("Payment failed:", error.message); + console.error("Payment failed:", err.message); } }
164-189
: React snippet: missing client/imports; potential undefined identifiers.Import/create a client (or use a provider hook) and import wrapFetchWithPayment.
+import { createThirdwebClient } from "thirdweb"; +import { wrapFetchWithPayment } from "thirdweb/x402"; +// If the app provides a client via context, prefer that hook (e.g., useThirdwebClient) import { useActiveWallet } from "thirdweb/react"; import { useMutation } from "@tanstack/react-query"; function PayableAPICall() { const wallet = useActiveWallet(); + const client = createThirdwebClient({ clientId: "your-client-id" }); const paidApiCall = useMutation({ mutationFn: async () => { if (!wallet) throw new Error("Wallet not connected"); - const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet); + const fetchWithPay = wrapFetchWithPayment(fetch, client, wallet); const response = await fetchWithPay('/api/paid-endpoint'); return response.json(); }, });
249-270
: serverWalletAddress is referenced but not declared in this snippet.Declare it (env‑based) and reuse the same variable across examples to avoid drift.
+const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +if (!serverWalletAddress) throw new Error("SERVER_WALLET_ADDRESS is not set"); export const middleware = paymentMiddleware( serverWalletAddress, { "/api/basic-data": { price: "$0.01", network: "base-sepolia", config: { description: "Basic data access" },
201-205
: Package name import — confirm accuracy for your version.Ensure paymentMiddleware import path is correct (e.g., "x402-next" vs scoped variants) for the version used in this repo.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apps/portal/src/app/payments/x402/page.mdx (1)
179-193
: Use a single source of truth for server wallet address; avoid hardcodingLiteral address at Line 179 conflicts with env at Lines 191–193. Use env everywhere and validate presence.
Apply this diff:
-import { createThirdwebClient } from "thirdweb"; +import { createThirdwebClient } from "thirdweb"; import { facilitator } from "thirdweb/x402"; import { paymentMiddleware } from "x402-next"; const client = createThirdwebClient({ secretKey: process.env.THIRDWEB_SECRET_KEY as string, }); +const serverWalletAddress = process.env.SERVER_WALLET_ADDRESS as string; +if (!serverWalletAddress) { + throw new Error("SERVER_WALLET_ADDRESS is not set"); +} + export const middleware = paymentMiddleware( - "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024", // Your server wallet address + serverWalletAddress, // Your server wallet address { "/api/paid-endpoint": { price: "$0.01", network: "base-sepolia", config: { description: "Access to paid content", }, }, }, facilitator({ client, - serverWalletAddress: process.env.SERVER_WALLET_ADDRESS, + serverWalletAddress, }), // thirdweb payment processor configuration );
🧹 Nitpick comments (4)
apps/portal/src/app/payments/x402/page.mdx (4)
74-74
: Avoid implying silent chain switchesMost wallets require prompting/consent; say “prompts” instead of “automatically switches.”
Apply this diff:
-- **Chain switching**: Automatically switches to the required payment network +- **Chain switching**: Prompts users to switch to the required payment network when needed
91-91
: Tone down “Real‑time settlement”Settlement depends on facilitator processing and chain finality.
Apply this diff:
-- **Real-time settlement**: Payments arrive in your wallet immediately after validation +- **Near‑real‑time settlement**: Payments are submitted for settlement after validation; timing depends on facilitator processing and chain finality.
139-156
: Prefer typed error handling over string includesIf the SDK exposes structured error types/codes, show that pattern to avoid brittle string checks.
Apply this diff if applicable:
-} catch (error) { - if (error.message.includes("Payment amount exceeds maximum")) { +} catch (error) { + if (error.code === "X402_MAX_EXCEEDED") { // Handle payment too expensive - } else if (error.message.includes("Wallet not connected")) { + } else if (error.code === "WALLET_NOT_CONNECTED") { // Handle wallet connection issues - } else if (error.message.includes("Payment already attempted")) { + } else if (error.code === "X402_ALREADY_ATTEMPTED") { // Handle retry scenarios } else { // Handle other errors (user rejected, insufficient funds, etc.) }If no typed errors exist, keep string checks but note they’re subject to change.
217-237
: Define serverWalletAddress in multi‑endpoint example
serverWalletAddress
is used but not defined in this snippet.Apply this diff:
export const middleware = paymentMiddleware( - serverWalletAddress, + process.env.SERVER_WALLET_ADDRESS as string, { "/api/basic-data": { price: "$0.01", network: "base-sepolia", config: { description: "Basic data access" }, }, "/api/premium-analytics": { price: "$0.05", network: "base", // Use mainnet for higher-value endpoints config: { description: "Premium analytics data" }, }, "/api/ai-processing": { price: "$0.10", network: "base", config: { description: "AI-powered data processing" }, }, }, - facilitator({ client, serverWalletAddress }), // thirdweb payment processor + facilitator({ client, serverWalletAddress: process.env.SERVER_WALLET_ADDRESS as string }), // thirdweb payment processor );Optionally hoist the env into a const and validate as shown above.
📜 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 (1)
apps/portal/src/app/payments/x402/page.mdx
(4 hunks)
🔇 Additional comments (7)
apps/portal/src/app/payments/x402/page.mdx (7)
63-64
: Replace “automatic negotiation” — server advertises; client followsReword to avoid implying client‑led negotiation.
Apply this diff:
-- **Network selection**: Client and server automatically negotiate the best payment network +- **Network selection**: Server advertises accepted network(s) in the 402 response; the client will build/send the payment on an advertised network if the connected wallet supports it.
205-210
: Facilitator options typo fix LGTMOptions naming (
client
,serverWalletAddress
) looks correct.If this PR’s goal is solely the typo fix, confirm no other wording needs updating elsewhere in the page referencing these options.
83-84
: Make gasless claims conditional and facilitator‑specificUnqualified “gasless” is misleading; support depends on facilitator, token/network, and limits.
Apply this diff:
-- **Gasless transactions**: thirdweb covers all gas costs for payment processing +- **Gasless transactions (when supported)**: A facilitator can sponsor gas so buyers pay no gas; availability and quotas depend on the facilitator, network/token support (e.g., EIP‑3009), and any plan limits. - **Gasless payments**: Payment transfers are performed in gasless fashion to reduce friction + **Gasless payments (when supported)**: Transfers may be sponsored by the facilitator on supported networks/tokens.Also applies to: 90-90
171-173
: Imports verified — no changes neededConfirmed that the npm package
x402-next
exportspaymentMiddleware
; the import in apps/portal/src/app/payments/x402/page.mdx (lines 171–173) is correct.
181-187
: Config types confirmed — example is correctprice accepts USD strings like "$0.01" (implied USDC) or a TokenAmount for custom tokens; network accepts x402 network slugs such as "base-sepolia".
125-132
: Confirmed: wrapFetchWithPayment signature & default max — add doc clarificationVerified: signature is wrapFetchWithPayment(fetch, client, wallet, maxValue: bigint) and omitting the 4th arg defaults to 1 USDC (6 decimals / base units).
Add a one-line clarification after the snippet in apps/portal/src/app/payments/x402/page.mdx (around lines 125–132):
"The 4th argument is the maximum payment in the token's smallest units (USDC has 6 decimals); omitting it defaults to 1 USDC. e.g. BigInt(5 * 10 ** 6) = 5 USDC."
49-59
: Replace static supported networks/tokens with the canonical support matrix (or add an “as of” date)Supported chains/tokens drift — either link to thirdweb’s live support pages or add “as of September 22, 2025” and confirm accuracy.
Location: apps/portal/src/app/payments/x402/page.mdx — lines 49–59 (also 61–62)
Canonical sources to link: thirdweb x402 facilitator docs; x402.wrapFetchWithPayment docs; thirdweb Universal Bridge (networks/tokens); thirdweb Supported Chains page.
Corrected a typo in the configuration function description.
PR-Codex overview
This PR focuses on enhancing the documentation for the
402 Gated Payments
feature, detailing its implementation, benefits, and components for both client and server sides, while improving clarity and terminology.Detailed summary
x402 payments
to402 Gated Payments
.Summary by CodeRabbit