diff --git a/crypto/sol/.env.example b/crypto/sol/.env.example new file mode 100644 index 0000000..e949837 --- /dev/null +++ b/crypto/sol/.env.example @@ -0,0 +1,15 @@ + +SOLANA_WS_URL="wss://api.mainnet-beta.solana.com" +SOLANA_WS_URL2="wss://mainnet.rpcpool.com" +SOLANA_HTTP_URL="https://api.mainnet-beta.solana.com" +DEVELOPER_CHAT_ID="777826553" +# Niki's +# FOLLOWED_WALLET="9U7D916zuQ8qcL9kQZqkcroWhHGho5vD8VNekvztrutN" +# My test Brave sync wallet +FOLLOWED_WALLET="7QXGLRjvyFAmxdRaP9Wk18KwWTMfspF4Na2sr3o3PzxV" + +TELEGRAM_BOT_TOKEN="6805059978:AAHNJKuOeazMSJHc3-BXRCsFfEVyFHeFnjw" +DISPLAY_CURRENCY=USD + +YOUR_WALLET="65nzyZXTLC81MthTo52a2gRJjqryTizWVqpK2fDKLye5" +PK={} \ No newline at end of file diff --git a/crypto/sol/app.py b/crypto/sol/app.py index 04e96f5..f8e8966 100644 --- a/crypto/sol/app.py +++ b/crypto/sol/app.py @@ -325,10 +325,17 @@ async def load_subscription_id(): return int(subscription_id) if subscription_id else None +async def get_token_name(mint_address): + try: + token_info = await solana_client.get_token_supply(Pubkey.from_string(mint_address)) + if token_info.value and 'symbol' in token_info.value: + return token_info.value['symbol'] + except Exception as e: + logging.error(f"Error fetching token name for {mint_address}: {str(e)}") + return None async def get_wallet_balances(wallet_address): balances = {} - token_addresses = [] logging.info(f"Getting balances for wallet: {wallet_address}") try: @@ -349,9 +356,9 @@ async def get_wallet_balances(wallet_address): mint = info['mint'] amount = float(info['tokenAmount']['uiAmount']) if amount > 0: - token_addresses.append(mint) - balances[mint] = amount - logging.debug(f"Balance for {mint}: {amount}") + token_name = await get_token_name(mint) or mint + balances[f"{token_name} ({mint})"] = amount + logging.debug(f"Balance for {token_name} ({mint}): {amount}") else: logging.warning(f"Unexpected data format for account: {account}") @@ -364,18 +371,15 @@ async def get_wallet_balances(wallet_address): except Exception as e: logging.error(f"Error getting wallet balances: {str(e)}") - return balances, token_addresses - - - + return balances async def list_initial_wallet_states(): global TOKEN_ADDRESSES, FOLLOWED_WALLET_VALUE, YOUR_WALLET_VALUE - followed_wallet_balances, followed_token_addresses = await get_wallet_balances(FOLLOWED_WALLET) - your_wallet_balances, your_token_addresses = await get_wallet_balances(YOUR_WALLET) + followed_wallet_balances = await get_wallet_balances(FOLLOWED_WALLET) + your_wallet_balances = await get_wallet_balances(YOUR_WALLET) - all_token_addresses = list(set(followed_token_addresses + your_token_addresses)) + all_token_addresses = list(set(followed_wallet_balances.keys()) | set(your_wallet_balances.keys())) token_prices = await get_token_prices(all_token_addresses) sol_price = await get_sol_price() @@ -415,10 +419,6 @@ async def list_initial_wallet_states(): await send_telegram_message(message) - - - - async def get_transaction_details_rpc(tx_signature, readfromDump=False): url = SOLANA_HTTP_URL # url = 'https://solana.drpc.org' @@ -491,6 +491,7 @@ async def process_log(log_result): f"Token In: {details['token_in']}\n" f"Token Out: {details['token_out']}\n" f"Amount In USD: {details['amount_in_USD']}\n" + f"Percentage Swapped: {details['percentage_swapped']:.2f}%" ) await send_telegram_message(message_text) @@ -519,9 +520,9 @@ async def parse_swap_logs(logs): amount_out_expected = 0 amount_out_actual = 0 order_id = None + before_source_balance = 0 for log in logs: - # Check for token identifiers if "Program log:" in log: if "order_id:" in log: order_id = log.split("order_id: ")[-1].strip() @@ -533,62 +534,61 @@ async def parse_swap_logs(logs): elif not token_out: token_out = log.split("Program log: ")[-1].strip() - # Use regex to find amount_in and amount_out patterns + if "before_source_balance:" in log: + before_source_balance = int(re.search(r"before_source_balance: (\d+)", log).group(1)) + if "amount_in" in log or "amount_out" in log: amount_matches = re.findall(r"(amount_in|amount_out): (\d+)", log) for amount_type, value in amount_matches: if amount_type == "amount_in": - amount_in = int(value)/1e6 + amount_in = int(value) elif amount_type == "amount_out": - amount_out_expected = int(value)/1e6 + amount_out_expected = int(value) - # Check for source_token_change and destination_token_change for additional details elif "source_token_change:" in log or "destination_token_change:" in log: changes = log.split(", ") for change in changes: if "source_token_change" in change: - amount_in = int(change.split(": ")[-1])/1e6 + amount_in = int(change.split(": ")[-1]) elif "destination_token_change" in change: - amount_out_actual = int(change.split(": ")[-1])/1e6 + amount_out_actual = int(change.split(": ")[-1]) token_prices = await get_token_prices([token_in, token_out]) - amount_in_usd = amount_in * token_prices.get(token_in, 0) - amount_out_usd = amount_out_actual * token_prices.get(token_out, 0) + amount_in_usd = amount_in / 1e6 * token_prices.get(token_in, 0) + amount_out_usd = amount_out_actual / 1e6 * token_prices.get(token_out, 0) + + # Calculate the percentage of the source balance that was swapped + percentage_swapped = (amount_in / before_source_balance) * 100 if before_source_balance > 0 else 0 return { "order_id": order_id, "token_in": token_in, "token_out": token_out, - "amount_in": amount_in, - "amount_out_expected": amount_out_expected, - "amount_out_actual": amount_out_actual, - "amount_in_USD": amount_in_usd , + "amount_in": amount_in / 1e6, + "amount_out_expected": amount_out_expected / 1e6, + "amount_out_actual": amount_out_actual / 1e6, + "amount_in_USD": amount_in_usd, "amount_out_USD": amount_out_usd, + "percentage_swapped": percentage_swapped } - async def follow_move(move): - followed_balances = await get_wallet_balances(FOLLOWED_WALLET) your_balances = await get_wallet_balances(YOUR_WALLET) + your_balance = your_balances.get(move['token_in'], 0) - followed_balance = followed_balances[move.token_in] - your_balance = your_balances[move.token_in] - - proportion = your_balance / followed_balance if followed_balance > 0 else 0 - amount_to_swap = move.amount_in * proportion + # Calculate the amount to swap based on the same percentage as the followed move + amount_to_swap = your_balance * (move['percentage_swapped'] / 100) if your_balance >= amount_to_swap: try: - # Initialize Jupiter client private_key = Keypair.from_bytes(base58.b58decode(os.getenv("PK"))) async_client = AsyncClient(SOLANA_WS_URL) jupiter = Jupiter(async_client, private_key) - # Perform the swap transaction_data = await jupiter.swap( - input_mint=move.token_in, - output_mint=move.token_out, - amount=int(amount_to_swap), + input_mint=move['token_in'], + output_mint=move['token_out'], + amount=int(amount_to_swap * 1e6), # Convert to lamports slippage_bps=1, ) @@ -601,8 +601,9 @@ async def follow_move(move): message = ( f"Move Followed:\n" - f"Swapped {amount_to_swap:.6f} {move['token']} " - f"for {transaction_data['outputAmount']:.6f} {move['to_token']}" + f"Swapped {amount_to_swap:.6f} {move['token_in']} " + f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n" + f"for {transaction_data['outputAmount'] / 1e6:.6f} {move['token_out']}" ) logging.info(message) await send_telegram_message(message) @@ -613,12 +614,12 @@ async def follow_move(move): else: message = ( f"Move Failed:\n" - f"Insufficient balance to swap {amount_to_swap:.6f} {move['token']}" + f"Insufficient balance to swap {amount_to_swap:.6f} {move['token_in']}" ) logging.warning(message) await send_telegram_message(message) - +# Helper functions (implement these according to your needs)