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

@quantulabs/agent-vault

v0.1.0

Published

TypeScript SDK for Agent Vault: multi-wallet PDA management for 8004 agents on Solana.

Readme

Agent Vault SDK

TypeScript SDK for managing Agent Vault PDA wallets for 8004 agents on Solana.

Devnet version.

Program ID: 36u7KMBuxjExvU6V2nfTX5SnNdYMGUupFiYouLzrgpfW

There is no mainnet release yet. Do not use with valuable assets.

Install

Requires Node.js 18+.

npm install github:QuantuLabs/Agent-Vault-SDK 8004-solana @solana/web3.js
# After npm publication:
# npm install @quantulabs/agent-vault 8004-solana @solana/web3.js

8004-solana is only needed by your app to register the agent. Agent Vault starts from the returned agentAsset. See the 8004-solana README for the full registration flow.

Quickstart

Use 8004-solana to get agentAsset, then use Agent Vault for wallets. wallet is the Solana signer you already use in your script or app, with a publicKey and signing support.

import { Connection } from "@solana/web3.js";
import { AgentVaultClient } from "@quantulabs/agent-vault";

const connection = new Connection("https://api.devnet.solana.com", "confirmed");
const agentAsset = "Your8004CoreAssetPubkey...";

const vault = AgentVaultClient.devnet({
  connection,
  signer: wallet,
});

const agent = vault.agent(agentAsset);

// Creates two wallets: one per label.
await agent.wallets.setup({ labels: ["treasury", "trading"] });

const wallets = await agent.wallets.listAll();
console.log(wallets.map((wallet) => [wallet.index, wallet.address.toBase58()]));

// After funding wallet #0 with the printed address:
await agent.wallets.send({ from: 0, to: recipient, sol: "0.0005" });

agentAsset is returned by 8004-solana registration. recipient is an external Solana public key.

Register Agent (8004-solana)

Agent Vault does not register agents. Register with 8004-solana, then pass the returned asset to Agent Vault as agentAsset.

import {
  IPFSClient,
  ServiceType,
  SolanaSDK,
  buildRegistrationFileJson,
} from "8004-solana";

const pinataJwt = process.env.PINATA_JWT;
const ipfs = pinataJwt
  ? new IPFSClient({ pinataEnabled: true, pinataJwt })
  : new IPFSClient({ url: "http://localhost:5001" });
const identity = new SolanaSDK({
  cluster: "devnet",
  signer: wallet,
  ipfsClient: ipfs,
});

const metadata = buildRegistrationFileJson({
  name: "Trading Agent",
  description: "Agent with isolated vault wallets",
  image: "ipfs://...",
  services: [{ type: ServiceType.MCP, value: "https://api.example.com/mcp" }],
  skills: ["natural_language_processing/natural_language_generation/text_completion"],
  domains: ["technology/software_engineering/software_engineering"],
});

const metadataUri = `ipfs://${await ipfs.addJson(metadata)}`;
const registered = await identity.registerAgent(metadataUri);
const agentAsset = registered.asset;
if (!agentAsset) throw new Error("8004 registration did not return an agent asset");

ipfs.addJson() returns a CID, so register with ipfs://<cid>. Set PINATA_JWT or run an IPFS HTTP API on http://localhost:5001. For collection, ATOM options, or richer metadata examples, use the 8004-solana README.

For app code, prefer the scoped API:

const agent = vault.agent(agentAsset);
await agent.wallets.listAll();

Use vault.wallets.* only when you intentionally want to pass agentAsset on every call.

IDs

There are two ids to keep straight:

| Name | Pass this | Meaning | | --- | --- | --- | | agentAsset | Public key or string | The 8004 Core Asset returned by registerAgent. It identifies the agent vault. | | wallet | Number | The wallet index inside that agent vault: 0, 1, 2, ... |

Do not pass the wallet PDA where the SDK asks for agentAsset.

const walletPda = agent.wallets.address(0);

Wallets

Create one wallet:

await agent.wallets.setup({ labels: ["treasury"] });

setup() creates one wallet per label. For example, labels: ["treasury", "trading", "ops"] creates three wallets.

List all wallets for one agent:

const wallets = await agent.wallets.listAll();

for (const wallet of wallets) {
  console.log(wallet.index, wallet.label, wallet.address.toBase58(), wallet.dataStatus);
}

Use pagination for large UIs:

await agent.wallets.list({ startIndex: 0, limit: 100 });
await agent.wallets.listAll({ startIndex: 100 });

Closed or dusted wallet PDAs are hidden by default:

await agent.wallets.listAll({ includeClosed: true });

listAll() reads the vault wallet count, derives every wallet PDA, and fetches accounts in chunks with getMultipleAccountsInfo. It does not require an indexer.

Funding

Most apps can fund Agent Vault wallets directly from any wallet UI, faucet, CLI, or backend transfer. List wallets first, then use the address for deposits.

const wallets = await agent.wallets.listAll();
const treasury = wallets[0];
if (!treasury) throw new Error("treasury wallet missing");

console.log("SOL deposit address:", treasury.address.toBase58());

For SOL, send directly to the wallet address. For SPL and Token-2022, send to the wallet ATA. Create it once if your sender cannot create recipient ATAs.

import { TOKEN_2022_PROGRAM_ID } from "@quantulabs/agent-vault";

await agent.wallets.token({
  action: "createAta",
  wallet: treasury.index,
  mint: splMint,
});
const splDepositAddress = agent.wallets.ataAddress(treasury.index, splMint);
console.log("SPL deposit address:", splDepositAddress.toBase58());

await agent.wallets.token({
  action: "createAta",
  wallet: treasury.index,
  mint: token2022Mint,
  tokenProgram: TOKEN_2022_PROGRAM_ID,
});
const token2022DepositAddress = agent.wallets.ataAddress(
  treasury.index,
  token2022Mint,
  TOKEN_2022_PROGRAM_ID,
);
console.log("Token-2022 deposit address:", token2022DepositAddress.toBase58());

Once the addresses exist, anyone can transfer SOL or tokens to them. Agent Vault authorization is only needed to move funds out.

Token-2022 mints with hooks, confidential transfers, frozen accounts, or non-transferable rules may require mint-specific handling outside this SDK.

Writes

High-level outbound methods sign, send, and confirm when the client has a signer:

await agent.wallets.send({ from: 0, to: 1, sol: "0.0001" });
await agent.wallets.send({ from: 0, to: recipient, sol: "0.0005" });
await agent.wallets.send({ from: 0, to: tokenAccount, mint, tokens: "12.5" });

Use sol and tokens in app code. Use raw lamports and baseUnits only when you explicitly need integer units. For token sends, mint is the SPL mint and to is either another wallet index or a destination token account.

External Signing

This is only for apps that prepare a transaction in one place and sign it elsewhere, for example a browser wallet, custody flow, or multisig. Normal scripts with AgentVaultClient.devnet({ signer: wallet }) can ignore this.

Example: prepare a withdrawal from wallet #0, let the user's wallet sign it, then send it yourself:

const plan = await agent.wallets.send({
  from: 0,
  to: recipient,
  sol: "0.0005",
  holder: wallet.publicKey,
  feePayer: wallet.publicKey,
  send: false,
  sign: false,
});

const signedTx = await wallet.signTransaction(plan.transaction);
const simulation = await connection.simulateTransaction(signedTx);
if (simulation.value.err) throw new Error(JSON.stringify(simulation.value.err));

const signature = await connection.sendRawTransaction(signedTx.serialize());
const confirmation = await connection.confirmTransaction(signature, "confirmed");
if (confirmation.value.err) throw new Error(JSON.stringify(confirmation.value.err));

holder is the current 8004 Core Asset owner that must authorize funds moving out. feePayer is the account paying the Solana transaction fee. The SDK still runs deployment and mainnet guards before returning the unsigned transaction.

Deployment Safety

Signed writes fail closed unless the configured release manifest and live deployment verify. AgentVaultClient.devnet(...) uses the bundled devnet manifest. Check it explicitly when debugging:

const verification = await vault.wallets.verifyDeployment();

if (!verification.ok) {
  throw new Error(verification.issues.join("\n"));
}

Use allowUnverifiedDeployment only as a client option for local or controlled devnet testing.

Development

npm install
NO_DNA=1 npm run check
NO_DNA=1 npm run e2e:devnet
NO_DNA=1 npm run pack:dry-run

e2e:devnet is preflight-only unless AGENT_VAULT_E2E_SEND=1 is set.