Skip to main content

Overview

  • Add nanopayments to an existing x402 client so it can pay gas-free when a server supports it, while still falling back to standard onchain payments when it does not.
  • Gas-free payments require a one-time USDC deposit into a Gateway Wallet contract. After depositing, all subsequent payments are offchain signatures with zero gas cost.
  • Your existing onchain payment flows continue to work unchanged. The client automatically selects the right payment method based on what the server offers.

Prerequisites

Before you begin, ensure you have:
  • An existing x402 client using @x402/core.
  • Node.js v18+ installed.
  • An EVM wallet private key for signing.
  • Testnet USDC from the Circle Faucet (for Gateway deposits).

Steps

Step 1. Install the SDK

npm install @circle-fin/x402-batching
If you plan to use CompositeEvmScheme (recommended for supporting both payment methods), also install:
npm install @x402/evm

Step 2. Choose your integration approach

Pick the option that best fits your setup. Use CompositeEvmScheme to route automatically based on the server’s payment requirements. When the server offers a Gateway option, the client uses BatchEvmScheme for a gas-free payment. When only standard onchain options are available, it falls back to ExactEvmScheme:
import { ExactEvmScheme } from "@x402/evm/exact/client";
import {
  CompositeEvmScheme,
  BatchEvmScheme,
} from "@circle-fin/x402-batching/client";

const composite = new CompositeEvmScheme(
  new BatchEvmScheme(signer),
  new ExactEvmScheme(signer),
);

client.register("eip155:*", composite);
No per-request routing code is needed. CompositeEvmScheme checks each payment option’s extra.name field and delegates to the correct scheme automatically.

Option B: Add Gateway support to an existing client

If you already have scheme registrations and want to add Gateway support with minimal changes:
import { registerBatchScheme } from "@circle-fin/x402-batching/client";

registerBatchScheme(client, { signer: account });

Option C: Gateway only

If you only need gas-free payments and don’t need standard onchain support, use GatewayClient directly. See the buyer quickstart for a full walkthrough.

Step 3. Deposit USDC into Gateway

Before making gas-free payments, deposit USDC from your wallet into the Gateway Wallet contract. This is a one-time onchain transaction:
import { GatewayClient } from "@circle-fin/x402-batching/client";

const gatewayClient = new GatewayClient({
  chain: "arcTestnet",
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
});

const balances = await gatewayClient.getBalances();
if (balances.gateway.available < 1_000_000n) {
  await gatewayClient.deposit("1");
}
After the deposit confirms, your Gateway balance is available for gas-free payments to any server that supports nanopayments.

Step 4. Check support before paying

Before attempting a gas-free payment, check whether the target server supports Gateway:
const support = await gatewayClient.supports(
  "https://api.example.com/resource",
);

if (!support.supported) {
  console.log("Server does not support Gateway -- falling back to onchain");
}
If you are using CompositeEvmScheme, this check is optional since the scheme handles fallback automatically.

Step 5. Understand deposit finality

When you deposit USDC into Gateway, the API waits for block confirmations before your balance becomes available. Wait times vary by blockchain:
BlockchainDeposit time
Arc Testnet~0.5 sec
Avalanche Fuji~8 sec
HyperEVM Testnet, Sei Atlantic~5 sec
Polygon PoS Amoy, Sonic Testnet~8 sec
Arbitrum Sepolia, Base Sepolia, Ethereum Sepolia, Optimism Sepolia, Unichain Sepolia, World Chain Sepolia~13-19 min
To avoid long deposit wait times, use Bridge Kit to bridge your USDC to a fast-finality blockchain before depositing into Gateway. Your Gateway balance works across all supported blockchains regardless of where you deposited.
import { BridgeKit } from "@circle-fin/bridge-kit";

const bridge = new BridgeKit();

const transfer = await bridge.transfer({
  sourceChain: "base-sepolia",
  destinationChain: "arc-testnet",
  amount: "10",
  token: "USDC",
});
await bridge.waitForCompletion(transfer.id);

const client = new GatewayClient({
  chain: "arcTestnet",
  privateKey: process.env.PRIVATE_KEY as `0x${string}`,
});
await client.deposit("10");

Step 6. Withdraw funds (optional)

Withdraw USDC from Gateway back to your wallet at any time. Withdrawals are instant for both same-blockchain and crosschain destinations:
await gatewayClient.withdraw("5");

await gatewayClient.withdraw("5", { chain: "baseSepolia" });

See also