minor fixes

This commit is contained in:
smypmsa
2025-03-06 13:52:40 +00:00
parent 4f800bbbbe
commit 25c304f0fe
5 changed files with 65 additions and 40 deletions
+18 -2
View File
@@ -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
+7 -10
View File
@@ -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
View File
@@ -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
View File
@@ -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 -3
View File
@@ -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))