Wallet Configuration
When using WALLET_MODEL, the Chaos AI platform reads your on-chain portfolio data to provide personalized analysis and transaction recommendations. This guide covers how to configure wallets, work with multiple chains, and use context overrides for deterministic testing.
WalletInfo basics
A wallet is defined by the WalletInfo interface:
interface WalletInfo {
address: string; // Wallet address (e.g., '0x...')
chain: string; // Blockchain identifier (e.g., 'ethereum', 'arbitrum')
}Pass wallets in the metadata.wallets array when creating a request:
import { Chaos, WALLET_MODEL } 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: 'What is my portfolio value?' },
],
metadata: {
user_id: 'user-123',
session_id: 'session-abc',
wallets: [
{ address: '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045', chain: 'ethereum' },
],
},
});Multi-chain wallets
The wallets array accepts multiple entries. This lets you query positions across different chains in a single request:
import { Chaos, WALLET_MODEL } 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: 'Show all my DeFi positions across chains' },
],
metadata: {
user_id: 'user-123',
session_id: 'session-abc',
wallets: [
{ address: '0xYourWallet', chain: 'ethereum' },
{ address: '0xYourWallet', chain: 'arbitrum' },
{ address: '0xYourWallet', chain: 'base' },
{ address: '0xYourWallet', chain: 'optimism' },
],
},
});You can also use different addresses per chain:
const response = await chaos.chat.responses.create({
model: WALLET_MODEL,
input: [
{ type: 'message', role: 'user', content: 'Compare my positions across wallets' },
],
metadata: {
user_id: 'user-123',
session_id: 'session-abc',
wallets: [
{ address: '0xWalletA', chain: 'ethereum' },
{ address: '0xWalletB', chain: 'arbitrum' },
{ address: '0xWalletC', chain: 'base' },
],
},
});RequestMetadata reference
The metadata field on every request has this shape:
interface RequestMetadata {
user_id: string; // Your user identifier
session_id: string; // Session identifier for conversation continuity
wallets?: WalletInfo[]; // Array of wallets to query
wallet_context_override?: WalletContextOverride; // Override wallet data (testing)
}| Field | Required | Description |
|---|---|---|
user_id | Yes | Identifies the user making the request |
session_id | Yes | Groups messages into a conversation. Use the same ID for follow-up questions |
wallets | No | Array of WalletInfo objects. Required for WALLET_MODEL to fetch on-chain data |
wallet_context_override | No | Replaces the live on-chain lookup with static data. Useful for testing |
WalletContextOverride for deterministic testing
When building and testing your integration, you may not want to depend on live on-chain data that changes constantly. WalletContextOverride lets you provide a fixed wallet state so the AI always sees the same portfolio.
interface WalletContextOverride {
wallet_address: string; // Wallet address being simulated
balances: BalanceOverride[]; // Token balances
protocol_positions?: ProtocolPositionOverride[]; // DeFi positions
prices?: Record<string, number>; // Token prices by symbol
}
interface BalanceOverride {
symbol: string; // Token symbol (e.g., 'ETH', 'USDC')
amount: number; // Token amount held
chain: string; // Blockchain (e.g., 'ethereum')
price?: number; // USD price per unit
value_usd?: number; // Total USD value (fallback)
}Basic override example
Here is a minimal override that sets a fixed wallet with ETH and USDC balances:
import { Chaos, WALLET_MODEL } 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: 'What is my portfolio value?' },
],
metadata: {
user_id: 'test-user',
session_id: 'test-session',
wallets: [{ address: '0xTestWallet', chain: 'ethereum' }],
wallet_context_override: {
wallet_address: '0xTestWallet',
balances: [
{ symbol: 'ETH', amount: 10, chain: 'ethereum', price: 3500 },
{ symbol: 'USDC', amount: 50000, chain: 'ethereum', price: 1 },
{ symbol: 'WBTC', amount: 0.5, chain: 'ethereum', price: 95000 },
],
prices: {
ETH: 3500,
USDC: 1,
WBTC: 95000,
},
},
},
});Override with protocol positions
You can also include DeFi protocol positions (lending, staking, LP) in the override:
import { Chaos, WALLET_MODEL } 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: 'What are my lending positions?' },
],
metadata: {
user_id: 'test-user',
session_id: 'test-session',
wallets: [{ address: '0xTestWallet', chain: 'ethereum' }],
wallet_context_override: {
wallet_address: '0xTestWallet',
balances: [
{ symbol: 'ETH', amount: 5, chain: 'ethereum', price: 3500 },
{ symbol: 'USDC', amount: 10000, chain: 'ethereum', price: 1 },
],
protocol_positions: [
{
id: 'aave-v3',
name: 'Aave V3',
chain: 'ethereum',
portfolio_items: [
{
name: 'Supply',
assets: [
{
symbol: 'WETH',
amount: 3.0,
price: 3500,
},
],
},
{
name: 'Borrow',
assets: [
{
symbol: 'USDC',
amount: 5000,
price: 1,
},
],
},
],
},
],
prices: {
ETH: 3500,
WETH: 3500,
USDC: 1,
},
},
},
});Using overrides with the Conversation class
The Conversation class accepts walletContextOverride in its constructor options:
import { Chaos, Conversation } from '@chaoslabs/ai-sdk';
const chaos = new Chaos({
apiKey: process.env.CHAOS_API_KEY!,
});
const conversation = new Conversation(chaos, {
userId: 'test-user',
wallets: [{ address: '0xTestWallet', chain: 'ethereum' }],
walletContextOverride: {
wallet_address: '0xTestWallet',
balances: [
{ symbol: 'ETH', amount: 10, chain: 'ethereum', price: 3500 },
{ symbol: 'USDC', amount: 25000, chain: 'ethereum', price: 1 },
],
prices: { ETH: 3500, USDC: 1 },
},
});
// All messages in this conversation use the overridden wallet context
const r1 = await conversation.send('What is my portfolio value?');
const r2 = await conversation.send('Should I deposit more ETH into Aave?');Next steps
- Quick Start -- Revisit the basics.
- Real-Time Streaming -- Handle streaming events for responsive UIs.