Bridge & Transfer
The Chaos AI SDK provides two generic primitives for moving assets: bridge (cross-chain) and transfer (same-chain). These are protocol-agnostic — the AI engine selects the best route and protocol automatically.
| Primitive | Constant | Type | Params |
|---|---|---|---|
bridge | PRIMITIVE_BRIDGE | BridgePrimitive | BridgeParams |
transfer | PRIMITIVE_TRANSFER | TransferPrimitive | TransferParams |
Both primitives are grouped in the TRANSFER_PRIMITIVES category array.
Cross-Chain Bridge
Send a natural-language bridge request using WALLET_MODEL. The AI engine determines the optimal bridge protocol and returns a BridgePrimitive with typed BridgeParams.
import {
Chaos,
WALLET_MODEL,
extractTransactionBlocks,
extractPrimitives,
isBridgePrimitive,
hasBlockers,
hasRisks,
getAllBlockers,
getAllWarnings,
getHighestRiskLevel,
} from '@chaoslabs/ai-sdk';
import type { BridgePrimitive, BridgeParams } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
// Step 1: Send a bridge request
const response = await chaos.chat.responses.create({
model: WALLET_MODEL,
input: [
{
type: 'message',
role: 'user',
content: 'Bridge 0.5 ETH from Ethereum to Arbitrum',
},
],
metadata: {
user_id: 'user-123',
session_id: 'session-bridge-demo',
wallets: [{ address: '0xYourWalletAddress', chain: 'ethereum' }],
},
});
console.log('Response status:', response.status);
// Step 2: Extract bridge primitives
const primitives = extractPrimitives(response);
const bridges = primitives.filter(isBridgePrimitive);
for (const bridge of bridges) {
const params: BridgeParams = bridge.params;
console.log('Bridge:', {
asset: params.asset,
amount: params.amount,
from_chain: params.from_chain,
to_chain: params.to_chain,
recipient: params.recipient,
});
if (bridge.display) {
console.log('Display:', bridge.display);
}
}
// Step 3: Check risks before signing
if (hasBlockers(response)) {
console.error('Blocked:', getAllBlockers(response));
process.exit(1);
}
if (hasRisks(response)) {
console.warn(`Risk level: ${getHighestRiskLevel(response)}`);
console.warn('Warnings:', getAllWarnings(response).map((w) => w.message));
}
// Step 4: Access raw transactions from action blocks
const txBlocks = extractTransactionBlocks(response);
for (const block of txBlocks) {
if (block.transactions) {
for (const seq of block.transactions) {
console.log('Requires approval:', seq.requiresApproval);
for (const tx of seq.transactions) {
console.log('Transaction:', { to: tx.to, value: tx.value });
}
}
}
}BridgeParams Fields
| Field | Type | Required | Description |
|---|---|---|---|
asset | string | Yes | Asset to bridge (e.g., 'ETH', 'USDC') |
amount | string | number | Yes | Amount to bridge |
from_chain | BridgeSupportedChain | Yes | Source chain |
to_chain | BridgeSupportedChain | Yes | Destination chain (must differ from from_chain) |
recipient | string | null | No | Recipient address on the destination chain |
asset_address | string | No | Contract address of the asset |
Supported chains: ethereum, arbitrum, optimism, base, polygon, avalanche, bsc, gnosis, ink, zksync, hyperliquid, solana.
Token Transfer
Transfer tokens to another address on the same chain. The AI engine returns a TransferPrimitive with typed TransferParams.
import {
Chaos,
WALLET_MODEL,
extractPrimitives,
isTransferTypedPrimitive,
hasBlockers,
getAllBlockers,
} from '@chaoslabs/ai-sdk';
import type { TransferPrimitive, TransferParams } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({ apiKey: process.env.CHAOS_API_KEY! });
const response = await chaos.chat.responses.create({
model: WALLET_MODEL,
input: [
{
type: 'message',
role: 'user',
content: 'Transfer 100 USDC to 0xRecipientAddress on Ethereum',
},
],
metadata: {
user_id: 'user-123',
session_id: 'session-transfer-demo',
wallets: [{ address: '0xYourWalletAddress', chain: 'ethereum' }],
},
});
// Extract transfer primitives using the type guard
const primitives = extractPrimitives(response);
const transfers = primitives.filter(isTransferTypedPrimitive);
for (const transfer of transfers) {
const params: TransferParams = transfer.params;
console.log('Transfer:', {
asset: params.asset,
amount: params.amount,
destination_address: params.destination_address,
chain: params.chain,
});
}
// Always check for blockers before signing
if (hasBlockers(response)) {
console.error('Blocked:', getAllBlockers(response));
process.exit(1);
}TransferParams Fields
| Field | Type | Required | Description |
|---|---|---|---|
asset | string | Yes | Asset to transfer (e.g., 'ETH', 'USDC') |
amount | string | number | Yes | Amount to transfer |
destination_address | string | Yes | Recipient wallet address |
chain | string | null | No | Chain to execute on |
Filter Bridge & Transfer Primitives
Use the isTransferPrimitive category validator to check if a primitive type string belongs to the transfer category (bridge or transfer). Use the TRANSFER_PRIMITIVES array to filter or iterate over the category.
import {
extractPrimitives,
isTransferPrimitive,
TRANSFER_PRIMITIVES,
PRIMITIVE_BRIDGE,
PRIMITIVE_TRANSFER,
} from '@chaoslabs/ai-sdk';
// Category validator: check if a string is a transfer-category primitive
console.log(isTransferPrimitive('bridge')); // true
console.log(isTransferPrimitive('transfer')); // true
console.log(isTransferPrimitive('swap')); // false
// TRANSFER_PRIMITIVES array contains both primitive types
console.log(TRANSFER_PRIMITIVES);
// ['bridge', 'transfer']
// Filter response primitives to only bridge & transfer
const allPrimitives = extractPrimitives(response);
const transferCategory = allPrimitives.filter((p) =>
isTransferPrimitive(p.type)
);
console.log(`Found ${transferCategory.length} bridge/transfer primitive(s)`);
// Use constants for type-safe comparisons
for (const p of transferCategory) {
if (p.type === PRIMITIVE_BRIDGE) {
console.log('Bridge:', p.params);
} else if (p.type === PRIMITIVE_TRANSFER) {
console.log('Transfer:', p.params);
}
}