1

I'm trying to create a swap transaction using the Jupiter API, and all seems to be done correctly until the part where I have to sign the transaction, it just fails and for me makes no sense since I'm using the Keypair for signing as the same as for interacting with the JUP API. Below is the code. Does anyone know what is happening here? Thanks!

from solders.hash import Hash
from solana.rpc.api import Client
from spl.token.client import Token
from solders.pubkey import Pubkey
from solders.keypair import Keypair
from solders.signature import Signature
from solders.system_program import TransferParams, transfer
from solana.transaction import Transaction

import requests
import base64
import json

LAMPORT_PER_SOL = 1000000000

# Get your keypair
keypair = Keypair().from_base58_string("x Base58 string obv")

# Create the client
client = Client("https://api.devnet.solana.com")
recent_blockhash = client.get_latest_blockhash()

# Print the public key of the new account
print(f"Your solana address (Public key): {keypair.pubkey()}")

"""
response = client.request_airdrop(keypair.pubkey(), 1_000_000_000)
print(response.to_json())
signature = Signature.from_string(json.loads(response.to_json())['result'])

# Confirm the transaction
client.confirm_transaction(signature)
print("Airdrop successful!")"""

# Check the balance
balance = json.loads(client.get_balance(keypair.pubkey()).to_json())
print(f"Balance for {keypair.pubkey()} is {balance['result']['value'] / LAMPORT_PER_SOL} SOL")

#####################################

while True:
    # Fetching the quote for swapping SOL to USDC
    quote_url = "https://quote-api.jup.ag/v6/quote"
    quote_params = {
        "inputMint": "So11111111111111111111111111111111111111112",
        "outputMint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",  # USDC
        "amount": 100000000,
        "slippageBps": 50
    }
    quote_response = requests.get(quote_url, params=quote_params)
    quote_data = quote_response.json()

    # Fetching the serialized transaction for the swap
    swap_url = "https://quote-api.jup.ag/v6/swap"
    swap_payload = {
        "quoteResponse": quote_data,
        "userPublicKey": str(keypair.pubkey()),
        "wrapAndUnwrapSol": True
    }

    swap_response = requests.post(swap_url, headers={'Content-Type': 'application/json'}, data=json.dumps(swap_payload))
    swap_data = swap_response.json()

    swap_transaction = swap_data.get('swapTransaction')

    try:
        transaction = Transaction.deserialize(base64.b64decode(swap_transaction))
        transaction.recent_blockhash = recent_blockhash.value.blockhash
        transaction.sign(keypair)
        raw_transaction = transaction.serialize()
        print(raw_transaction)

        # tx_signature = client.send_raw_transaction(raw_transaction)
        # print(f"Transaction Signature: {tx_signature}")
    except ValueError:
        print('Error deserializing swap transaction')

Basically the error is at transaction.sign(keypair)

Traceback (most recent call last):
  File "C:\Users\Account\Downloads\sol_sign.py", line 71, in <module>
    transaction.sign_partial(keypair)
  File "C:\Users\Account\AppData\Local\Programs\Python\Python310\lib\site-packages\solana\transaction.py", line 225, in sign_partial
    self._solders.partial_sign(partial_signers, self._solders.message.recent_blockhash)
solders.SignerError: keypair-pubkey mismatch

IMPORTANT EDIT: I changed the code to:

try:
    raw_transaction = VersionedTransaction.from_bytes(base64.b64decode(swap_transaction))
    print('Raw transaction: ', raw_transaction)
    print(raw_transaction.message.recent_blockhash)
    signature = keypair.sign_message(to_bytes_versioned(raw_transaction.message))
    signed_transaction = VersionedTransaction.populate(raw_transaction.message, [signature])
    print('Signed transaction: ', signed_transaction)

    tx_signature = client.simulate_transaction(signed_transaction).value
    print(f"Transaction Signature: {tx_signature}")
except ValueError as e:
    print('Error deserializing swap transaction', e)

Now im getting err: Some(BlockhashNotFound) when simulating the transaction, which doesnt makes sense since is retrieved from JUP API

1
  • Since your question has changed from one about pubkey/keypair mismatches to one about a missing blockhash, can you rewrite the question and the title to only deal with the latter? Thank you! Commented Dec 30, 2023 at 5:21

1 Answer 1

1

You're fetching a transaction from the Jupiter API, which is signed against a mainnet-beta blockhash, and then sending that transaction to devnet, where the blockhash doesn't exist.

Be sure to interact exclusively with mainnet-beta if you plan to use the Jupiter API, so create your client with:

client = Client("https://api.mainnet-beta.solana.com")

Be warned though: mainnet-beta does not allow for airdrops, and is meant for "real" usage, and not testing / development.

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.