# agentwallet-mastra-plugin

Non-custodial wallet + x402 payments + spend limits for [Mastra](https://mastra.ai) AI agents. Add complete on-chain payment capability to any Mastra agent in one line.

```typescript
tools: createAgentWalletTools({ privateKey: process.env.AGENT_PRIVATE_KEY })
```

[![npm version](https://badge.fury.io/js/agentwallet-mastra-plugin.svg)](https://www.npmjs.com/package/agentwallet-mastra-plugin)
[![Tests](https://img.shields.io/badge/tests-71%20passing-brightgreen)](https://github.com/up2itnow/mastra-plugin)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## What This Does

Mastra gives you a powerful agent framework. What it doesn't give you is the ability for agents to pay for things. This plugin closes that gap.

Your agents get:
- A **non-custodial wallet** on Base (they control their own keys)
- **USDC + ETH balance** checking
- **USDC payments** to any address
- **x402 payments** — automatic handling of HTTP 402 payment flows for paid APIs and data services
- **Cross-chain bridging** via Circle CCTP V2 (Base → Ethereum/Optimism/Arbitrum)
- **Spend limits** — per-transaction and daily caps you configure as the developer
- **Transaction history** — direct on-chain queries, no indexer required

## Install

```bash
npm install agentwallet-mastra-plugin agentwallet-sdk
```

Both packages are required. `agentwallet-sdk` is a peer dependency containing the on-chain logic.

## Quick Start

```typescript
import { createAgentWalletTools } from 'agentwallet-mastra-plugin';
import { Agent } from '@mastra/core';
import { openai } from '@ai-sdk/openai';

const agent = new Agent({
  name: 'PayingAgent',
  instructions: 'You can make payments using your wallet.',
  model: openai('gpt-4o'),
  tools: createAgentWalletTools({
    privateKey: process.env.AGENT_PRIVATE_KEY!,
  }),
});

const result = await agent.generate('What is my wallet address?');
```

## Configuration

```typescript
import { createAgentWalletTools } from 'agentwallet-mastra-plugin';

const tools = createAgentWalletTools({
  // Required: the agent's private key
  // Store this in a secrets manager, not in code
  privateKey: process.env.AGENT_PRIVATE_KEY!,

  // Optional: custom RPC endpoint (defaults to Base Mainnet public RPC)
  rpcUrl: process.env.BASE_RPC_URL,

  // Optional: enforce spending guardrails
  spendLimits: {
    perTxLimitUsdc: 10,   // max $10 per transaction
    dailyLimitUsdc: 100,  // max $100 per day (rolling 24h window)
  },

  // Optional: use testnet during development
  network: 'mainnet', // or 'testnet' (Base Sepolia)
});
```

## The 10 Tools

Each tool is registered with Mastra using `createTool` with strict Zod schemas. The agent sees them as normal tools and can call them naturally in conversation.

---

### `getWalletAddress`

Returns the agent's wallet address on Base. Use this to display the wallet or receive payments.

**Input:** _(none)_

**Output:**
```typescript
{
  success: true,
  address: "0xf39F...",
  network: "Base (chainId: 8453)"
}
```

---

### `getWalletBalance`

Returns USDC and ETH balances. Check this before attempting payments.

**Input:** _(none)_

**Output:**
```typescript
{
  success: true,
  address: "0xf39F...",
  usdcBalance: "42.5",     // human-readable
  ethBalance: "0.01",      // human-readable
  usdcRaw: "42500000",     // base units (6 decimals)
  ethRaw: "10000000000000000"
}
```

---

### `createWallet`

Generates a new non-custodial wallet. Returns the public address and a masked key hint.

**Input:**
```typescript
{ label?: string }  // optional name for your records
```

**Output:**
```typescript
{
  success: true,
  address: "0xABCD...",
  privateKeyHint: "0xac0974...2ff80 (store the full key securely)",
  warning: "IMPORTANT: Store the private key in a secure secrets manager immediately.",
  label: "my-agent-wallet"
}
```

> ⚠️ The private key appears **once** in the hint. Store it immediately in AWS Secrets Manager, HashiCorp Vault, or equivalent. This plugin never logs or transmits private keys.

---

### `sendPayment`

Send USDC to any address on Base. Enforces spend limits before submitting.

**Input:**
```typescript
{
  to: string;          // "0x..." recipient address
  amountUsdc: number;  // e.g. 5.00 for $5.00
  memo?: string;       // optional off-chain note
}
```

**Output:**
```typescript
{
  success: true,
  txHash: "0xabc...",
  amountUsdc: 5,
  to: "0x70997...",
  explorerUrl: "https://basescan.org/tx/0xabc..."
}
```

**Error cases:** `SPEND_LIMIT_EXCEEDED`, `INSUFFICIENT_BALANCE`, `NETWORK_ERROR`

---

### `x402Pay`

Make an HTTP request to a URL that requires x402 payment. Handles the entire payment flow automatically: detects the 402 response, pays in USDC on Base, then retries the original request.

**Input:**
```typescript
{
  url: string;              // URL to fetch
  method?: string;          // GET, POST, PUT, DELETE, PATCH (default: GET)
  body?: string;            // JSON body for POST/PUT
  maxPaymentUsdc?: number;  // max willing to pay (default: 1 USDC)
}
```

**Output:**
```typescript
{
  success: true,
  statusCode: 200,
  responseBody: "...",
  paymentMade: true
}
```

**Use cases:** Paid data feeds, premium AI APIs, TaskBridge task payments.

---

### `bridgePayment`

Bridge USDC from Base to another chain using Circle CCTP V2. Non-custodial — all signing happens locally.

**Input:**
```typescript
{
  amountUsdc: number;              // amount to bridge
  destinationChain: string;        // "ethereum" | "optimism" | "arbitrum"
  destinationAddress?: string;     // recipient (defaults to agent's own address)
  fastFinality?: boolean;          // true = ~12s, false = ~15min (default: true)
}
```

**Output:**
```typescript
{
  success: true,
  burnTxHash: "0xburn...",
  mintTxHash: "0xmint...",
  amountUsdc: 50,
  destinationChain: "optimism",
  status: "completed"
}
```

---

### `getPortfolio`

Full financial snapshot: balances, network, block height, and timestamp.

**Input:** _(none)_

**Output:**
```typescript
{
  success: true,
  address: "0xf39F...",
  usdcBalance: "100",
  ethBalance: "0.05",
  blockNumber: "23456789",
  timestamp: "2026-02-22T10:00:00.000Z"
}
```

---

### `getTransactionHistory`

Recent USDC transfer history, queried directly from Base event logs. No indexer required.

**Input:**
```typescript
{
  limit?: number;          // max results (1-100, default: 20)
  lookbackBlocks?: number; // blocks to search (default: 10000 ≈ ~6h on Base)
}
```

**Output:**
```typescript
{
  success: true,
  transactions: [
    {
      blockNumber: "23456000",
      txHash: "0xabc...",
      direction: "outgoing",
      amountUsdc: "5",
      counterparty: "0x70997..."
    }
  ],
  totalFound: 12,
  blocksSearched: 10000
}
```

---

### `getSpendLimits`

Inspect the current spend limit configuration. Agents can use this to understand what they're authorized to spend before planning a series of payments.

**Input:** _(none)_

**Output:**
```typescript
{
  success: true,
  limitsConfigured: true,
  perTxLimitUsdc: 10,
  dailyLimitUsdc: 100,
  spentTodayUsdc: 15.5,
  remainingDailyUsdc: 84.5,
  windowResetInMs: 43200000
}
```

---

### `checkSpendAllowance`

Pre-flight check: verify a specific amount is within limits before attempting a payment. Doesn't execute anything.

**Input:**
```typescript
{ amountUsdc: number }
```

**Output:**
```typescript
{
  success: true,
  allowed: false,
  amountUsdc: 15,
  blockedBy: "per-transaction limit (10 USDC)",
  perTxCheck: { limit: 10, withinLimit: false },
  dailyCheck: { limit: 100, spentToday: 15.5, wouldSpend: 30.5, withinLimit: true }
}
```

---

## Why Non-Custodial

**Custodial wallets** (like hosted API services) hold your agent's private key. This means:
- If the service is compromised, your funds are at risk
- The service can censor or freeze transactions
- You have a third-party dependency in your payments stack
- Privacy: the service knows every transaction your agent makes

**Non-custodial wallets** keep the private key in your environment:
- Only your agent can sign transactions
- No counterparty risk
- No third-party censorship
- Works offline/airgapped (except for RPC calls)

This plugin is built on `agentwallet-sdk`, which handles on-chain operations using [viem](https://viem.sh). Your private key never leaves the process that runs your agent.

## Security

### Private Key Handling

- The private key is passed in at plugin initialization and stored in memory only
- It is **never** logged, never serialized, never included in tool outputs
- `createWallet` shows a masked key hint — not the full key
- Use environment variables (or a secrets manager) to inject the key at runtime

```bash
# Never hardcode keys. Always use environment variables:
AGENT_PRIVATE_KEY=0x... node my-agent.js
```

### Spend Limits

Spend limits are enforced synchronously before any transaction reaches the blockchain. They're intentionally simple and conservative:

```typescript
spendLimits: {
  perTxLimitUsdc: 5,    // Each payment: max $5
  dailyLimitUsdc: 50,   // Per day: max $50
}
```

Limits reset on a rolling 24-hour window. The `checkSpendAllowance` tool lets agents verify limits before attempting payments.

### What This Plugin Does NOT Do

- Does not store or escrow any funds
- Does not have a backend service or central server
- Does not track or report transactions to any third party
- Does not require any API key other than your RPC URL

## Resources

- **[agentwallet-sdk](https://www.npmjs.com/package/agentwallet-sdk)** — The underlying SDK for on-chain operations
- **[AI Agent Economy](https://ai-agent-economy.com)** — Platform, docs, and community
- **[TaskBridge](https://ai-agent-economy.com/taskbridge)** — Agent-native job marketplace with built-in x402 payments
- **[Base Network](https://base.org)** — The L2 this plugin runs on (fast, cheap, EVM-compatible)
- **[Circle CCTP V2](https://www.circle.com/en/cross-chain-transfer-protocol)** — The bridge protocol used by `bridgePayment`

## Requirements

- Node.js >= 18
- `@mastra/core` >= 0.10.0
- `agentwallet-sdk` >= 2.4.0
- `zod` >= 3.0.0

## License

MIT — see [LICENSE](LICENSE)

---

Built by [AI Agent Economy](https://ai-agent-economy.com). Making autonomous payments safe, sovereign, and simple.
