typescriptswapsolanasolana-web3jssolana-transaction-instruction

How can I add swap instruction and transferSOL instruction to one transaction in Solana?


I would like to transfer some SOL to a specific wallet as a fee when a swap transaction occurs.

So, I made this code but it didn't work. Here, I used Jupiter Swap API to swap tokens. And I added my transferSOL instruction to the swap transaction.

Please help me.

Thanks.

const connection = new Connection(RPC_URL, "confirmed");
const tokenDecimals = await getTokenDecimals(connection, tokenAddress);
const slippageBps = parseInt(process.env.SLIPPAGEBPS || "") || 50;
let swapInfo: any;

swapInfo = await getSwapInfo(
    NATIVE_MINT.toBase58(),
    tokenAddress,
    amount * LAMPORTS_PER_SOL,
    slippageBps
);

const swapTransaction = await getSwapTransaction(swapInfo, anchorWallet);
const swapTransactionBuf = Buffer.from(swapTransaction, "base64");
const latestBlockHash = await connection.getLatestBlockhash();
const versionedTransaction =
    VersionedTransaction.deserialize(swapTransactionBuf);

const transferInstruction = SystemProgram.transfer({
    fromPubkey: sender.publicKey,
    toPubkey: receiverPublicKey,
    lamports: 0.01 * LAMPORTS_PER_SOL,
});

// Extract existing instructions from the versioned transaction
const existingInstructions = versionedTransaction.message.instructions;

// Add the transfer instruction to the list of instructions
const updatedInstructions = [...existingInstructions, transferInstruction];

// Reconstruct the message with the updated instructions
const updatedMessage = new TransactionMessage({
    payerKey: anchorWallet.payer.publicKey,
    recentBlockhash: latestBlockHash.blockhash,
    instructions: updatedInstructions,
});

// Create a new VersionedTransaction with the updated message
const updatedTransaction = new VersionedTransaction(updatedMessage);

// Sign the updated transaction
updatedTransaction.sign([anchorWallet.payer]);

These are Jupiter API functions.

const JUP_API = "https://quote-api.jup.ag/v6";

export const getSwapInfo = async (tokenA: string, tokenB: string, amount: number, slippageBps: number) => {
  const res = await axios.get(`${JUP_API}/quote?inputMint=${tokenA}&outputMint=${tokenB}&amount=${amount}&slippageBps=${slippageBps}`);
  const swapinfo = res.data;
  return swapinfo;
};

export const getSwapTransaction = async (quoteResponse: any, anchorWallet: Wallet) => {
  const swapResponse = await axios.post(`${JUP_API}/swap`, {
    quoteResponse,
    userPublicKey: anchorWallet.publicKey.toString(),
    wrapAndUnwrapSol: true,
    prioritizationFeeLamports: 200000, // or custom lamports: 1000
  });
  return swapResponse.data.swapTransaction;
};

Solution

  • You should get swap instructions instead of swap transaction using Jupiter Swap API.

    const instructions = (
        await axios.post(
          "https://quote-api.jup.ag/v6/swap-instructions",
          {
            quoteResponse: routeData,
            userPublicKey: ownerAddress,
            wrapAndUnwrapSol: true,
            computeUnitPriceMicroLamports: Math.floor(gasFee * 1e9), // ✅ Convert SOL Gas Fee to MicroLamports
          },
          {
            headers: {
              "Content-Type": "application/json",
            },
          }
        )
    ).data;
    

    And add these swap Instructions and your transferSOL instruction to one transaction.

    I hope this helps you.