Merge pull request #116 from yanCode/fix/retries

[Refactor] manual_buy.py & manual_sell.py
This commit is contained in:
Anton
2025-06-27 23:46:52 +02:00
committed by GitHub
2 changed files with 105 additions and 161 deletions
+48 -104
View File
@@ -18,7 +18,7 @@ from solders.keypair import Keypair
from solders.message import Message from solders.message import Message
from solders.pubkey import Pubkey from solders.pubkey import Pubkey
from solders.transaction import Transaction, VersionedTransaction from solders.transaction import Transaction, VersionedTransaction
from spl.token.instructions import get_associated_token_address from spl.token.instructions import create_idempotent_associated_token_account, get_associated_token_address
# Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py # Here and later all the discriminators are precalculated. See learning-examples/calculate_discriminator.py
EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399) EXPECTED_DISCRIMINATOR = struct.pack("<Q", 6966180631402821399)
@@ -126,123 +126,66 @@ async def buy_token(
# Calculate maximum SOL to spend with slippage # Calculate maximum SOL to spend with slippage
max_amount_lamports = int(amount_lamports * (1 + slippage)) max_amount_lamports = int(amount_lamports * (1 + slippage))
# Create associated token account with retries accounts = [
for ata_attempt in range(max_retries): AccountMeta(pubkey=PUMP_GLOBAL, is_signer=False, is_writable=False),
try: AccountMeta(pubkey=PUMP_FEE, is_signer=False, is_writable=True),
account_info = await client.get_account_info(associated_token_account, encoding="base64") AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
if account_info.value is None: AccountMeta(pubkey=bonding_curve, is_signer=False, is_writable=True),
print( AccountMeta(
f"Creating associated token account (Attempt {ata_attempt + 1})..." pubkey=associated_bonding_curve,
) is_signer=False,
create_ata_ix = spl_token.create_associated_token_account( is_writable=True,
payer=payer.pubkey(), owner=payer.pubkey(), mint=mint ),
) AccountMeta(
pubkey=associated_token_account,
is_signer=False,
is_writable=True,
),
AccountMeta(pubkey=payer.pubkey(), is_signer=True, is_writable=True),
AccountMeta(pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False),
AccountMeta(
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(pubkey=creator_vault, is_signer=False, is_writable=True),
AccountMeta(
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
),
AccountMeta(pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False),
]
msg = Message([create_ata_ix], payer.pubkey()) discriminator = struct.pack("<Q", 16927863322537952870)
tx_ata = await client.send_transaction( data = (
Transaction( discriminator
[payer], + struct.pack("<Q", int(token_amount * 10**6))
msg, + struct.pack("<Q", max_amount_lamports)
(await client.get_latest_blockhash()).value.blockhash, )
), buy_ix = Instruction(PUMP_PROGRAM, data, accounts)
opts=TxOpts( idempotent_ata_ix = create_idempotent_associated_token_account(
skip_preflight=True, preflight_commitment=Confirmed payer.pubkey(), payer.pubkey(), mint
), )
) msg = Message(
[set_compute_unit_price(1_000), idempotent_ata_ix, buy_ix], payer.pubkey()
)
recent_blockhash = await client.get_latest_blockhash()
opts = TxOpts(skip_preflight=True, preflight_commitment=Confirmed)
await client.confirm_transaction(
tx_ata.value, commitment="confirmed"
)
print("Associated token account created.")
print(
f"Associated token account address: {associated_token_account}"
)
break
else:
print("Associated token account already exists.")
print(
f"Associated token account address: {associated_token_account}"
)
break
except Exception as e:
print(
f"Attempt {ata_attempt + 1} to create associated token account failed: {e!s}"
)
if ata_attempt < max_retries - 1:
wait_time = 2**ata_attempt
print(f"Retrying in {wait_time} seconds...")
await asyncio.sleep(wait_time)
else:
print(
"Max retries reached. Unable to create associated token account."
)
return
# Continue with the buy transaction
for attempt in range(max_retries): for attempt in range(max_retries):
try: try:
accounts = [
AccountMeta(pubkey=PUMP_GLOBAL, is_signer=False, is_writable=False),
AccountMeta(pubkey=PUMP_FEE, is_signer=False, is_writable=True),
AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
AccountMeta(
pubkey=bonding_curve, is_signer=False, is_writable=True
),
AccountMeta(
pubkey=associated_bonding_curve,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=associated_token_account,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=payer.pubkey(), is_signer=True, is_writable=True
),
AccountMeta(
pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(pubkey=creator_vault, is_signer=False, is_writable=True),
AccountMeta(
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False
),
]
discriminator = struct.pack("<Q", 16927863322537952870)
data = (
discriminator
+ struct.pack("<Q", int(token_amount * 10**6))
+ struct.pack("<Q", max_amount_lamports)
)
buy_ix = Instruction(PUMP_PROGRAM, data, accounts)
msg = Message([set_compute_unit_price(1_000), buy_ix], payer.pubkey())
tx_buy = await client.send_transaction( tx_buy = await client.send_transaction(
Transaction( Transaction(
[payer], [payer],
msg, msg,
(await client.get_latest_blockhash()).value.blockhash, recent_blockhash.value.blockhash,
), ),
opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed), opts=opts,
) )
tx_hash = tx_buy.value
print( print(
f"Transaction sent: https://explorer.solana.com/tx/{tx_buy.value}" f"Transaction sent: https://explorer.solana.com/tx/{tx_hash}"
) )
await client.confirm_transaction(tx_hash, commitment="confirmed", sleep_seconds=1)
await client.confirm_transaction(tx_buy.value, commitment="confirmed")
print("Transaction confirmed") print("Transaction confirmed")
return # Success, exit the function return # Success, exit the function
except Exception as e: except Exception as e:
print(f"Attempt {attempt + 1} failed: {str(e)[:50]}") print(f"Attempt {attempt + 1} failed: {str(e)[:50]}")
if attempt < max_retries - 1: if attempt < max_retries - 1:
@@ -253,6 +196,7 @@ async def buy_token(
print("Max retries reached. Unable to complete the transaction.") print("Max retries reached. Unable to complete the transaction.")
def load_idl(file_path): def load_idl(file_path):
with open(file_path) as f: with open(file_path) as f:
return json.load(f) return json.load(f)
+55 -55
View File
@@ -157,72 +157,72 @@ async def sell_token(
print(f"Selling {token_balance_decimal} tokens") print(f"Selling {token_balance_decimal} tokens")
print(f"Minimum SOL output: {min_sol_output / LAMPORTS_PER_SOL:.10f} SOL") print(f"Minimum SOL output: {min_sol_output / LAMPORTS_PER_SOL:.10f} SOL")
accounts = [
AccountMeta(pubkey=PUMP_GLOBAL, is_signer=False, is_writable=False),
AccountMeta(pubkey=PUMP_FEE, is_signer=False, is_writable=True),
AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
AccountMeta(
pubkey=bonding_curve, is_signer=False, is_writable=True
),
AccountMeta(
pubkey=associated_bonding_curve,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=associated_token_account,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=payer.pubkey(), is_signer=True, is_writable=True
),
AccountMeta(
pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=creator_vault,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False
),
]
discriminator = struct.pack("<Q", 12502976635542562355)
data = (
discriminator
+ struct.pack("<Q", amount)
+ struct.pack("<Q", min_sol_output)
)
sell_ix = Instruction(PUMP_PROGRAM, data, accounts)
msg = Message([set_compute_unit_price(1_000), sell_ix], payer.pubkey())
recent_blockhash = await client.get_latest_blockhash()
opts = TxOpts(skip_preflight=True, preflight_commitment=Confirmed)
# Continue with the sell transaction # Continue with the sell transaction
for attempt in range(max_retries): for attempt in range(max_retries):
try: try:
accounts = [
AccountMeta(pubkey=PUMP_GLOBAL, is_signer=False, is_writable=False),
AccountMeta(pubkey=PUMP_FEE, is_signer=False, is_writable=True),
AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
AccountMeta(
pubkey=bonding_curve, is_signer=False, is_writable=True
),
AccountMeta(
pubkey=associated_bonding_curve,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=associated_token_account,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=payer.pubkey(), is_signer=True, is_writable=True
),
AccountMeta(
pubkey=SYSTEM_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=creator_vault,
is_signer=False,
is_writable=True,
),
AccountMeta(
pubkey=SYSTEM_TOKEN_PROGRAM, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
),
AccountMeta(
pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False
),
]
discriminator = struct.pack("<Q", 12502976635542562355)
data = (
discriminator
+ struct.pack("<Q", amount)
+ struct.pack("<Q", min_sol_output)
)
sell_ix = Instruction(PUMP_PROGRAM, data, accounts)
msg = Message([set_compute_unit_price(1_000), sell_ix], payer.pubkey())
tx = await client.send_transaction( tx = await client.send_transaction(
Transaction( Transaction(
[payer], [payer],
msg, msg,
(await client.get_latest_blockhash()).value.blockhash, recent_blockhash.value.blockhash,
), ),
opts=TxOpts(skip_preflight=True, preflight_commitment=Confirmed), opts=opts,
) )
tx_hash = tx.value
print(f"Transaction sent: https://explorer.solana.com/tx/{tx.value}") print(f"Transaction sent: https://explorer.solana.com/tx/{tx_hash}")
await client.confirm_transaction(tx_hash, commitment="confirmed", sleep_seconds=1)
await client.confirm_transaction(tx.value, commitment="confirmed")
print("Transaction confirmed") print("Transaction confirmed")
return # Success, exit the function return # Success, exit the function
except Exception as e: except Exception as e:
print(f"Attempt {attempt + 1} failed: {e!s}") print(f"Attempt {attempt + 1} failed: {e!s}")
if attempt < max_retries - 1: if attempt < max_retries - 1: