Raydium SDK V2 Demo

repository·master·Indexed 42 days ago

https://github.com/raydium-io/raydium-sdk-v2-demo

A demonstration repository for the Raydium SDK V2 (v0.0.1-alpha), providing example scripts for interacting with Raydium programs including CLMM and CPMM. Includes guides on performing swaps via the Swap API, managing CLMM market makers, fetching pool and wallet position information, and configuring reward settings using setRewards.

Tokens
10K
Snippets
19
Records
27
Agent score
54%

What's inside Raydium SDK V2

  1. Understand transaction method return values

    master

    All transaction-related build functions (e.g., raydium.clmm.openPositionFromBase, raydium.cpmm.createPool, etc.) return an object containing the transaction data and metadata required for execution.

    const { execute, transaction, builder, extInfo } = await raydium.clmm.openPositionFromBase({ xxx })
    • transaction or transactions: The built transaction(s) ready for signing/sending.
    • builder: Contains all instructions in the transaction (e.g., builder.allInstructions, builder.AllTxData).
    • extInfo: Public keys related to the transaction (e.g., poolId, programId).
  2. Configure the demo environment

    master

    Before running the demo, you must set up your configuration file:

    1. Copy config.ts.template to config.ts.
    2. Update the following values in config.ts:
      • <YOUR_WALLET_SECRET_KEY>: Your wallet's secret key.
      • <YOUR_RPC_URL>: Your preferred RPC endpoint.
      • <API_HOST>: Only required if testing on devnet.
  3. Run demo scripts and CLMM market maker

    master

    Run a specific demo script

    Use yarn dev followed by the path to the script. Note: If you intend to execute a transaction, you must uncomment the code in the last line of the script.

    yarn dev src/<FOLDER>/<SCRIPT_NAME>
    # Example:
    yarn dev src/cpmm/deposit.ts

    Run the CLMM market maker

    Run the market maker with specific arguments for poolId, create position deviation, and close position deviation. Note: You must uncomment the close position and create new position code parts in the script.

    yarn clmm-market <poolId> <create_deviation> <close_deviation>
    # Example:
    yarn clmm-market 8sLbNZoA1cfnvMJLPfp98ZLAnFSYCFApfJKMbiXNLwxj 10 20
  4. Perform a swap using the Raydium Swap API

    master

    To perform a swap, you must follow a two-step process: first, compute the swap details (price impact, route, etc.) using the /compute/swap-base-in endpoint, and then request the actual transaction data using the /transaction/swap-base-in endpoint.

    Step 1: Compute Swap

    Call the compute endpoint with the following parameters:

    • inputMint: The mint address of the token you are providing.
    • outputMint: The mint address of the token you want to receive.
    • amount: The amount of input token.
    • slippageBps: Slippage expressed in basis points (e.g., 0.5% = 50).
    • txVersion: Either 'V0' or 'LEGACY'.

    Step 2: Request Transaction

    Post to the transaction endpoint with a body containing:

    • computeUnitPriceMicroLamports: The priority fee (can be fetched from the API).
    • swapResponse: The full response object received from the compute step.
    • txVersion: The version used in the compute step.
    • wallet: The public key of the owner.
    • wrapSol: true if the input is SOL (to wrap it).
    • unwrapSol: true if the output is SOL (to unwrap it).
    • inputAccount: The token account address for the input mint (if not SOL).
    • outputAccount: The token account address for the output mint (if not SOL).

    Step 3: Sign and Send

    Transactions are returned as base64 encoded strings. Deserialize them based on the txVersion (VersionedTransaction for V0, Transaction for LEGACY), sign with the owner keypair, and send via the Solana connection.

    // 1. Compute the swap
    const { data: swapResponse } = await axios.get<SwapCompute>(`${API_URLS.SWAP_HOST}/compute/swap-base-in?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=${slippage * 100}&txVersion=${txVersion}`);
    
    // 2. Get the transaction
    const { data: swapTransactions } = await axios.post<{ id: string; version: string; success: boolean; data: { transaction: string }[] }>(`${API_URLS.SWAP_HOST}/transaction/swap-base-in`, {
      computeUnitPriceMicroLamports: String(priorityFee),
      swapResponse,
      txVersion,
      wallet: owner.publicKey.toBase58(),
      wrapSol: isInputSol,
      unwrapSol: isOutputSol,
      inputAccount: isInputSol ? undefined : inputTokenAcc?.toBase58(),
      outputAccount: isOutputSol ? undefined : outputTokenAcc?.toBase58(),
    });
    
    // 3. Deserialize and Sign
    const txBuf = Buffer.from(swapTransactions.data[0].transaction, 'base64');
    const transaction = txVersion === 'V0' ? VersionedTransaction.deserialize(txBuf) : Transaction.from(txBuf);
    transaction.sign(isV0Tx ? [owner] : owner);
  5. Perform a swap with referrer functionality via API

    master

    You can perform swap operations using the Raydium API by first computing the swap parameters and then requesting the transaction. This demo script demonstrates how to use the swap-base-in endpoints.

    Referrer Constraints

    Important: The referrer functionality is currently only supported for the following input mints:

    • SOL (Native SOL)
    • WSOL (Wrapped SOL)
    • USDC (USD Coin)
    • USDT (Tether)

    For any other input mints, the referrer parameters will be ignored by default without throwing an error.

    Workflow

    1. Fetch Priority Fees: Retrieve statistical transaction fees (vh: very high, h: high, m: medium) from the API to set the computeUnitPriceMicroLamports.
    2. Compute Swap: Call the compute/swap-base-in GET endpoint with parameters like inputMint, outputMint, amount, slippageBps, txVersion, and referrerBps.
    3. Get Transaction: Call the transaction/swap-base-in POST endpoint using the swapResponse obtained from the previous step. Include the referrerWallet in the request body.
    4. Sign and Send: Deserialize the returned base64 transactions (handling both VersionedTransaction and legacy Transaction) and send them to the network.
    // 1. Compute the swap
    const { data: swapResponse } = await axios.get<SwapCompute>(
      `${API_URLS.SWAP_HOST}/compute/swap-base-in?inputMint=${inputMint}&outputMint=${outputMint}&amount=${amount}&slippageBps=${slippage * 100}&txVersion=${txVersion}&referrerBps=${referrerBps}`
    );
    
    // 2. Request the transaction
    const { data: swapTransactions } = await axios.post<{ id: string; version: string; success: boolean; data: { transaction: string }[] }>( 
      `${API_URLS.SWAP_HOST}/transaction/swap-base-in`, 
      {
        computeUnitPriceMicroLamports: String(priorityFee.data.default.h),
        swapResponse,
        txVersion,
        wallet: owner.publicKey.toBase58(),
        wrapSol: isInputSol,
        unwrapSol: isOutputSol,
        inputAccount: isInputSol ? undefined : inputTokenAcc?.toBase58(),
        outputAccount: isOutputSol ? undefined : outputTokenAcc?.toBase58(),
        referrerWallet,
      }
    );
    
    // 3. Process and send transactions
    const allTxBuf = swapTransactions.data.map((tx) => Buffer.from(tx.transaction, 'base64'));
    const allTransactions = allTxBuf.map((txBuf) =>
      isV0Tx ? VersionedTransaction.deserialize(txBuf) : Transaction.from(txBuf)
    );
  6. Troubleshoot common Raydium SDK errors

    master

    Block height exceeded / exceeded CUs meter at BPF instruction

    • Transactions may have expired. Set higher priority fees using computeBudgetConfig.
    • If testing on devnet, ensure you have replaced the programId with the devnet equivalent.

    API returns null for fetchPoolById or fetchFarmInfoById

    • The Raydium API currently does not support devnet pool/farm data; use mainnet for these calls.
    • For devnet testing, use raydium.xxxx.getRpcPoolInfos instead, as it supports fetching pool info directly from the RPC.
    • Newly created pools may take a few minutes to sync to the API. Use getRpcPoolInfos for immediate data.

    Create AMM pool errors

    • 0x10001a9: This often occurs if using external tools (like Dexlab) that use the wrong devnet program ID. Use the createMarket.ts script provided in this demo to create markets on devnet.
    • lp amount is too less: Increase the base/quote amount. If using SOL/WSOL, it is recommended to provide more than 4 SOL ($4 \times 10^9$ lamports) in the initial amount.
  7. Fetch pool list by mints (Mainnet only)

    master

    Use raydium.api.fetchPoolByMints to retrieve a list of pools based on specific mint addresses. This method is currently supported on mainnet only.

    import { PoolFetchType } from '@raydium-io/raydium-sdk-v2'
    
    const list = await raydium.api.fetchPoolByMints({
      mint1: '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R', // required
      mint2: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v', // optional
      type: PoolFetchType.All, // optional
      sort: 'liquidity', // optional
      order: 'desc', // optional
      page: 1, // optional
    })
  8. Fetch Mint info and Token accounts

    master

    Get Mint information

    Retrieve information for a specific mint address via API or RPC:

    await raydium.token.getTokenInfo('<Mint address>')

    Fetch wallet token accounts

    Retrieve the token accounts for the connected wallet. To force a fresh fetch, pass { forceUpdate: true }:

    await raydium.account.fetchWalletTokenAccounts({ forceUpdate: true })
  9. Reclaim excess rent from SPL Token and Token-2022 accounts

    master

    You can reclaim excess SOL (rent) sitting in SPL Token and Token-2022 accounts using the createWithdrawExcessLamportsInstruction utility. This instruction calculates the excess amount automatically, ensuring the account remains rent-exempt and the token balance is untouched.

    To avoid exceeding the 1,232-byte transaction limit, accounts should be batched (using a constant like ACCOUNTS_PER_TX) because every instruction adds a writable account key to the transaction message.

    Workflow:

    1. Scan for reclaimable accounts using scanReclaimableRent.
    2. Batch the accounts to stay within transaction size limits.
    3. Use TxBuilder to construct transactions containing createWithdrawExcessLamportsInstruction for each account in the batch.
    4. Execute the transactions using versionMultiBuild to chain batches efficiently.

    Note: The demo script includes a DRY_RUN flag. When true, it uses connection.simulateTransaction to verify the expected lamport movement without sending actual transactions.

    import { TxBuilder } from '@raydium-io/raydium-sdk-v2'
    import { createWithdrawExcessLamportsInstruction } from './utils'
    
    // Inside a batch loop:
    const builder = new TxBuilder({
      connection,
      feePayer: owner.publicKey,
      cluster: raydium.cluster,
      owner: raydium.owner,
    })
    
    builder.addInstruction({
      instructions: batch.map((account) =>
        createWithdrawExcessLamportsInstruction({
          source: account.pubkey,
          destination: owner.publicKey,
          authority: owner.publicKey,
          programId: account.programId,
        })
      ),
    })
    
    const builtTxs = await builder.versionBuild({ txVersion })
    // ... execute builtTxs
  10. Get a Launchpad Pool ID from mint addresses

    master

    If you only have the mint addresses for a Launchpad pool, you can derive the Pool ID using the getPdaLaunchpadPoolId utility function. This requires the appropriate program ID (e.g., DEV_LAUNCHPAD_PROGRAM or LAUNCHPAD_PROGRAM) and the two mint addresses involved in the pool.

    const { publicKey: poolId } = getPdaLaunchpadPoolId(DEV_LAUNCHPAD_PROGRAM, mintA, mintB)