Skip to main content
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):
client.ts
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:
client.ts
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:
client.ts
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:
client.ts
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.