I tried a few variations and I cannot get the instruction to work or be defined correctly. I have this client code and I welcome suggestions about how to code the instruction variable - Error -
Uncaught error: instruction is not defined
import {TransactionInstruction} from '@solana/web3.js'
console.log(pg.PROGRAM_ID.toString());
// Get latest blockhash info
const blockhashInfo = await pg.connection.getLatestBlockhash();
console.log(blockhashInfo);
// Create transaction
const tx = new web3.Transaction({
...blockhashInfo,
});
console.log("tx ==",tx);
const programId = new web3.PublicKey(pg.PROGRAM_ID.toString());
// Add our hello world program instruction
const account1 = new web3.PublicKey("BkQTFDah5ogoy9FtcGKKvQr67cjrZABDYVY9om9o188s");
// 4dGDp3BuTaXiqJwwJhh9abUBBm6hMhRkidttr5N4Cemm
const account2 = new web3.PublicKey("4dGDp3BuTaXiqJwwJhh9abUBBm6hMhRkidttr5N4Cemm");
const amount = 1000;
// encode the payment instruction
const instructionObject = new TransactionInstruction({
instruction, // this is not defined
amount,
})
tx.add(
new web3.TransactionInstruction({
programId: pg.PROGRAM_ID,
keys: [
{pubkey: account1, isSigner: false, isWritable: true},
{pubkey: account2, isSigner: false, isWritable: true},
// add any additional keys here
],
//data: Buffer.from([]),
data: instructionObject.toBuffer(),
})
);
console.log("tx added ", tx);
// Sign transaction
tx.sign(pg.wallet.keypair);
// Send the transaction to the Solana cluster
const txHash = await pg.connection.sendRawTransaction(tx.serialize());
console.log(txHash);
The Rust contract is as follows -
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint,
entrypoint::ProgramResult,
program_error::ProgramError,
pubkey::Pubkey,
};
/// Custom program errors
#[derive(Debug, Clone, Copy)]
pub enum CustomError {
InsufficientFundsForTransaction,
}
impl From<CustomError> for ProgramError {
fn from(e: CustomError) -> Self {
ProgramError::Custom(e as u32)
}
}
/// Transfers lamports from one account (must be program owned)
/// to another account. The recipient can by any account
fn transfer_service_fee_lamports(
from_account: &AccountInfo,
to_account: &AccountInfo,
amount_of_lamports: u64,
) -> ProgramResult {
// Does the from account have enough lamports to transfer?
if **from_account.try_borrow_lamports()? < amount_of_lamports {
return Err(CustomError::InsufficientFundsForTransaction.into());
}
// Debit from_account and credit to_account
**from_account.try_borrow_mut_lamports()? -= amount_of_lamports;
**to_account.try_borrow_mut_lamports()? += amount_of_lamports;
Ok(())
}
/// Primary function handler associated with instruction sent
/// to your program
fn instruction_handler(accounts: &[AccountInfo]) -> ProgramResult {
// Get the 'from' and 'to' accounts
let account_info_iter = &mut accounts.iter();
let from_account = next_account_info(account_info_iter)?;
let to_service_account = next_account_info(account_info_iter)?;
// Extract a service 'fee' of 5 lamports for performing this instruction
transfer_service_fee_lamports(from_account, to_service_account, 5u64)?;
// Perform the primary instruction
// ... etc.
Ok(())
}
entrypoint!(process_instruction);
fn process_instruction(program_id: &Pubkey, accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
// Match the first byte of the instruction data to determine which instruction to execute
match instruction_data[0] {
0 => {
instruction_handler(accounts)?;
}
// ... etc.
_ => return Err(ProgramError::InvalidInstructionData),
}
Ok(())
}