2

I am trying to create and partial sign a transaction for create an account, but I keep receiving a keypair mismatch error. My code looks like this:

from spl.token.instructions import create_associated_token_account
from solana.keypair import Keypair
from solana.publickey import PublicKey
from solana.transaction import Transaction

signer = Keypair()

create_transaction_instruction = create_associated_token_account(
    payer=PublicKey(mintFeePayer), owner=signer.public_key, mint=PublicKey(mintPublicKey)
)

transaction = Transaction()
transaction.add(
    create_transaction_instruction
)

transaction.sign_partial(signer)

I am using https://github.com/michaelhly/solana-py which apparently is the most python unofficial library for this, I am open to use something else if it works.

And I always get:

Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "kinetic_sdk/__main__.py", line 49, in <module>
    transaction.sign_partial(signer)
  File "/Users/alexramirez/Library/Caches/pypoetry/virtualenvs/kinetic-sdk--u4hmztD-py3.8/lib/python3.8/site-packages/solana/transaction.py", line 299, in sign_partial
    self._solders.partial_sign(underlying_signers, self._solders.message.recent_blockhash)
solders.SignerError: keypair-pubkey mismatch
make: *** [run_sdk] Error 1

Thanks.

Updated code just using solders:

from solders.message import Message
from solders.keypair import Keypair
from solders.instruction import Instruction, AccountMeta
from solders.hash import Hash
from solders.transaction import Transaction
from solders.pubkey import Pubkey

TOKEN_PROGRAM_ID = Pubkey.from_string('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA')
ASSOCIATED_TOKEN_PROGRAM_ID = Pubkey.from_string('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL')
SYSVAR_RENT_PUBKEY = Pubkey.from_string('SysvarRent111111111111111111111111111111111')
ZERO_BYTES = bytes([0])
SYSTEM_PROGRAM_PROGRAM_ID = Pubkey.from_string('11111111111111111111111111111111')

owner = Keypair.from_base58_string('2an9mq3qY6e7PhGxHYRcw3JbpHLrBYgRzH5QBKgJZSxUUszYrgXQbRFZicuVWZLNiBzeUE3rgDma2EnYQKse8UpB')
fee_payer = Pubkey.from_string('MogXFseNqiFnRtk6wrDL9BDfKRZhjP5VBSiE1E35zeJ')

associated_token_address = Pubkey.from_string('3FuYhW79b3xbyixukA8pav6P9TgEwtCKPEhC1sULxBxG')

instruction = Instruction(
    ASSOCIATED_TOKEN_PROGRAM_ID,
    ZERO_BYTES,
    [
        AccountMeta(fee_payer, True, True),
        AccountMeta(associated_token_address, False, True),
        AccountMeta(owner.pubkey(), False, False),
        AccountMeta(SYSTEM_PROGRAM_PROGRAM_ID, False, False),
        AccountMeta(TOKEN_PROGRAM_ID, False, False),
        AccountMeta(SYSVAR_RENT_PUBKEY, False, False),
    ],
)

null_signer = NullSigner(owner.pubkey())

message = Message([instruction], owner.pubkey())
blockhash = Hash.default()  # replace with a real blockhash
transaction = Transaction([owner], message, blockhash)

print(transaction)

New Error:

thread '<unnamed>' panicked at 'Transaction::sign failed with error NotEnoughSigners', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/solana-sdk-1.10.25/src/transaction/mod.rs:710:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Traceback (most recent call last):
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.8/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "src/__main__.py", line 88, in <module>
    transaction = Transaction([owner], message, blockhash)
pyo3_runtime.PanicException: Transaction::sign failed with error NotEnoughSigners
make: *** [start] Error 1
4
  • have you tried making the payer and signer the same wallet? also, solana-py is one of if not the only library for interacting with Solana in python. tutorials and docs are lacking but its your best option.
    – Pixeled
    Aug 5, 2022 at 21:10
  • Thanks @Pixeled Signing doesn't show any errors when using the same wallet, but In my case I am creating a new account (signer), so the payer should be a hot wallet with SOL, the signer which is a new account doesn't have any SOL on it to pay the fee, so the account it is not created. Do you have by any change an example for creating a new account? :) Aug 7, 2022 at 7:13
  • I think the payer and the signer must be the same. here is a segment from the solana cookbook (solanacookbook.com/core-concepts/transactions.html#deep-dive). "All transactions require at least one writable account to sign the transaction. Once submitted, the writable signer account that is serialized first will be the fee payer. This account will pay for the cost of the transaction regardless of whether the transaction succeeds or fails. If the fee payer does not have a sufficient balance to pay the transaction fee, the transaction will be dropped."
    – Pixeled
    Aug 8, 2022 at 1:30
  • Could you add the code used to send the transaction
    – C.OG
    Aug 12, 2022 at 17:12

2 Answers 2

1

solana-py does support partial signing these days. You're just signing with the wrong keypair. The payer arg to create_associated_token_account needs to be the keypair that signs the tx, not the owner.

So you want something like:

from solana.keypair import Keypair
from solana.publickey import PublicKey
from solana.transaction import Transaction

signer = Keypair()

create_transaction_instruction = create_associated_token_account(
    payer=signer, owner=owner_pubkey, mint=PublicKey(mint_pubkey)
)

transaction = Transaction()
transaction.add(
    create_transaction_instruction
)

transaction.sign_partial(signer)
1
0

I don't think solana-py properly supports partial signing. It only supports Keypair, but lifts from the Rust SDK via solders. The Rust SDK partial signing is implemented around a generic Signer trait, one implementation of which is NullSigner (basically just a Pubkey) used as a place holder for absentee signers during partial signing. You're getting that error because all signers are not specified in some form. It may be easier to use solders directly as it does provide a NullSigner implementation.

6
  • Thank you @trent.sol, this is helpful. I was about to get to the conclusion that solana-py doesn't support partial signing. According to your suggestion of using solders do you mean that I should migrate my entire Transaction code from solana-py and reimplement it in solders or just the Instruction and the Signing part? I wonder if there is a sample code available. Aug 18, 2022 at 3:29
  • sorry i don't know the internals of either of those modules sufficiently to say whether they're compatible or not. from the docs, it looks like solders can do all the things on its own, though it's not pure python so installation may be complicated.
    – trent.sol
    Aug 18, 2022 at 4:18
  • I started trying to implement it using solders, but yes, it is more difficult than I thought. I'll keep trying, but if there is a snippet to create an account instruction with solders, would be helpful. Thanks! Aug 18, 2022 at 18:45
  • again sorry, never used it, don't write much python. i just browsed the docs/code of both modules and know how the core partial signing feature works since i co-wrote support for the rust SDK
    – trent.sol
    Aug 18, 2022 at 19:17
  • I have updated my code and the question with solders, your hints have been helpful so far. Thanks. Aug 20, 2022 at 10:03

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.