7

I'm trying to call a Solana Program, and when I run sendAndConfirmTransaction, it gives me Signature Verification Failed, and I'm not sure why.

const {sendAndConfirmTransaction, clusterApiUrl, Connection} = require("@solana/web3.js");

let signer = Keypair.generate();
let anotherKeypair = Keypair.generate();

let transaction = someInstruction(signer, anotherKeypair); 
let connection = new Connection(clusterApiUrl('testnet'));

sendAndConfirmTransaction(
  connection,
  transaction,
  [signer]
);
Evan Conrad
  • 3,993
  • 4
  • 28
  • 46

3 Answers3

8

In Solana, you need to pass in both the keypairs of the signer, and the keypairs of the accounts you're creating.

const {sendAndConfirmTransaction, clusterApiUrl, Connection} = require("@solana/web3.js");

let signer = Keypair.generate();
let anotherKeypair = Keypair.generate();

let transaction = someInstruction(signer, anotherKeypair); 
let connection = new Connection(clusterApiUrl('testnet'));

sendAndConfirmTransaction(
  connection,
  transaction,
  [signer, anotherKeypair] // <-- If you made the keypair, you probably want it here!
);

If you're using a wallet connect library, like @solana/wallet-adapter-react, you don't have the signer, but you will still have any keypairs of accounts your generating:

const { sendTransaction } = useWallet();

const anotherKeypair = Keypair.generate(); 

const signature = await sendTransaction(transaction, connection, {
  signers: [anotherKeypair] // You probably want to pass in the keypair here!
});
Evan Conrad
  • 3,993
  • 4
  • 28
  • 46
  • 1
    I give a +1 to this sentence: `In Solana, you need to pass in both the keypairs of the signer, and the keypairs of the accounts you're creating` – Ehsan Khodarahmi Dec 19 '21 at 10:39
  • This answer did not work for me, I posted the version that worked for me using paritalSign – azuldev Jun 04 '22 at 21:15
  • How would you partially sign a program rpc call i.e. `await program.methods.someMethod({...}).accounts({...}).signers(signers).rpc()` – Hyetigran Nov 15 '22 at 19:39
1

This worked for me.

tx.partialSign

let tx = new Transaction();
const anotherKeypair = Keypair.generate(); 

tx.recentBlockhash =  (await connection.getLatestBlockhash("finalized")).blockhash;
tx.feePayer = new PublicKey(publicKeyStringfromWallet);
console.log(tx)

tx.partialSign(anotherKeypair) // THIS SIGNS for web3 keypair

const { signature } = await window.solana.signAndSendTransaction(tx); //THIS signs wallet keypair
azuldev
  • 570
  • 6
  • 10
0

It depends on the isSigner key, if isSigner: true, you need to provide the signer.

For example, the following code will not work because we mention payerAta (Associated Token Account of Payer) has isSigner:true.

const instruction = new TransactionInstruction({
    keys: [
      {
        pubkey: programAta.address,
        isSigner: false,
        isWritable: true,
      },
      {
        pubkey: payerAta.address,
        isSigner: true,
        isWritable: true,
      },
    ],
    programId,
    data: Buffer.alloc(0), // All instructions are hellos
  });
  await sendAndConfirmTransaction(
    connection,
    new Transaction().add(instruction),
    [payer]
  );
}

In this case either we change payerAta to payer, or change the isSigner to false

Alex
  • 359
  • 3
  • 15