Skip to main content

Install

npm install @symmetry-hq/sdk @solana/web3.js @coral-xyz/anchor

Initialize the SDK

import { Connection } from "@solana/web3.js";
import { SymmetryCore } from "@symmetry-hq/sdk";

const connection = new Connection("https://api.mainnet-beta.solana.com");
const sdk = new SymmetryCore({
  connection,
  network: "mainnet",
  priorityFee: 50_000,
});

Fetch Vaults

const vaults = await sdk.fetchAllVaults();
console.log(`Found ${vaults.length} vaults`);

const vault = await sdk.fetchVault("<VAULT_PUBKEY>");
console.log(vault.formatted);

Load Prices

Fetching a vault does not include live prices. Call loadVaultPrice to get current oracle prices and compute TVL:
let vault = await sdk.fetchVault("<VAULT_PUBKEY>");
vault = await sdk.loadVaultPrice(vault);

console.log("TVL:", vault.tvl?.toString());
console.log("Token Price:", vault.price?.toString());

for (const asset of vault.formatted!.composition) {
  if (!asset.active) continue;
  console.log(`${asset.mint}: weight=${asset.weight / 100}%`);
}

Set Up a Wallet

For Node.js environments, create a wallet adapter from a keypair:
import { Keypair } from "@solana/web3.js";

const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
const wallet = {
  publicKey: keypair.publicKey,
  signTransaction: async <T>(tx: T): Promise<T> => {
    (tx as any).sign([keypair]);
    return tx;
  },
  signAllTransactions: async <T>(txs: T[]): Promise<T[]> => {
    txs.forEach((tx: any) => tx.sign([keypair]));
    return txs;
  },
  payer: keypair,
};
Never commit private keys to version control. Use environment variables or a secure key management solution.

Create a Vault

const result = await sdk.createVaultTx({
  creator: wallet.publicKey.toBase58(),
  start_price: "1.0",
  name: "My Vault",
  symbol: "MV",
  metadata_uri: "https://arweave.net/your-metadata-json",  // URL to JSON with name, symbol, description, image, cover
});

console.log("Vault mint:", result.mint);
console.log("Vault account:", result.vault);

await sdk.signAndSendTxPayloadBatchSequence({
  txPayloadBatchSequence: result,
  wallet,
});
The metadata_uri should point to a JSON file containing name, symbol, description, image, and cover fields. See Vaults for the full metadata spec. After creation, the vault has no tokens. Add tokens with addOrEditTokenTx and set weights with updateWeightsTx. For Pyth oracle price feed IDs, see Pyth Price Feed IDs. See Vaults for the full workflow.

Deposit into a Vault

const tx = await sdk.buyVaultTx({
  buyer: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_TOKEN_MINT>",
  contributions: [
    { mint: "So11111111111111111111111111111111111111112", amount: 1_000_000_000 },
  ],
  rebalance_slippage_bps: 100,
  per_trade_rebalance_slippage_bps: 100,
});

await sdk.signAndSendTxPayloadBatchSequence({
  txPayloadBatchSequence: tx,
  wallet,
});

const lockTx = await sdk.lockDepositsTx({
  buyer: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_TOKEN_MINT>",
});

await sdk.signAndSendTxPayloadBatchSequence({
  txPayloadBatchSequence: lockTx,
  wallet,
});
After locking, the rebalance is processed: price updates, auctions, and minting. Any wallet may execute these stage methods directly; keeper is an actor role, not a privilege role. See Rebalancing for the full flow.

Common Use Cases

Use CaseHow
Create a multi-token vaultcreateVaultTxaddOrEditTokenTxupdateWeightsTx
Deposit into a vaultbuyVaultTxlockDepositsTx → keeper processes → vault tokens minted
Withdraw from a vaultsellVaultTx → keeper processes → underlying tokens redeemed
Fast withdrawalsellVaultTx with all mints in keep_tokensredeemTokensTx
Read vault datafetchVaultloadVaultPrice → read vault.formatted
Run a keeper botCreate KeeperMonitor and call update() in a loop
Claim feeswithdrawVaultFeesTx

Next Steps