A minimal Solana program built with Anchor that executes external program instructions (CPI) with dynamic instruction data and a caller-provided list of remaining accounts.
- Exposes
execute_swap(ctx, instruction_data: Vec<u8>) - Builds a Solana
Instructionfor the specifiedexternal_programusing:instruction_databytes you pass to the methodremaining_accountsforwarded asAccountMeta[]in the same order
- Invokes the target program via
invoke.
{
"name": "execute_swap",
"accounts": [
{ "name": "user", "writable": true, "signer": true },
{ "name": "external_program" }
],
"args": [
{ "name": "instruction_data", "type": "bytes" }
]
}user: signer who pays for the transaction / invoking user.external_program: unchecked program ID of the target to call.remaining_accounts: all other accounts required by the external instruction in the exact order expected by that program.
anchor buildanchor testUpdate Anchor.toml as needed and then:
anchor deployimport { Program, AnchorProvider, web3 } from "@coral-xyz/anchor";
// program: Program<AmmExecutor>
// externalProgramId: web3.PublicKey
// accounts required by the target instruction in the correct order
const remainingAccounts: web3.AccountMeta[] = [
{ pubkey: acct1, isWritable: true, isSigner: false },
{ pubkey: acct2, isWritable: false, isSigner: false },
// ...
];
// Build the exact bytes required by the target program's instruction
// Keep this payload small; prefer accounts for large data.
const instructionData = Buffer.from([/* ... encoded ix data ... */]);
await program.methods
.executeSwap([...instructionData]) // bytes -> number[] or Buffer also works
.accounts({
user: provider.wallet.publicKey,
externalProgram: externalProgramId,
})
.remainingAccounts(remainingAccounts)
.rpc();- Ensure
remaining_accountsexactly matches the target program's expected order and flags. - Keep
instruction_datasmall (hundreds of bytes). For larger payloads, store data in an account and pass that account instead.
- Error:
memory allocation failed, out of memory- Reduce
instruction_datasize - Pass only the necessary
remaining_accountsand ensure correct order - If the target program expects big data, write it into an account and pass the account
- Reduce
external_programisUncheckedAccount; callers control which program is invoked. Gate or restrict at the client/transaction layer as needed.
MIT