mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-13 07:18:04 +00:00
feat: use idempotent ata instr, merge burn and close instr
This commit is contained in:
+17
-15
@@ -51,6 +51,8 @@ class AccountCleanupManager:
|
|||||||
return
|
return
|
||||||
|
|
||||||
balance = await self.client.get_token_account_balance(ata)
|
balance = await self.client.get_token_account_balance(ata)
|
||||||
|
instructions = []
|
||||||
|
|
||||||
if balance > 0 and CLEANUP_FORCE_CLOSE_WITH_BURN:
|
if balance > 0 and CLEANUP_FORCE_CLOSE_WITH_BURN:
|
||||||
logger.info(f"Burning {balance} tokens from ATA {ata} (mint: {mint})...")
|
logger.info(f"Burning {balance} tokens from ATA {ata} (mint: {mint})...")
|
||||||
burn_ix = burn(
|
burn_ix = burn(
|
||||||
@@ -62,13 +64,8 @@ class AccountCleanupManager:
|
|||||||
program_id=SystemAddresses.TOKEN_PROGRAM,
|
program_id=SystemAddresses.TOKEN_PROGRAM,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
await self.client.build_and_send_transaction(
|
instructions.append(burn_ix)
|
||||||
[burn_ix],
|
|
||||||
self.wallet.keypair,
|
|
||||||
skip_preflight=True,
|
|
||||||
priority_fee=priority_fee,
|
|
||||||
)
|
|
||||||
logger.info(f"✅ Burned successfully from ATA {ata}")
|
|
||||||
elif balance > 0:
|
elif balance > 0:
|
||||||
logger.info(
|
logger.info(
|
||||||
f"Skipping ATA {ata} with non-zero balance ({balance} tokens) "
|
f"Skipping ATA {ata} with non-zero balance ({balance} tokens) "
|
||||||
@@ -76,6 +73,7 @@ class AccountCleanupManager:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Include close account instruction
|
||||||
logger.info(f"Closing ATA: {ata}")
|
logger.info(f"Closing ATA: {ata}")
|
||||||
close_ix = close_account(
|
close_ix = close_account(
|
||||||
CloseAccountParams(
|
CloseAccountParams(
|
||||||
@@ -85,14 +83,18 @@ class AccountCleanupManager:
|
|||||||
program_id=SystemAddresses.TOKEN_PROGRAM,
|
program_id=SystemAddresses.TOKEN_PROGRAM,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
tx_sig = await self.client.build_and_send_transaction(
|
instructions.append(close_ix)
|
||||||
[close_ix],
|
|
||||||
self.wallet.keypair,
|
# Send both burn and close instructions in the same transaction
|
||||||
skip_preflight=True,
|
if instructions:
|
||||||
priority_fee=priority_fee,
|
tx_sig = await self.client.build_and_send_transaction(
|
||||||
)
|
instructions,
|
||||||
await self.client.confirm_transaction(tx_sig)
|
self.wallet.keypair,
|
||||||
logger.info(f"Closed successfully: {ata}")
|
skip_preflight=True,
|
||||||
|
priority_fee=priority_fee,
|
||||||
|
)
|
||||||
|
await self.client.confirm_transaction(tx_sig)
|
||||||
|
logger.info(f"Closed successfully: {ata}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Cleanup failed for ATA {ata}: {e!s}")
|
logger.warning(f"Cleanup failed for ATA {ata}: {e!s}")
|
||||||
|
|||||||
+10
-51
@@ -7,7 +7,7 @@ from typing import Final
|
|||||||
|
|
||||||
from solders.instruction import AccountMeta, Instruction
|
from solders.instruction import AccountMeta, Instruction
|
||||||
from solders.pubkey import Pubkey
|
from solders.pubkey import Pubkey
|
||||||
from spl.token.instructions import create_associated_token_account
|
from spl.token.instructions import create_idempotent_associated_token_account
|
||||||
|
|
||||||
from core.client import SolanaClient
|
from core.client import SolanaClient
|
||||||
from core.curve import BondingCurveManager
|
from core.curve import BondingCurveManager
|
||||||
@@ -93,10 +93,6 @@ class TokenBuyer(Trader):
|
|||||||
token_info.mint
|
token_info.mint
|
||||||
)
|
)
|
||||||
|
|
||||||
await self._ensure_associated_token_account(
|
|
||||||
token_info.mint, associated_token_account
|
|
||||||
)
|
|
||||||
|
|
||||||
tx_signature = await self._send_buy_transaction(
|
tx_signature = await self._send_buy_transaction(
|
||||||
token_info,
|
token_info,
|
||||||
associated_token_account,
|
associated_token_account,
|
||||||
@@ -124,51 +120,6 @@ class TokenBuyer(Trader):
|
|||||||
logger.error(f"Buy operation failed: {e!s}")
|
logger.error(f"Buy operation failed: {e!s}")
|
||||||
return TradeResult(success=False, error_message=str(e))
|
return TradeResult(success=False, error_message=str(e))
|
||||||
|
|
||||||
async def _ensure_associated_token_account(
|
|
||||||
self, mint: Pubkey, associated_token_account: Pubkey
|
|
||||||
) -> None:
|
|
||||||
"""Ensure associated token account exists, else create it.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
mint: Token mint
|
|
||||||
associated_token_account: Associated token account address
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
solana_client = await self.client.get_client()
|
|
||||||
account_info = await solana_client.get_account_info(
|
|
||||||
associated_token_account, encoding="base64"
|
|
||||||
)
|
|
||||||
|
|
||||||
if account_info.value is None:
|
|
||||||
logger.info(f"Creating associated token account for {mint}...")
|
|
||||||
|
|
||||||
create_ata_ix = create_associated_token_account(
|
|
||||||
payer=self.wallet.pubkey, owner=self.wallet.pubkey, mint=mint
|
|
||||||
)
|
|
||||||
|
|
||||||
tx_sig = await self.client.build_and_send_transaction(
|
|
||||||
[create_ata_ix],
|
|
||||||
self.wallet.keypair,
|
|
||||||
skip_preflight=True,
|
|
||||||
max_retries=self.max_retries,
|
|
||||||
priority_fee=await self.priority_fee_manager.calculate_priority_fee(
|
|
||||||
[mint, SystemAddresses.PROGRAM, SystemAddresses.TOKEN_PROGRAM]
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
await self.client.confirm_transaction(tx_sig)
|
|
||||||
logger.info(
|
|
||||||
f"Associated token account created: {associated_token_account}"
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
logger.info(
|
|
||||||
f"Associated token account already exists: {associated_token_account}"
|
|
||||||
)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"Error creating associated token account: {e!s}")
|
|
||||||
raise
|
|
||||||
|
|
||||||
async def _send_buy_transaction(
|
async def _send_buy_transaction(
|
||||||
self,
|
self,
|
||||||
token_info: TokenInfo,
|
token_info: TokenInfo,
|
||||||
@@ -225,6 +176,14 @@ class TokenBuyer(Trader):
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Prepare idempotent create ATA instruction: it will not fail if ATA already exists
|
||||||
|
idempotent_ata_ix = create_idempotent_associated_token_account(
|
||||||
|
self.wallet.pubkey,
|
||||||
|
self.wallet.pubkey,
|
||||||
|
token_info.mint,
|
||||||
|
SystemAddresses.TOKEN_PROGRAM
|
||||||
|
)
|
||||||
|
|
||||||
# Prepare buy instruction data
|
# Prepare buy instruction data
|
||||||
token_amount_raw = int(token_amount * 10**TOKEN_DECIMALS)
|
token_amount_raw = int(token_amount * 10**TOKEN_DECIMALS)
|
||||||
data = (
|
data = (
|
||||||
@@ -236,7 +195,7 @@ class TokenBuyer(Trader):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
return await self.client.build_and_send_transaction(
|
return await self.client.build_and_send_transaction(
|
||||||
[buy_ix],
|
[idempotent_ata_ix, buy_ix],
|
||||||
self.wallet.keypair,
|
self.wallet.keypair,
|
||||||
skip_preflight=True,
|
skip_preflight=True,
|
||||||
max_retries=self.max_retries,
|
max_retries=self.max_retries,
|
||||||
|
|||||||
Reference in New Issue
Block a user