DeFi Swap Operations

This example demonstrates how to request a token swap and parse the transaction response, including risk assessment and transaction primitives.

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

The Code

02-swap-action.ts
import {
  Chaos,
  WALLET_MODEL,
  extractText,
  extractBlocks,
  isTransactionActionBlock,
  hasRisks,
  hasBlockers,
  type TransactionActionBlock,
  type Primitive,
  type RequestMetadata,
} from '@chaoslabs/ai-sdk';
 
const config = {
  apiKey: process.env.CHAOS_STAGING_API_KEY || 'your-api-key',
  baseUrl: process.env.CHAOS_STAGING_URL || 'https://ai-staging.chaoslabs.co',
};
 
const walletConfig: RequestMetadata = {
  user_id: 'example-user',
  session_id: `example-session-${Date.now()}`,
  wallet_id: process.env.TEST_PORTFOLIO_ID || '0x...',
};
 
async function main() {
  const chaos = new Chaos({
    apiKey: config.apiKey,
    baseUrl: config.baseUrl,
  });
 
  // Request a swap operation
  const response = await chaos.chat.responses.create({
    model: WALLET_MODEL,
    input: [{ type: 'message', role: 'user', content: 'Swap 0.1 ETH to USDC' }],
    metadata: walletConfig,
  });
 
  if (response.status === 'failed') {
    console.error('Request failed:', response.error);
    return;
  }
 
  // Display text explanation
  console.log('Agent Response:', extractText(response));
 
  // Find transaction action blocks
  const blocks = extractBlocks(response);
  const actionBlocks = blocks.filter(isTransactionActionBlock);
 
  for (const action of actionBlocks) {
    displayTransactionAction(action);
  }
 
  // Risk assessment
  if (hasBlockers(response)) {
    console.log('WARNING: Transaction has blockers - cannot execute!');
  } else if (hasRisks(response)) {
    console.log('NOTICE: Review warnings before proceeding.');
  } else {
    console.log('OK: No significant risks detected.');
  }
}
 
function displayTransactionAction(action: TransactionActionBlock) {
  console.log(`\nAction: ${action.notes || 'Transaction'}`);
 
  // Display each primitive (swap, supply, etc.)
  if (action.primitives) {
    for (const prim of action.primitives) {
      displayPrimitive(prim);
    }
  }
 
  // Display risk information
  if (action.risks) {
    console.log(`\nRisk Level: ${action.risks.level?.toUpperCase()}`);
    
    if (action.risks.blockers?.length) {
      console.log('Blockers:');
      for (const blocker of action.risks.blockers) {
        console.log(`  [BLOCK] ${blocker}`);
      }
    }
    
    if (action.risks.warnings?.length) {
      console.log('Warnings:');
      for (const warning of action.risks.warnings) {
        console.log(`  [WARN] ${warning}`);
      }
    }
  }
}
 
function displayPrimitive(prim: Primitive) {
  console.log(`\n  Primitive: ${prim.primitive}`);
 
  // Display metadata for UI rendering
  if (prim.display) {
    if (prim.display.headline) {
      console.log(`    Headline: ${prim.display.headline}`);
    }
    if (prim.display.action_verb) {
      console.log(`    Action: ${prim.display.action_verb}`);
    }
    if (prim.display.line_items) {
      console.log('    Details:');
      for (const item of prim.display.line_items) {
        console.log(`      ${item.label}: ${item.value}`);
      }
    }
  }
 
  // Access raw parameters
  if (prim.params) {
    const { amount_in, token_in, token_out, chain } = prim.params as Record<string, unknown>;
    if (amount_in) console.log(`    Amount In: ${amount_in}`);
    if (token_in) console.log(`    Token In: ${token_in}`);
    if (token_out) console.log(`    Token Out: ${token_out}`);
    if (chain) console.log(`    Chain: ${chain}`);
  }
}
 
main();

How It Works

Transaction Action Blocks

When you request a DeFi operation, the response includes TransactionActionBlock objects containing:

PropertyDescription
primitivesArray of high-level operations (swap, supply, borrow)
transactionsRaw transaction data for wallet execution
risksRisk assessment with level, blockers, and warnings
notesHuman-readable description

Transaction Primitives

Primitives represent individual DeFi operations:

primitive-structure.ts
interface Primitive {
  primitive: string;        // 'swap', 'supply', 'borrow', etc.
  params: Record<string, unknown>;  // Operation-specific parameters
  display: {
    headline: string;       // "Swap 0.1 ETH for USDC"
    action_verb: string;    // "Swap", "Supply", "Borrow"
    line_items: Array<{     // Detailed breakdown
      label: string;
      value: string;
    }>;
  };
}

Risk Assessment

The SDK provides helper functions to check for risks:

risk-check.ts
import { hasRisks, hasBlockers } from '@chaoslabs/ai-sdk';
 
// Blockers prevent execution - always check first
if (hasBlockers(response)) {
  console.log('Cannot proceed - blockers present');
  return;
}
 
// Risks are warnings to review
if (hasRisks(response)) {
  console.log('Review warnings before proceeding');
}

Risk Levels

LevelMeaningAction
lowSafe to proceedExecute normally
mediumSome warningsReview before proceeding
highSignificant risksMay block execution
criticalDangerousRequires explicit confirmation
[@portabletext/react] Unknown block type "callout", specify a component for it in the `components.types` prop

Supported Operations

The Chaos AI understands natural language for various DeFi operations:

Swaps

  • "Swap 1 ETH to USDC"
  • "Exchange my WBTC for ETH"
  • "Convert 1000 USDC to DAI"

Lending

  • "Supply 100 USDC to Aave"
  • "Deposit ETH into Compound"

Borrowing

  • "Borrow 500 USDC against my ETH"
  • "What can I borrow on Aave?"

Next Steps