2

I am using a wallet adapter to sign 2 tx:

  1. create a stake account
  2. delegate

in a single wallet approval. and for some reason the tx failed with the following err:

Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 2: incorrect program id for instruction

the code split to 4 functions

  1. create delegate ACC and instructions
  2. prep for balance verify
  3. verify balance
  4. submit tx

it looks like this:

public async verifyBalance(lamportToSend: number, walletPubkey: PublicKey, transaction: Transaction) {
const balance = await this.solanaUtilsService.connection.getBalance(walletPubkey);
const txFee = (await this.solanaUtilsService.connection.getFeeForMessage(
  transaction.compileMessage(),
  'confirmed',
)).value;
const balanceCheck = lamportToSend < balance + txFee ? true : false;
if (!balanceCheck) {
  this._formatErrors({ message: 'not enogh balance' })
  // throw new Error('not enogh balance')
  return false;
}
 return balanceCheck
}

private async prepTx(lamports, tx, walletOwnerPk: PublicKey) {
// verify tx fee
const { blockhash } = await this.solanaUtilsService.connection.getLatestBlockhash();
const txVerify = new Transaction().add(tx)
txVerify.recentBlockhash = blockhash;
txVerify.feePayer = walletOwnerPk

const hasBalance = await this.verifyBalance(lamports, walletOwnerPk, txVerify)
if (hasBalance) {
  return true
} else {
  return false
}

}

public async delegate(lamportsToDelegate: number, walletOwnerPk: PublicKey, validatorVoteKey: string) {
const createStakeAccount = async (lamportToSend: number, stakeAccountOwner: PublicKey) => {
  const minimumAmount = await this.solanaUtilsService.connection.getMinimumBalanceForRentExemption(
    StakeProgram.space,
  );
  const fromPubkey = stakeAccountOwner;
  const newStakeAccount = new Keypair();
  const authorizedPubkey = stakeAccountOwner;
  const authorized = new Authorized(authorizedPubkey, authorizedPubkey);
  const lockup = new Lockup(0, 0, fromPubkey);
  const lamports = minimumAmount + lamportToSend;
  const stakeAccountIns: CreateStakeAccountParams = {
    fromPubkey,
    stakePubkey: newStakeAccount.publicKey,
    authorized,
    lockup,
    lamports
  }
  const newStakeAccountIns = StakeProgram.createAccount(stakeAccountIns)
  return { newStakeAccountIns, newStakeAccount }
}
try {
  const stakeAccountData = await createStakeAccount(lamportsToDelegate, walletOwnerPk)
  const stakeAcc: Keypair = stakeAccountData.newStakeAccount;
  const instruction: DelegateStakeParams = {
    stakePubkey: stakeAcc.publicKey,
    authorizedPubkey: walletOwnerPk,
    votePubkey: new PublicKey(validatorVoteKey)
  }
  const stakeAccIns: Transaction = stakeAccountData.newStakeAccountIns;
  const delegateTX: Transaction = StakeProgram.delegate(instruction);

  const stake: Transaction[] = [stakeAccIns, delegateTX]
  const validTx = await this.prepTx(lamportsToDelegate,delegateTX, walletOwnerPk)


  if (validTx) {
    this.sendTx(stake, walletOwnerPk, [stakeAcc])
  }
} catch (error) {
  console.log(error)
}

}

private async sendTx(txParam: TransactionInstruction[] | Transaction[], walletPk: PublicKey, extraSigners?: Keypair[]) {
try {
  const { lastValidBlockHeight, blockhash } = await this.solanaUtilsService.connection.getLatestBlockhash();
  const txArgs: TransactionBlockhashCtor = { feePayer: walletPk, blockhash, lastValidBlockHeight: lastValidBlockHeight }
  let transaction: Transaction = new Transaction(txArgs).add(...txParam);
  // this._walletStore.signTransaction(transaction);
  this._walletStore.signTransaction(transaction).subscribe({
    next: async (res: Transaction) => {

      if (extraSigners) transaction.partialSign(...extraSigners);

      //LMT: check null signatures
      for (let i = 0; i < transaction.signatures.length; i++) {
        if (!transaction.signatures[i].signature) {
          throw Error(`missing signature for ${transaction.signatures[i].publicKey.toString()}. Check .isSigner=true in tx accounts`)
        }
      }

      const rawTransaction = transaction.serialize({ requireAllSignatures: false });
      const signature = await this.solanaUtilsService.connection.sendRawTransaction(rawTransaction);
      console.log('https://solscan.io/tx/' + signature)
      const txSend: toastData = {
        message: 'transaction subbmitted',
        icon: 'information-circle-outline',
        segmentClass: "toastInfo"
      }
      this.toasterService.msg.next(txSend)
      const config: BlockheightBasedTransactionConfirmationStrategy = {
        signature, blockhash, lastValidBlockHeight: res.lastValidBlockHeight//.lastValidBlockHeight
      }
      await this.solanaUtilsService.connection.confirmTransaction(config) //.confirmTransaction(txid, 'confirmed');
      const txCompleted: toastData = {
        message: 'transaction completed',
        icon: 'information-circle-outline',
        segmentClass: "toastInfo"
      }
      this.toasterService.msg.next(txCompleted)
    },
    error: (err) => {
      this._formatErrors(err)
    },
  })

} catch (error) {
  console.log(error)
  // onMsg('transaction failed', 'error')
}

}

any ideas where it can fail?

4
  • According to your error, StakeProgram has an incorrect program id? What stake program is this, and is it deployed on the cluster you're connected to?
    – C.OG
    Commented Jul 27, 2022 at 13:42
  • i am connecting to testnet, and as you can see the stakeprogram id is settled automatically by the web3 package.
    – Avaulto
    Commented Jul 27, 2022 at 15:20
  • seems like the issue not occur on mainnet
    – Avaulto
    Commented Jul 27, 2022 at 16:06
  • ah, thought so!
    – C.OG
    Commented Jul 27, 2022 at 16:12

1 Answer 1

2

According to your error:

Error: failed to send transaction: Transaction simulation failed: Error processing Instruction 2: incorrect program id for instruction

The program_id for the StakeProgram doesn't match a program deployed on the cluster you're connecting to.

Try search for the program using an explorer to see if it exists on the cluster.

https://explorer.solana.com/address/<program_id>?cluster=testnet

Change testnet for the cluster you're connected to

2
  • Apparently, I used the vote key from different cluster @_@... thx!
    – Avaulto
    Commented Jul 27, 2022 at 17:16
  • done :), just pointing out again thats the validator key wasn’t valid, and not the program id(which is stake111111111111111111111111111ish... program for both mb and testnet)
    – Avaulto
    Commented Jul 28, 2022 at 11:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.