1414from eth_account .messages import encode_typed_data
1515
1616
17- # Chain and token constants
17+ # Chain and token constants for mainnet
1818BASE_CHAIN_ID = 8453
1919USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
2020
21+ # Chain and token constants for testnet (Base Sepolia)
22+ BASE_SEPOLIA_CHAIN_ID = 84532
23+ USDC_BASE_SEPOLIA = "0x036CbD53842c5426634e7929541eC2318f3dCF7e"
24+
25+
26+ def get_chain_config (network : str ) -> tuple [int , str ]:
27+ """
28+ Get chain ID and USDC contract address for a given network.
29+
30+ Args:
31+ network: Network identifier in EIP-155 format (e.g., "eip155:8453" or "eip155:84532")
32+
33+ Returns:
34+ Tuple of (chain_id, usdc_address)
35+ """
36+ if network == "eip155:84532" or network == "base-sepolia" :
37+ return BASE_SEPOLIA_CHAIN_ID , USDC_BASE_SEPOLIA
38+ # Default to mainnet
39+ return BASE_CHAIN_ID , USDC_BASE
40+
2141
2242def create_nonce () -> str :
2343 """Generate a random bytes32 nonce."""
@@ -34,6 +54,7 @@ def create_payment_payload(
3454 max_timeout_seconds : int = 300 ,
3555 extra : Optional [Dict [str , str ]] = None ,
3656 extensions : Optional [Dict [str , Any ]] = None ,
57+ asset : Optional [str ] = None ,
3758) -> str :
3859 """
3960 Create a signed x402 v2 payment payload.
@@ -45,11 +66,12 @@ def create_payment_payload(
4566 account: eth-account Account instance
4667 recipient: Payment recipient address (checksummed)
4768 amount: Amount in micro USDC (6 decimals, e.g., "1000" = $0.001)
48- network: Network identifier (default: Base mainnet)
69+ network: Network identifier (e.g., "eip155:8453" for Base mainnet, "eip155:84532" for Base Sepolia )
4970 resource_url: URL of the resource being accessed
5071 resource_description: Description of the resource
5172 max_timeout_seconds: Max timeout for the payment (default: 300)
5273 extra: Extra info for USDC domain (name, version)
74+ asset: USDC contract address (optional, derived from network if not provided)
5375
5476 Returns:
5577 Base64-encoded signed payment payload
@@ -62,12 +84,18 @@ def create_payment_payload(
6284 # Generate random nonce
6385 nonce = create_nonce ()
6486
65- # EIP-712 domain for Base USDC
87+ # Get chain config based on network
88+ chain_id , default_usdc = get_chain_config (network )
89+
90+ # Use provided asset address or default for the network
91+ usdc_address = asset or default_usdc
92+
93+ # EIP-712 domain for USDC (mainnet or testnet based on network)
6694 domain = {
6795 "name" : extra .get ("name" , "USD Coin" ) if extra else "USD Coin" ,
6896 "version" : extra .get ("version" , "2" ) if extra else "2" ,
69- "chainId" : BASE_CHAIN_ID ,
70- "verifyingContract" : USDC_BASE ,
97+ "chainId" : chain_id ,
98+ "verifyingContract" : usdc_address ,
7199 }
72100
73101 # EIP-712 types for TransferWithAuthorization
@@ -108,7 +136,7 @@ def create_payment_payload(
108136 "scheme" : "exact" ,
109137 "network" : network ,
110138 "amount" : amount ,
111- "asset" : USDC_BASE ,
139+ "asset" : usdc_address ,
112140 "payTo" : recipient ,
113141 "maxTimeoutSeconds" : max_timeout_seconds ,
114142 "extra" : extra or {"name" : "USD Coin" , "version" : "2" },
0 commit comments