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

@agent-fuel/sdk

v0.3.2

Published

TypeScript SDK for Agent Fuel — credit vault + reputation primitives for AI agents on Solana.

Readme

@agent-fuel/sdk

TypeScript SDK for Agent Fuel — credit vault + reputation primitives for AI agents on Solana.

Status: 0.3.0. Full read/write/stream surface live, plus the agent-fuel CLI. Published to npm with provenance.

CLI

Installing the package also installs an agent-fuel binary. Read commands work with zero setup over npx:

npx @agent-fuel/sdk vault   <OWNER_PUBKEY> <AGENT_PUBKEY>
npx @agent-fuel/sdk score   <AGENT_PUBKEY>
npx @agent-fuel/sdk policy  <OWNER_PUBKEY> <AGENT_PUBKEY>
npx @agent-fuel/sdk service <AUTHORITY_PUBKEY>

Action commands take a solana-keygen-style keypair JSON:

agent-fuel pay \
  --keypair         ~/.config/solana/agent.json \
  --service-keypair ~/.config/solana/svc-pyth.json \
  --owner           <OWNER_PUBKEY> \
  --amount          0.5

agent-fuel request-spend \
  --keypair ~/.config/solana/agent.json \
  --owner   <OWNER_PUBKEY> \
  --service <SERVICE_PUBKEY> \
  --amount  30

agent-fuel register-service \
  --sponsor         ~/.config/solana/id.json \
  --service-keypair ~/.config/solana/svc-pyth.json \
  --name            "Pyth BTC Feed" \
  --category        DataFeed

Plus agent-fuel keygen [--out path] to generate a fresh keypair (pubkey to stdout, secret to stderr — redirect with 2> to save). Global flags: --cluster devnet|mainnet-beta|testnet|localnet, --rpc <url>, --api-base <url>, --json for machine-readable output.

The six functions

| Function | Returns | What it does | | --- | --- | --- | | fuel.spend({ service, amountUsdc }) | { signature } | Pays a service from the agent's vault. Local six-check policy guardrail, then a single signed transaction. Idempotently creates the service's USDC ATA if needed. | | fuel.getScore(agent?) | ReputationLookup | Public reputation snapshot via REST. Score is null for unscored agents. | | fuel.getVaultBalance(ref?) | CreditVaultAccount | On-chain credit vault state with a derived balance field. Defaults to the agent's own vault when owner was passed to the constructor. | | fuel.getPolicy(ref?) | SpendPolicyAccount | On-chain spend policy: per-tx / hourly / lifetime caps, whitelist, freeze flag. | | fuel.checkService(serviceAuthority) | ServiceRegistryAccount | Service registry lookup by the registering wallet's pubkey. | | fuel.onEvent(callback, options?) | Subscription | WebSocket stream of events for an agent. Auto-reconnect with backoff. |

Plus one fetch wrapper for the x402 protocol — see Paying with x402 below.

Install

npm install @agent-fuel/sdk @solana/web3.js @coral-xyz/anchor

@solana/web3.js and @coral-xyz/anchor are peer dependencies; pin them yourself so your bot and the SDK share the same RPC client.

Usage

import { Keypair, PublicKey } from "@solana/web3.js";
import { AgentFuel } from "@agent-fuel/sdk";

const agent = Keypair.generate(); // load yours from a keystore

const fuel = new AgentFuel({
  agent,
  owner: new PublicKey("..."),      // the wallet that funded your vault
  cluster: "devnet",
  rpc: "https://api.devnet.solana.com",
  apiBase: "https://api.agentfuel.online", // your Agent Fuel backend
});

owner is optional. When you pass it, the agent-side methods (getVaultBalance, getPolicy, spend) default to your own vault — call them with no args. Pass owner per call only when inspecting someone else's vault. Calling a method that needs the owner without configuring one anywhere throws OwnerNotConfiguredError.

Read methods

// Public reputation snapshot (REST, no auth). Omit the arg to read your own.
const score = await fuel.getScore();
const otherScore = await fuel.getScore(otherAgentPubkey);

// On-chain credit vault state. With `owner` set on the constructor, no args
// reads your own vault. Pass a ref to inspect someone else's.
const vault = await fuel.getVaultBalance();
console.log(vault.balance, vault.frozen);
const otherVault = await fuel.getVaultBalance({ owner: otherOwner, agent: otherAgent });

// Same shape for the policy.
const policy = await fuel.getPolicy();

// Service registry lookup by the service's authority pubkey.
const service = await fuel.checkService(serviceAuthorityPubkey);

All methods throw AccountNotFoundError when the target doesn't exist on-chain (or returns 404 from the backend), and HttpError for non-2xx REST responses. Field names mirror the on-chain layout in snake_case so they line up with the backend's REST responses.

Paying a service

const { signature } = await fuel.spend({
  service: serviceAuthorityPubkey,
  amountUsdc: 250_000,              // micro-USDC (0.25 USDC)
});

spend() fetches the current vault + policy and applies the same six-check ladder the on-chain program enforces (programs/credit_vault/src/policy.rs) before submitting. Each policy failure surfaces as a typed error so the caller can branch on it without parsing strings:

| Error | When | | --- | --- | | VaultFrozenError | vault.frozen === true | | ZeroAmountError | amountUsdc <= 0 | | NotWhitelistedError | Whitelist is set and service isn't in it | | PerTxLimitExceededError | amountUsdc > policy.per_tx_limit_usdc | | HourlyLimitExceededError | Rolling 9 000-slot window would exceed policy.hourly_limit_usdc | | LifetimeLimitExceededError | vault.total_spent + amountUsdc > policy.lifetime_limit_usdc |

All six inherit from SpendPolicyError for a single catch-all. The same exceptions are thrown for chain-side failures too — if the on-chain VaultError lands between the pre-flight and the transaction (concurrent spend, window roll-over), the SDK maps the Anchor error code back to the matching typed error so your try/catch doesn't have to branch on where the rejection came from.

The service's USDC associated token account is created on-demand — the SDK prepends an idempotent ATA-create instruction before every spend, so callers don't need to pre-flight whether the service has ever received USDC. The agent pays the rent (~0.002 SOL).

Live events

const sub = fuel.onEvent(
  (frame) => {
    // frame.event_name is one of: Spent, Claimed, ScoreComputed, Deposited, ...
    console.log(frame.event_name, frame.payload);
  },
  { onStatus: (s) => console.log("ws:", s) },
);

// later
sub.close();

onEvent() opens a WebSocket to /ws/agents/:pk on the configured apiBase, parses each JSON frame into a typed LiveEventFrame, and fires callback for every event the backend broadcasts for that agent. Connection status flows through onStatus: connecting → open → reconnecting → open → … → closed. Reconnect uses exponential backoff (1 s → 2 s → 4 s → …, capped at 30 s) and the subscription survives transient network failures until you call sub.close().

By default it subscribes to your own agent. Pass { agent } to watch a different agent.

Runtime note: the SDK prefers globalThis.WebSocket (browsers, Node 22+) and falls back to the ws package for older Node, resolved lazily so browser bundlers don't pull ws in.

Paying with x402

paymentRequired(fuel, options?) returns a fetch-shaped function that transparently handles HTTP 402:

import { paymentRequired } from "@agent-fuel/sdk";

const fetchWithPayments = paymentRequired(fuel, {
  onPaymentRequired: (req) => console.log("paying", req.amountUsdc, "to", req.recipient),
  onPaid: (sig) => console.log("signature:", sig),
});

const res = await fetchWithPayments("https://data.example/feed");
const body = await res.json();

Flow:

  1. The wrapped request runs.
  2. If the response is 402, the SDK parses the X-Payment-Required header (JSON; or the response body as a fallback) for recipient and amountUsdcpayTo/maxAmountRequired are accepted as aliases for x402-spec servers.
  3. fuel.spend() is called with those values. All six policy guardrails apply; any failure throws the matching SpendPolicyError and the request is not retried.
  4. The original request is retried once with X-Payment: <signature>.

A second 402 propagates to the caller (no infinite loop). Malformed payment payloads throw PaymentParseError.

There's a runnable example under examples/x402-quickstart/ with both a dry-run mode (no Solana, 5-second smoke) and a real-devnet mode.

Program IDs

Re-exported from the vendored IDLs (see src/idl/):

import { PROGRAM_IDS } from "@agent-fuel/sdk";

PROGRAM_IDS.reputation; // PublicKey
PROGRAM_IDS.creditVault; // PublicKey

IDL access

Raw IDLs are exposed under sub-paths for downstream tooling (e.g. Anchor's Program constructor):

import reputationIdl from "@agent-fuel/sdk/idl/reputation";
import creditVaultIdl from "@agent-fuel/sdk/idl/credit-vault";

Development

npm install
npm run typecheck
npm run lint
npm run build        # emits dist/ (ESM + CJS + .d.ts) via tsup

Bootstrapping a devnet sandbox

npm run devnet:bootstrap provisions a complete devnet environment in one command: deploys a test USDC mint, mints initial supply to the owner, registers a service, initializes an agent profile, creates + funds a vault, and verifies the whole graph by reading it back through the SDK.

npm run build           # bootstrap imports from dist/
npm run devnet:bootstrap

Defaults to the Solana CLI keypair at ~/.config/solana/id.json as the owner-agent identity (needs ~0.05 SOL on devnet — solana airdrop 1 --url devnet if low). Generates the service + mint keypairs under ~/.config/agent-fuel/, idempotently — reruns after a partial failure are safe.

The script writes a devnet-config.json manifest with every pubkey + path, and prints the exact env-var block to copy into the x402-quickstart example for a real end-to-end spend() against devnet.

Refreshing the IDLs

The IDLs under src/idl/ are committed copies — the SDK build, CI, and downstream consumers never depend on anchor build. When the Anchor programs change, re-vendor manually and commit:

# at repo root
anchor build
# in clients/sdk/
npm run vendor-idl
git add src/idl/

Releasing

Releases are tag-driven. The SDK Release workflow publishes to npm with provenance on any sdk-v* tag push, and refuses to publish if the tag, package.json version, and CHANGELOG.md don't all agree.

# 1. bump version in package.json + add a `## [x.y.z]` section to CHANGELOG.md
# 2. commit
git commit -am "release(sdk): v0.1.1"
# 3. tag + push
git tag sdk-v0.1.1
git push --follow-tags
# 4. (after publish lands) bump the pin in clients/web/package.json

The workflow needs the repo secret NPM_TOKEN (an automation token with publish rights to the @agent-fuel scope). Provenance attestation is handled by GitHub OIDC — no extra config needed beyond the id-token: write permission already in the workflow.