Skip to content

About

Non-custodial crypto wallets for AI agents with on-chain spending limits. ERC-6551, x402 compatible, Base Mainnet.

Topics

Resources

Contributing

Security policy

Stars

13 stars

Watchers

1 watching

Forks

Latest commit

 

History

202 Commits

Folders and files

Repository files navigation

AgentWallet SDK

npm CI

The agentwallet-sdk npm package is a TypeScript library for policy-aware agent payments. It is non-custodial: callers supply their own viem WalletClient, and the SDK does not store keys or operate a custodial service.

This source is agentwallet-sdk 8.0.0. Published versions 7.0.0 and earlier lack the October 25, 2026 security repairs. agentwallet-sdk is the only npm name this project publishes. @agentwallet/sdk is a different package owned by an unrelated maintainer and is not part of this SDK.

What ships

Area Public surface Source
Smart-wallet client createWallet, policy writes, budget reads src/index.ts
x402 Client, middleware, budget tracking, multi-asset helpers src/x402/
Local policy SpendingPolicy (reserve/commit/release), UptoBillingPolicy src/policy/
Spend outcomes classifySpendAttempt, classifySpendError, isEvmTxHash src/outcomes/
Tokens Registry, decimals, transfers, optional Solana helpers src/tokens/
Receipts Portable provider-receipt normalization src/receipts/
Identity ERC-8004, reputation, validation, and UAID clients src/identity/
Payment modules Bridge, swap, router, and mutual-stake escrow src/

These are exported code surfaces. Their presence does not claim an official deployment, production use, regulatory status, or support for every network.

Payment flow (reserve → execute → settle | release | hold-unknown)

After execute, classify the attempt and apply it to a SpendingPolicy reservation:

import {
  SpendingPolicy,
  classifySpendAttempt,
} from "agentwallet-sdk";

const policy = new SpendingPolicy({
  rollingCap: { maxAmount: 1_007_700, windowMs: 86_400_000 },
  includeProtocolFee: true, // hold principal + 0.77% x402 fee
});

const reserved = await policy.reserve({
  merchant: "api.example.com",
  amount: 1_000_000, // exact USDC base units
  idempotencyKey: "tool:base:usdc:payee:1000000",
});
if (reserved.status !== "reserved" || !reserved.reservation) {
  throw new Error(reserved.reason ?? "not reserved");
}

const outcome = classifySpendAttempt({
  receipt: { status: "success", transactionHash: txHash },
  txHash,
  chainId: 8453,
  amount: 1_000_000n,
  fee: 7_700n,
  idempotencyKey: reserved.reservation.idempotencyKey,
});

policy.applyOutcome(reserved.reservation, outcome);
// settled → commit  |  released → retry-safe release  |  hold-unknown → lock, no auto-retry

A locked (hold-unknown) reservation is released only by policy.reconcileLocked(reservation, publicClient), which checks the recorded transaction hashes on the recorded chain.

check() still exists as a reserve-then-commit wrapper. Prefer reserve / execute / applyOutcome() so an unknown broadcast cannot free the hold. A timer never unlocks hold-unknown.

Only reserved authorizes a new execution. existing returns the earlier attempt for observation or reconciliation. The security repairs change retry, metadata, bridge and swap behavior; read the migration notes before adopting this branch.

Install

npm install agentwallet-sdk viem

Solana helpers use an optional peer dependency:

npm install @solana/web3.js @solana/spl-token

@solana/web3.js supports native SOL operations. Install @solana/spl-token as well when using SPL-token balance or transfer helpers.

Stellar x402 payments (StellarX402Adapter, stellarX402Pay) use an optional peer dependency, version 14 or later:

npm install @stellar/stellar-sdk

Connect to an existing smart wallet

The SDK requires a viem wallet client. This budget-reading example also requires an already deployed AgentAccountV2 address; a predicted address is not sufficient because checkBudget() reads contract state. Start on a test network or a deployment you control.

import {
  NATIVE_TOKEN,
  checkBudget,
  createWallet,
} from "agentwallet-sdk";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { baseSepolia } from "viem/chains";

const privateKey = process.env.AGENT_PRIVATE_KEY;
const accountAddress = process.env.AGENT_WALLET_ADDRESS;

if (!privateKey || !accountAddress) {
  throw new Error(
    "Set AGENT_PRIVATE_KEY and a deployed AGENT_WALLET_ADDRESS",
  );
}

const account = privateKeyToAccount(privateKey as `0x${string}`);
const walletClient = createWalletClient({
  account,
  chain: baseSepolia,
  transport: http(),
});

const wallet = createWallet({
  accountAddress: accountAddress as `0x${string}`,
  chain: "base-sepolia",
  walletClient,
});

const budget = await checkBudget(wallet, NATIVE_TOKEN);
console.log({
  perTxLimit: budget.perTxLimit.toString(),
  remainingInPeriod: budget.remainingInPeriod.toString(),
});

This example reads policy state. Functions such as setSpendPolicy(), agentExecute(), agentTransferToken(), bridge, swap, and escrow methods can submit transactions and consume gas. agentTransferToken() resolves to { status: "executed" | "queued" } — a queued transfer moved no tokens. Upgrading from 7.x? Read the 8.0.0 migrations in docs/security-remediation.md.

Contract and network boundaries

  • The package ships AgentAccountV2Abi and AgentAccountFactoryV2Abi.
  • The repository does not ship Solidity sources or an official deployment manifest.
  • deployWallet() requires a factory address, token contract, token ID, RPC, and caller-controlled wallet client.
  • createWallet() currently maps Base, Base Sepolia, Ethereum, Arbitrum, Polygon, Optimism, Avalanche, Unichain, Linea, Sonic, and World Chain runtime clients in src/index.ts.
  • walletFromEnv() maps CHAIN_NAME / CHAIN_ID onto those keys. It does not pass viem display names such as "arbitrum one" into createWallet(). Unknown or conflicting chain settings throw; Base is used only when no chain is configured.
  • Every agent/owner write first verifies the account (verifyAgentWallet). Pass deployment and/or expectedCodeHash to createWallet() for a strong deployment identity.
  • setPolicyFromEnv() copies a single configured spend limit onto the omitted dimension. A missing env var is not written as 0 (the on-chain disable-all sentinel).
  • Spending policy only governs transactions routed through the matching smart wallet contract. It cannot protect funds held outside that boundary.
  • Network support differs by module. Read the module source and tests before moving funds.

Verify a clean checkout

npm ci
npm run build
npm test
npm run lint
npm audit --audit-level=high

The test suite covers the core SDK plus x402, policy, receipt, token, identity, and bridge behavior. Tests are not evidence that a third-party deployment or external payment endpoint is available.

Related repositories

  • AgentPay MCP exposes payment tools through MCP and owns the Smithery listing. This SDK does not ship a Smithery start command and must not be installed as @agentwallet/sdk.
  • AgentPay Wallet Starter provides a no-funds combined verification path.

Security and contributions

License

MIT. See LICENSE.

About

Non-custodial crypto wallets for AI agents with on-chain spending limits. ERC-6551, x402 compatible, Base Mainnet.

Topics

Resources

Contributing

Security policy

Stars

13 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages