mirror of
https://github.com/chainstacklabs/pumpfun-bonkfun-bot.git
synced 2026-08-08 21:17:46 +00:00
fix: pyproject.toml, module paths
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Command-line interface for the pump.fun trading bot.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
import config as config
|
||||
from trading.trader import PumpTrader
|
||||
from utils.logger import get_logger, setup_file_logging
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
def parse_args() -> argparse.Namespace:
|
||||
"""Parse command line arguments.
|
||||
|
||||
Returns:
|
||||
Parsed arguments
|
||||
"""
|
||||
parser = argparse.ArgumentParser(description="Trade tokens on pump.fun.")
|
||||
parser.add_argument(
|
||||
"--yolo", action="store_true", help="Run in YOLO mode (continuous trading)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--match",
|
||||
type=str,
|
||||
help="Only trade tokens with names or symbols matching this string",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bro", type=str, help="Only trade tokens created by this user address"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--marry", action="store_true", help="Only buy tokens, skip selling"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--amount",
|
||||
type=float,
|
||||
help=f"Amount of SOL to spend on each buy (default: {config.BUY_AMOUNT})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--buy-slippage",
|
||||
type=float,
|
||||
help=f"Buy slippage tolerance (default: {config.BUY_SLIPPAGE})",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--sell-slippage",
|
||||
type=float,
|
||||
help=f"Sell slippage tolerance (default: {config.SELL_SLIPPAGE})",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
"""Main entry point for the CLI."""
|
||||
setup_file_logging("pump_trading.log")
|
||||
|
||||
args = parse_args()
|
||||
|
||||
# Get configuration values, preferring command line args over config.py
|
||||
rpc_endpoint: str | None = os.environ.get("SOLANA_NODE_RPC_ENDPOINT")
|
||||
wss_endpoint: str | None = os.environ.get("SOLANA_NODE_WSS_ENDPOINT")
|
||||
private_key: str | None = os.environ.get("SOLANA_PRIVATE_KEY")
|
||||
|
||||
# Validate configuration values
|
||||
if not rpc_endpoint or not rpc_endpoint.startswith(("http://", "https://")):
|
||||
logger.error("Invalid RPC endpoint. Must start with http:// or https://")
|
||||
sys.exit(1)
|
||||
|
||||
if not wss_endpoint or not wss_endpoint.startswith(("ws://", "wss://")):
|
||||
logger.error("Invalid WebSocket endpoint. Must start with ws:// or wss://")
|
||||
sys.exit(1)
|
||||
|
||||
if not private_key or len(private_key) < 80:
|
||||
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
|
||||
)
|
||||
sell_slippage: float = (
|
||||
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
|
||||
private_key=private_key,
|
||||
buy_amount=buy_amount,
|
||||
buy_slippage=buy_slippage,
|
||||
sell_slippage=sell_slippage,
|
||||
max_retries=config.MAX_RETRIES,
|
||||
)
|
||||
|
||||
try:
|
||||
await trader.start(
|
||||
match_string=args.match,
|
||||
bro_address=args.bro,
|
||||
marry_mode=args.marry,
|
||||
yolo_mode=args.yolo,
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Trading stopped by user")
|
||||
except Exception as e:
|
||||
logger.error(f"Trading stopped due to error: {str(e)}")
|
||||
finally:
|
||||
try:
|
||||
await trader.solana_client.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def sync_main():
|
||||
asyncio.run(main())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,68 @@
|
||||
"""
|
||||
Configuration for the pump.fun trading bot.
|
||||
"""
|
||||
|
||||
# Trading parameters
|
||||
BUY_AMOUNT: int | float = 0.000_001 # Amount of SOL to spend when buying
|
||||
BUY_SLIPPAGE: float = 0.4 # 40% slippage tolerance for buying
|
||||
SELL_SLIPPAGE: float = 0.4 # 40% slippage tolerance for selling
|
||||
|
||||
|
||||
# Configuration for priority fee settings
|
||||
ENABLE_DYNAMIC_PRIORITY_FEE: bool = False # Enable dynamic priority fee calculation
|
||||
ENABLE_FIXED_PRIORITY_FEE: bool = True # Enable fixed priority fee
|
||||
FIXED_PRIORITY_FEE: int = 2_000 # Fixed priority fee in microlamports
|
||||
EXTRA_PRIORITY_FEE: float = (
|
||||
0.0 # Percentage increase applied to priority fee (0.1 = 10%)
|
||||
)
|
||||
HARD_CAP_PRIOR_FEE: int = (
|
||||
200_000 # Maximum allowed priority fee in microlamports (hard cap)
|
||||
)
|
||||
|
||||
|
||||
# Retries and timeouts
|
||||
MAX_RETRIES: int = 10 # Number of retries for transaction sending
|
||||
# TODO: waiting times will be replaced with retries to shorten delays
|
||||
WAIT_TIME_AFTER_CREATION: int | float = (
|
||||
15 # Time to wait after token creation (in seconds)
|
||||
# Too short a delay may cause the RPC node to be unaware of the bonding curve account
|
||||
)
|
||||
WAIT_TIME_AFTER_BUY: int | float = (
|
||||
15 # Time to wait after a buy transaction is confirmed (in seconds)
|
||||
# Acts as a simple holding period
|
||||
# Too short delay may cause the RPC node to be unaware of account balance
|
||||
)
|
||||
WAIT_TIME_BEFORE_NEW_TOKEN: int | float = (
|
||||
5 # Time to wait after a sell transaction is confirmed (in seconds)
|
||||
# Provides a pause between completed trades, can be set to 0
|
||||
)
|
||||
|
||||
|
||||
# Maximum age (in seconds) for a token to be considered "fresh" and eligible for processing.
|
||||
# This threshold is checked before processing starts - tokens older than this are skipped
|
||||
# since they likely contain outdated information from the websocket stream
|
||||
MAX_TOKEN_AGE: int | float = 0.1
|
||||
|
||||
|
||||
# Node provider configuration
|
||||
# Tested with Chainstack nodes (https://console.chainstack.com), but you can use any node provider
|
||||
# You can get a trader node https://docs.chainstack.com/docs/solana-trader-nodes
|
||||
MAX_RPS: int = 25 # TODO: not implemented. Max RPS to avoid rate limit errors
|
||||
|
||||
|
||||
def validate_priority_fee_config() -> None:
|
||||
"""Validate priority fee configuration values."""
|
||||
if not isinstance(ENABLE_DYNAMIC_PRIORITY_FEE, bool):
|
||||
raise ValueError("ENABLE_DYNAMIC_PRIORITY_FEE must be a boolean")
|
||||
if not isinstance(ENABLE_FIXED_PRIORITY_FEE, bool):
|
||||
raise ValueError("ENABLE_FIXED_PRIORITY_FEE must be a boolean")
|
||||
if not isinstance(FIXED_PRIORITY_FEE, int) or FIXED_PRIORITY_FEE < 0:
|
||||
raise ValueError("FIXED_PRIORITY_FEE must be a non-negative integer")
|
||||
if not isinstance(EXTRA_PRIORITY_FEE, float) or EXTRA_PRIORITY_FEE < 0:
|
||||
raise ValueError("EXTRA_PRIORITY_FEE must be a non-negative float")
|
||||
if not isinstance(HARD_CAP_PRIOR_FEE, int) or HARD_CAP_PRIOR_FEE < 0:
|
||||
raise ValueError("HARD_CAP_PRIOR_FEE must be a non-negative integer")
|
||||
|
||||
|
||||
# Validate config on import
|
||||
validate_priority_fee_config()
|
||||
+1
-1
@@ -18,7 +18,7 @@ from solders.message import Message
|
||||
from solders.pubkey import Pubkey
|
||||
from solders.transaction import Transaction
|
||||
|
||||
from src.utils.logger import get_logger
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
+3
-3
@@ -8,9 +8,9 @@ from typing import Final
|
||||
from construct import Flag, Int64ul, Struct
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.pubkeys import LAMPORTS_PER_SOL, TOKEN_DECIMALS
|
||||
from src.utils.logger import get_logger
|
||||
from core.client import SolanaClient
|
||||
from core.pubkeys import LAMPORTS_PER_SOL, TOKEN_DECIMALS
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@ import statistics
|
||||
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
from core.client import SolanaClient
|
||||
from core.priority_fee import PriorityFeePlugin
|
||||
from src.core.client import SolanaClient
|
||||
from src.utils.logger import get_logger
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.priority_fee.dynamic_fee import DynamicPriorityFee
|
||||
from src.core.priority_fee.fixed_fee import FixedPriorityFee
|
||||
from src.utils.logger import get_logger
|
||||
from core.client import SolanaClient
|
||||
from core.priority_fee.dynamic_fee import DynamicPriorityFee
|
||||
from core.priority_fee.fixed_fee import FixedPriorityFee
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -9,18 +9,18 @@ from solders.instruction import AccountMeta, Instruction
|
||||
from solders.pubkey import Pubkey
|
||||
from spl.token.instructions import create_associated_token_account
|
||||
|
||||
from core.client import SolanaClient
|
||||
from core.curve import BondingCurveManager
|
||||
from core.priority_fee.manager import PriorityFeeManager
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.curve import BondingCurveManager
|
||||
from src.core.pubkeys import (
|
||||
from core.pubkeys import (
|
||||
LAMPORTS_PER_SOL,
|
||||
TOKEN_DECIMALS,
|
||||
PumpAddresses,
|
||||
SystemAddresses,
|
||||
)
|
||||
from src.core.wallet import Wallet
|
||||
from src.trading.base import TokenInfo, Trader, TradeResult
|
||||
from src.utils.logger import get_logger
|
||||
from core.wallet import Wallet
|
||||
from trading.base import TokenInfo, Trader, TradeResult
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
@@ -8,18 +8,18 @@ from typing import Final
|
||||
from solders.instruction import AccountMeta, Instruction
|
||||
from solders.pubkey import Pubkey
|
||||
|
||||
from core.client import SolanaClient
|
||||
from core.curve import BondingCurveManager
|
||||
from core.priority_fee.manager import PriorityFeeManager
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.curve import BondingCurveManager
|
||||
from src.core.pubkeys import (
|
||||
from core.pubkeys import (
|
||||
LAMPORTS_PER_SOL,
|
||||
TOKEN_DECIMALS,
|
||||
PumpAddresses,
|
||||
SystemAddresses,
|
||||
)
|
||||
from src.core.wallet import Wallet
|
||||
from src.trading.base import TokenInfo, Trader, TradeResult
|
||||
from src.utils.logger import get_logger
|
||||
from core.wallet import Wallet
|
||||
from trading.base import TokenInfo, Trader, TradeResult
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
+10
-10
@@ -8,17 +8,17 @@ import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
import config
|
||||
import config as config
|
||||
from core.client import SolanaClient
|
||||
from core.curve import BondingCurveManager
|
||||
from core.priority_fee.manager import PriorityFeeManager
|
||||
from src.core.client import SolanaClient
|
||||
from src.core.curve import BondingCurveManager
|
||||
from src.core.pubkeys import PumpAddresses
|
||||
from src.core.wallet import Wallet
|
||||
from src.monitoring.listener import PumpTokenListener
|
||||
from src.trading.base import TokenInfo, TradeResult
|
||||
from src.trading.buyer import TokenBuyer
|
||||
from src.trading.seller import TokenSeller
|
||||
from src.utils.logger import get_logger
|
||||
from core.pubkeys import PumpAddresses
|
||||
from core.wallet import Wallet
|
||||
from monitoring.listener import PumpTokenListener
|
||||
from trading.base import TokenInfo, TradeResult
|
||||
from trading.buyer import TokenBuyer
|
||||
from trading.seller import TokenSeller
|
||||
from utils.logger import get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user