POST /api/v1/instructions returns raw Solana instructions instead of a complete transaction. Use this when you need to combine swap instructions with other logic in a single transaction.
import { Connection, TransactionMessage, VersionedTransaction, PublicKey, AddressLookupTableAccount,} from "@solana/web3.js";const connection = new Connection("https://api.mainnet-beta.solana.com");// 1. Fetch address lookup tablesconst altAccounts: AddressLookupTableAccount[] = [];for (const altAddress of data.addressLookupTableAddresses) { const altAccount = await connection.getAddressLookupTable(new PublicKey(altAddress)); if (altAccount.value) altAccounts.push(altAccount.value);}// 2. Convert raw instructions to TransactionInstructionconst instructions = data.instructions.map((ix) => ({ programId: new PublicKey(ix.programId), keys: ix.accounts.map((acc) => ({ pubkey: new PublicKey(acc.publicKey), isSigner: acc.isSigner, isWritable: acc.isWritable, })), data: Buffer.from(ix.data, "base64"),}));// 3. Build v0 transactionconst { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash();const messageV0 = new TransactionMessage({ payerKey: wallet.publicKey, recentBlockhash: blockhash, instructions,}).compileToV0Message(altAccounts);const transaction = new VersionedTransaction(messageV0);transaction.sign([wallet]);// 4. Submitconst signature = await connection.sendRawTransaction(transaction.serialize());await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight });
Always include the addressLookupTableAddresses when building a v0 transaction. Without them, the transaction may exceed the size limit for multi-hop routes.