From 7bf78830f0e0089b6ec4ad9ed8f5d4cd22eed1f8 Mon Sep 17 00:00:00 2001 From: smypmsa Date: Mon, 31 Mar 2025 15:14:07 +0000 Subject: [PATCH] fix: fixes in initial implementation --- learning-examples/manual_sell_pumpswap.py | 78 ++++++++++------------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/learning-examples/manual_sell_pumpswap.py b/learning-examples/manual_sell_pumpswap.py index 9e3a21b..8a84a86 100644 --- a/learning-examples/manual_sell_pumpswap.py +++ b/learning-examples/manual_sell_pumpswap.py @@ -3,6 +3,7 @@ import os import struct import base58 +from dotenv import load_dotenv from solana.rpc.async_api import AsyncClient from solana.rpc.commitment import Confirmed from solana.rpc.types import MemcmpOpts, TxOpts @@ -14,6 +15,8 @@ from solders.pubkey import Pubkey from solders.transaction import VersionedTransaction from spl.token.instructions import get_associated_token_address +load_dotenv() + RPC_ENDPOINT = os.environ.get("SOLANA_NODE_RPC_ENDPOINT") TOKEN_MINT = Pubkey.from_string("35ySx7Rt3RqeTp75QB81FgRvPT5yDY2m5BupsUYDpump") PRIVATE_KEY = base58.b58decode(os.environ.get("SOLANA_PRIVATE_KEY")) @@ -32,6 +35,9 @@ SYSTEM_TOKEN_PROGRAM = Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss62 SYSTEM_PROGRAM = Pubkey.from_string("11111111111111111111111111111111") SYSTEM_ASSOCIATED_TOKEN_ACCOUNT_PROGRAM = Pubkey.from_string("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL") PUMP_SWAP_EVENT_AUTHORITY = Pubkey.from_string("GS4CU59F31iL7aR2Q8zVS8DRrcRnXX1yjQ66TqNVQnaR") +LAMPORTS_PER_SOL = 1_000_000_000 +COMPUTE_UNIT_PRICE = 10_000 +COMPUTE_UNIT_BUDGET = 100_000 async def get_market_address_by_base_mint(client: AsyncClient, base_mint_address: Pubkey, amm_program_id: Pubkey) -> Pubkey: @@ -88,29 +94,17 @@ async def get_market_data(client: AsyncClient, market_address: Pubkey): return parsed_data -async def get_token_price_from_pool(client: AsyncClient, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float: +async def calculate_token_pool_price(client: AsyncClient, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float: base_balance_resp = await client.get_token_account_balance(pool_base_token_account) quote_balance_resp = await client.get_token_account_balance(pool_quote_token_account) base_amount = float(base_balance_resp.value.ui_amount) quote_amount = float(quote_balance_resp.value.ui_amount) - token_price = base_amount / quote_amount + token_price = quote_amount / base_amount - return token_price, base_amount, quote_amount + return token_price -async def calculate_sol_amount_from_token(client: AsyncClient, token_amount: float, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey) -> float: - _, base_amount, quote_amount = await get_token_price_from_pool(client, pool_base_token_account, pool_quote_token_account) - - k = base_amount * quote_amount - new_base_amount = base_amount + token_amount - new_quote_amount = k / new_base_amount - sol_amount = quote_amount - new_quote_amount - - sol_received = sol_amount * (1 - 0.25 / 100) - - return sol_received - -def create_ata_idempotent_ix(payer_pubkey, owner_pubkey): +def create_ata_idempotent_ix(payer_pubkey, owner_pubkey) -> Instruction: """ Create an instruction to create an Associated Token Account for WSOL in an idempotent way. """ @@ -131,32 +125,26 @@ async def sell_pump_swap(client: AsyncClient, pump_fun_amm_pool: Pubkey, payer: user_quote_token_account: Pubkey, pool_base_token_account: Pubkey, pool_quote_token_account: Pubkey, slippage: float = 0.25): - token_balance = await client.get_token_account_balance(user_quote_token_account) + # Get token balance + token_balance = int((await client.get_token_account_balance(user_base_token_account)).value.amount) token_balance_decimal = token_balance / 10**TOKEN_DECIMALS print(f"Token balance: {token_balance_decimal}") if token_balance == 0: print("No tokens to sell.") return + + # Calculate token price + token_price_sol = await calculate_token_pool_price(client, pool_base_token_account, pool_quote_token_account) + print(f"Price per Token: {token_price_sol:.20f} SOL") + + # Calculate minimum SOL output + amount = token_balance + min_sol_output = float(token_balance_decimal) * float(token_price_sol) + slippage_factor = 1 - slippage + min_sol_output = int((min_sol_output * slippage_factor) * LAMPORTS_PER_SOL) - token_price, base_amount, quote_amount = await get_token_price_from_pool(client, pool_base_token_account, pool_quote_token_account) - - k = base_amount * quote_amount - new_quote_amount = quote_amount + token_balance_decimal - new_base_amount = k / new_quote_amount - expected_sol_amount = base_amount - new_base_amount - - expected_sol_after_fee = expected_sol_amount * (1 - 0.25 / 100) - min_sol_output_float = expected_sol_after_fee * (1 - slippage) - min_sol_output = min(int(min_sol_output_float * 10**9), 18_446_744_073_709_551_615) - print(f"Selling {token_balance_decimal} tokens") - print(f"Expected SOL: {expected_sol_after_fee:.9f}") - print(f"Min SOL with {slippage*100}% slippage: {min_sol_output/10**9:.9f}") - - print(f"Token balance to sell (raw): {token_balance}") - print(f"Min SOL output (raw): {min_sol_output}") - - data = SELL_DISCRIMINATOR + struct.pack("