mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-07-28 07:47:43 +00:00
fix(examples): add pool-v2 account to pumpswap, repair geyser listener
PumpSwap (manual_buy_pumpswap.py / manual_sell_pumpswap.py)
- Real on-chain pump-swap buys use 24 accounts; the IDL is incomplete
(lists 23). Missing 24th account is pool-v2 PDA, derived from seed
["pool-v2", base_mint] under the pump-amm program.
- Without it, pump-amm throws AnchorError 6023 (Overflow) at buy.rs:400/414
after the trade transfers complete (the source of the earlier "pre-existing
overflow" — was actually a missing account, not a math bug).
- find_pool_v2(base_mint) added; appended to both buy and sell account lists
after fee_program. The April-28 breaking-fee accounts (still gated behind
INCLUDE_BREAKING_FEE_ACCOUNTS) come after pool-v2 — matching the doc's
"All accounts till bonding-curve-v2 and pool-v2 remain the same."
- AsyncClient timeout bumped to 120s so the heavy getProgramAccounts pool
lookup doesn't time out on slower RPC paths.
- Live-verified on mainnet with 9PwadsGz...pump:
buy 2xgdJJsDMzoMyxJzrCATKwGfpX7M... err=None (24 accounts)
sell 4vdBkGpCMQYEWncj5k1suGzKPUMQ... err=None (24 accounts)
manual_buy_geyser.py
- Fixes IndexError when create tx references ALT-loaded keys
(matches the same fix applied to manual_buy.py).
- Re-enables the 15s sleep + on-chain price/fee_recipient lookup that
were commented out for testing — needed for buys on real pools.
- Live-verified: 45wSgX2Pu1LLZWLgu3e9qdhRaGJjqwMqQP5HdeV7zMBqNXziB2uEgxQd5bAqvAhBLFnAqzbuK3LAWowhxZxdemJ
(18-account buy, err=None) on Token-2022 cashback-enabled INSIDER mint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -344,6 +344,11 @@ async def listen_for_create_transaction_geyser():
|
|||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Skip txs whose create ix references ALT-loaded accounts not in
|
||||||
|
# msg.account_keys (indices >= len(msg.account_keys)).
|
||||||
|
if any(idx >= len(msg.account_keys) for idx in ix.accounts):
|
||||||
|
continue
|
||||||
|
|
||||||
# Found a create instruction
|
# Found a create instruction
|
||||||
token_data = decode_create_instruction_geyser(
|
token_data = decode_create_instruction_geyser(
|
||||||
ix.data, msg.account_keys, ix.accounts
|
ix.data, msg.account_keys, ix.accounts
|
||||||
@@ -513,9 +518,9 @@ async def main():
|
|||||||
print("New token created:")
|
print("New token created:")
|
||||||
print(json.dumps(token_data, indent=2))
|
print(json.dumps(token_data, indent=2))
|
||||||
|
|
||||||
# sleep_duration_sec = 15
|
sleep_duration_sec = 15
|
||||||
# print(f"Waiting for {sleep_duration_sec} seconds for things to stabilize...")
|
print(f"Waiting {sleep_duration_sec}s for the bonding curve account to propagate...")
|
||||||
# await asyncio.sleep(sleep_duration_sec)
|
await asyncio.sleep(sleep_duration_sec)
|
||||||
|
|
||||||
mint = Pubkey.from_string(token_data["mint"])
|
mint = Pubkey.from_string(token_data["mint"])
|
||||||
bonding_curve = Pubkey.from_string(token_data["bondingCurve"])
|
bonding_curve = Pubkey.from_string(token_data["bondingCurve"])
|
||||||
|
|||||||
@@ -283,6 +283,16 @@ def find_fee_config() -> Pubkey:
|
|||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def find_pool_v2(base_mint: Pubkey) -> Pubkey:
|
||||||
|
"""Derive the PDA for the pool-v2 account (per-base-mint), required as the
|
||||||
|
last "pre-upgrade" account on every pump-swap buy/sell."""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[b"pool-v2", bytes(base_mint)],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Mayhem Mode Fee Handling
|
# Mayhem Mode Fee Handling
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -518,6 +528,8 @@ async def buy_pump_swap(
|
|||||||
AccountMeta(pubkey=user_volume_accumulator, is_signer=False, is_writable=True),
|
AccountMeta(pubkey=user_volume_accumulator, is_signer=False, is_writable=True),
|
||||||
AccountMeta(pubkey=find_fee_config(), is_signer=False, is_writable=False),
|
AccountMeta(pubkey=find_fee_config(), is_signer=False, is_writable=False),
|
||||||
AccountMeta(pubkey=PUMP_FEE_PROGRAM, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_FEE_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
# pool-v2 PDA (per-base-mint) — the last "pre-upgrade" account.
|
||||||
|
AccountMeta(pubkey=find_pool_v2(base_mint), is_signer=False, is_writable=False),
|
||||||
]
|
]
|
||||||
# 2 new accounts required from 2026-04-28 16:00 UTC pump-swap program upgrade,
|
# 2 new accounts required from 2026-04-28 16:00 UTC pump-swap program upgrade,
|
||||||
# AFTER pool-v2: breaking-upgrade fee recipient (readonly, second-to-last) and
|
# AFTER pool-v2: breaking-upgrade fee recipient (readonly, second-to-last) and
|
||||||
@@ -643,9 +655,9 @@ async def buy_pump_swap(
|
|||||||
|
|
||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
"""Execute the complete buy flow."""
|
"""Execute the complete buy flow."""
|
||||||
sol_amount_to_spend = 0.000001 # Amount of SOL to spend on the purchase
|
sol_amount_to_spend = 0.001 # Amount of SOL to spend on the purchase
|
||||||
|
|
||||||
async with AsyncClient(RPC_ENDPOINT) as client:
|
async with AsyncClient(RPC_ENDPOINT, timeout=120) as client:
|
||||||
# Step 1: Find the pool address for our token
|
# Step 1: Find the pool address for our token
|
||||||
market_address = await get_market_address_by_base_mint(
|
market_address = await get_market_address_by_base_mint(
|
||||||
client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID
|
client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID
|
||||||
|
|||||||
@@ -236,6 +236,16 @@ def find_fee_config() -> Pubkey:
|
|||||||
return derived_address
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
|
def find_pool_v2(base_mint: Pubkey) -> Pubkey:
|
||||||
|
"""Derive the PDA for the pool-v2 account (per-base-mint), required as the
|
||||||
|
last "pre-upgrade" account on every pump-swap buy/sell."""
|
||||||
|
derived_address, _ = Pubkey.find_program_address(
|
||||||
|
[b"pool-v2", bytes(base_mint)],
|
||||||
|
PUMP_AMM_PROGRAM_ID,
|
||||||
|
)
|
||||||
|
return derived_address
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
# Mayhem Mode Fee Handling
|
# Mayhem Mode Fee Handling
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -506,6 +516,8 @@ async def sell_pump_swap(
|
|||||||
),
|
),
|
||||||
AccountMeta(pubkey=find_fee_config(), is_signer=False, is_writable=False),
|
AccountMeta(pubkey=find_fee_config(), is_signer=False, is_writable=False),
|
||||||
AccountMeta(pubkey=PUMP_FEE_PROGRAM, is_signer=False, is_writable=False),
|
AccountMeta(pubkey=PUMP_FEE_PROGRAM, is_signer=False, is_writable=False),
|
||||||
|
# pool-v2 PDA (per-base-mint) — the last "pre-upgrade" account.
|
||||||
|
AccountMeta(pubkey=find_pool_v2(base_mint), is_signer=False, is_writable=False),
|
||||||
]
|
]
|
||||||
# 2 new accounts required from 2026-04-28 16:00 UTC pump-swap program upgrade,
|
# 2 new accounts required from 2026-04-28 16:00 UTC pump-swap program upgrade,
|
||||||
# AFTER pool-v2: breaking-upgrade fee recipient (readonly, second-to-last) and
|
# AFTER pool-v2: breaking-upgrade fee recipient (readonly, second-to-last) and
|
||||||
@@ -571,7 +583,7 @@ async def sell_pump_swap(
|
|||||||
|
|
||||||
async def main() -> None:
|
async def main() -> None:
|
||||||
"""Execute the complete sell flow."""
|
"""Execute the complete sell flow."""
|
||||||
async with AsyncClient(RPC_ENDPOINT) as client:
|
async with AsyncClient(RPC_ENDPOINT, timeout=120) as client:
|
||||||
# Step 1: Find the pool address for our token
|
# Step 1: Find the pool address for our token
|
||||||
market_address = await get_market_address_by_base_mint(
|
market_address = await get_market_address_by_base_mint(
|
||||||
client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID
|
client, TOKEN_MINT, PUMP_AMM_PROGRAM_ID
|
||||||
|
|||||||
Reference in New Issue
Block a user