> ## Documentation Index
> Fetch the complete documentation index at: https://docs.symmetry.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Examples

> End-to-end code examples for common Symmetry integration scenarios.

## Setup

All examples use this shared setup:

```typescript theme={null}
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import {
  SymmetryCore,
  KeeperMonitor,
  RebalanceHandler,
  getJupTokenLedgerAndSwapInstructions,
  getSwapPairs,
  isRebalanceRequired,
} from "@symmetry-hq/sdk";

function createWallet(keypair: Keypair) {
  return {
    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,
  };
}

const connection = new Connection("https://api.mainnet-beta.solana.com");
const keypair = Keypair.fromSecretKey(/* your secret key bytes */);
const wallet = createWallet(keypair);

const sdk = new SymmetryCore({
  connection,
  network: "mainnet",
  priorityFee: 50_000,
});
```

<Note>
  Examples work with both SPL and Token Extensions (`Token22`) mints where token mint inputs are used.
</Note>

***

## Create a Vault with Tokens

Creates a 2-token vault with SOL (50%) and USDC (50%).

The `metadata_uri` must point to a JSON file with the vault's metadata. The JSON should contain at minimum `name`, `symbol`, `description`, `image`, and `cover` fields. You can add any extra fields (website, social links, etc.) for your own integrations to consume.

Example metadata JSON at the URI:

```json theme={null}
{
  "name": "Diversified Index",
  "symbol": "DIVX",
  "description": "A diversified vault tracking SOL, USDC, and other tokens.",
  "image": "https://arweave.net/your-token-image-url",
  "cover": "https://arweave.net/your-cover-image-url"
}
```

```typescript theme={null}
const vaultResult: VaultCreationTx = await sdk.createVaultTx({
  creator: wallet.publicKey.toBase58(),
  start_price: "1.0",
  name: "Diversified Index",
  symbol: "DIVX",
  metadata_uri: "https://arweave.net/your-metadata-json",  // URL to JSON with name, symbol, description, image, cover
  host_platform_params: {
    host_pubkey: wallet.publicKey.toBase58(),
    host_deposit_fee_bps: 10,
    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:", vaultResult.mint);
console.log("Vault account:", vaultResult.vault);

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

// Add SOL with Pyth oracle (find price feed IDs at https://docs.pyth.network/price-feeds/core/price-feeds/price-feed-ids)
const addSolTx: TxPayloadBatchSequence = await sdk.addOrEditTokenTx(
  { vault: vaultResult.vault, manager: wallet.publicKey.toBase58() },
  {
    token_mint: "So11111111111111111111111111111111111111112",
    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: "7UVimffxr9ow1uXYxsr4LHAcV58mLzhmwaeKvJ1pjLiE",
      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",
    }],
  }
);
await sdk.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: addSolTx, wallet });

const addUsdcTx: TxPayloadBatchSequence = await sdk.addOrEditTokenTx(
  { vault: vaultResult.vault, manager: wallet.publicKey.toBase58() },
  {
    token_mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
    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: "Dpw1EAVrSB1ibxiDQyTAW6Zip3J4Btk2x4SgApQCeFbX",
      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: 6,
      twap_seconds_ago: 0,
      twap_secondary_seconds_ago: 0,
      quote_token: "usd",
    }],
  }
);
await sdk.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: addUsdcTx, wallet });

const weightsTx: TxPayloadBatchSequence = await sdk.updateWeightsTx(
  { vault: vaultResult.vault, manager: wallet.publicKey.toBase58() },
  {
    token_weights: [
      { mint: "So11111111111111111111111111111111111111112", weight_bps: 5000 },
      { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", weight_bps: 5000 },
    ],
  }
);
await sdk.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: weightsTx, wallet });
```

***

## Deposit into a Vault

```typescript theme={null}
const VAULT_MINT = "<VAULT_TOKEN_MINT>";

// Amounts are raw (smallest units): SOL = 9 decimals, USDC = 6 decimals
const buyTx: TxPayloadBatchSequence = await sdk.buyVaultTx({
  buyer: wallet.publicKey.toBase58(),
  vault_mint: VAULT_MINT,
  contributions: [
    { mint: "So11111111111111111111111111111111111111112", amount: 500_000_000 },   // 0.5 SOL
    { mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", amount: 50_000_000 }, // 50 USDC
  ],
  rebalance_slippage_bps: 100,
  per_trade_rebalance_slippage_bps: 100,
});

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

const lockTx = await sdk.lockDepositsTx({
  buyer: wallet.publicKey.toBase58(),
  vault_mint: VAULT_MINT,
});

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

***

## Standard Withdrawal

```typescript theme={null}
const sellTx: TxPayloadBatchSequence = await sdk.sellVaultTx({
  seller: wallet.publicKey.toBase58(),
  vault_mint: "<VAULT_TOKEN_MINT>",
  withdraw_amount: 1_000_000,  // raw vault token amount to burn
  keep_tokens: [],
  rebalance_slippage_bps: 100,
  per_trade_rebalance_slippage_bps: 100,
});

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

### Withdraw and Keep Specific Tokens

```typescript theme={null}
const sellTx: TxPayloadBatchSequence = await sdk.sellVaultTx({
  seller: wallet.publicKey.toBase58(),
  vault_mint: VAULT_MINT,
  withdraw_amount: 1_000_000,
  keep_tokens: ["So11111111111111111111111111111111111111112"],
  rebalance_slippage_bps: 100,
  per_trade_rebalance_slippage_bps: 100,
});
```

***

## Fast Withdrawal

Pass every mint from `vault.composition` to skip auctions:

```typescript theme={null}
const vault = await sdk.fetchVault("<VAULT_PUBKEY>");
const allMints = vault.formatted!.composition.map(asset => asset.mint);

const sellTx = await sdk.sellVaultTx({
  seller: wallet.publicKey.toBase58(),
  vault_mint: vault.formatted!.mint,
  withdraw_amount: 1_000_000,
  keep_tokens: allMints,
  rebalance_slippage_bps: 100,
  per_trade_rebalance_slippage_bps: 100,
});
await sdk.signAndSendTxPayloadBatchSequence({ txPayloadBatchSequence: sellTx, wallet });

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

***

## Read Vault Data

```typescript theme={null}
let vault = await sdk.fetchVault("<VAULT_PUBKEY>");
vault = await sdk.loadVaultPrice(vault);

const info: FormattedVault = vault.formatted!;
console.log("Name:", info.name);
console.log("Symbol:", info.symbol);
console.log("TVL:", vault.tvl?.toString());
console.log("Token Price:", vault.price?.toString());
console.log("Supply:", info.supply_outstanding);
console.log("Creator:", info.creator);
console.log("Host:", info.host);

console.log("\nComposition:");
for (const asset of info.composition) {
  if (!asset.active) continue;
  console.log(`  ${asset.mint}: weight=${asset.weight / 100}%, amount=${asset.amount}`);
}

console.log("\nFee Settings:");
const fees = info.fee_settings;
console.log(`  Creator deposit: ${fees.creator_deposit_fee_bps / 100}%`);
console.log(`  Creator withdrawal: ${fees.creator_withdraw_fee_bps / 100}%`);
console.log(`  Creator management: ${fees.creator_management_fee_bps / 100}%`);
console.log(`  Creator performance: ${fees.creator_performance_fee_bps / 100}%`);

console.log("\nAutomation:", info.automation_settings.enabled);
console.log("Deposits enabled:", info.deposits_settings.enabled);
```

***

## List All Vaults with Prices

```typescript theme={null}
const vaults = await sdk.fetchAllVaults();

for (const vault of vaults) {
  try {
    const priced = await sdk.loadVaultPrice(vault);
    console.log(
      `${priced.formatted!.name} (${priced.formatted!.symbol})` +
      ` | TVL: $${priced.tvl?.toFixed(2)}` +
      ` | Price: $${priced.price?.toFixed(6)}` +
      ` | Tokens: ${priced.formatted!.composition.filter(a => a.active).length}`
    );
  } catch (e) {
    console.log(`${vault.formatted!.name}: price load failed`);
  }
}
```

***

## Update Vault Fees

```typescript theme={null}
const tx = await sdk.editFeesTx(
  {
    vault: "<VAULT_PUBKEY>",
    manager: wallet.publicKey.toBase58(),
  },
  {
    creator_deposit_fee_bps: 25,
    creator_withdraw_fee_bps: 25,
    creator_management_fee_bps: 200,   // currently disabled in global config
    creator_performance_fee_bps: 1000, // currently disabled in global config
    managers_deposit_fee_bps: 0,
    managers_withdraw_fee_bps: 0,
    managers_management_fee_bps: 0,    // currently disabled in global config
    managers_performance_fee_bps: 0,   // currently disabled in global config
    vault_deposit_fee_bps: 10,
    vault_withdraw_fee_bps: 10,
    modification_delay: 86400,
  }
);

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

***

## Run a Keeper Bot

```typescript theme={null}
const keeper = new KeeperMonitor({
  wallet,
  connection,
  network: "mainnet",
  jupiterApiKey: "<YOUR_JUPITER_API_KEY>",
  maxAllowedAccounts: 64,
  priorityFee: 50_000,
  simulateTransactions: false,
});

// Option A: Run indefinitely
while (true) {
  try {
    await keeper.update();
  } catch (e) {
    console.error("Keeper update error:", e);
  }
  await new Promise(r => setTimeout(r, 10_000));
}

// Option B: Run for a fixed duration
await keeper.run(600);
```

***

## Handle a Single Rebalance

```typescript theme={null}
await RebalanceHandler.run({
  intentPubkey: new PublicKey("<REBALANCE_INTENT_PUBKEY>"),
  wallet,
  connection,
  network: "mainnet",
  jupiterApiKey: "<JUP_API_KEY>",
  maxAllowedAccounts: 64,
  priorityFee: 50_000,
});
```

***

## Claim Fees

```typescript theme={null}
const claimTx = await sdk.withdrawVaultFeesTx({
  claimer: wallet.publicKey.toBase58(),
  vault: "<VAULT_PUBKEY>",
});

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

***

## Check and Trigger Rebalance

```typescript theme={null}
const vault = await sdk.fetchVault("<VAULT_PUBKEY>");
const pricedVault = await sdk.loadVaultPrice(vault);
const needsRebalance = await isRebalanceRequired(pricedVault, connection);

if (needsRebalance) {
  const tx = await sdk.rebalanceVaultTx({
    keeper: wallet.publicKey.toBase58(),
    vault_mint: vault.mint.toBase58(),
    rebalance_slippage_bps: 100,
    per_trade_rebalance_slippage_bps: 100,
  });

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

***

## Set Up Manager Authorities

```typescript theme={null}
const tx = await sdk.editManagersTx(
  {
    vault: "<VAULT_PUBKEY>",
    manager: wallet.publicKey.toBase58(),
  },
  {
    managers: [
      {
        pubkey: "<MANAGER_1_PUBKEY>",
        fee_split_weight_bps: 6000,
        authorities: {
          managers: true,
          fees: true,
          schedule: true,
          automation: true,
          lp: true,
          metadata: true,
          deposits: true,
          force_rebalance: true,
          custom_rebalance: true,
          add_token: true,
          update_weights: true,
          make_direct_swap: true,
        },
      },
      {
        pubkey: "<MANAGER_2_PUBKEY>",
        fee_split_weight_bps: 4000,
        authorities: {
          managers: false,
          fees: false,
          schedule: false,
          automation: false,
          lp: false,
          metadata: true,
          deposits: true,
          force_rebalance: false,
          custom_rebalance: false,
          add_token: false,
          update_weights: true,
          make_direct_swap: false,
        },
      },
    ],
    modification_delay: 172800,
  }
);

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

***

## Enable Automation

```typescript theme={null}
const tx = await sdk.editAutomationTx(
  {
    vault: "<VAULT_PUBKEY>",
    manager: wallet.publicKey.toBase58(),
  },
  {
    enabled: true,
    rebalance_slippage_threshold_bps: 100,
    per_trade_rebalance_slippage_threshold_bps: 100,
    rebalance_activation_threshold_abs_bps: 500,
    rebalance_activation_threshold_rel_bps: 1000,
    rebalance_activation_cooldown: 3600,
    modification_delay: 86400,
  }
);

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

***

## Monitor Rebalance Intents for a Vault

```typescript theme={null}
const VAULT_PUBKEY: string = "<VAULT_PUBKEY>";

const rebalanceIntents: UIRebalanceIntent[] = await sdk.fetchVaultRebalanceIntents(VAULT_PUBKEY);

for (const ri of rebalanceIntents) {
  const data: FormattedRebalanceIntent = ri.formatted_data;
  console.log(`Intent: ${data.pubkey}`);
  console.log(`  Type: ${data.rebalance_type}`);
  console.log(`  Action: ${data.current_action}`);
  console.log(`  Owner: ${data.owner}`);

  if (ri.deposit_data) {
    console.log(`  Deposits:`);
    for (const token of ri.deposit_data.tokens) {
      console.log(`    ${token.mint}: ${token.amount}`);
    }
  }

  if (ri.auction_data) {
    console.log(`  Auction stages:`);
    for (const stage of ri.auction_data.auction_stages) {
      console.log(`    ${new Date(stage.start_time * 1000).toISOString()} - ${new Date(stage.end_time * 1000).toISOString()}`);
    }
  }
}
```

***

## Add Bounty to a Vault

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

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

***

## Build a Portfolio Tracker

```typescript theme={null}
async function getPortfolio(ownerPubkey: string) {
  const allVaults = await sdk.fetchAllVaults();
  const portfolio = [];

  for (const vault of allVaults) {
    const pricedVault = await sdk.loadVaultPrice(vault);
    const vaultMint = pricedVault.mint.toBase58();

    portfolio.push({
      name: pricedVault.formatted!.name,
      symbol: pricedVault.formatted!.symbol,
      mint: vaultMint,
      price: pricedVault.price?.toNumber(),
      tvl: pricedVault.tvl?.toNumber(),
      composition: pricedVault.formatted!.composition
        .filter(a => a.active)
        .map(a => ({
          mint: a.mint,
          weight: a.weight / 100,
          amount: a.amount,
        })),
    });
  }

  return portfolio;
}
```

***

## Common Patterns

### Error Handling

```typescript theme={null}
try {
  const tx = await sdk.buyVaultTx({ /* ... */ });
  const sigs = await sdk.signAndSendTxPayloadBatchSequence({
    txPayloadBatchSequence: tx,
    wallet,
  });
  console.log("Success:", sigs);
} catch (error) {
  console.error("Transaction failed:", error);
}
```

### Preflight Mode

<Warning>
  `simulateTransactions: true` enables a preflight-style send path in the SDK — it does **not** perform offline-only simulation. Transactions are still sent to the network. Do not use on production keys if you expect zero chain side-effects.
</Warning>

```typescript theme={null}
const sigs = await sdk.signAndSendTxPayloadBatchSequence({
  txPayloadBatchSequence: tx,
  wallet,
  simulateTransactions: true,
});
```

### Working with Amounts

Token amounts are always in the smallest unit (lamports):

| Token   | Decimals | 1 token =                        |
| ------- | -------- | -------------------------------- |
| SOL     | 9        | 1,000,000,000 lamports           |
| USDC    | 6        | 1,000,000                        |
| General | N        | `rawAmount = humanAmount * 10^N` |

This applies to `contributions[].amount`, `withdraw_amount`, `amount_in`, `amount_out`, bounty `amount`, `min_bounty_amount`, and `max_bounty_amount`.

### Vault Mint vs Vault Account

Two addresses are associated with each vault:

* **Vault mint** (`vault.mint`): The token mint of the vault token. Used in `buyVaultTx`, `sellVaultTx`, `rebalanceVaultTx`.
* **Vault account** (`vault.ownAddress` or `vault.formatted.pubkey`): The on-chain state account. Used in `fetchVault`, `addOrEditTokenTx`, `editFeesTx`, etc.

To go from mint → account: `getVaultState(mintPubkey)` (PDA derivation).
To go from account → mint: read `vault.mint` from the fetched vault.
