Documentation Index
Fetch the complete documentation index at: https://developers.circle.com/llms.txt
Use this file to discover all available pages before exploring further.
Overview
- Construct and sign EIP-3009
TransferWithAuthorizationmessages that authorize Circle Gateway to transfer USDC from your Gateway balance. - Use this when integrating payment signing into a custom workflow, building a non-JavaScript client, or understanding the signing mechanism that the SDK handles automatically.
Prerequisites
Before you begin, ensure you have:- An EVM wallet with a private key for signing.
- Deposited USDC in a Gateway Wallet contract (see the buyer quickstart).
- Familiarity with EIP-712 typed data signing.
- Installed the viem library (
npm install viem).
Steps
Step 1. Construct the EIP-712 domain
Gateway uses a custom EIP-712 domain namedGatewayWalletBatched. This is
specific to Gateway’s batching feature and is not the standard USDC domain.
sign.ts
verifyingContract is the GatewayWallet contract address for the blockchain
you are transacting on. Find the address for your target chain in the
EVM contract addresses reference. You
can also retrieve it programmatically using getVerifyingContract() from the
SDK or from the 402 response’s accepts array (in the
extra.verifyingContract field).
Step 2. Define the typed data
TheTransferWithAuthorization type follows the
EIP-3009 specification:
sign.ts
$1.00 = 1000000, $0.01 = 10000, $0.001 =
1000. Always convert dollar amounts to base units before signing.
sign.ts
Step 3. Sign the typed data
Use theviem library’s signTypedData to produce the EIP-712 signature:
sign.ts
Step 4. Assemble and send the payment payload
Encode the payment payload as base64 JSON and attach it to your HTTP request in thePayment-Signature header. The server-side facilitator settles this payment
through the Settle x402 Payment
API endpoint:
sign.ts
Step 5. Use BatchEvmScheme for the x402 protocol (alternative)
If you are integrating with an existing x402 client (such as @x402/core), use
the BatchEvmScheme class instead of constructing the payload manually. It
handles domain construction, nonce generation, and payload encoding:
sign-x402.ts
Troubleshoot invalid_signature
Gateway returns invalid_signature for any EIP-712 domain or field mismatch
without specifying which field is wrong. If your signature is rejected, check
every item in this list:
- Domain name must be exactly
"GatewayWalletBatched". Common mistakes include"GatewayWallet","Gateway", and"USDC". verifyingContractmust be the GatewayWallet contract address, not the USDC token address or GatewayMinter. See EVM contract addresses for the correct address on each chain.chainIdmust be the standard EVM chain ID (for example,5042002for Arc Testnet). Do not use the Gateway domain identifier.noncemust be a unique random 32-byte value for every payment. Reusing a nonce causes the sameinvalid_signatureerror.validBeforemust be at least 3 days in the future. Shorter validity periods are rejected withauthorization_validity_too_short.valuemust be in USDC base units (6 decimals). Passing a dollar amount instead of base units causes an amount mismatch.frommust match the address derived from the private key that signed the message.
The EIP-712 domain for payment authorizations (
GatewayWalletBatched) is
different from the domain used for Gateway withdrawal and crosschain transfer
operations (GatewayWallet). If you are building manual signing for both
payments and withdrawals, use the correct domain for each operation. The SDK’s
client.withdraw() and client.pay() methods handle this automatically.