1

The code below is copied from the code here

describe("hello-solana", () => {

    // Loading these from local files for development
    //
    const connection = new Connection(`http://localhost:8899`, 'confirmed');
    const payer = createKeypairFromFile(require('os').homedir() + '/.config/solana/id.json');
    const program = createKeypairFromFile('./program/target/so/program-keypair.json');
  
    it("Say hello!", async () => {

        // We set up our instruction first.
        //
        let ix = new TransactionInstruction({
            keys: [
                {pubkey: payer.publicKey, isSigner: true, isWritable: true}
            ],
            programId: program.publicKey,
            data: Buffer.alloc(0), // No data
        });

        // Now we send the transaction over RPC
        //
        await sendAndConfirmTransaction(
            connection, 
            new Transaction().add(ix), // Add our instruction (you can add more than one)
            [payer]
        );
    });
  })

In creating the TransactionInstruction, the following object was passed {pubkey: payer.publicKey, isSigner: true, isWritable: true} setting the payer.publicKey as the signer.

Then later on, when submitting the transaction via sendAndConfirmTransaction, the payer is passed again as a signer:

await sendAndConfirmTransaction(
 connection, 
 new Transaction().add(ix), // Add our instruction (you can add more than one)
 [payer]
)

Question is, why is the key that would be the signer specified twice? When constructing the transaction objects and when submitting the transaction?

Also checking the documentation of sendAndConfirmTransaction which can be seen here the type signature for the function is as follows:

sendAndConfirmTransaction(connection: Connection, transaction: Transaction, 
signers: Signer[], options?: ConfirmOptions): Promise<TransactionSignature>

I noticed that signers is an array. Meaning multiple signers can be passed in right? If so, what does it mean to have multiple signers passed in? Is that how multi-signature features are implemented?

1 Answer 1

1

Here the instruction is being built, where the keys specify the accounts that the instruction requires. In this case there is only 1 account (payer.publicKey) and it is required to be a signer. The actual signing does not occur here, it is simply specifying that the account must be a signer.

let ix = new TransactionInstruction({
            keys: [
                {pubkey: payer.publicKey, isSigner: true, isWritable: true}
            ],
            programId: program.publicKey,
            data: Buffer.alloc(0), // No data
        });

Here the instruction above is being added to a new transaction and sent, with the payer specified as a signer to sign the transaction.

await sendAndConfirmTransaction(
 connection, 
 new Transaction().add(ix), // Add our instruction (you can add more than one)
 [payer]
)

A common example of where multiple signers are passed in is when initializing an account using a new randomly generated keypair.

Check out the create-account program example: https://github.com/solana-developers/program-examples/blob/main/basics/create-account/native/tests/test.ts#L38

https://github.com/solana-developers/program-examples/blob/main/basics/create-account/native/program/src/lib.rs#L17

4
  • Why can't I omit [payer] since isSigner:true is already set when creating TransactionInstruction?
    – dade
    Commented Sep 9, 2022 at 19:35
  • I looked at the create-account and I ask, why should newKeypair be included as part of the signer (and not just have payer)? I ask, since newKeypair is not created yet and hence does not contain any SOL, how then can it be able to sign and pay a transaction?
    – dade
    Commented Sep 9, 2022 at 19:39
  • 1
    isSigner:true is saying that the payer.publicKey must be a signer (but the actual signing does not occur here). Think of it as creating a form that requires someone's signature. Including [payer] as a signer in sendAndConfirmTransaction is when payer actually signs. Think of this as the user required as a signer on the form actually signing the form and then sending it out.
    – john
    Commented Sep 9, 2022 at 19:54
  • 1
    When initializing a new account with a new keypair, the keypair has to be included as a signer on the instruction basically to prove that the whoever controls that keypair approves using that keypair to initialize a new account.
    – john
    Commented Sep 9, 2022 at 20:00

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.