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

@bvcc/agent-sdk

v0.1.4

Published

TypeScript SDK for operating a BVCC Agent Wallet from an off-chain AI agent. On-chain spending limits, no private-key custody by BVCC.

Readme

@bvcc/agent-sdk

Give your AI agent a wallet it can use on its own — inside spending limits you set.

Think of it like a prepaid card you hand to a bot: it can send funds and swap tokens by itself, but only up to the daily amount, only the tokens you allow, and only to the places you allow. Those limits live on the blockchain, so the agent physically cannot go past them — not even if something goes wrong.

This package is the toolkit your agent (Hermes, ElizaOS, a trading bot, a script…) uses to actually move funds within those rules.

⚠️ Beta software. It is non-custodial: you hold the keys, BVCC never can. The agent's key is "live", so always keep it secret and start with small limits. Try it on a test network (Arbitrum Sepolia) before using real money.


In plain terms

  • You create a BVCC Agent Wallet and authorize an agent in the dashboard: you paste the agent's public address and set its rules (e.g. "up to 5 USDC/day, only USDC and ETH, may swap on Uniswap"), then sign with Face ID.
  • The agent has its own keypair — you generate it; BVCC never issues or sees it. With its key and this SDK it can send, swap, and check balances, and every action is checked against your rules automatically.
  • If it tries something outside the rules, the action simply fails — no funds move. You stay in control.

What your agent can do with it

  • Send ETH (or BNB) and tokens like USDC.
  • Swap tokens on Uniswap (v3 and v4).
  • Check its balances and how much of its allowance is left.
  • Find out why an action would fail before trying it (so it doesn't waste gas).

Get started in 3 steps

1. Install

npm install @bvcc/agent-sdk viem

2. Give it your two values

You need two things:

  • Wallet address — your BVCC Agent Wallet address, from the dashboard (starts with 0x).
  • Agent key — the private key of the agent you authorized. You create this keypair yourself, authorize its public address in the dashboard, and keep the private key secret in an .env file. BVCC never issues or sees it.

First time? Generate an agent keypair, then authorize the printed address in the dashboard:

import { generatePrivateKey, privateKeyToAccount } from "viem/accounts";
const key = generatePrivateKey();
console.log("Authorize this address in the dashboard:", privateKeyToAccount(key).address);
console.log("Save this as AGENT_PRIVATE_KEY (keep it secret):", key);
import { BvccAgentClient, parseEther } from "@bvcc/agent-sdk";

const agent = new BvccAgentClient({
  account: process.env.AGENT_PRIVATE_KEY as `0x${string}`, // the agent's secret key
  walletAddress: "0xYourWalletAddress...",                  // your Agent Wallet
  network: 42161, // Arbitrum One. Others: 1 Ethereum, 56 BNB, 8453 Base, 137 Polygon, 421614 Arbitrum testnet
});

3. Do something

const result = await agent.sendNative("0xFriend...", parseEther("0.01"));

if (result.ok) {
  console.log("Done! Transaction:", result.txHash);
} else {
  console.log("It didn't go through:", result.humanMessage);
  console.log("Try this:", result.suggestedAction);
}

Every action answers the same way: either ok: true with a transaction hash, or ok: false with a plain-English reason and a suggestion. No cryptic errors.


A few things people ask

Who pays the network fee (gas)? The agent's key does, from its own small balance. So fund the agent address with a little ETH (on Arbitrum, cents). It never touches your main wallet for gas.

What if the agent's key leaks? Whoever has it can only act within the limits you set on-chain — they can't drain the wallet, change the limits, or move disallowed tokens. Set tight limits and you cap the worst case. (Still: treat the key like a password.)

Is my money safe with BVCC? BVCC never holds your keys or funds and can't move them. Everything is enforced by the wallet contract on the blockchain, not by us.

Can it spend more than I allowed? No. The blockchain rejects it. This SDK can predict what will happen, but the contract is what actually enforces the rules.

Do I need to know Solidity / smart contracts? No. If you can copy two values and call a function, you can use it.


Common actions

import { parseEther, parseUnits } from "@bvcc/agent-sdk";

// Send native coin (ETH/BNB)
await agent.sendNative(to, parseEther("0.01"));

// Send a token (USDC has 6 decimals → parseUnits("5", 6) = 5 USDC)
await agent.sendToken(usdcAddress, to, parseUnits("5", 6));

// Swap on Uniswap v3
await agent.swapExactInputV3({
  tokenIn: usdc, tokenOut: weth,
  amountIn: parseUnits("10", 6),
  amountOutMinimum: minOut, // the least you'll accept — quote it first (see below)
  fee: 500,
});

// Swap on Uniswap v4
await agent.swapV4ExactIn({
  tokenIn: usdc, tokenOut: weth,
  amountIn: parseUnits("10", 6),
  amountOutMinimum: minOut,
  fee: 500, tickSpacing: 10,
});

Check before you act (saves gas)

// Will this swap work? Simulate it without sending. If not, get the reason.
const check = await agent.dryRunSwapV4({
  tokenIn: usdc, tokenOut: weth, amountIn: parseUnits("0.1", 6),
  amountOutMinimum: 1n, fee: 500, tickSpacing: 10,
});
if (!check.ok) console.log("Would fail:", check.failure?.humanMessage);

// Or plan a swap and let the SDK fetch a price quote + set a safe minimum:
const plan = await agent.buildSwapPlan({
  protocol: "v4", tokenIn: "USDC", tokenOut: "WETH",
  amountIn: parseUnits("0.1", 6), fee: 500, tickSpacing: 10,
  quote: true, slippageBps: 50, // 0.5%
});

See what the agent can do and what it has

const status = await agent.getAgentStatus();   // active? expired? paused? + your rules
const caps   = await agent.getCapabilities();  // can it send? swap v3/v4? + helpful notes
const eth    = await agent.getNativeBalance();
const tokens = await agent.getBalances(["USDC", "WETH"]); // names or addresses
const left   = await agent.getRemaining();     // how much of each limit is left

Runnable scripts for all of the above live in examples/ (01–13).


For developers

The rest is reference detail. The plain-language part above is enough to use the SDK.

How it works under the hood

A BVCC Agent Wallet is a smart wallet (ERC-4337 / ERC-7821). The owner authorizes an agent EOA (a normal wallet address) with on-chain spending rules: per-tx, daily, rolling-period and lifetime budgets, per-token limits, and token / protocol / recipient whitelists.

The agent path is deliberately simple — the agent is a plain EOA that signs a normal transaction calling executeAsAgent, pays its own gas, and the wallet enforces every limit. No Account Abstraction, bundler, or WebAuthn here; the owner's Face ID signer is only used to authorize the agent from the dashboard.

agent EOA ──(normal tx, pays gas)──▶ AgentWallet.executeAsAgent(batch)
                                         └─ enforces limits, then runs the batch

The contract is the source of truth. Everything this SDK adds (canSpend*, dryRun*, getCapabilities, buildSwapPlan, explainFailure) only predicts and explains — it never enforces or bypasses the rules, and a passing preflight is not a guarantee (state can change before the tx lands). The SDK never logs or stores private keys; decoded errors contain selectors and addresses only.

Structured results

Action methods return a discriminated ActionResult:

type ActionResult =
  | { ok: true;  action; txHash; network; chainId; walletAddress; agentAddress }
  | { ok: false; action; errorName; humanMessage; suggestedAction; rawError;
      network; chainId; walletAddress; agentAddress };

explainFailure(error) (or the exported decodeRevert) turns any revert — a viem error or raw revert data — into { errorName, humanMessage, suggestedAction, rawError }, mapping the wallet's custom errors (limits, whitelists, expiry, pause) to plain language. Selectors are computed at load, so they never drift.

Batching & low-level primitives

// Several actions in one atomic transaction:
await agent.execute([
  agent.buildSendToken(usdc, alice, 1_000_000n),
  agent.buildSendNative(bob, parseEther("0.001")),
]);

execute() → tx hash and executeAndWait() → receipt are the low-level primitives (unchanged across versions). build* helpers are pure and return Execution items you can compose. run(action, executions) sends a batch and returns an ActionResult.

Swaps in detail

| Helper | Use for | Router | | --- | --- | --- | | swapExactInputV3 | v3 pools (simplest, widely whitelisted) | SwapRouter02 | | swapV4ExactIn | v4 pools | Universal Router 2.1.1 + Permit2 | | swapViaUniversalRouter | v3 via the classic Universal Router | classic UR + Permit2 |

The router(s) must be in the agent's allowedProtocols and tokenIn in allowedTokens; output returns to the wallet. v4 pools are keyed by (fee, tickSpacing, hooks), so pass tickSpacing (e.g. USDC/WETH on Arbitrum = fee 500, tickSpacing 10). nativeOut: true unwraps WETH to ETH; path enables multi-hop.

The UR and v4 paths use Permit2 funding: approve(token → Permit2) + Permit2.approve(token → router) + execute(... payerIsUser=true). Nothing is transferred blindly, so a wrong router address reverts instead of losing funds. Permit2's address is hardcoded (same on every chain); the Universal Router is preconfigured only on Arbitrum One — pass router on other chains. The v4 encoder is verified byte-for-byte against a real app.uniswap.org swap and validated on Arbitrum One.

Swap execution helpers take addresses; buildSwapPlan, resolveToken, and the balance helpers also accept symbols from the token registry. buildSwapPlan never throws on quote/read failures — it returns the plan with a warning.

API reference

Actions → ActionResult: sendNative · sendToken · approve · swapExactInputV3 · swapV4ExactIn · swapViaUniversalRouter · run

Low-level: executeHex · executeAndWait → receipt · build*Execution[] · encodeExecutions

Reads: getAgentStatus · getCapabilities · getRemaining · getPermission · getNativeBalance · getTokenBalance · getBalances · getDailySpentNative · getTokenSpent · isPaused

Allowances: getErc20Allowance · getPermit2Allowance · needsApproval

Simulate & explain: dryRun · dryRunSendNative · dryRunSendToken · dryRunApprove · dryRunSwapV3 · dryRunSwapV4 · simulateAndExplain · explainFailure

Preflight: canSpendNative · canSpendToken · Planning: buildSwapPlan

Exported helpers: decodeRevert · resolveToken · TOKENS · applySlippage · quoteV3ExactInputSingle · quoteV4ExactInputSingle · NETWORKS · viem re-exports (parseEther, formatUnits, …).

Networks, tokens & fees

Factories share one address on every chain (CREATE2). Built in: Arbitrum One (42161), BNB Chain (56), Ethereum (1), Base (8453), Polygon (137), Arbitrum Sepolia (421614). Pass a full BvccNetwork object, or just rpcUrl, for a custom endpoint.

The token registry (resolveToken, getBalances) holds verified addresses for common tokens per chain (Binance-Peg stables are 18 decimals on BNB Chain). Unknown symbols throw — pass an address. Router/quoter addresses are only set where verified; elsewhere pass them explicitly.

The wallet charges the BVCC agent fee (0.15%) automatically on-chain — you don't encode it; it's separate from your budget accounting and from gas.

For AI-runtime wrappers

The SDK ships a declarative capability catalog at the subpath @bvcc/agent-sdk/catalog — a single, explicit, Zod-typed list of the actions an AI runtime may invoke. Wrappers (the @bvcc/agent-mcp MCP server, and future OpenClaw / ElizaOS adapters) generate their tools from it, so an action is described once and every runtime gets it. Importing the core SDK does not pull in the catalog or Zod.

License

MIT