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.

install
source · Clone the upstream repo
git clone https://github.com/diegosouzapw/awesome-omni-skill
Claude Code · Install into ~/.claude/skills/
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"
manifest: skills/ai-agents/eth-agent/SKILL.md
safety · automated scan (low risk)
This is a pattern-based risk scan, not a security review. Our crawler flagged:
  • references .env files
Always read a skill's source content before installing. Patterns alone don't mean the skill is malicious — but they warrant attention.
source content

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:

  • code
    : Machine-readable (e.g.,
    DAILY_LIMIT_EXCEEDED
    )
  • message
    : Human-readable description
  • suggestion
    : Recovery action
  • retryable
    : Boolean
  • retryAfter
    : Milliseconds to wait (if applicable)

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

ProtocolTokensSpeedFeesNotes
CCTP (Circle)USDC10-20 min$0No slippage, 1:1 burn/mint
StargateUSDC, USDT5-15 min~0.06%Has slippage
AcrossUSDC, USDT2-5 minVariableInstant 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.

eth-agent — OpenSkillIndex