Bridge & Transfer

Updated

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.

PrimitiveConstantTypeParams
bridgePRIMITIVE_BRIDGEBridgePrimitiveBridgeParams
transferPRIMITIVE_TRANSFERTransferPrimitiveTransferParams

Both primitives are grouped in the TRANSFER_PRIMITIVES category array.

[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

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.

bridge.ts
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

FieldTypeRequiredDescription
assetstringYesAsset to bridge (e.g., 'ETH', 'USDC')
amountstring | numberYesAmount to bridge
from_chainBridgeSupportedChainYesSource chain
to_chainBridgeSupportedChainYesDestination chain (must differ from from_chain)
recipientstring | nullNoRecipient address on the destination chain
asset_addressstringNoContract 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.

transfer.ts
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

FieldTypeRequiredDescription
assetstringYesAsset to transfer (e.g., 'ETH', 'USDC')
amountstring | numberYesAmount to transfer
destination_addressstringYesRecipient wallet address
chainstring | nullNoChain 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.

filter.ts
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);
  }
}
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop
Was this helpful?