-
Notifications
You must be signed in to change notification settings - Fork 7
Description
Background
The x402 protocol's PaymentRequirements schema currently only includes the asset field (token address) but does not provide token metadata such as decimals or symbol. This makes it difficult for client applications to correctly format and display payment amounts without hardcoding token-specific information.
When displaying amounts to users, clients need to convert from atomic units (e.g., 100000 for USDC) to human-readable decimals (e.g., 0.1 USDC). Without knowing the token's decimal places, clients must either:
- Hardcode decimals for known tokens (not scalable)
- Query token metadata on-chain (adds latency and complexity)
- Maintain a token registry (maintenance burden)
This limitation becomes critical when x402 needs to support multiple payment tokens beyond USDC, such as:
- USDT (6 decimals)
- DAI (18 decimals)
- Custom ERC20 tokens (varying decimals)
Problem
Current state:
- x402 protocol limitation: The
PaymentRequirementsschema only includesasset(token address), not token metadata - Client-side workarounds required: Applications must implement their own solutions to determine token decimals
- Inconsistent developer experience: Each project handles token formatting differently
Example of the impact:
// Showcase frontend currently hardcodes USDC decimals
// examples/showcase/client/src/components/PaymentDialog.tsx:413
(parseFloat(paymentRequirements.extra.businessAmount) / 1000000).toFixed(6)This approach works only for USDC and breaks when supporting other tokens with different decimal places.
Proposed Solution
Option 1: Add tokenDecimals to extra field (Recommended)
Modify @x402x/core's addSettlementExtra function to automatically include token decimals:
// typescript/packages/core/src/utils.ts
export function addSettlementExtra(
requirements: PaymentRequirements,
params: { ... }
): PaymentRequirements {
const config = getNetworkConfig(requirements.network);
const extra: SettlementExtra = {
// ... existing fields ...
tokenDecimals: config.usdc.decimals, // 👈 Add this
tokenSymbol: config.usdc.symbol, // 👈 Optional: also add symbol
};
return {
...requirements,
extra: {
...requirements.extra,
...extra,
},
};
}Frontend usage:
const decimals = paymentRequirements.extra.tokenDecimals || 6; // Fallback to USDC
const displayAmount = (parseFloat(atomicAmount) / Math.pow(10, decimals)).toFixed(decimals);Option 2: Fetch token metadata from blockchain
Query token decimals on-chain when needed, but this adds latency and complexity.
Benefits
- ✅ Future-proof: Ready for multi-token support
- ✅ Better DX: Developers don't need to manage token metadata
- ✅ Consistent: All SDK users get correct decimals automatically
- ✅ Backward compatible: Uses
extrafield, doesn't break x402 protocol
Related Files
typescript/packages/core/src/utils.ts-addSettlementExtra()functiontypescript/packages/core/src/types.ts-SettlementExtratype definitiontypescript/packages/core/src/config.ts- Network configs with USDC infoexamples/showcase/client/src/components/PaymentDialog.tsx- Frontend display logic
Timeline
Priority: Medium
This should be implemented when x402 adds support for payment tokens other than USDC. The current USDC-only implementation can continue using hardcoded decimals without issues.
Trigger conditions:
- When adding support for USDT, DAI, or other ERC20 tokens
- When allowing resource servers to accept multiple token types
- When building client SDKs that need to support various tokens
Context
This issue was identified during the dynamic facilitator fee implementation, where we noticed that client applications lack standardized token metadata in PaymentRequirements.
Related topics:
- Multi-token payment support
- Client SDK development
- Payment UI/UX improvements
- Gas metrics monitoring implementation
- Dynamic fee calculation integration