michaelhly / solana-py

Solana Python SDK
https://michaelhly.github.io/solana-py
MIT License
979 stars 252 forks source link

Any way to use send_transaction() reliably? #399

Open chiwalfrm opened 6 months ago

chiwalfrm commented 6 months ago

I have a lot of problems with send_transaction(), in that I get a lot of timeouts. The errors look like this.

Traceback (most recent call last):
  File "/home/vmware/b.py", line 49, in <module>
    client.send_transaction(
  File "/home/vmware/.local/lib/python3.10/site-packages/solana/rpc/api.py", line 1067, in send_transaction
    txn_resp = self.send_raw_transaction(txn.serialize(), opts=opts_to_use)
  File "/home/vmware/.local/lib/python3.10/site-packages/solana/rpc/api.py", line 996, in send_raw_transaction
    return self.__post_send_with_confirm(*post_send_args)
  File "/home/vmware/.local/lib/python3.10/site-packages/solana/rpc/api.py", line 1124, in __post_send_with_confirm
    self.confirm_transaction(sig, conf_comm, last_valid_block_height=last_valid_block_height)
  File "/home/vmware/.local/lib/python3.10/site-packages/solana/rpc/api.py", line 1177, in confirm_transaction
    raise UnconfirmedTxError(f"Unable to confirm transaction {tx_sig}")
solana.rpc.core.UnconfirmedTxError: Unable to confirm transaction 62CZWwK9CPhkPGWXJYs6dLZ3hUty9Dja6hVy7t5YRzYySFdxjPgYnXmUeWcijuGYfR3Pt889wnacaUVFVwTks9Ce

Since I want to use this to send to many addresses and reliability is needed, what can I do to prevent these 'Unable to confirm transaction' errors?

This is the line that I use to send the transaction:

        client.send_transaction(
                transaction,
                lawrenceprivate_keysol,
                opts = TxOpts(
                        skip_confirmation = False,
                        preflight_commitment = Confirmed
                )
        )
chiwalfrm commented 6 months ago

It is so unreliable I don't know what I am doing wrong. >50% failure rate. When it works, the function comes back in 5 seconds, and when it fails, it takes 90 seconds and then comes back with "Error: Unable to confirm transaction "

woodychanjm commented 5 months ago

same problem here. what is the best practices for send_transaction?

gtors commented 5 months ago

I failed 100% in the last two days... Transactions don't get in blockchain even if specifying setComputeUnitPrice/setComputeUnitLimit instructions

woodychanjm commented 5 months ago

I failed 100% in the last two days... Transactions don't get in blockchain even if specifying setComputeUnitPrice/setComputeUnitLimit instructions

can show us the code?

gtors commented 5 months ago

I failed 100% in the last two days... Transactions don't get in blockchain even if specifying setComputeUnitPrice/setComputeUnitLimit instructions

The problem turned out to be in the RPC nodes (specifically Alchemy and GetBlock). After switching to the Quicknode, the problem mostly vanished.

can show us the code?

I can't show the exact code because it contains some business logic, but it is very similar to this one:

from decimal import Decimal

from solana.rpc.api import Client
from solana.transaction import Transaction
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer

src: Keypair = ...
dst: Pubkey = ...
sol_amount = Decimal("0.5")
sol_lamports = Decimal("1e+9")

tx = Transaction(fee_payer=src.pubkey())
# SOL transfer
tx.add(
    transfer(
        TransferParams(
            from_pubkey=src.pubkey(),
            to_pubkey=dst,
            lamports=int(sol_amount * sol_lamports),
        )
    )
)
# Extra fee
tx.add(set_compute_unit_limit(300_000))
tx.add(set_compute_unit_price(1000))

client = Client()
tx_sig = client.send_transaction(tx, src).value
client.confirm_transaction(tx_sig)
woodychanjm commented 5 months ago

I failed 100% in the last two days... Transactions don't get in blockchain even if specifying setComputeUnitPrice/setComputeUnitLimit instructions

The problem turned out to be in the RPC nodes (specifically Alchemy and GetBlock). After switching to the Quicknode, the problem mostly vanished.

can show us the code?

I can't show the exact code because it contains some business logic, but it is very similar to this one:

from decimal import Decimal

from solana.rpc.api import Client
from solana.transaction import Transaction
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
from solders.keypair import Keypair
from solders.pubkey import Pubkey
from solders.system_program import TransferParams, transfer

src: Keypair = ...
dst: Pubkey = ...
sol_amount = Decimal("0.5")
sol_lamports = Decimal("1e+9")

tx = Transaction(fee_payer=src.pubkey())
# SOL transfer
tx.add(
    transfer(
        TransferParams(
            from_pubkey=src.pubkey(),
            to_pubkey=dst,
            lamports=int(sol_amount * sol_lamports),
        )
    )
)
# Extra fee
tx.add(set_compute_unit_limit(300_000))
tx.add(set_compute_unit_price(1000))

client = Client()
tx_sig = client.send_transaction(tx, src).value
client.confirm_transaction(tx_sig)

I think you can adjust the TxOpts like: opts = TxOpts(skip_confirmation=False, preflight_commitment="confirmed") and add retry logic