export interface GuardrailConfig { maxSolPerTransaction: number // Max SOL per single transaction maxTransactionsPerMinute: number // Rate limit dailySpendingLimitSol: number // Max SOL spent per 24 hours allowedPrograms: string[] // Whitelist of Solana programs blockedAddresses: string[] // Blacklist of recipient addresses}export const DEFAULT_GUARDRAIL_CONFIG: GuardrailConfig = { maxSolPerTransaction: 2.0, maxTransactionsPerMinute: 5, dailySpendingLimitSol: 10.0, allowedPrograms: [ '11111111111111111111111111111111', // System Program 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA', // SPL Token Program 'ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL', // Associated Token Program 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4', // Jupiter v6 'Stake11111111111111111111111111111111111111', // Stake Program 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', // Token Metadata Program ], blockedAddresses: [],}
Purpose: Prevent a single transaction from spending too much SOL.Default: 2.0 SOL per transactionExample:
const guardrails = new Guardrails({ maxSolPerTransaction: 1.0 })const result = guardrails.validate('wallet-id', 1.5, [], 'recipient-address')console.log(result)// {// allowed: false,// reason: 'Amount 1.5 SOL exceeds per-transaction limit of 1.0 SOL',// guardrails: ['max_per_tx']// }
Source:src/core/transaction/guardrails.ts:38-45
2. Rate Limiting (Transactions Per Minute)
Purpose: Prevent agents from spamming transactions.Default: 5 transactions per minuteImplementation:
Tracks timestamps of recent transactions in a sliding 60-second window
Rejects new transactions if count exceeds limit
Old timestamps (>5 minutes) are automatically pruned
Example:
const guardrails = new Guardrails({ maxTransactionsPerMinute: 3 })// Agent sends 3 transactions in 30 secondsguardrails.recordTransaction('wallet-id', 0.1)guardrails.recordTransaction('wallet-id', 0.2)guardrails.recordTransaction('wallet-id', 0.3)// 4th transaction is blockedconst result = guardrails.validate('wallet-id', 0.1, [])console.log(result)// {// allowed: false,// reason: 'Rate limit exceeded: 3/3 transactions per minute',// guardrails: ['max_per_tx', 'rate_limit']// }
Source:src/core/transaction/guardrails.ts:47-61
3. Daily Spending Limit
Purpose: Cap the total SOL an agent can spend in 24 hours.Default: 10.0 SOL per dayImplementation:
Tracks cumulative spending per wallet
Resets every 24 hours (86,400,000 ms)
Prevents agents from draining wallets over time
Example:
const guardrails = new Guardrails({ dailySpendingLimitSol: 5.0 })// Agent has already spent 4.8 SOL todayguardrails.recordTransaction('wallet-id', 4.8)// Attempting to spend another 0.5 SOL is blockedconst result = guardrails.validate('wallet-id', 0.5, [])console.log(result)// {// allowed: false,// reason: 'Daily spending limit exceeded: 4.8000 + 0.5 > 5.0 SOL',// guardrails: ['max_per_tx', 'rate_limit', 'daily_limit']// }
Source:src/core/transaction/guardrails.ts:63-72
4. Program Allowlist
Purpose: Only allow transactions with approved Solana programs.Default Allowlist:
System Program (native SOL transfers)
SPL Token Program (token transfers)
Associated Token Program (token account creation)
Jupiter v6 (DEX aggregator)
Stake Program (native staking)
Token Metadata Program (NFT metadata)
Implementation:
Transaction engine passes program IDs to guardrails
Rejects if any program is not in the allowlist
Empty allowlist = all programs allowed (not recommended)
Example:
const guardrails = new Guardrails({ allowedPrograms: [ '11111111111111111111111111111111', // System Program 'JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4', // Jupiter ],})// Agent tries to interact with an unknown programconst result = guardrails.validate( 'wallet-id', 0.5, ['UNKNOWNProgramXXXXXXXXXXXXXXXXXXXXXXXXX'],)console.log(result)// {// allowed: false,// reason: 'Programs not in allowlist: UNKNOWNProgramXXXXXXXXXXXXXXXXXXXXXXXXX',// guardrails: ['max_per_tx', 'rate_limit', 'daily_limit', 'program_allowlist']// }
Source:src/core/transaction/guardrails.ts:74-87
5. Blocked Addresses
Purpose: Prevent transfers to specific addresses (e.g., known scam addresses).Default: Empty (no addresses blocked)Example:
const guardrails = new Guardrails()// Check current configconsole.log(guardrails.getConfig())// Update specific limitsguardrails.updateConfig({ maxSolPerTransaction: 5.0, dailySpendingLimitSol: 20.0,})// Add a program to the allowlistconst currentConfig = guardrails.getConfig()guardrails.updateConfig({ allowedPrograms: [...currentConfig.allowedPrograms, 'NewProgramID'],})
const info = guardrails.getSpendingInfo('wallet-id')console.log(info)// {// recentTxCount: 2, // Transactions in the last minute// dailySpend: 3.5, // SOL spent today// dailyRemaining: 6.5, // SOL remaining for today// perTxLimit: 2.0 // Max per transaction// }
The TransactionEngine automatically validates all transactions against guardrails.Example: SOL Transfer (src/core/transaction/transaction-engine.ts:51-116):
All transactions (SOL transfers, token swaps, staking, etc.) go through guardrail validation. A blocked transaction is logged but never sent to the blockchain.
Location:data/logs/transactions.jsonlFormat: One JSON object per line (JSONL)Example:
{"id":"uuid-1","walletId":"wallet-id","agentId":"agent-1","type":"transfer","status":"confirmed","signature":"5KJh3...","details":{"to":"HN7cA...","amount":0.5,"token":"SOL"},"guardrailsApplied":["max_per_tx","rate_limit","daily_limit"],"timestamp":"2026-03-03T12:00:00.000Z"}{"id":"uuid-2","walletId":"wallet-id","agentId":"agent-1","type":"swap","status":"blocked","error":"Amount 5 SOL exceeds per-transaction limit of 2.0 SOL","details":{"inputToken":"SOL","outputToken":"USDC","amount":5},"guardrailsApplied":["max_per_tx"],"timestamp":"2026-03-03T12:01:00.000Z"}
Fields:
id - Unique transaction ID
walletId - Wallet that initiated the transaction
agentId - Agent that made the decision (if applicable)
type - Transaction type (transfer, swap, stake, etc.)
guardrailsApplied - List of guardrails that were checked
error - Error message (if failed or blocked)
timestamp - ISO 8601 timestamp
Location:data/logs/agent-{agentId}.jsonlFormat: One decision per lineExample:
{"agentId":"agent-1","cycle":1,"observations":{"wallet":{"name":"DCA-Bot-wallet","address":"HN7cA..."},"balances":{"sol":0.5,"tokens":[]}},"reasoning":"Balance is low, requesting airdrop","action":{"skill":"airdrop","params":{"amount":2}},"outcome":"Successfully airdropped 2 SOL","timestamp":"2026-03-03T12:00:00.000Z"}{"agentId":"agent-1","cycle":2,"observations":{"wallet":{"name":"DCA-Bot-wallet","address":"HN7cA..."},"balances":{"sol":2.5,"tokens":[]}},"reasoning":"Executing DCA: swap 0.5 SOL for USDC","action":{"skill":"swap","params":{"inputToken":"SOL","outputToken":"USDC","amount":0.5}},"outcome":"Swap successful","timestamp":"2026-03-03T12:00:30.000Z"}
Fields:
agentId - Agent that made the decision
cycle - Decision cycle number
observations - Current state (wallet, balances, recent txs)
reasoning - LLM’s reasoning for the decision
action - Skill invoked (if any)
outcome - Result of the action
timestamp - ISO 8601 timestamp
Location:data/logs/events.jsonlFormat: One event per lineExample: