Operate Voltr vaults and every strategy integration from one CLI, plus runnable programmatic examples
All vault operations — setup, deposits/withdrawals, and every supported strategy (Kamino, Spot, Trustful) — now live in a single repository: github.com/voltrxyz/sdk-scripts.It replaces the old per-protocol script repos (kamino-scripts, spot-scripts, trustful-scripts, lend-scripts, drift-scripts, client-raydium-clmm-scripts) with two complementary entry points:
CLI
The recommended interface for vault managers and operators. Every operation is one <group>:<action> command driven by a JSON profile and per-call flags. No source edits to change runtime values.
Programmatic examples
Runnable TypeScript for developers embedding the operation builders directly in their own services, bots, or transaction pipelines. One self-contained file per action.
The CLI and examples both wrap the lower-level @voltr/vault-sdk and the protocol adapter packages. Use the CLI for routine operations; drop down to the SDK or examples when you embed Voltr in your own code.
Driving these operations from a coding agent? The Voltr Agent Skill ships vault-manager-cli.md and vault-manager-sdk.md references plus runnable examples/sdk/ flows (create vault, add adaptor + init strategy, allocate, read state).
Validate the bundled example profile. This is fully offline — no RPC, no keypair, no deployed vault — and the quickest way to confirm your checkout works:
A profile is one JSON file describing one vault deployment: its cluster, asset, optional lookup table, and any integration addresses. Routine operational values live in the profile; per-call values are flags; secrets are never in the profile. The profile is validated with zod on load, so a missing or malformed field fails before any RPC call.
# Copy the example and edit it:cp configs/examples/usdc.mainnet.example.json configs/my-vault.json# vault.assetMintAddress / vault.assetTokenProgram (required)# vault.vaultAddress (leave empty until vault:init prints it)# integrations.<adapter>.* (only the adapters you use)
Commands sign as one of three roles. Each resolves its keypair path from a flag, falling back to an environment variable — the flag wins. If neither is set, the command fails up front naming both.
# .env (gitignored) — copy .env.example and set once:RPC_URL=https://your-rpcADMIN_KEYPAIR=/path/to/admin.jsonMANAGER_KEYPAIR=/path/to/manager.jsonUSER_KEYPAIR=/path/to/user.json
No keypair material lives in profiles — only paths, via flag or env. Keep keypair files outside the repo, restrict permissions (chmod 600), and prefer env vars over flags so secret paths don’t land in shell history. The read-only *:query:* commands and check need no keypair.
The RPC URL resolves in this order (first non-empty wins): --rpc-url flag → RPC_URL env → HELIUS_RPC_URL env → rpcUrl in the profile.
Every transaction command takes --mode (default print). A command builds first (reading chain state over RPC, and the Jupiter API for swaps), then dispatches the mode — so a reachable RPC is required in every mode except check.
Mode
Sends on-chain?
What it does
print(default)
No
Prints { label, instructionCount, lookupTableAddresses } + operation metadata. The no-send preview.
simulate
No
One simulateTransaction RPC; prints OK/FAILED, compute units, program logs, explorer URL.
multisig
No
Emits a base64/base58 transaction message to import into a multisig (e.g. Squads). Requires --multisig-address.
execute
Yes
Signs with the role keypair, sends, confirms; prints the signature and compute units.
Never execute blind. Preview with --mode print, confirm with --mode simulate, then --mode execute. For a multisig-controlled vault, use --mode multisig --multisig-address <VAULT_SIGNER_PDA> and import the printed payload instead of signing locally.
# 1. print: confirm the plan builds and the instruction/LUT counts look rightpnpm cli -- --profile configs/my-vault.json --mode print vault:deposit --amount 1000000# 2. simulate: confirm it would succeed on-chainpnpm cli -- --profile configs/my-vault.json --mode simulate vault:deposit --amount 1000000# 3. execute: send it for realpnpm cli -- --profile configs/my-vault.json --mode execute vault:deposit --amount 1000000
The following assume RPC_URL and the role keypairs are set in .env. Run each with --mode print then --mode simulate before --mode execute.
Initialize a vault
# admin signs; manager is just an address. A fresh vault keypair is generated and its address printed.pnpm cli -- --profile configs/my-vault.json --mode execute \ vault:init --manager <MANAGER_PUBKEY> --name "My USDC Vault" --max-cap 100000000000# Record the printed "Generated vault address" as vault.vaultAddress in the profile.# (alt) init + LP-token metadata in one transaction:pnpm cli -- --profile configs/my-vault.json --mode execute \ vault:init-and-set-token-metadata --manager <MANAGER_PUBKEY> --name "My USDC Vault" \ --max-cap 100000000000 --metadata-name "My USDC Vault Token" --metadata-symbol MYUSDC \ --metadata-uri https://example.com/metadata.json
vault:init cannot use --mode multisig: a fresh vault keypair must sign initialization, which a multisig payload can’t carry. Use --mode execute.
Add an adapter (one-time admin step)
vault:add-adaptor defaults to the Kamino adaptor; pass --adaptor-program for the others.
For automation, bots, and services that embed Voltr directly, the examples/ directory holds runnable TypeScript — one self-contained file per action that imports the public operation builders, inspects a BuiltOperation, and routes it through the shared transaction processor. They are the lower-level programmatic path; the CLI remains the primary interface for routine operations.
# Configure via env (the examples read the same profile + RPC precedence as the CLI):export VOLTR_PROFILE=configs/my-vault.json # default if unsetexport RPC_URL=https://your-rpcexport MANAGER_KEYPAIR=/path/to/manager.json # and/or ADMIN_KEYPAIR / USER_KEYPAIR# List every example with its group, role, and network requirement:pnpm examples:list# Run a file directly (no arguments — config comes from env):pnpm exec tsx examples/src/kamino/market-withdraw.ts# …or by name through the dispatcher:pnpm example -- kamino:market-withdraw
Per-run values (amounts, rates) are clearly marked constants at the top of each file. Every setting has both an env var and an equivalent flag (--profile, --rpc-url, --mode, --multisig-address, --yes); --help lists them.
Examples default to print and never send. execute is gated — type yes at the prompt, or set VOLTR_CONFIRM=1 for non-interactive runs. No secrets are committed: addresses come from your profile, keypairs from env vars.
allocate — sequence builders from more than one package through the shared processor
Examples import only documented package exports (@voltr/scripts-core, @voltr/scripts-kamino, @voltr/scripts-spot, @voltr/scripts-trustful). See examples/README.md for the full catalog and the offline pnpm examples:check verification.