mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-17 17:28:05 +00:00
Merge pull request #124 from chainstacklabs/feat/upd-buy-instr
Add global_volume_accumulator and user_volume_accumulator to buy instructions (bonding curve, amm)
This commit is contained in:
+1074
-2
File diff suppressed because it is too large
Load Diff
+1045
-2
File diff suppressed because it is too large
Load Diff
@@ -104,6 +104,27 @@ def _find_creator_vault(creator: Pubkey) -> Pubkey:
|
|||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def _find_global_volume_accumulator() -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"global_volume_accumulator"
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def _find_user_volume_accumulator(user: Pubkey) -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"user_volume_accumulator",
|
||||||
|
bytes(user)
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
async def buy_token(
|
async def buy_token(
|
||||||
mint: Pubkey,
|
mint: Pubkey,
|
||||||
bonding_curve: Pubkey,
|
bonding_curve: Pubkey,
|
||||||
@@ -153,6 +174,8 @@ async def buy_token(
|
|||||||
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
|
pubkey=PUMP_EVENT_AUTHORITY, is_signer=False, is_writable=False
|
||||||
),
|
),
|
||||||
AccountMeta(pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=_find_global_volume_accumulator(), is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=_find_user_volume_accumulator(payer.pubkey()), is_signer=False, is_writable=True),
|
||||||
]
|
]
|
||||||
|
|
||||||
discriminator = struct.pack("<Q", 16927863322537952870)
|
discriminator = struct.pack("<Q", 16927863322537952870)
|
||||||
|
|||||||
@@ -101,6 +101,27 @@ def find_creator_vault(creator: Pubkey) -> Pubkey:
|
|||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def _find_global_volume_accumulator() -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"global_volume_accumulator"
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def _find_user_volume_accumulator(user: Pubkey) -> Pubkey:
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"user_volume_accumulator",
|
||||||
|
bytes(user)
|
||||||
|
],
|
||||||
|
PUMP_PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
def create_pump_create_instruction(
|
def create_pump_create_instruction(
|
||||||
mint: Pubkey,
|
mint: Pubkey,
|
||||||
mint_authority: Pubkey,
|
mint_authority: Pubkey,
|
||||||
@@ -177,6 +198,8 @@ def create_buy_instruction(
|
|||||||
AccountMeta(pubkey=creator_vault, is_signer=False, is_writable=True),
|
AccountMeta(pubkey=creator_vault, is_signer=False, is_writable=True),
|
||||||
AccountMeta(pubkey=PUMP_EVENT_AUTHORITY, 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),
|
AccountMeta(pubkey=PUMP_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=_find_global_volume_accumulator(), is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=_find_user_volume_accumulator(user), is_signer=False, is_writable=True),
|
||||||
]
|
]
|
||||||
|
|
||||||
data = (
|
data = (
|
||||||
|
|||||||
@@ -20,16 +20,16 @@ from solana.rpc.commitment import Confirmed
|
|||||||
from solana.rpc.types import MemcmpOpts, TxOpts
|
from solana.rpc.types import MemcmpOpts, TxOpts
|
||||||
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
|
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
|
||||||
from solders.instruction import AccountMeta, Instruction
|
from solders.instruction import AccountMeta, Instruction
|
||||||
from solders.system_program import TransferParams, transfer
|
|
||||||
from solders.keypair import Keypair
|
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.system_program import TransferParams, transfer
|
||||||
from solders.transaction import VersionedTransaction
|
from solders.transaction import VersionedTransaction
|
||||||
from spl.token.instructions import (
|
from spl.token.instructions import (
|
||||||
|
SyncNativeParams,
|
||||||
create_idempotent_associated_token_account,
|
create_idempotent_associated_token_account,
|
||||||
get_associated_token_address,
|
get_associated_token_address,
|
||||||
sync_native,
|
sync_native,
|
||||||
SyncNativeParams
|
|
||||||
)
|
)
|
||||||
|
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
@@ -165,6 +165,44 @@ def find_coin_creator_vault(coin_creator: Pubkey) -> Pubkey:
|
|||||||
)
|
)
|
||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
|
def find_global_volume_accumulator() -> Pubkey:
|
||||||
|
"""Derive the Program Derived Address (PDA) for the global volume accumulator.
|
||||||
|
|
||||||
|
Calculates the deterministic PDA that tracks global trading volume
|
||||||
|
across all pools in the PUMP AMM protocol.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived global volume accumulator account
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"global_volume_accumulator"
|
||||||
|
],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
def find_user_volume_accumulator(user: Pubkey) -> Pubkey:
|
||||||
|
"""Derive the Program Derived Address (PDA) for a user's volume accumulator.
|
||||||
|
|
||||||
|
Calculates the deterministic PDA that tracks trading volume
|
||||||
|
for a specific user in the PUMP AMM protocol.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user: Pubkey of the user account
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived user volume accumulator account
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[
|
||||||
|
b"user_volume_accumulator",
|
||||||
|
bytes(user)
|
||||||
|
],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
async def calculate_token_pool_price(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:
|
||||||
"""Calculate the current price of tokens in an AMM pool.
|
"""Calculate the current price of tokens in an AMM pool.
|
||||||
|
|
||||||
@@ -229,6 +267,10 @@ async def buy_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer:
|
|||||||
print(f"Buying {base_amount_out / (10**TOKEN_DECIMALS):.10f} tokens")
|
print(f"Buying {base_amount_out / (10**TOKEN_DECIMALS):.10f} tokens")
|
||||||
print(f"Maximum SOL input: {max_sol_input / LAMPORTS_PER_SOL:.10f} SOL")
|
print(f"Maximum SOL input: {max_sol_input / LAMPORTS_PER_SOL:.10f} SOL")
|
||||||
|
|
||||||
|
# Calculate required PDAs for volume tracking
|
||||||
|
global_volume_accumulator = find_global_volume_accumulator()
|
||||||
|
user_volume_accumulator = find_user_volume_accumulator(payer.pubkey())
|
||||||
|
|
||||||
# Define all accounts needed for the buy instruction
|
# Define all accounts needed for the buy instruction
|
||||||
accounts = [
|
accounts = [
|
||||||
AccountMeta(pubkey=pump_fun_amm_market, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=pump_fun_amm_market, is_signer=False, is_writable=False),
|
||||||
@@ -250,6 +292,8 @@ async def buy_pump_swap(client: AsyncClient, pump_fun_amm_market: Pubkey, payer:
|
|||||||
AccountMeta(pubkey=PUMP_AMM_PROGRAM_ID, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_AMM_PROGRAM_ID, is_signer=False, is_writable=False),
|
||||||
AccountMeta(pubkey=coin_creator_vault_ata, is_signer=False, is_writable=True),
|
AccountMeta(pubkey=coin_creator_vault_ata, is_signer=False, is_writable=True),
|
||||||
AccountMeta(pubkey=coin_creator_vault_authority, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=coin_creator_vault_authority, is_signer=False, is_writable=False),
|
||||||
|
AccountMeta(pubkey=global_volume_accumulator, is_signer=False, is_writable=True),
|
||||||
|
AccountMeta(pubkey=user_volume_accumulator, is_signer=False, is_writable=True),
|
||||||
]
|
]
|
||||||
|
|
||||||
data = BUY_DISCRIMINATOR + struct.pack("<Q", base_amount_out) + struct.pack("<Q", max_sol_input)
|
data = BUY_DISCRIMINATOR + struct.pack("<Q", base_amount_out) + struct.pack("<Q", max_sol_input)
|
||||||
|
|||||||
+1
-1
@@ -86,7 +86,7 @@ async def start_bot(config_path: str):
|
|||||||
"wait_before_new_token", 15
|
"wait_before_new_token", 15
|
||||||
),
|
),
|
||||||
max_token_age=cfg.get("timing", {}).get("max_token_age", 0.001),
|
max_token_age=cfg.get("timing", {}).get("max_token_age", 0.001),
|
||||||
token_wait_timeout=cfg.get("timing", {}).get("token_wait_timeout", 30),
|
token_wait_timeout=cfg.get("timing", {}).get("token_wait_timeout", 120),
|
||||||
# Cleanup settings
|
# Cleanup settings
|
||||||
cleanup_mode=cfg.get("cleanup", {}).get("mode", "disabled"),
|
cleanup_mode=cfg.get("cleanup", {}).get("mode", "disabled"),
|
||||||
cleanup_force_close_with_burn=cfg.get("cleanup", {}).get(
|
cleanup_force_close_with_burn=cfg.get("cleanup", {}).get(
|
||||||
|
|||||||
@@ -49,3 +49,34 @@ class PumpAddresses:
|
|||||||
LIQUIDITY_MIGRATOR: Final[Pubkey] = Pubkey.from_string(
|
LIQUIDITY_MIGRATOR: Final[Pubkey] = Pubkey.from_string(
|
||||||
"39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"
|
"39azUYFWPz3VHgKCf3VChUwbpURdCHRxjWVowf5jUJjg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_global_volume_accumulator() -> Pubkey:
|
||||||
|
"""
|
||||||
|
Derive the Program Derived Address (PDA) for the global volume accumulator.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived global volume accumulator account
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[b"global_volume_accumulator"],
|
||||||
|
PumpAddresses.PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def find_user_volume_accumulator(user: Pubkey) -> Pubkey:
|
||||||
|
"""
|
||||||
|
Derive the Program Derived Address (PDA) for a user's volume accumulator.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user: Pubkey of the user account
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Pubkey of the derived user volume accumulator account
|
||||||
|
"""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[b"user_volume_accumulator", bytes(user)],
|
||||||
|
PumpAddresses.PROGRAM,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|||||||
@@ -195,6 +195,12 @@ class TokenBuyer(Trader):
|
|||||||
AccountMeta(
|
AccountMeta(
|
||||||
pubkey=PumpAddresses.PROGRAM, is_signer=False, is_writable=False
|
pubkey=PumpAddresses.PROGRAM, is_signer=False, is_writable=False
|
||||||
),
|
),
|
||||||
|
AccountMeta(
|
||||||
|
pubkey=PumpAddresses.find_global_volume_accumulator(), is_signer=False, is_writable=True
|
||||||
|
),
|
||||||
|
AccountMeta(
|
||||||
|
pubkey=PumpAddresses.find_user_volume_accumulator(self.wallet.pubkey), is_signer=False, is_writable=True
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Prepare idempotent create ATA instruction: it will not fail if ATA already exists
|
# Prepare idempotent create ATA instruction: it will not fail if ATA already exists
|
||||||
|
|||||||
Reference in New Issue
Block a user