‹ 首页

sanctum

@sendaifun · 收录于 1 周前

Complete Sanctum SDK for liquid staking, LST swaps, and Infinity pool operations on Solana. Use when working with LSTs (mSOL, jitoSOL, bSOL, INF), staking SOL, swapping between liquid staking tokens, or integrating Sanctum's liquidity infrastructure.

适合你,如果你在 Solana 上开发流动性质押或 LST 相关应用

/ 下载安装
sanctum.skill双击,或拖进 Claude 桌面版 / Cowork,即完成安装↓ .skill↓ .zip
用别的 agent?下载 .zip 解压,把文件夹放进它的技能目录
Claude Code~/.claude/skills/(项目级 .claude/skills/)
Codex CLI~/.codex/skills/
Cursor自动读取上面两处目录
其他工具见其文档的「skills」目录;两个下载是同一份文件,只是名字不同
/ 通过 npx 安装 校验哈希
npx oh-my-skill add sendaifun/skills/sanctum
/ 通过 bash 安装
curl -fsSL https://oh-my-skill.com/install.sh | bash -s -- sendaifun/skills/sanctum
/ 已经装过?验证本机副本,不用重装
npx oh-my-skill verify sendaifun/skills/sanctum
安装目标可用 --agent / --scope 或 --to 明确指定;省略时只会在唯一已存在的 agent 目录上自动选择,零命中或多命中会停止并提示。content_hash 缺失或不一致均拒装。
116GitHub stars
~3.1K最小装载
~3.1K含声明引用
~18K文本包总量
镜像托管

怎么用

技能原文 SKILL.md作者撰写 · Apache-2.0 · 064d4de

Sanctum Development Guide

A comprehensive guide for building Solana applications with Sanctum - Solana's largest LST (Liquid Staking Token) platform powering 1,361+ LSTs.

Overview

Sanctum provides unified liquid staking infrastructure on Solana:

  • Infinity Pool: Multi-LST liquidity pool with zero-slippage swaps
  • Router: Instant LST-to-LST swaps via stake account routing
  • Reserve: Instant SOL liquidity for LST withdrawals
  • LST Creation: Launch custom liquid staking tokens
  • INF Token: Yield-bearing token representing Infinity pool shares
Key Stats
  • 1,361+ LSTs supported
  • $1.4B+ in swap volume facilitated
  • ~8,000 SOL ($1M+) in fees shared with stakers
  • Partners: Jupiter (jupSOL), Bybit (bbSOL), Drift (dSOL), crypto.com (cdcSOL)
Quick Start
API Setup
const SANCTUM_API_BASE = 'https://sanctum-api.ironforge.network';

// All endpoints require API key
const headers = {
  'Content-Type': 'application/json',
};

// Example: Get all LST metadata
const response = await fetch(
  `${SANCTUM_API_BASE}/lsts?apiKey=${API_KEY}`
);
const lsts = await response.json();
Common LST Addresses
const LST_MINTS = {
  // Native SOL (wrapped)
  SOL: 'So11111111111111111111111111111111111111112',

  // Sanctum INF (Infinity pool token)
  INF: '5oVNBeEEQvYi1cX3ir8Dx5n1P7pdxydbGF2X4TxVusJm',

  // Major LSTs
  mSOL: 'mSoLzYCxHdYgdzU16g5QSh3i5K3z3KZK7ytfqcJm7So',      // Marinade
  jitoSOL: 'J1toso1uCk3RLmjorhTtrVwY9HJ7X8V9yYac6Y7kGCPn', // Jito
  bSOL: 'bSo13r4TkiE4KumL71LsHTPpL2euBYLFx6h9HP3piy1',      // BlazeStake

  // Partner LSTs
  jupSOL: 'jupSoLaHXQiZZTSfEWMTRRgpnyFm8f6sZdosWBjx93v',   // Jupiter
  bbSOL: 'bbso1MfE7KVL7DhqwZ6dVfKrD3oNV1PEykLNM4kk5dD',    // Bybit
  dSOL: 'Dso1bDeDjCQxTrWHqUUi63oBvV7Mdm6WaobLbQ7gnPQ',     // Drift

  // Other popular LSTs
  hSOL: 'he1iusmfkpAdwvxLNGV8Y1iSbj4rUy6yMhEA3fotn9A',     // Helius
  pwrSOL: 'pWrSoLAhue6jUxUMbWaY8izMhNpWfhiJk7M3Fy3p1Kt',   // Power
  laineSOL: 'LAinEtNLgpmCP9Rvsf5Hn8W6EhNiKLZQti1xfWMLy6X', // Laine
};
Core Concepts
1. LST (Liquid Staking Token)

LSTs represent staked SOL that remains liquid. When you stake SOL through a stake pool:

  • You receive LST tokens representing your stake
  • The stake earns validator rewards
  • LSTs can be traded, used in DeFi, or swapped back to SOL
2. INF Token

INF is Sanctum's flagship yield-bearing token:

  • Represents share of Infinity pool's multi-LST holdings
  • Reward-bearing: Value increases vs SOL (not rebasing)
  • Earns weighted average of all LST yields + trading fees
  • No lockups - hold to earn, swap out anytime
// INF increases in value over time
// Example: 1 INF deposited at 1.0 SOL might be worth 1.05 SOL later
const infValue = await getInfSolValue(); // Returns current INF/SOL rate
3. SOL Value Calculators

On-chain programs that convert LST amounts to intrinsic SOL value:

// Each LST has a dedicated calculator
const SOL_VALUE_CALCULATORS = {
  SPL: 'sp1V4h2gWorkGhVcazBc22Hfo2f5sd7jcjT4EDPrWFF',
  SanctumSpl: 'sspUE1vrh7xRoXxGsg7vR1zde2WdGtJRbyK9uRumBDy',
  SanctumSplMulti: 'ssmbu3KZxgonUtjEMCKspZzxvUQCxAFnyh1rcHUeEDo',
  Marinade: 'mare3SCyfZkAndpBRBeonETmkCCB3TJTTrz8ZN2dnhP',
  Lido: '1idUSy4MGGKyKhvjSnGZ6Zc7Q4eKQcibym4BkEEw9KR',
  wSOL: 'wsoGmxQLSvwWpuaidCApxN5kEowLe2HLQLJhCQnj4bE',
};
API Reference
Base URL
https://sanctum-api.ironforge.network

All endpoints require apiKey query parameter.

Get LST Metadata
// Get all LSTs
GET /lsts?apiKey={key}

// Get specific LST by mint or symbol
GET /lsts/{mintOrSymbol}?apiKey={key}

// Response
interface LstMetadata {
  symbol: string;
  mint: string;
  decimals: number;
  tokenProgram: string;
  logoUri: string;
  name: string;
  tvl: number;         // Total Value Locked
  apy: number;         // Current APY
  holders: number;
}
Get APY Data
// Get validator APYs
GET /validators/apy?apiKey={key}

// Response
interface ValidatorApy {
  [validatorId: string]: {
    avgApy: number;
    timeseries: Array<{epoch: number; apy: number}>;
  };
}

// Get LST historical APYs
GET /lsts/{mintOrSymbol}/apys?apiKey={key}&limit={n}

// Response
interface LstApyHistory {
  apys: Array<{
    epoch: number;
    epochEndTs: number;
    apy: number;
  }>;
}
Swap LSTs
// Get swap quote and unsigned transaction
GET /swap/token/order?apiKey={key}&inp={inputMint}&out={outputMint}&amt={amount}&mode={ExactIn|ExactOut}&signer={walletPubkey}&slippageBps={bps}

// Response
interface SwapOrderResponse {
  tx: string;           // Base64 encoded transaction
  inpAmt: string;       // Input amount
  outAmt: string;       // Output amount
  source: string;       // Swap source (Infinity, Router, etc.)
  feeAmt: string;       // Fee amount
  feeMint: string;      // Fee token mint
}

// Execute signed swap
POST /swap/token/execute
Body: {
  signedTx: string;     // Base64 signed transaction
  orderResponse: object; // Original order response
}

// Response
interface SwapExecuteResponse {
  txSignature: string;
}
Deposit Stake Account
// Convert native stake account to LST
GET /swap/depositStake/order?apiKey={key}&stakeAccount={pubkey}&outputLstMint={mint}&signer={wallet}

POST /swap/depositStake/execute
Body: {
  signedTx: string;
  orderResponse: object;
}
Withdraw to Stake Account
// Convert LST back to stake account
GET /swap/withdrawStake/order?apiKey={key}&lstMint={mint}&amount={amount}&signer={wallet}&deactivate={boolean}

POST /swap/withdrawStake/execute
Body: {
  signedTx: string;
  orderResponse: object;
}
TypeScript Integration
Full Client Implementation
import { Connection, PublicKey, Transaction, Keypair } from '@solana/web3.js';

class SanctumClient {
  private apiKey: string;
  private baseUrl = 'https://sanctum-api.ironforge.network';
  private connection: Connection;

  constructor(apiKey: string, connection: Connection) {
    this.apiKey = apiKey;
    this.connection = connection;
  }

  // Get all LSTs
  async getLsts(): Promise<LstMetadata[]> {
    const response = await fetch(
      `${this.baseUrl}/lsts?apiKey=${this.apiKey}`
    );
    return response.json();
  }

  // Get specific LST
  async getLst(mintOrSymbol: string): Promise<LstMetadata> {
    const response = await fetch(
      `${this.baseUrl}/lsts/${mintOrSymbol}?apiKey=${this.apiKey}`
    );
    return response.json();
  }

  // Get swap quote
  async getSwapQuote(params: {
    inputMint: string;
    outputMint: string;
    amount: string;
    mode: 'ExactIn' | 'ExactOut';
    signer: string;
    slippageBps?: number;
  }): Promise<SwapOrderResponse> {
    const url = new URL(`${this.baseUrl}/swap/token/order`);
    url.searchParams.set('apiKey', this.apiKey);
    url.searchParams.set('inp', params.inputMint);
    url.searchParams.set('out', params.outputMint);
    url.searchParams.set('amt', params.amount);
    url.searchParams.set('mode', params.mode);
    url.searchParams.set('signer', params.signer);
    if (params.slippageBps) {
      url.searchParams.set('slippageBps', params.slippageBps.toString());
    }

    const response = await fetch(url.toString());
    return response.json();
  }

  // Execute swap
  async executeSwap(
    orderResponse: SwapOrderResponse,
    signer: Keypair
  ): Promise<string> {
    // Decode and sign transaction
    const txBuffer = Buffer.from(orderResponse.tx, 'base64');
    const transaction = Transaction.from(txBuffer);
    transaction.sign(signer);

    // Send to API
    const response = await fetch(`${this.baseUrl}/swap/token/execute`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        signedTx: transaction.serialize().toString('base64'),
        orderResponse,
      }),
    });

    const result = await response.json();
    return result.txSignature;
  }

  // Swap LSTs (convenience method)
  async swapLst(params: {
    inputMint: string;
    outputMint: string;
    amount: string;
    signer: Keypair;
    slippageBps?: number;
  }): Promise<string> {
    const quote = await this.getSwapQuote({
      inputMint: params.inputMint,
      outputMint: params.outputMint,
      amount: params.amount,
      mode: 'ExactIn',
      signer: params.signer.publicKey.toBase58(),
      slippageBps: params.slippageBps || 50,
    });

    return this.executeSwap(quote, params.signer);
  }
}
Usage Examples
const connection = new Connection('https://api.mainnet-beta.solana.com');
const sanctum = new SanctumClient(API_KEY, connection);

// Get all LSTs
const lsts = await sanctum.getLsts();
console.log(`Found ${lsts.length} LSTs`);

// Get INF token info
const inf = await sanctum.getLst('INF');
console.log(`INF APY: ${inf.apy}%`);

// Swap 1 SOL to mSOL
const signature = await sanctum.swapLst({
  inputMint: LST_MINTS.SOL,
  outputMint: LST_MINTS.mSOL,
  amount: '1000000000', // 1 SOL (9 decimals)
  signer: wallet,
  slippageBps: 50,
});
console.log('Swap TX:', signature);

// Swap mSOL to INF
const infSwap = await sanctum.swapLst({
  inputMint: LST_MINTS.mSOL,
  outputMint: LST_MINTS.INF,
  amount: '500000000', // 0.5 mSOL
  signer: wallet,
});
Infinity Pool
How It Works

Infinity is a multi-LST liquidity pool enabling zero-slippage swaps:

  1. SOL Value Calculation: Each LST's value is calculated from on-chain stake pool state
  2. Fair Pricing: Swaps execute at intrinsic SOL value (no AMM curves)
  3. Fee Structure: 8 bps per swap, 10 bps for withdrawals
  4. Fee Distribution: 90% to LPs (INF holders), 10% to protocol
Add Liquidity (Get INF)
// Deposit SOL or any LST to get INF
async function addLiquidity(
  sanctum: SanctumClient,
  lstMint: string,
  amount: string,
  signer: Keypair
): Promise<string> {
  // Swap LST/SOL for INF
  return sanctum.swapLst({
    inputMint: lstMint,
    outputMint: LST_MINTS.INF,
    amount,
    signer,
  });
}

// Example: Add 10 SOL to Infinity
const tx = await addLiquidity(
  sanctum,
  LST_MINTS.SOL,
  '10000000000',
  wallet
);
Remove Liquidity
// Withdraw from Infinity pool
async function removeLiquidity(
  sanctum: SanctumClient,
  outputMint: string,
  infAmount: string,
  signer: Keypair
): Promise<string> {
  // Swap INF for desired LST/SOL
  return sanctum.swapLst({
    inputMint: LST_MINTS.INF,
    outputMint: outputMint,
    amount: infAmount,
    signer,
  });
}

// Example: Withdraw to SOL
const tx = await removeLiquidity(
  sanctum,
  LST_MINTS.SOL,
  '5000000000', // 5 INF
  wallet
);
Router
How Swaps Work

The Router enables LST-to-LST swaps via stake accounts:

  1. StakeWrappedSol: Stake SOL into pool, receive LST
  2. WithdrawWrappedSol: Withdraw undelegated SOL from reserve
  3. DepositStake: Deposit stake account, receive LST
  4. SwapViaStake: Route through shared validators
Fee Structure

| Operation | Fee | |-----------|-----| | StakeWrappedSol | 0 bps | | WithdrawWrappedSol | 1 bps | | DepositStake | 10 bps (waived for SOL output) | | SwapViaStake | Varies by route |

Jupiter Integration

Sanctum Router is integrated with Jupiter. Use Jupiter SDK for optimal routing:

import { Jupiter } from '@jup-ag/core';

const jupiter = await Jupiter.load({
  connection,
  cluster: 'mainnet-beta',
  user: wallet.publicKey,
});

// Jupiter automatically routes through Sanctum when optimal
const routes = await jupiter.computeRoutes({
  inputMint: new PublicKey(LST_MINTS.mSOL),
  outputMint: new PublicKey(LST_MINTS.jitoSOL),
  amount: 1_000_000_000n,
  slippageBps: 50,
});
Staking SOL
Direct Staking
// Stake SOL to get LST
async function stakeSol(
  sanctum: SanctumClient,
  lstMint: string,
  solAmount: string,
  signer: Keypair
): Promise<string> {
  return sanctum.swapLst({
    inputMint: LST_MINTS.SOL,
    outputMint: lstMint,
    amount: solAmount,
    signer,
  });
}

// Stake 5 SOL for jupSOL
const tx = await stakeSol(
  sanctum,
  LST_MINTS.jupSOL,
  '5000000000',
  wallet
);
Unstaking (Instant)
// Instant unstake via Infinity/Reserve
async function instantUnstake(
  sanctum: SanctumClient,
  lstMint: string,
  amount: string,
  signer: Keypair
): Promise<string> {
  return sanctum.swapLst({
    inputMint: lstMint,
    outputMint: LST_MINTS.SOL,
    amount,
    signer,
  });
}
Delayed Unstaking (Lower Fees)
// Withdraw to stake account (requires epoch wait)
async function delayedUnstake(
  sanctum: SanctumClient,
  lstMint: string,
  amount: string,
  signer: Keypair,
  deactivate: boolean = true
): Promise<string> {
  const url = new URL(`${sanctum.baseUrl}/swap/withdrawStake/order`);
  url.searchParams.set('apiKey', sanctum.apiKey);
  url.searchParams.set('lstMint', lstMint);
  url.searchParams.set('amount', amount);
  url.searchParams.set('signer', signer.publicKey.toBase58());
  url.searchParams.set('deactivate', deactivate.toString());

  const response = await fetch(url.toString());
  const orderResponse = await response.json();

  return sanctum.executeSwap(orderResponse, signer);
}
Data Queries
Get APYs
// Get all LST APYs
async function getLstApys(sanctum: SanctumClient): Promise<Map<string, number>> {
  const lsts = await sanctum.getLsts();
  const apyMap = new Map();

  for (const lst of lsts) {
    apyMap.set(lst.symbol, lst.apy);
  }

  return apyMap;
}

// Get specific LST historical APY
async function getLstApyHistory(
  sanctum: SanctumClient,
  lstMint: string,
  limit: number = 30
): Promise<Array<{epoch: number; apy: number}>> {
  const response = await fetch(
    `${sanctum.baseUrl}/lsts/${lstMint}/apys?apiKey=${sanctum.apiKey}&limit=${limit}`
  );
  const data = await response.json();
  return data.apys;
}
Get TVL
// Get TVL for specific LSTs
async function getTvl(
  sanctum: SanctumClient,
  symbols: string[]
): Promise<Map<string, number>> {
  const tvlMap = new Map();

  for (const symbol of symbols) {
    const lst = await sanctum.getLst(symbol);
    tvlMap.set(symbol, lst.tvl);
  }

  return tvlMap;
}
Get User Holdings
import { getAccount, getAssociatedTokenAddress } from '@solana/spl-token';

async function getUserLstBalances(
  connection: Connection,
  wallet: PublicKey,
  lstMints: string[]
): Promise<Map<string, bigint>> {
  const balances = new Map();

  for (const mint of lstMints) {
    try {
      const ata = await getAssociatedTokenAddress(
        new PublicKey(mint),
        wallet
      );
      const account = await getAccount(connection, ata);
      balances.set(mint, account.amount);
    } catch {
      balances.set(mint, 0n);
    }
  }

  return balances;
}
Program IDs
Core Programs

| Program | ID | Description | |---------|------|-------------| | S Controller | 5ocnV1qiCgaQR8Jb8xWnVbApfaygJ8tNoZfgPwsgx9kx | Infinity pool management | | Flat Fee Pricing | f1tUoNEKrDp1oeGn4zxr7bh41eN6VcfHjfrL3ZqQday | Fee calculation (deprecated) | | Flat Slab | s1b6NRXj6ygNu1QMKXh2H9LUR2aPApAAm1UQ2DjdhNV | Current fee program |

SOL Value Calculators

| Calculator | ID | |------------|------| | SPL | sp1V4h2gWorkGhVcazBc22Hfo2f5sd7jcjT4EDPrWFF | | SanctumSpl | sspUE1vrh7xRoXxGsg7vR1zde2WdGtJRbyK9uRumBDy | | SanctumSplMulti | ssmbu3KZxgonUtjEMCKspZzxvUQCxAFnyh1rcHUeEDo | | Marinade | mare3SCyfZkAndpBRBeonETmkCCB3TJTTrz8ZN2dnhP | | Lido | 1idUSy4MGGKyKhvjSnGZ6Zc7Q4eKQcibym4BkEEw9KR | | wSOL | wsoGmxQLSvwWpuaidCApxN5kEowLe2HLQLJhCQnj4bE |

Stake Pool Programs

| Program | ID | |---------|------| | SanctumSpl Stake Pool | SP12tWFxD9oJsVWNavTTBZvMbA6gkAmxtVgxdqvyvhY | | SanctumSplMulti Stake Pool | SPMBzsVUuoHA4Jm6KunbsotaahvVikZs1JyTW6iJvbn |

Resources
Skill Structure
sanctum/
├── SKILL.md                              # This file
├── resources/
│   ├── api-reference.md                  # Complete API documentation
│   ├── lst-reference.md                  # LST addresses and metadata
│   └── program-ids.md                    # All program addresses
├── examples/
│   ├── lst-swap/README.md                # LST swap examples
│   ├── staking/README.md                 # Staking/unstaking examples
│   ├── infinity-pool/README.md           # Infinity operations
│   └── liquidity/README.md               # Add/remove liquidity
└── docs/
    └── troubleshooting.md                # Common issues
按 Apache-2.0 许可原样转载,未经改动 · 在 GitHub 查看 →

评论

登录即可评论;带「已验证安装」的,是发布者名下有本店的安装或持有记录。