Policy builders are helper functions that construct PolicyConfig objects for common strategy execution scenarios. A policy must exist onchain before any strategy instruction can be executed by the vault.
What is a Policy?
A programInteraction policy defines exactly which instructions the vault’s smart account is permitted to execute. It is enforced onchain by the Squads program when executeTransactionSync is called.
A policy consists of:
instructionsConstraints — a list of InstructionConstraint objects, each specifying:
programId — which program is allowed
dataConstraints — which instruction discriminators match (first 8 bytes of instruction data)
accountConstraints — which specific public keys must be present
Adding a Policy to a Vault
Policies are added by the vault manager role:
import {
ExponentVault,
createKaminoDepositPolicy,
KAMINO_MARKETS,
KAMINO_RESERVES,
KaminoMarket,
} from "@exponent-labs/exponent-sdk";
import { Connection, Transaction, sendAndConfirmTransaction } from "@solana/web3.js";
const connection = new Connection("https://api.mainnet-beta.solana.com");
const vault = await ExponentVault.load({ connection, address: vaultAddress });
const solReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["SOL"].pubkey;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];
// Build the policy config
const policyConfig = createKaminoDepositPolicy({
allowedReserves: [solReserve],
allowedLendingMarkets: [mainMarket],
});
// Add it to the vault — requires payer, squads program, policy seed, and transaction index
const ix = vault.ixAddPolicy({
payer: managerWallet.publicKey,
policyConfig,
squadsProgram: squadsProgram,
nextPolicySeed: nextPolicySeed,
nextTransactionIndex: nextTransactionIndex,
});
const tx = new Transaction().add(ix);
await sendAndConfirmTransaction(connection, tx, [managerWallet]);
Exponent Core Policy
createCorePolicy builds a policy that permits strip and merge operations on the Exponent Core program (ExponentnaRg3CQbW6dqQNZKXp7gtZ9DGMp1cwC4HAS7).
import { createCorePolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";
const EXPONENT_VAULT = new PublicKey("...");
const policyConfig = createCorePolicy({
allowedVaults: [EXPONENT_VAULT],
actions: ["strip", "merge"],
});
Parameters
| Parameter | Type | Description |
|---|
allowedVaults | PublicKey[] | Optional. Exponent Core vault addresses to constrain |
allowedSyMints | PublicKey[] | Optional. SY mint public keys — use with vaultsForSyMints |
vaultsForSyMints | PublicKey[] | Optional. Vault addresses corresponding to each SY mint (same order as allowedSyMints) |
actions | CorePolicyAction[] | Which actions to allow: "initializeYieldPosition", "strip", "merge" |
spendingLimits | SpendingLimit[] | Optional. Spending limits |
threshold | number | Optional. Number of signers required (default 1) |
timeLock | number | Optional. Time lock in seconds (default 0) |
You can constrain by vault address directly (allowedVaults) or by SY mint (allowedSyMints + vaultsForSyMints). If you omit both, any vault is allowed for the specified actions.
See Core Instructions for usage examples.
Exponent CLMM Policy
createClmmPolicy builds a policy that permits all CLMM operations on the Exponent CLMM program (XPC1MM4dYACDfykNuXYZ5una2DsMDWL24CrYubCvarC) — including providing liquidity, trading PT/YT, and claiming farm emissions.
import { createClmmPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";
const CLMM_MARKET = new PublicKey("...");
const policyConfig = createClmmPolicy({
allowedMarkets: [CLMM_MARKET],
});
Parameters
| Parameter | Type | Description |
|---|
allowedMarkets | PublicKey[] | Optional. CLMM MarketThree addresses to constrain — omit to allow any market |
threshold | number | Optional. Number of signers required (default 1) |
timeLock | number | Optional. Time lock in seconds (default 0) |
Omitting allowedMarkets permits CLMM operations on any market. Specify market addresses to restrict the vault to specific pools.
See CLMM Instructions for usage examples.
Exponent Orderbook Policy
createOrderbookPolicy builds a policy that permits interacting with the Exponent Orderbook program (XPBookgQTN2p8Yw1C2La35XkPMmZTCEYH77AdReVvK1).
import { createOrderbookPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";
const SY_MINT = new PublicKey("...");
const policyConfig = createOrderbookPolicy({
allowedSyMints: [SY_MINT],
actions: ["postOffer", "marketOffer", "removeOffer", "withdrawFunds"],
});
Parameters
| Parameter | Type | Description |
|---|
allowedSyMints | PublicKey[] | SY mint public keys that are allowed |
actions | OrderbookPolicyAction[] | Which actions to allow: "postOffer", "marketOffer", "removeOffer", "withdrawFunds" |
spendingLimits | SpendingLimit[] | Optional. Spending limits |
threshold | number | Optional. Number of signers required (default 1) |
timeLock | number | Optional. Time lock in seconds (default 0) |
See Orderbook Instructions for usage examples.
Kamino Lend Policies
Deposit Policy
createKaminoDepositPolicy builds a policy that permits calling depositReserveLiquidityAndObligationCollateral on the Kamino Lending program.
import { createKaminoDepositPolicy } from "@exponent-labs/exponent-sdk";
const policyConfig = createKaminoDepositPolicy({
allowedReserves: [solReserve],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description |
|---|
allowedReserves | PublicKey[] | Reserve public keys that can receive deposits |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys |
Withdraw Policy
createKaminoWithdrawPolicy builds a policy that permits calling withdrawObligationCollateralAndRedeemReserveCollateral on the Kamino Lending program.
import { createKaminoWithdrawPolicy } from "@exponent-labs/exponent-sdk";
const policyConfig = createKaminoWithdrawPolicy({
allowedReserves: [solReserve],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description |
|---|
allowedReserves | PublicKey[] | Reserve public keys allowed as withdrawal sources |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys |
Borrow Policy
createKaminoBorrowPolicy builds a policy that permits calling borrowObligationLiquidity on the Kamino Lending program.
import { createKaminoBorrowPolicy } from "@exponent-labs/exponent-sdk";
const policyConfig = createKaminoBorrowPolicy({
allowedReserves: [solReserve],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description |
|---|
allowedReserves | PublicKey[] | Reserve public keys allowed for borrowing |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys |
Repay Policy
createKaminoRepayPolicy builds a policy that permits calling repayObligationLiquidity on the Kamino Lending program.
import { createKaminoRepayPolicy } from "@exponent-labs/exponent-sdk";
const policyConfig = createKaminoRepayPolicy({
allowedReserves: [solReserve],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description |
|---|
allowedReserves | PublicKey[] | Reserve public keys allowed for repayment |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys |
Full Access Policy
createKaminoFullAccessPolicy creates a single policy covering multiple Kamino actions. This is useful when a strategy requires deposit, withdraw, borrow, and repay on the same reserves.
import {
createKaminoFullAccessPolicy,
KAMINO_MARKETS,
KAMINO_RESERVES,
KaminoMarket,
} from "@exponent-labs/exponent-sdk";
const solReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["SOL"].pubkey;
const usdcReserve = KAMINO_RESERVES[KaminoMarket.MAIN]["USDC"].pubkey;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];
const policyConfig = createKaminoFullAccessPolicy({
allowedReserves: [solReserve, usdcReserve],
allowedActions: ["deposit", "withdraw", "borrow", "repay"],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description | | | |
|---|
allowedReserves | PublicKey[] | Reserve public keys allowed for all specified actions | | | |
allowedActions | `(“deposit" | "withdraw" | "borrow" | "repay”)[]` | Which Kamino actions to permit |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys | | | |
Using a combined policy simplifies vault administration when a strategy requires multiple operations on the same reserves. The allocator passes the same policyPda to all Kamino calls.
Unified Kamino Policy
createKaminoPolicy is a unified API that supports both allowedReserves and allowedDepositMints as optional constraints. This provides finer-grained control than createKaminoFullAccessPolicy — you can constrain by the liquidity mint in addition to (or instead of) the reserve address.
import {
createKaminoPolicy,
KAMINO_MARKETS,
KAMINO_RESERVES,
KaminoMarket,
} from "@exponent-labs/exponent-sdk";
const usdcMint = KAMINO_RESERVES[KaminoMarket.MAIN]["USDC"].mint;
const mainMarket = KAMINO_MARKETS[KaminoMarket.MAIN];
const policyConfig = createKaminoPolicy({
allowedDepositMints: [usdcMint],
actions: ["deposit", "withdraw"],
allowedLendingMarkets: [mainMarket],
});
Parameters
| Parameter | Type | Description |
|---|
allowedReserves | PublicKey[] | Optional. Reserve public keys to constrain |
allowedDepositMints | PublicKey[] | Optional. Liquidity mint public keys to constrain |
actions | KaminoPolicyAction[] | Which actions to allow: "deposit", "withdraw", "borrow", "repay" |
allowedLendingMarkets | PublicKey[] | Optional. Lending market public keys |
spendingLimits | SpendingLimit[] | Optional. Spending limits |
threshold | number | Optional. Number of signers required (default 1) |
timeLock | number | Optional. Time lock in seconds (default 0) |
Both allowedReserves and allowedDepositMints are optional. Omit both to allow any reserve and mint for the specified actions.
Titan Swap Policy
createTitanSwapPolicy builds a policy that permits calling SwapRouteV2 on the Titan program (T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT).
import { createTitanSwapPolicy } from "@exponent-labs/exponent-sdk";
import { PublicKey } from "@solana/web3.js";
const USDC_MINT = new PublicKey("...");
const SOL_MINT = new PublicKey("...");
const policyConfig = createTitanSwapPolicy({
allowedMints: [USDC_MINT, SOL_MINT],
});
Parameters
| Parameter | Type | Description |
|---|
allowedMints | PublicKey[] | Optional. Token mints to constrain — applies to both input and output mints |
threshold | number | Optional. Number of signers required (default 1) |
timeLock | number | Optional. Time lock in seconds (default 0) |
The allowedMints constraint applies to both the input mint and the output mint of the swap. Omitting it permits swaps between any tokens.
See Titan Instructions for usage examples.