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

@symmetry-hq/sdk

v1.0.18

Published

Symmetry V3 SDK

Downloads

1,787

Readme

@symmetry-hq/sdk

TypeScript SDK for the Symmetry V3 protocol on Solana — on-chain infrastructure for creating and managing multi-token vaults with automated rebalancing, oracle-based pricing, and permissionless keeper execution.

Documentation | LLMs.txt | App | Discord

Have questions or need help integrating? Join our Discord.

Installation

npm install @symmetry-hq/sdk

Peer Dependencies

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

Quick Start

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, // optional, micro-lamports (default: 25,000)
});

// Fetch all vaults
const vaults = await sdk.fetchAllVaults();

// Fetch a single vault and load its price
let vault = await sdk.fetchVault("<VAULT_PUBKEY>");
vault = await sdk.loadVaultPrice(vault);
console.log(vault.formatted);

Core Concepts

Vaults

A vault is an on-chain account that holds a configurable set of SPL tokens with target weights. Each vault:

  • Holds multiple SPL tokens with individually configurable target weights
  • Mints its own SPL token — vault token holders have proportional ownership of the underlying tokens
  • Supports multi-source oracle pricing (Pyth, Raydium CPMM; Raydium CLMM and Switchboard are currently disabled) with configurable aggregation
  • Has a flexible fee structure (deposit, withdrawal, management, performance) split across creator, host platform, managers, and protocol. Management and performance fees are currently disabled at the protocol level.
  • Supports up to 100 tokens, 10 managers, and 4 oracle sources per token

Intents

All configuration changes to a vault go through an intent system. An intent is an on-chain change request — editing fees, metadata, token composition, weights, etc. — with optional time-locks and bounty incentives for keepers to execute them.

Rebalance Intents

Deposits, withdrawals, and periodic rebalances are processed through the same on-chain flow. They progress through a multi-step auction:

  1. Deposit tokens — user contributes tokens to the vault
  2. Lock deposits — freezes contributions and starts the process
  3. Price updates — oracle prices are refreshed on-chain
  4. Auction — keepers execute flash swaps to settle the vault toward target weights
  5. Mint / Redeem — vault tokens are minted (deposits) or underlying tokens are released (withdrawals)
  6. Claim bounty — keepers collect their rewards

Keepers

Keepers are off-chain agents that monitor the protocol, execute pending tasks (intents, price updates, auctions), and earn bounties. All keeper operations are permissionless — developers can build custom keeper bots using the SDK's transaction-building methods. The SDK also ships with KeeperMonitor and RebalanceHandler as reference implementations that work out of the box.


API Reference

Constructor

const sdk = new SymmetryCore({
  connection: Connection,     // Solana RPC connection
  network: "devnet" | "mainnet",
  priorityFee?: number,       // compute unit price in micro-lamports (default: 25,000)
});

Configuration

setPriorityFee(priorityFee: number): void

Updates the priority fee for all subsequent transactions.

fetchGlobalConfig(): Promise<GlobalConfig>

Returns the protocol-wide configuration account (fee limits, bounty settings, rebalance parameters).


Fetching Vaults

fetchVault(vaultPubkey: string): Promise<Vault>

Fetch a single vault by its account public key.

fetchMultipleVaults(vaultPubkeys: string[]): Promise<Map<string, Vault>>

Batch-fetch multiple vaults. Returns a map keyed by public key.

fetchAllVaults(filter?: VaultFilter): Promise<Vault[]>

Fetch all vaults on-chain with an optional role filter:

type VaultFilter = {
  type: "creator" | "host" | "manager";
  pubkey: string;
};

fetchCreatedVaults(creatorPubkey: string): Promise<Vault[]>

Fetch vaults created by a specific public key.

fetchHostedVaults(hostPubkey: string): Promise<Vault[]>

Fetch vaults hosted by a specific public key.

fetchManagedVaults(managerPubkey: string): Promise<Vault[]>

Fetch vaults managed by a specific public key.

fetchVaultsFromMints(mints: string[]): Promise<Map<string, Vault>>

Look up vaults by their SPL token mint addresses. Returns a map keyed by mint.

deriveVaultsByMints(mints: string[]): Promise<Map<string, string>>

Derive vault account addresses from mint addresses without RPC calls. Returns a mint-to-pubkey map.

loadVaultPrice(vault: Vault): Promise<Vault>

Loads live oracle prices for all tokens in the vault, computes the vault's total value, and returns the updated object.


Fetching Intents

fetchIntent(intentPubkey: string): Promise<Intent>

Fetch a single intent by its public key.

fetchMultipleIntents(intentPubkeys: string[]): Promise<Map<string, Intent>>

Batch-fetch multiple intents.

fetchAllIntents(filter?: IntentFilter): Promise<Intent[]>

Fetch all intents with an optional filter:

type IntentFilter = {
  type: "manager" | "vault";
  pubkey: string;
};

fetchCreatedIntents(creatorPubkey: string): Promise<Intent[]>

Fetch intents created by a specific manager.

fetchVaultIntents(vaultPubkey: string): Promise<Intent[]>

Fetch all intents for a specific vault.


Fetching Rebalance Intents

fetchRebalanceIntent(pubkey: string): Promise<UIRebalanceIntent>

Fetch a single rebalance intent.

fetchMultipleRebalanceIntents(pubkeys: string[]): Promise<Map<string, UIRebalanceIntent>>

Batch-fetch multiple rebalance intents.

fetchAllRebalanceIntents(filter?: RebalanceIntentFilter): Promise<UIRebalanceIntent[]>

Fetch all rebalance intents with an optional filter:

type RebalanceIntentFilter = {
  type: "owner" | "vault";
  pubkey: string;
};

fetchOwnerRebalanceIntents(ownerPubkey: string): Promise<UIRebalanceIntent[]>

Fetch rebalance intents owned by a specific public key.

fetchVaultRebalanceIntents(vaultPubkey: string): Promise<UIRebalanceIntent[]>

Fetch rebalance intents for a specific vault.


Fetching Fee Accounts

fetchWithdrawVaultFees(pubkey: string): Promise<WithdrawVaultFees>

Fetch a single fee withdrawal account.

fetchMultipleWithdrawVaultFees(pubkeys: string[]): Promise<Map<string, WithdrawVaultFees>>

Batch-fetch multiple fee withdrawal accounts.

fetchAllWithdrawVaultFees(filter?: WithdrawVaultFeesFilter): Promise<WithdrawVaultFees[]>

Fetch all fee withdrawal accounts with an optional filter:

type WithdrawVaultFeesFilter = {
  type: "vault" | "manager" | "creator" | "host" | "symmetry";
  pubkey: string;
};

Convenience methods: fetchVaultWithdrawVaultFees, fetchManagerWithdrawVaultFees, fetchCreatorWithdrawVaultFees, fetchHostWithdrawVaultFees, fetchSymmetryWithdrawVaultFees.


Creating Vaults

createVaultTx(params): Promise<VaultCreationTx>

Creates a new vault. Returns the vault's token mint, account address, and the transaction payload.

The metadata_uri is a URL (max 200 chars) pointing to a JSON file describing the vault. It should contain name (vault token name), symbol (vault token ticker), description (vault description), image (token image/icon URL), and cover (vault cover image URL). You can add any extra fields for your own integrations (social links, website, etc.):

{
  "name": "My Vault",
  "symbol": "MVT",
  "description": "A multi-token vault.",
  "image": "https://arweave.net/token-image-url",
  "cover": "https://arweave.net/cover-image-url"
}
const result = await sdk.createVaultTx({
  creator: wallet.publicKey.toBase58(),
  start_price: "1.0",    // initial price in USDC
  name: "My Vault",
  symbol: "MVT",
  metadata_uri: "https://arweave.net/your-metadata-json",  // URL to JSON with name, symbol, description, image, cover
  host_platform_params: {            // optional
    host_pubkey: "<HOST_PUBKEY>",
    host_deposit_fee_bps: 10,        // 0.1%
    host_withdraw_fee_bps: 10,
    host_management_fee_bps: 0,      // currently disabled in global config
    host_performance_fee_bps: 0,     // currently disabled in global config
  },
});

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

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

Editing Vault Settings

All edit methods create an intent that modifies the vault. If the setting has no modification delay and no scheduled activation, the intent is executed immediately in the same transaction.

Each method accepts a TaskContext and a settings object, returning a TxPayloadBatchSequence:

interface TaskContext {
  vault: string;               // vault public key
  manager: string;             // authorized manager public key
  activation_timestamp?: number; // optional scheduled activation (unix seconds)
  expiration_timestamp?: number; // optional expiration
  min_bounty?: number;         // optional min bounty override
  max_bounty?: number;         // optional max bounty override
}

| Method | Settings Type | Description | |--------|--------------|-------------| | editCreatorTx | EditCreatorSettings | Transfer vault creator role | | editManagersTx | EditManagerSettings | Edit managers, weights, and authority bitmasks | | editFeesTx | EditFeeSettings | Update fee structure | | editScheduleTx | EditScheduleSettings | Configure repeating time cycles that gate deposits, automation, and management windows | | editAutomationTx | EditAutomationSettings | Configure rebalance automation | | editLpTx | EditLpSettings | Configure LP settings | | editMetadataTx | EditMetadataSettings | Update name, symbol, and metadata URI (JSON with name, symbol, description, image, cover) | | editDepositsTx | EditDepositsSettings | Enable or disable deposits | | editForceRebalanceTx | EditForceRebalanceSettings | Enable or disable force rebalance | | editCustomRebalanceTx | EditCustomRebalanceSettings | Enable or disable custom rebalance | | editAddTokenDelayTx | EditAddTokenSettings | Set time-lock for adding tokens | | editUpdateWeightsDelayTx | EditUpdateWeightsSettings | Set time-lock for weight updates | | editSwapDelayTx | EditMakeDirectSwapSettings | Set time-lock for direct swaps |

Token Composition

addOrEditTokenTx(context: TaskContext, settings: AddOrEditTokenInput): Promise<TxPayloadBatchSequence>

Add a new token to the vault or update an existing token's oracle configuration:

const tx = await sdk.addOrEditTokenTx(
  { vault: "<VAULT_PUBKEY>", manager: "<MANAGER>" },
  {
    token_mint: "<TOKEN_MINT>",
    active: true,
    min_oracles_thresh: 1,
    min_conf_bps: 10,
    conf_thresh_bps: 200,
    conf_multiplier: 1.0,
    oracles: [
      {
        oracle_type: "pyth",
        account_lut_id: 0,
        account_lut_index: 0,
        account: "<PYTH_PRICE_ACCOUNT>",
        weight_bps: 10000,
        is_required: true,
        conf_thresh_bps: 200,
        volatility_thresh_bps: 200,
        max_slippage_bps: 1000,
        min_liquidity: 0,
        staleness_thresh: 120,
        staleness_conf_rate_bps: 50,
        token_decimals: 9,
        twap_seconds_ago: 0,
        twap_secondary_seconds_ago: 0,
        quote_token: "usd",
      },
    ],
  }
);

updateWeightsTx(context: TaskContext, settings: UpdateWeightsInput): Promise<TxPayloadBatchSequence>

Update target weights for all tokens in the vault:

const tx = await sdk.updateWeightsTx(
  { vault: "<VAULT_PUBKEY>", manager: "<MANAGER>" },
  {
    token_weights: [
      { mint: "<TOKEN_MINT_1>", weight_bps: 5000 },
      { mint: "<TOKEN_MINT_2>", weight_bps: 3000 },
      { mint: "<TOKEN_MINT_3>", weight_bps: 2000 },
    ], // basis points, must sum to 10000
  }
);

makeDirectSwapTx(context, settings, jup_swap_ix?): Promise<TxPayloadBatchSequence>

Execute a direct token swap within the vault via Jupiter.


Intent Execution & Cancellation

executeVaultIntentTx(params): Promise<TxPayloadBatchSequence>

Execute a pending intent after its time-lock has elapsed:

await sdk.executeVaultIntentTx({
  keeper: wallet.publicKey.toBase58(),
  intent: "<INTENT_PUBKEY>",
});

executeDirectSwapVaultIntentTx(params): Promise<TxPayloadBatchSequence>

Execute a pending direct swap intent with a flash swap:

await sdk.executeDirectSwapVaultIntentTx({
  keeper: wallet.publicKey.toBase58(),
  intent: "<INTENT_PUBKEY>",
  jup_swap_ix: jupiterSwapInstruction,
  jup_address_lookup_table_addresses: [...],
});

cancelVaultIntentTx(params): Promise<TxPayloadBatchSequence>

Cancel and close an intent account:

await sdk.cancelVaultIntentTx({
  keeper: wallet.publicKey.toBase58(),
  intent: "<INTENT_PUBKEY>",
});

Deposits & Withdrawals

buyVaultTx(params): Promise<TxPayloadBatchSequence>

Deposit tokens into a vault to receive vault tokens:

const tx = await sdk.buyVaultTx({
  buyer: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_MINT>",
  contributions: [
    { mint: "So11111111111111111111111111111111111111112", amount: 1_000_000_000 }, // 1 SOL
    { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", amount: 100_000_000 }, // 100 USDC
  ],
  rebalance_slippage_bps: 100,             // optional (default: 1%)
  per_trade_rebalance_slippage_bps: 100,   // optional
});

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

depositTokensTx(params): Promise<TxPayloadBatchSequence>

Add more tokens to an existing deposit before locking:

const tx = await sdk.depositTokensTx({
  buyer: wallet.publicKey.toBase58(),
  contributions: [{ mint: "<MINT>", amount: 500_000_000 }],
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

lockDepositsTx(params): Promise<TxPayloadBatchSequence>

Lock deposits and start the auction process:

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

sellVaultTx(params): Promise<TxPayloadBatchSequence>

Withdraw from a vault by burning vault tokens:

const tx = await sdk.sellVaultTx({
  seller: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_MINT>",
  withdraw_amount: 1_000_000,       // vault tokens to burn
  keep_tokens: [],                  // mints to receive directly without rebalancing
  rebalance_slippage_bps: 100,
});

Rebalancing

rebalanceVaultTx(params): Promise<TxPayloadBatchSequence>

Trigger a rebalance to bring the vault back to its target weights:

const tx = await sdk.rebalanceVaultTx({
  keeper: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_MINT>",
  rebalance_slippage_bps: 100,
});

cancelRebalanceIntentTx(params): Promise<TxPayloadBatchSequence>

Cancel an active rebalance intent:

const tx = await sdk.cancelRebalanceIntentTx({
  keeper: wallet.publicKey.toBase58(),
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

Oracle Price Updates

updateTokenPricesTx(params): Promise<TxPayloadBatchSequence>

Refresh on-chain oracle prices for all tokens in a vault during a rebalance:

const tx = await sdk.updateTokenPricesTx({
  keeper: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

updatePythPriceFeedsTx(params): Promise<TxPayloadBatchSequence>

Update specific Pyth price feeds from on-chain price accounts:

const tx = await sdk.updatePythPriceFeedsTx({
  keeper: wallet.publicKey.toBase58(),
  accounts: ["<PYTH_PRICE_ACCOUNT_1>", "<PYTH_PRICE_ACCOUNT_2>"],
});

Flash Swaps

flashSwapTx(params): Promise<TxPayloadBatchSequence>

Execute an atomic flash swap during rebalance auctions — withdraws tokens from the vault, performs a swap (e.g. via Jupiter), and deposits the result back in a single transaction:

const tx = await sdk.flashSwapTx({
  keeper: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
  mint_in: "<DEPOSIT_TOKEN_MINT>",
  mint_out: "<WITHDRAW_TOKEN_MINT>",
  amount_in: 1_000_000,
  amount_out: 1_000_000,
  jup_swap_ix: jupiterSwapInstruction,
  jup_token_ledger_ix: jupiterTokenLedgerInstruction,
  jup_address_lookup_table_addresses: [...],
});

Minting & Redeeming

mintTx(params): Promise<TxPayloadBatchSequence>

Mint vault tokens after a deposit completes its auctions:

const tx = await sdk.mintTx({
  keeper: wallet.publicKey.toBase58(),
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

redeemTokensTx(params): Promise<TxPayloadBatchSequence>

Redeem underlying tokens from a completed withdrawal:

const tx = await sdk.redeemTokensTx({
  keeper: wallet.publicKey.toBase58(),
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

Bounties

addBountyTx(params): Promise<TxPayloadBatchSequence>

Add bounty to a vault for incentivizing keeper automation:

const tx = await sdk.addBountyTx({
  keeper: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
  amount: 100_000_000, // lamports
});

claimBountyTx(params): Promise<TxPayloadBatchSequence>

Claim bounty rewards after completing rebalance tasks:

const tx = await sdk.claimBountyTx({
  keeper: wallet.publicKey.toBase58(),
  rebalance_intent: "<REBALANCE_INTENT_PUBKEY>",
});

Fee Management

withdrawVaultFeesTx(params): Promise<TxPayloadBatchSequence>

Withdraw and claim accumulated fees from a vault. Automatically detects which fee types the claimer is authorized to collect (protocol, creator, host, or manager fees):

const tx = await sdk.withdrawVaultFeesTx({
  claimer: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
});

claimTokenFeesFromVaultTx(params): Promise<TxPayloadBatchSequence>

Claim remaining fee tokens from an existing WithdrawVaultFees account:

const tx = await sdk.claimTokenFeesFromVaultTx({
  claimer: wallet.publicKey.toBase58(),
  withdrawVaultFees: "<WITHDRAW_VAULT_FEES_PUBKEY>",
});

Lookup Tables

rewriteLookupTablesTx(params): Promise<TxPayloadBatchSequence>

Rebuild address lookup tables for a vault (needed when LUTs are full after adding tokens):

const tx = await sdk.rewriteLookupTablesTx({
  signer: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_MINT>",
  additional_accounts: ["<ACCOUNT_1>", "<ACCOUNT_2>"],
});

Sending Transactions

All transaction-building methods return a TxPayloadBatchSequence. Batches are sent sequentially; transactions within a batch are sent in parallel.

signAndSendTxPayloadBatchSequence(params): Promise<TransactionSignature[][]>

const signatures = await sdk.signAndSendTxPayloadBatchSequence({
  txPayloadBatchSequence: tx,
  wallet,
  simulateTransactions: false, // optional
});

signAndSendVersionedTxs(params): Promise<TransactionSignature[][]>

const signatures = await sdk.signAndSendVersionedTxs({
  versionedTxs,
  wallet,
});

Keeper Monitor (Reference Implementation)

KeeperMonitor is an example keeper implementation included in the SDK. It provides automated monitoring and execution of all pending protocol tasks.

import { KeeperMonitor } from "@symmetry-hq/sdk";

const keeper = new KeeperMonitor({
  wallet,                          // wallet with signing capability
  connection,                      // Solana RPC connection
  network: "mainnet",
  jupiterApiKey: "<JUP_API_KEY>",
  maxAllowedAccounts: 64,
  priorityFee: 50_000,            // optional
  simulateTransactions: false,     // optional
});

while (true) {
  await keeper.update();
  await new Promise(r => setTimeout(r, 10_000));
}

The keeper automatically monitors and executes pending intents, handles the full rebalance lifecycle (price updates, Jupiter flash swaps, minting, redeeming, bounty claims), and manages concurrent task execution.


Standalone Utilities

| Export | Description | |--------|-------------| | getJupTokenLedgerAndSwapInstructions | Build Jupiter swap instructions for flash swaps | | getSwapPairs | Compute required swap pairs for a rebalance intent | | isRebalanceRequired | Check whether a vault needs rebalancing based on its threshold settings |


Constants

| Constant | Value | Description | |----------|-------|-------------| | VAULTS_V3_PROGRAM_ID | BASKT7aKd8n7ibpUbwLP3Wiyxyi3yoiXsxBk4Hpumate | Program address | | COMPUTE_UNITS | 1,000,000 | Default compute unit limit | | PRIORITY_FEE | 25,000 | Default priority fee (micro-lamports) | | MAX_SUPPORTED_TOKENS_PER_VAULT | 100 | Max tokens per vault | | MAX_MANAGERS_PER_VAULT | 10 | Max managers per vault | | MAX_ORACLES_PER_TOKEN | 4 | Max oracle sources per token | | HUNDRED_PERCENT_BPS | 10,000 | 100% in basis points |

Supported Oracles

| Type | Enum | Description | |------|------|-------------| | Pyth | 0 | Pyth Network price feeds via Hermes (Price Feed IDs) | | Raydium CLMM | 1 | Raydium Concentrated Liquidity AMM TWAP (currently disabled on-chain) | | Raydium CPMM | 2 | Raydium Constant Product AMM TWAP | | Switchboard | 3 | Switchboard oracle feeds (currently disabled on-chain) |

Each token in a vault supports up to 4 oracle sources with configurable aggregation (e.g. weighted percentile).

Networks

| Network | WSOL Mint | USDC Mint | |---------|-----------|-----------| | mainnet | So11111111111111111111111111111111111111112 | EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v | | devnet | So11111111111111111111111111111111111111112 | USDCoctVLVnvTXBEuP9s8hntucdJokbo17RwHuNXemT |

License

BUSL-1.1 (Business Source License 1.1)