Files
pumpfun-bonkfun-bot_github/cli.py
T
2025-03-06 16:14:17 +00:00

132 lines
3.9 KiB
Python

#!/usr/bin/env python3
"""
Command-line interface for the pump.fun trading bot.
"""
import argparse
import asyncio
import os
import sys
from typing import Any, Dict
import config
from src.trading.trader import PumpTrader
from src.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") or config.PUBLIC_RPC_ENDPOINT
)
wss_endpoint: str | None = (
os.environ.get("SOLANA_NODE_WSS_ENDPOINT") or config.PUBLIC_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
if __name__ == "__main__":
asyncio.run(main())