Search code examples
pythonsolanaanchor-solana

Unable to Sign Solana Transaction using solana-py throws not enough signers


using solana library from pip

pip install solana

and then trying to perform withdraw_from_vote_account

txn = txlib.Transaction(fee_payer=wallet_keypair.pubkey())
# txn.recent_blockhash = blockhash
txn.add(
        vp.withdraw_from_vote_account(
            vp.WithdrawFromVoteAccountParams(
                vote_account_from_pubkey=vote_account_keypair.pubkey(),
                to_pubkey=validator_keypair.pubkey(),
                withdrawer=wallet_keypair.pubkey(),
                lamports=2_000_000_000,
            )
        )
    )
txn.sign(wallet_keypair)
txn.serialize_message()
solana_client.send_transaction(txn).value

This throw me an error

Traceback (most recent call last):
  File "main.py", line 119, in <module>
    solana_client.send_transaction(txn).value
  File "venv/lib/python3.8/site-packages/solana/rpc/api.py", line 1057, in send_transaction
    txn.sign(*signers)
  File "venv/lib/python3.8/site-packages/solana/transaction.py", line 239, in sign
    self._solders.sign(signers, self._solders.message.recent_blockhash)
solders.SignerError: not enough signers

I tried to workaround with adding more keypair to sign

txn.sign(wallet_keypair,validator_keypair)

Doing this it throws me an error on the sign method

self._solders.sign(signers, self._solders.message.recent_blockhash)
solders.SignerError: keypair-pubkey mismatch

not sure how to resolve this any help appreciated


Solution

  • The error message isn't very useful, but you need a blockhash on the message in your transaction in order to properly sign it, ie:

    blockhash = solana_client.get_latest_blockhash().value['blockhash']
    txn = txlib.Transaction(recent_blockhash=blockhash, fee_payer=wallet_keypair.pubkey())
    

    A few other notes: txn.serialize_message() doesn't modify the transaction in place, but rather returns the transaction bytes, so there's no need to call it at all.

    And finally, send_transaction actually does the work of fetching the blockhash and signing the transaction, so you can simplify the whole thing to:

    txn = txlib.Transaction(fee_payer=wallet_keypair.pubkey())
    txn.add(
            vp.withdraw_from_vote_account(
                vp.WithdrawFromVoteAccountParams(
                    vote_account_from_pubkey=vote_account_keypair.pubkey(),
                    to_pubkey=validator_keypair.pubkey(),
                    withdrawer=wallet_keypair.pubkey(),
                    lamports=2_000_000_000,
                )
            )
        )
    solana_client.send_transaction(txn, wallet_keypair).value