Awesome-omni-skill eth-agent
Expert knowledge for using the eth-agent library - the simplest, safest way for AI agents to send stablecoins on Ethereum. Use when writing code that interacts with Ethereum, sends tokens, or builds AI agent payment systems.
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ai-agents/eth-agent" ~/.claude/skills/diegosouzapw-awesome-omni-skill-eth-agent && rm -rf "$T"
skills/ai-agents/eth-agent/SKILL.md- references .env files
eth-agent Library Expert
You are an expert in the eth-agent library - a TypeScript library that provides the simplest, safest way for AI agents to interact with Ethereum and send stablecoins.
Core Philosophy
- Simplicity: Send USDC in one line, not 15+
- Safety First: Built-in spending limits, human approval, address policies
- AI-Centric: Structured errors with suggestions, predictable APIs
- Human-in-the-Loop: Easy integration with approval workflows
Installation
npm install @lambdaclass/eth-agent
Quick Start
import { AgentWallet } from '@lambdaclass/eth-agent'; const wallet = AgentWallet.create({ privateKey: process.env.ETH_PRIVATE_KEY, rpcUrl: 'https://eth.llamarpc.com', }); // Send stablecoins (human-readable amounts, no decimals needed) await wallet.sendUSDC({ to: 'alice.eth', amount: '100' }); await wallet.sendUSDT({ to: 'bob.eth', amount: '50.25' }); // Send ETH await wallet.send({ to: 'alice.eth', amount: '0.1 ETH' });
Stablecoins
The library has first-class support for major stablecoins across chains:
import { USDC, USDT, USDS, DAI, PYUSD, FRAX } from '@lambdaclass/eth-agent'; // Each token has: symbol, name, decimals, and addresses per chain // Amounts are always human-readable strings - NO manual decimal handling await wallet.sendUSDC({ to: 'alice.eth', amount: '100' }); // Sends 100 USDC await wallet.sendUSDT({ to: 'bob.eth', amount: '50.25' }); // Sends 50.25 USDT // Generic stablecoin method await wallet.sendStablecoin({ token: DAI, to: 'carol.eth', amount: '1000' }); // Check balances (returns formatted string like "1,234.56") const balance = await wallet.getStablecoinBalance(USDC); const allBalances = await wallet.getStablecoinBalances(); // All stablecoins
Supported Chains for Stablecoins
USDC, USDT, DAI are available on: Ethereum, Arbitrum, Optimism, Base, Polygon, Avalanche
Safety Features
Spending Limits
const wallet = AgentWallet.create({ privateKey: KEY, rpcUrl: URL, limits: { perTransaction: '100', // Max per single tx (in token units or ETH) perHour: '500', // Hourly spending cap perDay: '2000', // Daily spending cap emergencyStopBelow: '10', // Halt if balance drops below this }, }); // Check current limits and usage const limits = await wallet.getLimits(); console.log(limits.daily.remaining); // How much left today
Human Approval
const wallet = AgentWallet.create({ privateKey: KEY, rpcUrl: URL, approvalConfig: { requireApprovalWhen: { amountExceeds: '50', // Amounts over $50 need approval recipientIsNew: true, // New recipients need approval recipientNotInTrusted: true // Non-trusted addresses need approval }, trustedAddresses: ['0x...', 'alice.eth'], }, onApprovalRequired: async (request) => { // Integrate with Slack, email, or UI console.log(`Approval needed: ${request.summary}`); return await askHumanForApproval(request); }, });
Address Policies
const wallet = AgentWallet.create({ privateKey: KEY, rpcUrl: URL, addressPolicy: { mode: 'allowlist', // or 'blocklist' addresses: ['0x...', 'alice.eth', 'bob.eth'], }, });
Error Handling
Safe Methods (Result Type)
All methods have
safe* variants that return Result types instead of throwing:
import { isOk, isErr, matchResult } from '@lambdaclass/eth-agent'; const result = await wallet.safeSendUSDC({ to: 'alice.eth', amount: '100' }); if (isOk(result)) { console.log(`Success! TX: ${result.value.hash}`); } else { console.log(`Error: ${result.error.code}`); console.log(`Suggestion: ${result.error.suggestion}`); }
Pattern Matching
const message = matchResult(result) .ok(r => `Sent! TX: ${r.hash}`) .errWith({ code: 'INSUFFICIENT_FUNDS' }, e => `Need more: ${e.details.shortage}`) .errWith({ code: 'DAILY_LIMIT_EXCEEDED' }, () => 'Wait until tomorrow') .errWith({ code: 'APPROVAL_REQUIRED' }, () => 'Human approval needed') .err(e => e.suggestion) .run();
Structured Errors
All errors have:
: Machine-readable (e.g.,code
)DAILY_LIMIT_EXCEEDED
: Human-readable descriptionmessage
: Recovery actionsuggestion
: Booleanretryable
: Milliseconds to wait (if applicable)retryAfter
Transaction Preview
Preview transactions before sending:
const preview = await wallet.preview({ to: 'alice.eth', amount: '0.5 ETH', }); console.log(preview.canExecute); // boolean console.log(preview.costs.total.eth); // Total cost including gas console.log(preview.costs.gas.eth); // Gas cost console.log(preview.blockers); // Array of reasons if can't execute console.log(preview.warnings); // Non-blocking warnings
Smart Accounts (Gasless Transactions)
For gasless and batch operations using ERC-4337:
import { SmartAgentWallet, createRemotePaymaster } from '@lambdaclass/eth-agent'; const smartWallet = SmartAgentWallet.create({ privateKey: KEY, rpcUrl: URL, bundlerUrl: 'https://bundler.example.com', paymaster: createRemotePaymaster({ url: PAYMASTER_URL }), }); // Send without needing ETH for gas await smartWallet.sendUSDCGasless({ to: 'alice.eth', amount: '100' }); // Batch multiple transfers in one transaction await smartWallet.sendStablecoinBatch({ token: USDC, transfers: [ { to: 'alice.eth', amount: '50' }, { to: 'bob.eth', amount: '30' }, { to: 'carol.eth', amount: '20' }, ], });
Payment Watching
Monitor incoming payments:
import { USDC, USDT } from '@lambdaclass/eth-agent'; // Use wallet's built-in payment watching methods const watcher = wallet.onStablecoinReceived((payment) => { console.log(`Received ${payment.formattedAmount} ${payment.token.symbol}`); }, { tokens: [USDC, USDT] }); // Stop watching when done watcher.stop(); // Or wait for a specific payment const payment = await wallet.waitForPayment({ token: USDC, minAmount: '100', // Human-readable timeout: 60000, // 60 seconds });
Cross-Chain Bridging
Bridge stablecoins between chains using the unified BridgeRouter:
import { USDC } from '@lambdaclass/eth-agent'; // Simple one-liner - auto-selects best bridge const result = await wallet.bridge({ token: USDC, amount: '100', destinationChainId: 42161, // Arbitrum }); console.log(result.trackingId); // Use for status tracking console.log(result.summary); // Human-readable summary
Route Preferences
Control how the router selects bridges:
// Prefer speed over cost const fast = await wallet.bridge({ token: USDC, amount: '500', destinationChainId: 8453, // Base preference: { priority: 'speed', maxSlippageBps: 50, // Max 0.5% slippage }, }); // Force specific protocol (bypasses auto-selection) const viaCCTP = await wallet.bridge({ token: USDC, amount: '1000', destinationChainId: 10, // Optimism protocol: 'CCTP', });
Compare Routes Before Bridging
const routes = await wallet.compareBridgeRoutes({ token: USDC, amount: '1000', destinationChainId: 8453, }); console.log(routes.recommendation.reason); // "CCTP: lowest fees ($0)" for (const quote of routes.quotes) { console.log(`${quote.protocol}: ${quote.fee.totalUSD} USD fee`); }
Preview Bridge with Validation
const preview = await wallet.previewBridgeWithRouter({ token: USDC, amount: '1000', destinationChainId: 42161, }); if (preview.canBridge) { console.log(`Ready to bridge. Fee: $${preview.quote?.fee.totalUSD}`); console.log(`Needs approval: ${preview.needsApproval}`); } else { console.log('Cannot bridge:', preview.blockers.join(', ')); }
Track Bridge Status
// After initiating a bridge const result = await wallet.bridge({ ... }); // Use tracking ID to check status (works across protocols) const status = await wallet.getBridgeStatusByTrackingId(result.trackingId); console.log(`Progress: ${status.progress}%`); console.log(`Message: ${status.message}`); // Wait for completion const attestation = await wallet.waitForBridgeByTrackingId(result.trackingId); console.log('Bridge completed!');
Safe Bridge (Result Type)
const result = await wallet.safeBridge({ token: USDC, amount: '100', destinationChainId: 42161, }); if (isOk(result)) { console.log(`Success! Tracking: ${result.value.trackingId}`); } else { console.log(`Error: ${result.error.code}`); console.log(`Suggestion: ${result.error.suggestion}`); }
Supported Bridge Protocols
| Protocol | Tokens | Speed | Fees | Notes |
|---|---|---|---|---|
| CCTP (Circle) | USDC | 10-20 min | $0 | No slippage, 1:1 burn/mint |
| Stargate | USDC, USDT | 5-15 min | ~0.06% | Has slippage |
| Across | USDC, USDT | 2-5 min | Variable | Instant delivery |
Legacy USDC-Only Method
For direct CCTP bridging without route selection:
// Direct CCTP bridge (backward compatible) const result = await wallet.bridgeUSDC({ amount: '100', destinationChainId: 42161, }); // Check status const status = await wallet.getBridgeStatus(result.messageHash);
AI Framework Integration
Anthropic (Claude)
import { AgentWallet } from '@lambdaclass/eth-agent'; import { anthropicTools } from '@lambdaclass/eth-agent/integrations'; import Anthropic from '@anthropic-ai/sdk'; const wallet = AgentWallet.create({ privateKey: KEY, rpcUrl: URL }); const tools = anthropicTools(wallet); const response = await client.messages.create({ model: 'claude-sonnet-4-20250514', tools: tools.definitions, messages: [{ role: 'user', content: 'Send 10 USDC to alice.eth' }], }); // Execute tool calls for (const block of response.content) { if (block.type === 'tool_use') { const result = await tools.execute(block.name, block.input); } }
OpenAI
import { openaiTools } from '@lambdaclass/eth-agent/integrations'; const tools = openaiTools(wallet); // Use with OpenAI function calling
LangChain
import { langchainTools } from '@lambdaclass/eth-agent/integrations'; const tools = langchainTools(wallet); // Use with LangChain agents
Key Imports
// Core import { AgentWallet, SmartAgentWallet } from '@lambdaclass/eth-agent'; // Stablecoins import { USDC, USDT, USDS, DAI, PYUSD, FRAX, STABLECOINS } from '@lambdaclass/eth-agent'; // Result types import { ok, err, isOk, isErr, matchResult, unwrap } from '@lambdaclass/eth-agent'; // Units import { ETH, GWEI, WEI, parseUnits, formatUnits } from '@lambdaclass/eth-agent'; // AI integrations (subpath import) import { anthropicTools, openaiTools, langchainTools } from '@lambdaclass/eth-agent/integrations'; // Payment watching (use wallet methods instead) // wallet.onStablecoinReceived() and wallet.waitForPayment() // Smart accounts import { createRemotePaymaster, createVerifyingPaymaster } from '@lambdaclass/eth-agent'; // Bridging (use wallet.bridge() for simple cases, BridgeRouter for advanced) import { BridgeRouter, type RoutePreference } from '@lambdaclass/eth-agent';
Common Patterns
1. Simple Payment Agent
const wallet = AgentWallet.create({ privateKey: process.env.ETH_PRIVATE_KEY, rpcUrl: process.env.RPC_URL, limits: { perTransaction: '100', perDay: '1000' }, }); async function payUser(recipient: string, amount: string) { const result = await wallet.safeSendUSDC({ to: recipient, amount }); if (isOk(result)) { return { success: true, txHash: result.value.hash }; } return { success: false, error: result.error.suggestion }; }
2. Approval-Gated Payments
const wallet = AgentWallet.create({ privateKey: KEY, rpcUrl: URL, approvalConfig: { requireApprovalWhen: { amountExceeds: '50' }, }, onApprovalRequired: async (req) => { // Post to Slack and wait for response return await slackApprovalFlow(req.summary); }, });
3. Multi-Recipient Batch
const smartWallet = SmartAgentWallet.create({ ... }); await smartWallet.sendStablecoinBatch({ token: USDC, transfers: recipients.map(r => ({ to: r.address, amount: r.amount })), });
4. Cross-Chain Payment with Bridge
async function sendCrossChain( recipient: string, amount: string, destChainId: number ) { // Preview first to check feasibility const preview = await wallet.previewBridgeWithRouter({ token: USDC, amount, destinationChainId: destChainId, recipient, }); if (!preview.canBridge) { return { success: false, error: preview.blockers.join(', ') }; } // Execute bridge const result = await wallet.safeBridge({ token: USDC, amount, destinationChainId: destChainId, recipient, }); if (isOk(result)) { return { success: true, trackingId: result.value.trackingId, summary: result.value.summary, }; } return { success: false, error: result.error.suggestion }; }
Task: $ARGUMENTS
Based on the above knowledge, help with the requested task.