1

I was wondering what is the best way to send a transaction and ensure it gets processed. At the moment i am using this python code that sends an already signed transaction:

from solana.rpc.commitment import Confirmed
from solana.rpc.core import UnconfirmedTxError
from solana.rpc.types import TxOpts
from solders.transaction import VersionedTransaction 


    async def send_transaction(async_client: AsyncClient, signed_txn: VersionedTransaction) -> str:
        opts = TxOpts(
            skip_preflight=False,
            preflight_commitment=Confirmed,
            skip_confirmation=False,
        )
        try:
            result = await async_client.send_raw_transaction(txn=bytes(signed_txn), opts=opts)
            transaction_id = json.loads(result.to_json())["result"]
            return transaction_id
        except UnconfirmedTxError:
            raise Exception("Transaction confirmation timed out. Please set a higher priority fee")

Sometimes this code works well and transactions are processed and confirmed, but other times I get the UnconfirmedTxError, which contains this message: "Unable to confirm transaction <transaction_id>". Sometimes this happens even if I set a very high priority fee for the transaction.

My question is: when i catch the UnconfirmedTxError, is it safe to retry sending the transaction right away, or is there the risk that the same transaction will be executed twice? Should i perform any additional checks before retrying?

Overall, am I using the correct approach for sending transactions? Any advice would be very much appreciated.

1 Answer 1

1

Looking through the solana-py code, it looks like it'll usually do the right thing. You're forcing send_raw_transaction to also confirm the transaction, which eventually calls into https://github.com/michaelhly/solana-py/blob/7f2f3cb8e4028cddc5d550e39f66e031942a9884/src/solana/rpc/async_api.py#L1126

In confirm_transaction however, if last_valid_block_height isn't provided, there's a hardcoded 90 second timeout at https://github.com/michaelhly/solana-py/blob/7f2f3cb8e4028cddc5d550e39f66e031942a9884/src/solana/rpc/async_api.py#L1160

This isn't always correct -- if there's a lot of forking, your transaction's blockhash might be valid for longer than 90 seconds, which means there's a small (but possible) chance that your transaction lands after the 90 second wait.

If you want the confirmation logic to be totally correct, you'll need to set the last_valid_block_height in TxOpts to whatever came out of RPC with your blockhash. If you do that, then you're sure the transaction will never succeed if confirm_transaction fails.

After that, if confirm_transaction fails, you can safely re-sign and send the transaction.

1
  • Thanks, very clear answer! Commented Jul 12 at 17:24

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.