After creating your vault, you need to set up strategies so funds can be deployed to DeFi protocols. This is a two-step process:
- Add the adaptor to your vault (one-time per adaptor program, you may skip this if you have done so on the UI)
- Initialize the strategy for each specific protocol/market you want to deploy to
Vault creation ≠ Strategy initialization. A newly created vault has no strategies. Deposited funds will sit idle until you complete the steps in this guide.
Key Concepts
Adaptors vs. Strategies
- Adaptor: An on-chain program that knows how to interact with a category of protocols (e.g., the Kamino adaptor interacts with Kamino, Drift adaptor interacts with Drift…)
- Strategy: A specific deployment target within an adaptor (e.g., “lend USDC on Kamino Main Market”)
A vault can have multiple strategies across multiple adaptors.
Adaptor Program IDs
Each adaptor has a unique on-chain program ID:
import {
LENDING_ADAPTOR_PROGRAM_ID,
DRIFT_ADAPTOR_PROGRAM_ID,
} from "@voltr/vault-sdk";
| Adaptor | Program ID |
|---|
| Lending Adaptor | aVoLTRCRt3NnnchvLYH6rMYehJHwM5m45RmLBZq7PGz |
| Drift Adaptor | EBN93eXs5fHGBABuajQqdsKRkCgaqtJa8vEFD6vKXiP |
| Kamino Adaptor | to6Eti9CsC5FGkAtqiPphvKD2hiQiLsS8zWiDBqBPKR |
LENDING_ADAPTOR_PROGRAM_ID and DRIFT_ADAPTOR_PROGRAM_ID are exported directly from the SDK. For other adaptors (Kamino, Jupiter, Raydium, Trustful), check the respective script repositories for their program IDs.
Available Strategies
| Strategy Type | Adaptor | Protocols | Guide |
|---|
| Lending | Lending Adaptor | Kamino, Marginfi, Save, Drift Spot, Jupiter Lend | See scripts below |
| Drift Perps/JLP | Drift Adaptor | Drift Protocol | See scripts below |
| Raydium CLMM | Raydium Adaptor | Raydium | See scripts below |
| Off-chain | Trustful Adaptor | CEX, OTC, MPC | See scripts below |
Step 1: Add Adaptor
Before initializing any strategy, you must add the corresponding adaptor program to your vault. This is a one-time operation per adaptor type.
import { VoltrClient } from "@voltr/vault-sdk";
import {
Connection,
Keypair,
PublicKey,
sendAndConfirmTransaction,
} from "@solana/web3.js";
import fs from "fs";
const connection = new Connection("your-rpc-url");
const client = new VoltrClient(connection);
const adminKp = Keypair.fromSecretKey(
Uint8Array.from(JSON.parse(fs.readFileSync("/path/to/admin.json", "utf-8")))
);
const vault = new PublicKey("your-vault-pubkey");
const adaptorProgramId = new PublicKey("adaptor-program-id");
const addAdaptorIx = await client.createAddAdaptorIx({
vault,
admin: adminKp.publicKey,
payer: adminKp.publicKey,
adaptorProgram: adaptorProgramId,
});
const txSig = await sendAndConfirmTransaction(
[addAdaptorIx],
connection,
[adminKp]
);
console.log("Adaptor added:", txSig);
Step 2: Initialize Strategy
Strategy initialization is protocol-specific — each protocol requires different remaining accounts and an instructionDiscriminator.
Generic Code Snippet
import { VoltrClient } from "@voltr/vault-sdk";
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
const connection = new Connection("your-rpc-url");
const client = new VoltrClient(connection);
const adminKp = Keypair.fromSecretKey(/* ... */);
const managerKp = Keypair.fromSecretKey(/* ... */);
const vault = new PublicKey("your-vault-pubkey");
const strategy = new PublicKey("strategy-pda");
const adaptorProgram = new PublicKey("adaptor-program-id");
const instructionDiscriminator = Buffer.from([/* 8-byte discriminator */]);
const initStrategyIx = await client.createInitializeStrategyIx(
{
instructionDiscriminator,
},
{
payer: adminKp.publicKey,
manager: managerKp.publicKey,
vault,
strategy,
adaptorProgram,
remainingAccounts: [
// Protocol-specific accounts
],
}
);
const txSig = await sendAndConfirmTransaction(
[initStrategyIx],
connection,
[adminKp]
);
The instructionDiscriminator, strategy address, and remainingAccounts are all protocol-specific. Use the initialization scripts from the protocol repositories below as reference implementations.
Protocol-Specific Initialization Scripts