-
Notifications
You must be signed in to change notification settings - Fork 588
[SDK] Improve token info discovery for x402 payments #8142
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?
[SDK] Improve token info discovery for x402 payments #8142
Conversation
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🦋 Changeset detectedLatest commit: 3c6fdd0 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughAdds a new X402 playground UI (left/right sections and container), updates the X402 page to use it, adjusts middleware pricing/defaults, and enhances x402 core types/flows: facilitator “supported” API with filters, default asset detection, token metadata inference, response/error handling, and schema/type updates. Includes a changeset entry. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant L as X402LeftSection (UI)
participant R as X402RightSection (UI)
participant WF as wrapFetchWithPayment
participant F as ThirdwebX402Facilitator
participant S as Paywalled API (middleware)
participant W as Wallet
participant C as Chain
U->>L: Select chain/token/amount/payTo
L->>R: Options (chain, tokenAddress, decimals, amount, payTo)
U->>R: Click "Pay"
R->>WF: fetch(url, opts) wrapped with payment
WF->>S: Initial request (no payment)
S-->>WF: 402 response (requirements or error)
WF->>F: supported({ chainId, tokenAddress? })
F-->>WF: Supported kinds + default/supported assets
WF->>W: Request signature/tx per selected requirement
W->>C: Submit on-chain approval/permit/transfer
C-->>W: Submitted/confirmed (per waitUtil)
WF->>S: Retry with X-402 payment headers
S-->>WF: 200 OK + JSON
WF-->>R: Response data or error
R-->>U: Show result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 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. |
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
🧹 Nitpick comments (2)
apps/playground-web/src/app/payments/x402/components/X402Playground.tsx (1)
19-44
: Add explicit return type for X402PlaygroundLine 19 currently declares
export function X402Playground()
without a return type, but our TypeScript guideline calls for explicit return types. Please annotate the component accordingly.Apply this diff:
-export function X402Playground() { +export function X402Playground(): React.JSX.Element {apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx (1)
14-153
: Add explicit return type for X402LeftSectionLine 14 defines
export function X402LeftSection(...)
without a return type. To stay consistent with our TypeScript rules, please specify the component’s return type.Use this update:
-export function X402LeftSection(props: { +export function X402LeftSection(props: { options: X402PlaygroundOptions; setOptions: React.Dispatch<React.SetStateAction<X402PlaygroundOptions>>; -}) { +}): React.JSX.Element {
📜 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 (13)
.changeset/dirty-experts-kiss.md
(1 hunks)apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
(1 hunks)apps/playground-web/src/app/payments/x402/components/X402Playground.tsx
(1 hunks)apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
(1 hunks)apps/playground-web/src/app/payments/x402/components/constants.ts
(1 hunks)apps/playground-web/src/app/payments/x402/components/types.ts
(1 hunks)apps/playground-web/src/app/payments/x402/page.tsx
(2 hunks)apps/playground-web/src/middleware.ts
(3 hunks)packages/thirdweb/src/x402/common.ts
(5 hunks)packages/thirdweb/src/x402/facilitator.ts
(7 hunks)packages/thirdweb/src/x402/fetchWithPayment.ts
(2 hunks)packages/thirdweb/src/x402/schemas.ts
(2 hunks)packages/thirdweb/src/x402/types.ts
(2 hunks)
🧰 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/app/payments/x402/components/X402Playground.tsx
packages/thirdweb/src/x402/fetchWithPayment.ts
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/components/constants.ts
apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/schemas.ts
apps/playground-web/src/app/payments/x402/components/types.ts
apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
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:
apps/playground-web/src/app/payments/x402/components/X402Playground.tsx
packages/thirdweb/src/x402/fetchWithPayment.ts
packages/thirdweb/src/x402/facilitator.ts
apps/playground-web/src/app/payments/x402/components/constants.ts
apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/schemas.ts
apps/playground-web/src/app/payments/x402/components/types.ts
apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
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/app/payments/x402/components/X402Playground.tsx
apps/playground-web/src/app/payments/x402/components/constants.ts
apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/middleware.ts
apps/playground-web/src/app/payments/x402/components/types.ts
apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
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/fetchWithPayment.ts
packages/thirdweb/src/x402/facilitator.ts
packages/thirdweb/src/x402/common.ts
packages/thirdweb/src/x402/schemas.ts
packages/thirdweb/src/x402/types.ts
**/types.ts
📄 CodeRabbit inference engine (AGENTS.md)
Provide and re‑use local type barrels in a
types.ts
file
Files:
apps/playground-web/src/app/payments/x402/components/types.ts
packages/thirdweb/src/x402/types.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/dirty-experts-kiss.md
🧠 Learnings (7)
📚 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/playground-web/src/app/payments/x402/components/X402Playground.tsx
apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
apps/playground-web/src/app/payments/x402/page.tsx
apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
📚 Learning: 2025-05-30T17:14:25.332Z
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Applied to files:
packages/thirdweb/src/x402/facilitator.ts
📚 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 apps/{dashboard,playground}/**/*.{ts,tsx} : Import UI primitives from `@/components/ui/_` (e.g., Button, Input, Tabs, Card)
Applied to files:
apps/playground-web/src/app/payments/x402/page.tsx
📚 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/wallets/** : EIP-1193, EIP-5792, EIP-7702 standard support in wallet modules
Applied to files:
packages/thirdweb/src/x402/schemas.ts
packages/thirdweb/src/x402/types.ts
📚 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/playground-web/src/app/payments/x402/components/X402RightSection.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 .changeset/*.md : Version bump rules: patch for non‑API changes; minor for new/modified public API
Applied to files:
.changeset/dirty-experts-kiss.md
📚 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/types.ts
🧬 Code graph analysis (8)
apps/playground-web/src/app/payments/x402/components/X402Playground.tsx (4)
apps/playground-web/src/app/payments/x402/components/types.ts (1)
X402PlaygroundOptions
(4-11)apps/playground-web/src/app/payments/x402/components/constants.ts (2)
chain
(6-6)token
(7-10)apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx (1)
X402LeftSection
(14-153)apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx (1)
X402RightSection
(24-268)
packages/thirdweb/src/x402/facilitator.ts (1)
packages/thirdweb/src/x402/schemas.ts (1)
FacilitatorSupportedResponse
(94-96)
apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx (3)
apps/playground-web/src/app/payments/x402/components/types.ts (1)
X402PlaygroundOptions
(4-11)apps/playground-web/src/lib/client.ts (1)
THIRDWEB_CLIENT
(20-43)apps/playground-web/src/app/payments/components/LeftSection.tsx (1)
LeftSection
(21-492)
apps/playground-web/src/app/payments/x402/page.tsx (1)
apps/playground-web/src/app/payments/x402/components/X402Playground.tsx (1)
X402Playground
(19-44)
apps/playground-web/src/middleware.ts (2)
apps/playground-web/src/app/payments/x402/components/constants.ts (1)
token
(7-10)packages/thirdweb/src/x402/settle-payment.ts (1)
settlePayment
(126-187)
packages/thirdweb/src/x402/common.ts (2)
packages/thirdweb/src/x402/types.ts (3)
DefaultAsset
(109-109)ERC20TokenAmount
(96-107)SupportedSignatureType
(92-94)packages/thirdweb/src/x402/facilitator.ts (3)
facilitator
(89-244)supported
(204-240)ThirdwebX402Facilitator
(24-46)
apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx (3)
apps/playground-web/src/app/payments/x402/components/types.ts (1)
X402PlaygroundOptions
(4-11)packages/thirdweb/src/x402/fetchWithPayment.ts (1)
wrapFetchWithPayment
(51-138)apps/playground-web/src/lib/client.ts (1)
THIRDWEB_CLIENT
(20-43)
packages/thirdweb/src/x402/types.ts (1)
packages/thirdweb/src/x402/schemas.ts (2)
SupportedSignatureTypeSchema
(60-63)FacilitatorSupportedAssetSchema
(65-73)
⏰ 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, vite)
- GitHub Check: E2E Tests (pnpm, esbuild)
- GitHub Check: E2E Tests (pnpm, webpack)
- GitHub Check: Unit Tests
- GitHub Check: Build Packages
- GitHub Check: Analyze (javascript)
setOptions((v) => ({ | ||
...v, | ||
tokenAddress: token.address as `0x${string}`, | ||
tokenSymbol: token.symbol || "", | ||
tokenDecimals: token.decimals || 18, | ||
})); |
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.
Fix decimals fallback to handle zero-decimal tokens
Line 66 uses token.decimals || 18
, which incorrectly overwrites legitimate zero-decimal tokens with 18 and inflates the on-chain amount by 10^18. This breaks payments for any 0-decimal asset (e.g., certain governance tokens). Please switch to a nullish check so that 0
is preserved.
Apply this diff:
- tokenDecimals: token.decimals || 18,
+ tokenDecimals: token.decimals ?? 18,
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
setOptions((v) => ({ | |
...v, | |
tokenAddress: token.address as `0x${string}`, | |
tokenSymbol: token.symbol || "", | |
tokenDecimals: token.decimals || 18, | |
})); | |
setOptions((v) => ({ | |
...v, | |
tokenAddress: token.address as `0x${string}`, | |
tokenSymbol: token.symbol || "", | |
tokenDecimals: token.decimals ?? 18, | |
})); |
🤖 Prompt for AI Agents
In apps/playground-web/src/app/payments/x402/components/X402LeftSection.tsx
around lines 62 to 67, the fallback uses `token.decimals || 18` which overwrites
legitimate 0 values; change the fallback to a nullish check so zero is preserved
(e.g., set tokenDecimals to `token.decimals ?? 18` or otherwise explicitly check
for null/undefined) ensuring the decimals remain a number and 0 is not replaced
by 18.
payTo: ${props.options.payTo}, | ||
network: defineChain(${props.options.chain.id}), | ||
price: { | ||
amount: "${Number(props.options.amount) * 10 ** props.options.tokenDecimals}", | ||
asset: { | ||
address: ${props.options.tokenAddress}, | ||
}, | ||
}, |
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.
Fix server code interpolation and amount conversion
Rendering the snippet as-is drops the quotes around payTo
/address
, so the preview outputs payTo: 0xabc...
which is invalid JavaScript and will throw immediately when copied. On top of that, coercing amount
with Number(...) * 10 ** ...
will emit scientific notation (e.g. 1e+24
) for larger values, which breaks settlePayment
. The snippet already imports toUnits
, so we should rely on it and keep the interpolated values quoted.
- payTo: ${props.options.payTo},
+ payTo: "${props.options.payTo}",
@@
- amount: "${Number(props.options.amount) * 10 ** props.options.tokenDecimals}",
+ amount: toUnits("${props.options.amount}", ${props.options.tokenDecimals}).toString(),
@@
- address: ${props.options.tokenAddress},
+ address: "${props.options.tokenAddress}",
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
payTo: ${props.options.payTo}, | |
network: defineChain(${props.options.chain.id}), | |
price: { | |
amount: "${Number(props.options.amount) * 10 ** props.options.tokenDecimals}", | |
asset: { | |
address: ${props.options.tokenAddress}, | |
}, | |
}, | |
payTo: "${props.options.payTo}", | |
network: defineChain(${props.options.chain.id}), | |
price: { | |
amount: toUnits("${props.options.amount}", ${props.options.tokenDecimals}).toString(), | |
asset: { | |
address: "${props.options.tokenAddress}", | |
}, | |
}, |
🤖 Prompt for AI Agents
In apps/playground-web/src/app/payments/x402/components/X402RightSection.tsx
around lines 108 to 115, the generated snippet interpolates payTo and token
address without quotes and converts amount using Number(...) * 10 ** ..., which
yields invalid JS and scientific notation; update the template so payTo and
token address are rendered as quoted strings, and replace the manual numeric
conversion with the existing toUnits(props.options.amount,
props.options.tokenDecimals) call (stringified) to produce a safe integer string
for amount; keep defineChain(${props.options.chain.id}) as-is and ensure the
final amount value is inserted as a quoted string.
const amount = queryParams.get("amount") || "0.01"; | ||
const tokenAddress = queryParams.get("tokenAddress") || token.address; | ||
const decimals = queryParams.get("decimals") || token.decimals.toString(); | ||
|
||
const result = await settlePayment({ | ||
resourceUrl, | ||
method, | ||
paymentData, | ||
payTo: payTo as `0x${string}`, | ||
network: defineChain(Number(chainId)), | ||
price: "$0.01", | ||
// price: { | ||
// amount: toUnits(amount as string, parseInt(decimals as string)).toString(), | ||
// asset: { | ||
// address: tokenAddress as `0x${string}`, | ||
// decimals: decimals ? parseInt(decimals) : token.decimals, | ||
// eip712: { | ||
// name: token.name, | ||
// version: token.version, | ||
// }, | ||
// }, | ||
// }, | ||
price: { | ||
amount: toUnits( | ||
amount as string, | ||
parseInt(decimals as string), | ||
).toString(), | ||
asset: { | ||
address: tokenAddress as `0x${string}`, | ||
decimals: decimals ? parseInt(decimals) : token.decimals, | ||
}, | ||
}, |
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.
Validate decimals
before computing price units.
Line 52 now calls toUnits
with parseInt(decimals as string)
, but we never confirm the query param is actually numeric. If a client sends a malformed decimals
(or even an empty string), parseInt
yields NaN
, toUnits
throws, and the middleware responds with a 500 instead of a controlled 4xx. Please validate the parsed value and use the safe number when constructing the price payload.
Apply this diff to harden the handler:
- const amount = queryParams.get("amount") || "0.01";
- const tokenAddress = queryParams.get("tokenAddress") || token.address;
- const decimals = queryParams.get("decimals") || token.decimals.toString();
+ const amount = queryParams.get("amount") || "0.01";
+ const tokenAddress = queryParams.get("tokenAddress") || token.address;
+ const decimalsParam = queryParams.get("decimals");
+ const decimals =
+ decimalsParam === null
+ ? token.decimals
+ : Number.parseInt(decimalsParam, 10);
+
+ if (!Number.isInteger(decimals) || decimals < 0) {
+ return NextResponse.json(
+ { error: "Invalid token decimals parameter" },
+ { status: 400 },
+ );
+ }
@@
- price: {
- amount: toUnits(
- amount as string,
- parseInt(decimals as string),
- ).toString(),
- asset: {
- address: tokenAddress as `0x${string}`,
- decimals: decimals ? parseInt(decimals) : token.decimals,
- },
- },
+ price: {
+ amount: toUnits(amount, decimals).toString(),
+ asset: {
+ address: tokenAddress as `0x${string}`,
+ decimals,
+ },
+ },
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const amount = queryParams.get("amount") || "0.01"; | |
const tokenAddress = queryParams.get("tokenAddress") || token.address; | |
const decimals = queryParams.get("decimals") || token.decimals.toString(); | |
const result = await settlePayment({ | |
resourceUrl, | |
method, | |
paymentData, | |
payTo: payTo as `0x${string}`, | |
network: defineChain(Number(chainId)), | |
price: "$0.01", | |
// price: { | |
// amount: toUnits(amount as string, parseInt(decimals as string)).toString(), | |
// asset: { | |
// address: tokenAddress as `0x${string}`, | |
// decimals: decimals ? parseInt(decimals) : token.decimals, | |
// eip712: { | |
// name: token.name, | |
// version: token.version, | |
// }, | |
// }, | |
// }, | |
price: { | |
amount: toUnits( | |
amount as string, | |
parseInt(decimals as string), | |
).toString(), | |
asset: { | |
address: tokenAddress as `0x${string}`, | |
decimals: decimals ? parseInt(decimals) : token.decimals, | |
}, | |
}, | |
const amount = queryParams.get("amount") || "0.01"; | |
const tokenAddress = queryParams.get("tokenAddress") || token.address; | |
const decimalsParam = queryParams.get("decimals"); | |
const decimals = | |
decimalsParam === null | |
? token.decimals | |
: Number.parseInt(decimalsParam, 10); | |
if (!Number.isInteger(decimals) || decimals < 0) { | |
return NextResponse.json( | |
{ error: "Invalid token decimals parameter" }, | |
{ status: 400 }, | |
); | |
} | |
const result = await settlePayment({ | |
resourceUrl, | |
method, | |
paymentData, | |
payTo: payTo as `0x${string}`, | |
network: defineChain(Number(chainId)), | |
price: { | |
amount: toUnits(amount, decimals).toString(), | |
asset: { | |
address: tokenAddress as `0x${string}`, | |
decimals, | |
}, | |
}, |
🤖 Prompt for AI Agents
In apps/playground-web/src/middleware.ts around lines 41 to 60, the handler
calls toUnits(parseInt(decimals as string)) without validating the query param;
if decimals is non-numeric this produces NaN and crashes with a 500. Parse the
decimals param to a number, check Number.isFinite/!Number.isNaN and that it's an
integer within a valid range (e.g. 0–36); if invalid, return a 400 response
explaining the invalid decimals; otherwise use the parsed safeNumber for both
toUnits and the asset.decimals field (falling back to token.decimals when the
param is missing). Ensure no direct call to toUnits with a potentially NaN
value.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8142 +/- ##
==========================================
- Coverage 56.28% 56.28% -0.01%
==========================================
Files 906 906
Lines 59208 59208
Branches 4180 4178 -2
==========================================
- Hits 33324 33323 -1
- Misses 25780 25781 +1
Partials 104 104
🚀 New features to boost your workflow:
|
PR-Codex overview
This PR focuses on enhancing the
x402
payment system by improving token information discovery, updating components for better user experience, and refining payment handling logic.Detailed summary
x402
payments.X402PlaygroundOptions
type to includechain
,tokenAddress
,tokenSymbol
,tokenDecimals
,amount
, andpayTo
.fetchWithPayment.ts
to include error handling.constants.ts
to usebase
chain instead ofarbitrumSepolia
.X402Playground
component to manage user input and state.schemas.ts
.facilitator.ts
to support dynamic filters for supported payment kinds.X402LeftSection
andX402RightSection
.Summary by CodeRabbit
New Features
Improvements
Documentation