x402 Bridge
Move USDC across chains instantly using the x402 payment protocol
The x402 Bridge lets users and AI agents transfer USDC between supported networks without waiting for canonical bridges. Instead of 2–5 minute delays, RelAI uses a liquidity network model — the destination wallet receives funds immediately from a pre-funded pool, while the source payment is settled on-chain via x402.
Supported networks are defined in a central config (networks.js). Adding a new network requires no changes to bridge routes or API endpoints — the GET /v1/bridge/networks endpoint always reflects the current set.
How It Works
Every bridge transfer follows the same two-step flow regardless of which networks are involved:
The x402 payment scheme depends on the source network type:
scheme: svm-exacttransferWithAuthorization — gasless signed approvalscheme: exactLiquidity guard: Before requesting payment, the bridge verifies destination pool balance. If insufficient, a 503 insufficient_liquidity error is returned before any payment — the user is never charged for an unavailable route.
Supported Networks
The list of supported networks is always current — query GET /v1/bridge/networks to get available directions at runtime. The bridge UI and SDK use this endpoint automatically.
| Network | Type | x402 Scheme | Token | Status |
|---|---|---|---|---|
| Solana | SVM | svm-exact | USDC | Live |
| SKALE Base | EVM | exact | USDC | Live |
| Base | EVM | exact | USDC | Live |
Adding a new network
Add a network object to server/src/services/bridge/networks.js with its id, type (solana or evm), token address, RPC, and payout() / getBalance() functions. No changes to routes or API endpoints required.
Liquidity & Rebalancing
RelAI maintains pre-funded USDC wallets on each supported network. After every payout, the system checks if the destination pool has fallen below the rebalance threshold. If so, it automatically rebalances via Circle CCTP.
- Burn USDC on Solana via Circle CCTP
- Wait for Circle attestation (~20s)
- Mint native USDC on Base
- Deposit to SKALE Base via SKALE IMA
- Burn USDC on Base via Circle CCTP
- Wait for Circle attestation (~20s)
- Receive + mint native USDC on Solana
Rebalance runs asynchronously — it does not block bridge payouts. Current liquidity is available via the GET /v1/bridge/balances endpoint.
Using the Bridge UI
The bridge is available at /bridge. It supports Phantom wallet (Solana) and MetaMask / any injected EVM wallet (SKALE Base).
- 1Select direction: Solana → SKALE Base or SKALE Base → Solana
- 2Connect your source wallet (Phantom or MetaMask)
- 3Enter amount and destination wallet address
- 4Click Bridge — approve the x402 payment in your wallet. USDC arrives on the destination chain within seconds.
Management API
All bridge operations are available via the v1 Management API. Requires an X-Service-Key header. Routes are config-driven — new networks are added without changing endpoints.
/v1/bridge/networksList all enabled bridge directions (config-driven)
/v1/bridge/quoteGet fee and net output for a given USD amount (params: amount, from, to)
/v1/bridge/balancesCurrent USDC liquidity on all enabled networks
/v1/bridge/:directionBridge between networks (e.g. solana-to-skale-base). Returns 402, pay with x402.
curl https://api.relai.fi/v1/bridge/networks \
-H "X-Service-Key: sk_live_..."
# Response
{
"directions": [
{ "id": "solana-to-skale-base", "from": { "id": "solana", "label": "Solana" }, "to": { "id": "skale-base", "label": "SKALE Base" } },
{ "id": "skale-base-to-solana", "from": { "id": "skale-base", "label": "SKALE Base" }, "to": { "id": "solana", "label": "Solana" } }
]
}{
"success": true,
"direction": "solana-to-skale-base",
"from": "solana",
"to": "skale-base",
"destinationWallet": "0xYourSkaleAddress",
"amountOut": 9990000,
"amountOutUsd": 9.99,
// Payout tx on destination chain (SKALE Base)
"txHash": "0xabc123...",
"explorerUrl": "https://skale-base-explorer.skalenodes.com/tx/0xabc123...",
// Payment tx on source chain (Solana)
"paymentTxHash": "5Kq7...",
"paymentExplorerUrl": "https://solscan.io/tx/5Kq7..."
}SDK Integration
Use createX402Client from @relai-fi/x402 — it handles the 402 payment automatically. The direction string comes from /v1/bridge/networks.
import { createX402Client } from '@relai-fi/x402';
import { Keypair } from '@solana/web3.js';
const keypair = Keypair.fromSecretKey(Buffer.from(process.env.SOLANA_KEY!, 'base64'));
const x402 = createX402Client({
wallets: {
solana: {
publicKey: keypair.publicKey,
signTransaction: async (tx: any) => { tx.sign([keypair]); return tx; },
},
},
defaultHeaders: { 'X-Service-Key': process.env.RELAI_SERVICE_KEY! },
});
const res = await x402.fetch(
'https://api.relai.fi/v1/bridge/solana-to-skale-base',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 10.0, destinationWallet: '0xYourSkaleBaseAddress' }),
}
);
const result = await res.json();
// result.paymentTxHash — Solana payment tx
// result.txHash — SKALE Base payout tx
// result.explorerUrl — SKALE Base explorer link
console.log('Payment:', result.paymentExplorerUrl);
console.log('Payout:', result.explorerUrl);import { ethers } from 'ethers';
import { createX402Client } from '@relai-fi/x402';
const provider = new ethers.JsonRpcProvider(process.env.SKALE_RPC_URL);
const signer = new ethers.Wallet(process.env.EVM_KEY!, provider);
const x402 = createX402Client({
wallets: {
evm: {
address: signer.address,
signTypedData: (domain: any, types: any, message: any) =>
signer.signTypedData(domain, types, message),
},
},
defaultHeaders: { 'X-Service-Key': process.env.RELAI_SERVICE_KEY! },
});
const res = await x402.fetch(
'https://api.relai.fi/v1/bridge/skale-base-to-solana',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ amount: 5.0, destinationWallet: 'YourSolanaAddress' }),
}
);
const result = await res.json();
// result.paymentTxHash — SKALE Base payment tx
// result.txHash — Solana payout tx
console.log('Payout:', result.explorerUrl); // solscan.ioFees & Limits
| Bridge fee | 1% (100 bps) of input amount, minimum $0.01 |
| Gas fees | Sponsored by RelAI facilitator — $0 for user |
| Minimum | $0.05 USDC |
| Maximum | $1 USDC per transaction (beta) |
| Settlement time | ~3 seconds (payout on destination chain) |
Error Handling
insufficient_liquidityThe destination pool does not have enough USDC for this transfer. Returned before any payment is requested. Check /v1/bridge/balances and retry when liquidity is restored.
Payment RequiredStandard x402 response. Use the RelAI SDK createX402Client to handle this automatically.
Validation errorInvalid amount or destinationWallet format. Check that the destination address matches the target chain format (EVM 0x... or Solana base58).
try {
const result = await mgmt.bridgeSolanaToSkale(100.0, '0x...', x402);
} catch (err) {
if (err.message.includes('insufficient_liquidity')) {
const { skaleBase } = await mgmt.getBridgeBalances();
console.log(`Retry later. Available: $${skaleBase.usd} USDC`);
}
}