npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

agentwallet-sdk

v2.5.0

Published

TypeScript SDK for Agent Wallet — autonomous crypto spending for AI agents with user-set limits

Readme

🤖 Agent Wallet SDK

Let your AI agent spend crypto. Stay in control.

Agent Wallet gives AI agents autonomous spending power with hard on-chain limits. No more choosing between "agent can drain everything" and "every transaction needs manual approval."

Agent wants to spend $15 → ✅ Auto-approved (under $25 limit)
Agent wants to spend $500 → ⏳ Queued for your approval
Agent spent $490 today → 🛑 Next tx queued ($500/day limit hit)
```text

## How We Compare

| | **agentwallet-sdk** | **Coinbase Agentic Wallet** | **MoonPay Agents** |
|---|---|---|---|
| **Custody** | Non-custodial (keys on device) | Semi-custodial (TEE) | Non-custodial (claimed) |
| **Spend Limits** | On-chain (smart contract) | API-enforced | Not documented |
| **Chains** | 5 (Base, ETH, Arb, Polygon, Sepolia) | Base only | Unclear |
| **Agent Identity** | ERC-8004 + ERC-6551 | None | None |
| **Open Source** | MIT | Partial | Closed |
| **x402 Payments** | Native | Supported | "Compatible" |

> On-chain spend limits can't be bypassed even if the API layer is compromised. That's the difference between policy and math.

## Why Agent Wallet?

| Approach | Problem |
|----------|---------|
| Raw EOA wallet | Agent can drain everything. One prompt injection = rugged. |
| Multisig (Safe) | Every tx needs human sigs. Kills agent autonomy. |
| Custodial API (Stripe) | Centralized, KYC friction, not crypto-native. |
| **Agent Wallet** | **Agents spend freely within limits. Everything else queues for approval.** |

Built on **ERC-6551** (token-bound accounts). Your agent's wallet is tied to an NFT — portable, auditable, fully on-chain.

## Quick Start

```bash
npm install @agentwallet/sdk viem
```text

```typescript
import {
  createWallet,
  setSpendPolicy,
  agentExecute,
  checkBudget,
  getPendingApprovals,
  approveTransaction,
  NATIVE_TOKEN,
} from '@agentwallet/sdk';
import { createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';

// 1. Connect to your agent's wallet
const walletClient = createWalletClient({
  account: privateKeyToAccount('0xAGENT_PRIVATE_KEY'),
  transport: http('https://mainnet.base.org'),
});

const wallet = createWallet({
  accountAddress: '0xYOUR_AGENT_ACCOUNT',
  chain: 'base',
  walletClient,
});

// 2. Owner sets spending limits (one-time setup)
await setSpendPolicy(wallet, {
  token: NATIVE_TOKEN,  // ETH
  perTxLimit: 25_000000000000000n,   // 0.025 ETH per tx
  periodLimit: 500_000000000000000n, // 0.5 ETH per day
  periodLength: 86400,               // 24 hours
});

// 3. Agent spends autonomously
await agentExecute(wallet, {
  to: '0xSOME_SERVICE',
  value: 10_000000000000000n, // 0.01 ETH — under limit, executes immediately
});

// 4. Check remaining budget
const budget = await checkBudget(wallet, NATIVE_TOKEN);
console.log(`Remaining today: ${budget.remainingInPeriod}`);

// 5. Owner reviews queued transactions
const pending = await getPendingApprovals(wallet);
for (const tx of pending) {
  console.log(`Pending #${tx.txId}: ${tx.amount} to ${tx.to}`);
  await approveTransaction(wallet, tx.txId);
}
```text

## API Reference

### `createWallet(config)`

Connect to an existing AgentAccountV2 contract.

| Param | Type | Description |
|-------|------|-------------|
| `accountAddress` | `Address` | Deployed AgentAccountV2 address |
| `chain` | `string` | `'base'` \| `'base-sepolia'` \| `'ethereum'` \| `'arbitrum'` \| `'polygon'` |
| `walletClient` | `WalletClient` | viem wallet client (agent or owner key) |
| `rpcUrl?` | `string` | Custom RPC URL |

### `setSpendPolicy(wallet, policy)` — Owner only

Set per-token spending limits.

| Field | Type | Description |
|-------|------|-------------|
| `token` | `Address` | Token address (`NATIVE_TOKEN` for ETH) |
| `perTxLimit` | `bigint` | Max single tx (0 = all txs need approval) |
| `periodLimit` | `bigint` | Max per rolling window (0 = no autonomous spending) |
| `periodLength` | `number` | Window in seconds (default: 86400 = 24h) |

### `agentExecute(wallet, { to, value?, data? })`

Execute a native ETH transaction. Auto-approves if within limits, queues if over.

**Returns:** `{ executed: boolean, txHash: Hash, pendingTxId?: bigint }`

### `agentTransferToken(wallet, { token, to, amount })`

Transfer ERC20 tokens, respecting spend limits.

### `checkBudget(wallet, token?)`

Check remaining autonomous spending budget.

**Returns:** `{ token, perTxLimit, remainingInPeriod }`

### `getPendingApprovals(wallet, fromId?, toId?)`

List all pending (unexecuted, uncancelled) transactions awaiting owner approval.

### `approveTransaction(wallet, txId)` — Owner only

Approve and execute a queued transaction.

### `cancelTransaction(wallet, txId)` — Owner only

Cancel a queued transaction.

### `setOperator(wallet, operator, authorized)` — Owner only

Add or remove an agent operator address.

### `getBudgetForecast(wallet, token?, now?)`

**[MAX-ADDED]** Time-aware budget forecast — know not just what's left, but when it refills.

**Returns:** `BudgetForecast` — includes `remainingInPeriod`, `secondsUntilReset`, `utilizationPercent`, full period metadata.

```typescript
const forecast = await getBudgetForecast(wallet, NATIVE_TOKEN);
console.log(`${forecast.utilizationPercent}% used, resets in ${forecast.secondsUntilReset}s`);
```text

### `getWalletHealth(wallet, operators?, tokens?, now?)`

**[MAX-ADDED]** Single-call diagnostic snapshot for agent self-monitoring.

**Returns:** `WalletHealth` — address, NFT binding, operator epoch, active operator statuses, pending queue depth, budget forecasts.

```typescript
const health = await getWalletHealth(wallet, [agentHotWallet], [NATIVE_TOKEN, usdcAddress]);
if (health.pendingQueueDepth > 5) console.warn('Queue backing up!');
if (!health.activeOperators[0].active) console.error('Agent operator deactivated!');
```text

### `batchAgentTransfer(wallet, transfers)`

**[MAX-ADDED]** Execute multiple token transfers sequentially — reduces boilerplate for multi-recipient payments.

```typescript
const hashes = await batchAgentTransfer(wallet, [
  { token: USDC, to: serviceA, amount: 100n },
  { token: USDC, to: serviceB, amount: 200n },
]);
```text

### `getActivityHistory(wallet, { fromBlock?, toBlock? })`

**[MAX-ADDED]** Query on-chain event history for self-auditing — no external indexer needed.

**Returns:** `ActivityEntry[]` — sorted by block number, covers executions, queued txs, approvals, cancellations, policy updates, operator changes.

```typescript
const history = await getActivityHistory(wallet, { fromBlock: 10000n });
for (const entry of history) {
  console.log(`[${entry.type}] block ${entry.blockNumber}: ${JSON.stringify(entry.args)}`);
}
```text

## Supported Chains

| Chain | Status | Best For |
|-------|--------|----------|
| **Base** | ✅ Primary | Low gas, USDC native |
| **Base Sepolia** | ✅ Testnet | Development |
| **Ethereum** | ✅ | High-value operations |
| **Arbitrum** | ✅ | DeFi agents |
| **Polygon** | ✅ | Micropayments |

## x402 Protocol Support

Agent Wallet natively supports the [x402 protocol](https://x402.org) — the open standard for HTTP 402 machine payments. Your agent can automatically pay any x402-enabled API (Stripe, Coinbase, etc.) using USDC on Base, while respecting on-chain spend limits.

### Quick Start

```typescript
import { createWallet, createX402Client } from 'agentwallet-sdk';

// 1. Create your wallet
const wallet = createWallet({ accountAddress, chain: 'base', walletClient });

// 2. Create an x402-aware client
const client = createX402Client(wallet, {
  globalDailyLimit: 50_000_000n,  // 50 USDC/day
  globalPerRequestMax: 5_000_000n, // 5 USDC max per request
  serviceBudgets: [
    { service: 'api.weather.com', maxPerRequest: 1_000_000n, dailyLimit: 10_000_000n },
  ],
});

// 3. Use it like fetch — 402 responses are handled automatically
const response = await client.fetch('https://api.weather.com/forecast');
const data = await response.json();
// If the API returned 402, the client:
//   - Parsed payment requirements from the PAYMENT-REQUIRED header
//   - Checked your budget (client-side + on-chain)
//   - Paid USDC via your AgentWallet contract
//   - Retried the request with payment proof
```text

### Drop-in Fetch Replacement

```typescript
import { createX402Fetch } from 'agentwallet-sdk';

const x402Fetch = createX402Fetch(wallet, { globalDailyLimit: 100_000_000n });

// Use exactly like fetch()
const res = await x402Fetch('https://any-x402-api.com/endpoint');
```text

### Budget Controls

```typescript
// Check spending
const summary = client.getDailySpendSummary();
console.log(`Today's spend: ${summary.global} (resets at ${summary.resetsAt})`);

// View transaction log
const logs = client.getTransactionLog({ service: 'api.weather.com' });

// Add budget at runtime
client.budgetTracker.setServiceBudget({
  service: 'new-api.com',
  maxPerRequest: 2_000_000n,
  dailyLimit: 20_000_000n,
});
```text

### Payment Approval Callback

```typescript
const client = createX402Client(wallet, {
  onBeforePayment: async (req, url) => {
    console.log(`About to pay ${req.amount} to ${req.payTo} for ${url}`);
    return true; // return false to reject
  },
  onPaymentComplete: (log) => {
    console.log(`Paid ${log.amount} via tx ${log.txHash}`);
  },
});
```text

### How x402 Works

```text
Agent → GET /api/data → Server returns 402 + PAYMENT-REQUIRED header
  ↓
Client parses payment requirements (amount, token, recipient, network)
  ↓
Budget check (client-side caps + on-chain spend limits)
  ↓
AgentWallet executes USDC transfer on Base
  ↓
Client retries request with X-PAYMENT header (payment proof)
  ↓
Server verifies payment → returns 200 + data
```text

Your agent's keys never leave the non-custodial wallet. All payments respect on-chain spend limits set by the wallet owner.

## ERC-8004: On-Chain Agent Identity (v2.3.0)

Give your AI agent a portable, censorship-resistant identity on Ethereum via [ERC-8004 Trustless Agents](https://eips.ethereum.org/EIPS/eip-8004).

ERC-8004 provides three things:

- **Identity Registry** — ERC-721 NFT that resolves to an agent's registration file (name, description, services, capabilities)
- **Reputation Registry** — On-chain feedback signals (composable scoring)
- **Validation Registry** — Hooks for stakers, zkML verifiers, and TEE oracles

The SDK integrates the Identity Registry. Non-custodial — keys never leave the device.

```typescript
import { ERC8004Client, buildDataURI, validateRegistrationFile } from '@agentwallet/sdk';

const identity = new ERC8004Client({
  registryAddress: '0xYOUR_REGISTRY',
  chain: 'base',
});

// Register your agent on-chain (auto-builds data URI if you don't pass one)
const { txHash, agentId } = await identity.registerAgent(
  walletClient,
  {
    name: 'TradingAgent',
    description: 'Autonomous DeFi trading agent with x402 support',
    services: [
      { name: 'A2A', endpoint: 'https://agent.example/.well-known/agent-card.json', version: '0.3.0' },
      { name: 'MCP', endpoint: 'https://mcp.agent.example/', version: '2025-06-18' },
    ],
    x402Support: true,
    active: true,
    supportedTrust: ['reputation'],
  },
  'ipfs://QmYourCID'  // or omit to store fully on-chain as data URI
);

// Register the AI model powering this agent
await identity.setModelMetadata(walletClient, agentId!, {
  model: 'claude-3-5-sonnet',
  provider: 'anthropic',
  version: '2.3.0',
  capabilities: ['trading', 'research', 'payments'],
  framework: 'custom',
});

// Resolve any agent's full identity
const agentData = await identity.lookupAgentIdentity(42n);
console.log(agentData.registrationFile?.name);    // "TradingAgent"
console.log(agentData.modelMetadata?.model);       // "claude-3-5-sonnet"
console.log(agentData.owner);                      // NFT owner address

// Validate a registration file before publishing
const errors = validateRegistrationFile(agentData.registrationFile!);
if (errors.length === 0) console.log('Valid ERC-8004 registration ✅');
```text

### Agent Registry Identifier

Each agent is globally identified by a namespaced string:

```text
eip155:8453:0xRegistryAddress  ← namespace:chainId:contractAddress
```text

```typescript
import { formatAgentRegistry } from '@agentwallet/sdk';
const id = formatAgentRegistry(8453, '0xYOUR_REGISTRY');
// → "eip155:8453:0xYOUR_REGISTRY"
```text

### Fully On-Chain Storage (No IPFS Required)

```typescript
import { buildDataURI, parseDataURI } from '@agentwallet/sdk';

// Encode registration file as a base64 data URI (embeds in the NFT)
const uri = buildDataURI({ name: 'MyAgent', description: '...', type: '...' });
// → "data:application/json;base64,eyJ0eXBlIjoi..."

// Decode it back
const file = parseDataURI(uri);
```text

---

## How It Works

1. **Deploy** an AgentAccountV2 (ERC-6551 token-bound account tied to an NFT)
2. **Configure** spend policies per token — set per-tx and daily limits
3. **Register** your agent's hot wallet as an operator
4. **Register on-chain identity** via ERC-8004 (optional but recommended)
5. **Agent operates autonomously** — transactions within limits execute instantly
6. **Over-limit transactions queue** — owner gets notified, approves or cancels

All limits enforced on-chain. No off-chain dependencies. Fully auditable.

## License

MIT