mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-07-27 23:37:45 +00:00
minor fixes
This commit is contained in:
@@ -72,10 +72,19 @@ async def main() -> None:
|
||||
args = parse_args()
|
||||
|
||||
# Get configuration values, preferring command line args over config.py
|
||||
rpc_endpoint: str | None = args.rpc or os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||
wss_endpoint: str | None = args.wss or os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
||||
rpc_endpoint: str | None = (
|
||||
args.rpc
|
||||
or os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||
or config.PUBLIC_RPC_ENDPOINT
|
||||
)
|
||||
wss_endpoint: str | None = (
|
||||
args.wss
|
||||
or os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
||||
or config.PUBLIC_WSS_ENDPOINT
|
||||
)
|
||||
private_key: str | None = args.key or os.environ.get("SOLANA_PRIVATE_KEY")
|
||||
|
||||
# Validate configuration values
|
||||
if not rpc_endpoint or rpc_endpoint.startswith(("http://", "https://")):
|
||||
logger.error("Invalid RPC endpoint. Must start with http:// or https://")
|
||||
sys.exit(1)
|
||||
@@ -88,6 +97,7 @@ async def main() -> None:
|
||||
logger.error("Invalid private key. Key appears to be missing or too short")
|
||||
sys.exit(1)
|
||||
|
||||
# Get trading parameters
|
||||
buy_amount: float = args.amount if args.amount is not None else config.BUY_AMOUNT
|
||||
buy_slippage: float = (
|
||||
args.buy_slippage if args.buy_slippage is not None else config.BUY_SLIPPAGE
|
||||
@@ -96,6 +106,12 @@ async def main() -> None:
|
||||
args.sell_slippage if args.sell_slippage is not None else config.SELL_SLIPPAGE
|
||||
)
|
||||
|
||||
# Not implemented parameters
|
||||
enable_dynamic_prior__fee = (
|
||||
config.ENABLE_DYNAMIC_PRIORITY_FEE
|
||||
) # TODO: to be implemented
|
||||
prior_fee_multiplier = config.EXTRA_PRIORITY_FEE # TODO: to be implemented
|
||||
|
||||
trader: PumpTrader = PumpTrader(
|
||||
rpc_endpoint=rpc_endpoint, # type: ignore
|
||||
wss_endpoint=wss_endpoint, # type: ignore
|
||||
|
||||
@@ -6,20 +6,17 @@ Configuration for the pump.fun trading bot.
|
||||
BUY_AMOUNT = 0.0001 # Amount of SOL to spend when buying
|
||||
BUY_SLIPPAGE = 0.2 # 20% slippage tolerance for buying
|
||||
SELL_SLIPPAGE = 0.2 # 20% slippage tolerance for selling
|
||||
ENABLE_DYNAMIC_PRIORITY_FEE = (
|
||||
True # TODO: getRecentPriorityFee is used to get current priority fee
|
||||
)
|
||||
EXTRA_PRIORITY_FEE = 0.1 # TODO: 10% increase in dynamic priority fee
|
||||
ENABLE_DYNAMIC_PRIORITY_FEE = True # TODO: not implemented. getRecentPriorityFee is used to get current priority fee
|
||||
EXTRA_PRIORITY_FEE = 0.1 # TODO: not implemented. 10% increase in dynamic priority fee
|
||||
|
||||
TOKEN_DECIMALS: int = 6
|
||||
# Retries and timeouts
|
||||
MAX_RETRIES: int = 5
|
||||
WAIT_TIME_AFTER_BUY: int = 20
|
||||
WAIT_TIME_AFTER_BUY: int = 5
|
||||
WAIT_TIME_BEFORE_NEW_TOKEN: int = 5
|
||||
WAIT_TIME_AFTER_CREATION: int = 15
|
||||
WAIT_TIME_AFTER_CREATION: int = 5
|
||||
|
||||
# TODO: RPS of your node to avoid rate limit errors
|
||||
# Node provier configuration
|
||||
# You can also get a trader node https://docs.chainstack.com/docs/solana-trader-nodes
|
||||
MAX_RPS = 25
|
||||
|
||||
MAX_RPS = 25 # TODO: not implemented. Max RPS to avoid rate limit errors
|
||||
PUBLIC_RPC_ENDPOINT = "https://api.mainnet-beta.solana.com"
|
||||
PUBLIC_WSS_ENDPOINT = "wss://api.mainnet-beta.solana.com"
|
||||
|
||||
+1
-2
@@ -3,12 +3,11 @@ Solana client abstraction for blockchain operations.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from typing import Any, Dict, List, Optional, Tuple, Union
|
||||
from typing import Any, Dict
|
||||
|
||||
from solana.rpc.async_api import AsyncClient
|
||||
from solana.rpc.commitment import Confirmed
|
||||
from solana.rpc.types import TxOpts
|
||||
from solders.instruction import Instruction
|
||||
from solders.keypair import Keypair
|
||||
from solders.pubkey import Pubkey
|
||||
from solders.transaction import Transaction
|
||||
|
||||
+33
-23
@@ -6,10 +6,8 @@ import asyncio
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
import config
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.curve import BondingCurveManager
|
||||
from src.core.pubkeys import PumpAddresses
|
||||
@@ -120,26 +118,25 @@ class PumpTrader:
|
||||
try:
|
||||
await self._save_token_info(token_info)
|
||||
|
||||
logger.info("Waiting for 15 seconds for the bonding curve to stabilize...")
|
||||
await asyncio.sleep(15)
|
||||
|
||||
try:
|
||||
token_price = await self.curve_manager.calculate_price(
|
||||
token_info.bonding_curve
|
||||
)
|
||||
logger.info(f"Token price: {token_price:.10f} SOL")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get token price: {str(e)}")
|
||||
token_price = 0
|
||||
logger.info(
|
||||
f"Waiting for {config.WAIT_TIME_AFTER_CREATION} seconds for the bonding curve to stabilize..."
|
||||
)
|
||||
await asyncio.sleep(config.WAIT_TIME_AFTER_CREATION)
|
||||
|
||||
logger.info(
|
||||
f"Buying {self.buy_amount:.6f} SOL worth of {token_info.symbol}..."
|
||||
)
|
||||
buy_result = await self.buyer.execute(token_info)
|
||||
buy_result: TradeResult = await self.buyer.execute(token_info)
|
||||
|
||||
if buy_result.success:
|
||||
logger.info(f"Successfully bought {token_info.symbol}")
|
||||
self._log_trade("buy", token_info, token_price, buy_result.tx_signature)
|
||||
self._log_trade(
|
||||
"buy",
|
||||
token_info,
|
||||
buy_result.price, # type: ignore
|
||||
buy_result.amount, # type: ignore
|
||||
buy_result.tx_signature,
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
f"Failed to buy {token_info.symbol}: {buy_result.error_message}"
|
||||
@@ -147,16 +144,22 @@ class PumpTrader:
|
||||
|
||||
# Sell token if not in marry mode
|
||||
if not marry_mode and buy_result.success:
|
||||
logger.info("Waiting for 20 seconds before selling...")
|
||||
await asyncio.sleep(20)
|
||||
logger.info(
|
||||
f"Waiting for {config.WAIT_TIME_AFTER_BUY} seconds before selling..."
|
||||
)
|
||||
await asyncio.sleep(config.WAIT_TIME_AFTER_BUY)
|
||||
|
||||
logger.info(f"Selling {token_info.symbol}...")
|
||||
sell_result = await self.seller.execute(token_info)
|
||||
sell_result: TradeResult = await self.seller.execute(token_info)
|
||||
|
||||
if sell_result.success:
|
||||
logger.info(f"Successfully sold {token_info.symbol}")
|
||||
self._log_trade(
|
||||
"sell", token_info, token_price, sell_result.tx_signature
|
||||
"sell",
|
||||
token_info,
|
||||
sell_result.price, # type: ignore
|
||||
sell_result.amount, # type: ignore
|
||||
sell_result.tx_signature,
|
||||
)
|
||||
else:
|
||||
logger.error(
|
||||
@@ -168,9 +171,9 @@ class PumpTrader:
|
||||
# Wait before looking for the next token
|
||||
if yolo_mode:
|
||||
logger.info(
|
||||
"YOLO mode enabled. Waiting 5 seconds before looking for next token..."
|
||||
f"YOLO mode enabled. Waiting {config.WAIT_TIME_BEFORE_NEW_TOKEN} seconds before looking for next token..."
|
||||
)
|
||||
await asyncio.sleep(5)
|
||||
await asyncio.sleep(config.WAIT_TIME_BEFORE_NEW_TOKEN)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error handling token {token_info.symbol}: {str(e)}")
|
||||
@@ -190,7 +193,12 @@ class PumpTrader:
|
||||
logger.info(f"Token information saved to {file_name}")
|
||||
|
||||
def _log_trade(
|
||||
self, action: str, token_info: TokenInfo, price: float, tx_hash: str | None
|
||||
self,
|
||||
action: str,
|
||||
token_info: TokenInfo,
|
||||
price: float,
|
||||
amount: float,
|
||||
tx_hash: str | None,
|
||||
) -> None:
|
||||
"""Log trade information.
|
||||
|
||||
@@ -198,6 +206,7 @@ class PumpTrader:
|
||||
action: Trade action (buy/sell)
|
||||
token_info: Token information
|
||||
price: Token price in SOL
|
||||
amount: Trade amount in SOL
|
||||
tx_hash: Transaction hash
|
||||
"""
|
||||
os.makedirs("trades", exist_ok=True)
|
||||
@@ -208,6 +217,7 @@ class PumpTrader:
|
||||
"token_address": str(token_info.mint),
|
||||
"symbol": token_info.symbol,
|
||||
"price": price,
|
||||
"amount": amount,
|
||||
"tx_hash": tx_hash,
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ Tests websocket monitoring for new pump.fun tokens
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
import config
|
||||
from core.pubkeys import PumpAddresses
|
||||
from monitoring.listener import PumpTokenListener
|
||||
from trading.base import TokenInfo
|
||||
@@ -43,7 +45,7 @@ async def test_pump_token_listener(
|
||||
):
|
||||
"""Test the token listener functionality"""
|
||||
wss_endpoint = os.environ.get(
|
||||
"SOLANA_NODE_WSS_ENDPOINT", "wss://api.mainnet-beta.solana.com"
|
||||
"SOLANA_NODE_WSS_ENDPOINT", config.PUBLIC_WSS_ENDPOINT
|
||||
)
|
||||
logger.info(f"Connecting to WebSocket: {wss_endpoint}")
|
||||
listener = PumpTokenListener(wss_endpoint, PumpAddresses.PROGRAM)
|
||||
@@ -76,7 +78,7 @@ async def test_pump_token_listener(
|
||||
|
||||
logger.info(f"Detected {len(callback.detected_tokens)} tokens")
|
||||
for token in callback.detected_tokens:
|
||||
logger.info(f" - 🪙 {token.name} ({token.symbol}): {token.mint}")
|
||||
logger.info(f" - {token.name} ({token.symbol}): {token.mint}")
|
||||
|
||||
return callback.detected_tokens
|
||||
|
||||
@@ -84,6 +86,7 @@ async def test_pump_token_listener(
|
||||
if __name__ == "__main__":
|
||||
match_string = None # Update if you want to filter tokens by name/symbol
|
||||
creator_address = None # Update if you want to filter tokens by creator address
|
||||
test_duration = 60
|
||||
test_duration = 15
|
||||
|
||||
logger.info("Starting token listener test")
|
||||
asyncio.run(test_pump_token_listener(match_string, creator_address, test_duration))
|
||||
|
||||
Reference in New Issue
Block a user