Skip to main content
The X402Client wraps fetch with automatic x402 payment handling. When a server returns HTTP 402 Payment Required, the client signs an EIP-3009 USDC transfer and retries the request — transparently. Optionally, when autoDraw is enabled and paired with a MorphoClient, the client will automatically borrow USDC from Morpho Blue when the Safe account balance is insufficient.

How x402 Works

  1. Agent sends a regular HTTP request via x402.get() or x402.post()
  2. Server responds 402 Payment Required with payment requirements
  3. The underlying @x402/fetch library handles the payment: it signs an EIP-3009 transferWithAuthorization for USDC
  4. Request is retried with the payment signature
  5. Server verifies via the Coinbase CDP facilitator
  6. Payment settles, server returns the data

Constructor

import { X402Client } from '@agether/sdk';

const x402 = new X402Client({
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  rpcUrl: 'https://base-rpc.publicnode.com',
  backendUrl: process.env.AGETHER_BACKEND_URL || 'http://95.179.189.214:3001',
  agentId: '17676',
  accountAddress: '0xYourSafeAccountAddress', // Payments come from Safe account

  // Optional spending controls
  autoDraw: true,
  dailySpendLimitUsdc: '100',    // $100/day max
  autoYield: false,              // When enabled, tries to withdraw from supply positions before borrowing
});

Configuration

ParameterTypeRequiredDefaultDescription
privateKeystringEither this or walletClientAgent wallet private key for signing
walletClientWalletClientEither this or privateKeyviem WalletClient with an attached account
rpcUrlstringYesBase RPC endpoint
backendUrlstringYesAgether backend URL
agentIdstringNoERC-8004 agent ID (sent as X-Agent-Id header)
accountAddressstringNoSafe account address (payments come from here via EIP-1271)
autoDrawbooleanNofalseEnable auto-borrow from Morpho when low
dailySpendLimitUsdcstringNoMax daily USDC spend (e.g. "100")
autoYieldbooleanNofalseWhen enabled, the client tries to withdraw from supply positions (earned yield) before borrowing new USDC from Morpho
validatorModulestringNoAgether8004ValidationModule address for EIP-1271 signature prefixing

Methods

get<T>(url, options?)

Make a GET request to an x402-enabled endpoint. Returns an X402Response<T> object.
const response = await x402.get<{ result: string }>('https://api.example.com/data');

if (response.success) {
  console.log('Data:', response.data);
  if (response.paymentInfo) {
    console.log('Paid:', response.paymentInfo.amount, response.paymentInfo.asset);
    console.log('TX:', response.paymentInfo.txHash);
  }
} else {
  console.log('Error:', response.error);
}

post<T>(url, body?, options?)

Make a POST request with x402 payment handling.
const response = await x402.post<{ inference: string }>(
  'https://api.example.com/inference',
  { prompt: 'Summarize this document...' }
);

if (response.success) {
  console.log('Result:', response.data?.inference);
}

payWithAutoDraw<T>(url, options?)

Make a request with automatic Morpho borrowing when USDC balance is insufficient. Requires passing a morphoClient in the options.
import { MorphoClient, X402Client } from '@agether/sdk';

const morpho = new MorphoClient({
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  rpcUrl: 'https://base-rpc.publicnode.com',
  agentId: '17676',
});

const x402 = new X402Client({
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  rpcUrl: 'https://base-rpc.publicnode.com',
  backendUrl: process.env.AGETHER_BACKEND_URL || 'http://95.179.189.214:3001',
  agentId: '17676',
  accountAddress: '0xSafeAccount',
  autoDraw: true,
  dailySpendLimitUsdc: '50',
});

const response = await x402.payWithAutoDraw('https://api.example.com/resource', {
  morphoClient: morpho,
});

if (response.autoDrawInfo) {
  console.log('Auto-borrowed:', response.autoDrawInfo.borrowed, 'USDC');
  console.log('Borrow TX:', response.autoDrawInfo.borrowTx);
}

getAddress()

Get the payment address (Safe account if accountAddress is set, otherwise EOA).
const addr = x402.getAddress();

getSpendingTracker()

Get the current daily spending tracker state.
const tracker = x402.getSpendingTracker();
console.log('Date:', tracker.date);
console.log('Total borrowed today:', tracker.totalBorrowed.toString());
console.log('Daily limit:', tracker.dailyLimit.toString());

getRemainingDailyAllowance()

Get remaining daily spending allowance in USDC (human-readable string).
const remaining = x402.getRemainingDailyAllowance();
console.log('Remaining:', remaining); // e.g. "87.50" or "unlimited"

Response Type

All methods return X402Response<T>:
interface X402Response<T> {
  success: boolean;
  data?: T;
  error?: string;
  paymentInfo?: {
    amount: string;
    asset: string;
    network: string;
    txHash?: string;
  };
  autoDrawInfo?: {
    borrowed: string;
    borrowTx: string;
    reason: string;
  };
}

Spending Controls

Daily Spending Cap

Set dailySpendLimitUsdc to cap total auto-draw borrows per day. The client rejects payments that would exceed the limit.

Auto-Yield Waterfall

When autoYield: true, the client tries to withdraw from supply positions (earned yield) before borrowing new USDC from Morpho. This minimizes unnecessary borrowing.

Validator Module

Set validatorModule to the Agether8004ValidationModule address for EIP-1271 signature prefixing on x402 payments.

Spending Tracker

Daily borrows are tracked internally. Resets at midnight UTC. Query via getSpendingTracker() or getRemainingDailyAllowance().

EIP-1271 Smart Wallet Signatures

Since the Safe account is a smart wallet (not an EOA), the X402Client uses EIP-1271 for signature validation. When accountAddress is set:
  1. The from field in the EIP-3009 authorization is set to the Safe account
  2. The signature is padded to >65 bytes to trigger USDC’s bytes overload of transferWithAuthorization
  3. USDC calls isValidSignature on the Safe account. The Safe7579 adapter routes the call to Agether8004ValidationModule.isValidSignatureWithSender(), which recovers the signer via ECDSA and checks it matches identityRegistry.ownerOf(agentId) — the current ERC-8004 NFT holder.
This padding is handled automatically by the X402Client. No manual intervention needed.

Safe Account Requirement

The X402Client uses the Safe account (smart wallet) as the payment source, not the EOA. The account must have USDC. Options to fund it:
import { MorphoClient } from '@agether/sdk';

const morpho = new MorphoClient({ privateKey, rpcUrl, agentId: '17676' });

// Option 1: Transfer USDC from EOA
await morpho.fundAccount('50'); // Move $50 USDC from EOA to Safe account

// Option 2: Borrow from Morpho (requires collateral)
await morpho.depositAndBorrow('WETH', '0.1', '100');

Complete Example

import { X402Client, MorphoClient } from '@agether/sdk';

const morpho = new MorphoClient({
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  rpcUrl: 'https://base-rpc.publicnode.com',
  agentId: '17676',
});

const x402 = new X402Client({
  privateKey: process.env.AGENT_PRIVATE_KEY!,
  rpcUrl: 'https://base-rpc.publicnode.com',
  backendUrl: process.env.AGETHER_BACKEND_URL || 'http://95.179.189.214:3001',
  agentId: '17676',
  accountAddress: '0xSafeAccount',
  autoDraw: true,
  dailySpendLimitUsdc: '50',
});

// Make paid requests — payment handled automatically
const response = await x402.get('https://api.example.com/compute');
if (response.success) {
  console.log('Result:', response.data);
}

// Check remaining allowance
console.log('Remaining today:', x402.getRemainingDailyAllowance());
With autoDraw enabled, the client will automatically borrow from Morpho when the Safe account has insufficient USDC. Ensure you have collateral deposited and understand the health factor implications.