← Back to blog

Solana Raydium SDK Swap Example in TypeScript with Magic SDK

web3solanatypescript

Solana Raydium SDK Swap Example in TypeScript with Magic SDK

TL;DR

  • Use Raydium SDK's Liquidity.makeSwapInstructionSimple() to build swap instructions
  • Sign transactions with Magic SDK for wallet-as-a-service integration
  • Add priority fees with ComputeBudgetProgram for faster transaction processing

Requirements: Node.js, @solana/web3.js, @raydium-io/raydium-sdk, @magic-sdk/admin

npm install @solana/web3.js @raydium-io/raydium-sdk @magic-sdk/admin

In this tutorial, we'll demonstrate how to perform a token swap on Solana using the Raydium SDK in TypeScript. Additionally, we'll show how to use the Magic SDK for signing transactions. We'll also include a method to convert SOL to lamports using Solana's web3.js library.

Step 2: Import Necessary Modules

import {
  Connection,
  PublicKey,
  SystemProgram,
  TransactionInstruction,
  LAMPORTS_PER_SOL,
  ComputeBudgetProgram,
  VersionedTransaction,
  TransactionMessage,
} from "@solana/web3.js";
import { Liquidity } from "@raydium-io/raydium-sdk";
import { Magic } from "@magic-sdk/admin";

Step 3: Setup Magic SDK and Solana Connection

Initialize the Magic SDK and Solana connection:

const magic = new Magic("YOUR_MAGIC_API_KEY", {
  extensions: [
    new SolanaExtension({
      rpcUrl: "YOUR RPC URL",
    }),
  ],
});
const connection = new Connection("YOUR RPC URL");
const wallet = magic.wallet;

Step 4: Helper Functions

Add Priority Instructions (Optional)

You can omit this part if the makeSwapInstructionSimple already has a builtin setup for priority instructions.

function addPriorityInstructions(
  instructions: TransactionInstruction[]
): TransactionInstruction[] {
  const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({
    units: 1000000,
  });
  const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({
    microLamports: 1000,
  });
  instructions.unshift(modifyComputeUnits, addPriorityFee);
  return instructions;
}

Create Fee Transfer Instruction (Optional)

If you want to have a fee usage mechanism you can add the instruction that is returned in this function.

async function createFeeTransferInstruction(
  amount: number,
  feeWallet: PublicKey,
  userWallet: PublicKey
): Promise<TransactionInstruction> {
  const feeAmount = Math.ceil(amount * 0.0005);
  const feeAmountInLamports = feeAmount * LAMPORTS_PER_SOL;
  return SystemProgram.transfer({
    fromPubkey: userWallet,
    toPubkey: feeWallet,
    lamports: feeAmountInLamports,
  });
}

Step 5: Perform Swap Transaction

Integrate the helper functions to perform the swap:

async function performSwap(
  amountIn: number,
  minAmountOut: number,
  poolKeys: any,
  userTokenAccounts: any,
  feeWallet: PublicKey,
  fixedSide: any
) {
  const swapTransaction = await Liquidity.makeSwapInstructionSimple({
    connection,
    poolKeys,
    userKeys: {
      tokenAccounts: userTokenAccounts,
      owner: wallet.publicKey,
    },
    amountIn,
    amountOut: minAmountOut,
    fixedSide,
  });
 
  const recentBlockhash = await connection.getLatestBlockhash();
  let instructions =
    swapTransaction.innerTransactions[0].instructions.filter(Boolean);
 
  const feeTransferInstruction = await createFeeTransferInstruction(
    amountIn,
    feeWallet,
    wallet.publicKey
  );
  instructions.push(feeTransferInstruction);
 
  instructions = addPriorityInstructions(instructions);
 
  const versionedTransaction = new VersionedTransaction(
    new TransactionMessage({
      payerKey: wallet.publicKey,
      recentBlockhash: recentBlockhash.blockhash,
      instructions: instructions,
    }).compileToV0Message()
  );
 
  const signedTransaction =
    await magic.wallet.signTransaction(versionedTransaction);
  return signedTransaction;
}

Step 6: Example Usage

Call the performSwap function with the necessary parameters:

(async () => {
  const amountInSOL = 1;
  const amountInLamports = amountInSOL * LAMPORTS_PER_SOL;
  const minAmountOut = 500000;
  const poolKeys = {}; // Replace with actual pool keys
  const userTokenAccounts = {}; // Replace with actual user token accounts
  const feeWallet = new PublicKey("YOUR_FEE_WALLET_ADDRESS");
  const fixedSide = {}; // Replace with actual fixed side information
 
  try {
    const signedTransaction = await performSwap(
      amountInLamports,
      minAmountOut,
      poolKeys,
      userTokenAccounts,
      feeWallet,
      fixedSide
    );
    console.log("Signed Transaction:", signedTransaction);
 
    const signature = await connection.sendRawTransaction(
      Buffer.from(swapTransaction.rawTransaction as string, "base64")
    );
    const recentBlockhashForSwap =
      await connection.getLatestBlockhash("finalized");
    const confirmation = await connection.confirmTransaction(
      {
        signature,
        ...recentBlockhashForSwap,
      },
      "confirmed"
    );
 
    if (confirmation.value.err) {
      console.error("Error buying token:", confirmation.value.err);
    }
    console.log("Confirmed! Transaction ID:", `https://solscan.io/tx/${signature}`);
  } catch (error) {
    console.error("Error performing swap:", error);
  }
})();

Conclusion

In this guide, we've shown how to perform a token swap using the Raydium SDK with the Magic SDK for transaction signing in TypeScript. We also included how to convert SOL to lamports and add a priority fee to your transactions. This approach ensures that your swaps are processed efficiently while also including a usage fee.

Related Posts