This guide pays an x402 service on Base Sepolia from a Sui keypair. The agent never holds funds on the destination chain — it spends Sui stablecoins, and a dWallet signs for the destination.
Cross-chain is live on testnet. This example pays a Base Sepolia (eip155:84532) endpoint.
Full example on GitHub The complete, runnable version of this guide — examples/x402/exact-cross-chain.
Prerequisites
A Sui testnet keypair with a USDC balance
Node.js 24+
An x402 endpoint on the destination chain to call
1. Install dependencies
npm install @tentaclepay/sdk @ika.xyz/sdk @mysten/sui @x402/core @x402/evm @x402/fetch
2. Set up the Sui and Ika clients
The cross-chain signer needs a Sui client (to pay on Sui) and an Ika client (to coordinate the dWallet signature):
import { getNetworkConfig , IkaClient } from "@ika.xyz/sdk" ;
import { SuiGrpcClient } from "@mysten/sui/grpc" ;
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519" ;
const keypair = Ed25519Keypair . fromSecretKey ( process . env . CLIENT_PRIVATE_KEY ! );
const verifierUrl = "https://testnet-verifier.tentaclepay.com" ;
const suiClient = new SuiGrpcClient ({
network: "testnet" ,
baseUrl: "https://fullnode.testnet.sui.io:443" ,
});
const ikaClient = new IkaClient ({
suiClient ,
config: getNetworkConfig ( "testnet" ),
});
await ikaClient . initialize ();
3. Create the cross-chain signer
createCrossChainEvmSigner returns a signer that looks like a normal EVM signer to x402 — but every signature is produced by the dWallet, paid for with USDC on Sui:
import { createCrossChainEvmSigner } from "@tentaclepay/sdk/x402/evm" ;
const crossChainEvmSigner = await createCrossChainEvmSigner (
keypair ,
verifierUrl ,
suiClient ,
ikaClient
);
4. Register the destination scheme and wrap fetch
Register the destination chain’s exact scheme with the cross-chain signer, then wrap fetch:
import { x402Client } from "@x402/core/client" ;
import { ExactEvmScheme } from "@x402/evm" ;
import { wrapFetchWithPayment } from "@x402/fetch" ;
const client = new x402Client ();
client . register ( "eip155:84532" , new ExactEvmScheme ( crossChainEvmSigner ));
const fetchWithPayment = wrapFetchWithPayment ( fetch , client );
5. Make the request and read the receipt
The call is identical to a native x402 request. The settlement happens on the destination chain:
import { x402HTTPClient } from "@x402/core/client" ;
const response = await fetchWithPayment ( "http://localhost:3000/weather" , {
method: "GET" ,
headers: { "Content-Type" : "application/json" },
});
console . log ( "Response:" , await response . json ());
if ( response . ok ) {
const httpClient = new x402HTTPClient ( client );
const paymentResponse = httpClient . getPaymentSettleResponse (( name ) =>
response . headers . get ( name )
);
console . log (
"Transaction:" ,
`https://sepolia.basescan.org/tx/ ${ paymentResponse . transaction } `
);
}
The transaction digest is on the destination chain — funded by the USDC paid on Sui.
Next steps
Architecture How the dWallet, verifier, and on-chain contract authorize each payment.