fixes and starbility ()tetrt

This commit is contained in:
Dobromir Popov 2024-11-05 16:38:37 +02:00
parent 8f6a788717
commit 0780878c50
4 changed files with 227 additions and 165 deletions

View File

@ -15,6 +15,9 @@ TELEGRAM_BOT_TOKEN="6749075936:AAHUHiPTDEIu6JH7S2fQdibwsu6JVG3FNG0"
DISPLAY_CURRENCY=USD DISPLAY_CURRENCY=USD
FOLLOW_AMOUNT=2 FOLLOW_AMOUNT=2
FOLLOW_AMOUNT=percentage
LIQUIDITY_TOKENS=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,So11111111111111111111111111111111111111112
# Niki's to Sync: [PROD] # Niki's to Sync: [PROD]
FOLLOWED_WALLET="7keSmTZozjmuX66gd9GBSJYEHnMqsyutWpvuuKtXZKDH" FOLLOWED_WALLET="7keSmTZozjmuX66gd9GBSJYEHnMqsyutWpvuuKtXZKDH"

View File

@ -21,6 +21,7 @@ SOLANA_HTTP_URL = os.getenv("SOLANA_HTTP_URL")
DISPLAY_CURRENCY = os.getenv('DISPLAY_CURRENCY', 'USD') DISPLAY_CURRENCY = os.getenv('DISPLAY_CURRENCY', 'USD')
BOT_NAME = os.getenv("BOT_NAME") BOT_NAME = os.getenv("BOT_NAME")
FOLLOW_AMOUNT = os.getenv('FOLLOW_AMOUNT', 'percentage') FOLLOW_AMOUNT = os.getenv('FOLLOW_AMOUNT', 'percentage')
LIQUIDITY_TOKENS = os.getenv('LIQUIDITY_TOKENS', 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v').split(',')
SOLANA_ENDPOINTS = [ SOLANA_ENDPOINTS = [
"wss://api.mainnet-beta.solana.com", "wss://api.mainnet-beta.solana.com",

View File

@ -25,11 +25,18 @@ from solana.rpc.async_api import AsyncClient
from solana.rpc.types import TxOpts from solana.rpc.types import TxOpts
from solana.rpc.commitment import Confirmed, Finalized, Processed from solana.rpc.commitment import Confirmed, Finalized, Processed
from solders.transaction import VersionedTransaction
from solders.rpc.requests import GetTransaction
from solders.signature import Signature
from solders.pubkey import Pubkey
from solders.keypair import Keypair from solders.keypair import Keypair
from solana.rpc.async_api import AsyncClient from solders.transaction import VersionedTransaction
from solana.rpc.commitment import Processed from solders.transaction import Transaction
from solana.rpc.types import TxOpts from solders.message import Message
from solders.instruction import Instruction
from solders.hash import Hash
from solders.instruction import CompiledInstruction
from solders import message
from jupiter_python_sdk.jupiter import Jupiter from jupiter_python_sdk.jupiter import Jupiter
import asyncio import asyncio
@ -251,8 +258,8 @@ class SolanaAPI:
await solana_ws.subscribe() await solana_ws.subscribe()
if first_subscription: if first_subscription:
await async_safe_call( self.on_initial_subscription, solana_ws.subscription_id)
first_subscription = False first_subscription = False
await async_safe_call(self.on_initial_subscription, solana_ws.subscription_id)
await async_safe_call(self.on_bot_message,f"Solana mainnet connected ({solana_ws.subscription_id})...") await async_safe_call(self.on_bot_message,f"Solana mainnet connected ({solana_ws.subscription_id})...")
@ -503,7 +510,7 @@ class SolanaAPI:
if transfer['mint'] in DEX.TOKENS_INFO or 'decimals' not in DEX.TOKENS_INFO[transfer['mint']]: if transfer['mint'] in DEX.TOKENS_INFO or 'decimals' not in DEX.TOKENS_INFO[transfer['mint']]:
await self.get_token_metadata_symbol(transfer['mint']) await self.get_token_metadata_symbol(transfer['mint'])
# get actual prices # get actual prices
current_price = await self.get_token_prices([transfer['mint']]) current_price = await DEX.get_token_prices([transfer['mint']])
if parsed_result["token_in"] is None: if parsed_result["token_in"] is None:
parsed_result["token_in"] = transfer['mint'] parsed_result["token_in"] = transfer['mint']
@ -529,7 +536,9 @@ class SolanaAPI:
parsed_result["percentage_swapped"] = (parsed_result["amount_in"] / parsed_result["before_source_balance"]) * 100 parsed_result["percentage_swapped"] = (parsed_result["amount_in"] / parsed_result["before_source_balance"]) * 100
else: else:
# calculate based on total wallet value: FOLLOWED_WALLET_VALUE # calculate based on total wallet value: FOLLOWED_WALLET_VALUE
parsed_result["percentage_swapped"] = (parsed_result["amount_in_USD"] / DEX.FOLLOWED_WALLET_VALUE) * 100 # division by 0
# parsed_result["percentage_swapped"] = (parsed_result["amount_in_USD"] / DEX.FOLLOWED_WALLET_VALUE) * 100
pass
except Exception as e: except Exception as e:
logging.error(f"Error calculating percentage swapped: {e}") logging.error(f"Error calculating percentage swapped: {e}")
@ -563,7 +572,7 @@ class SolanaAPI:
# return float(balance['uiTokenAmount']['amount']) # return float(balance['uiTokenAmount']['amount'])
# return 0.0 # return 0.0
async def get_transaction_details_with_retry(self, transaction_id, retry_delay = 5, max_retries = 16): async def get_transaction_details_with_retry(self, transaction_id, retry_delay = 5, max_retries = 16, backoff= True):
# wait for the transaction to be confirmed # wait for the transaction to be confirmed
# await async_client.wait_for_confirmation(Signature.from_string(transaction_id)) # await async_client.wait_for_confirmation(Signature.from_string(transaction_id))
# query every 5 seconds for the transaction details until not None or 30 seconds # query every 5 seconds for the transaction details until not None or 30 seconds
@ -574,10 +583,11 @@ class SolanaAPI:
break break
except Exception as e: except Exception as e:
logging.error(f"Error fetching transaction details: {e}") logging.error(f"Error fetching transaction details: {e}")
retry_delay = retry_delay * 1.2
logging.info(f"({_} of {max_retries}) Waiting for transaction details for {transaction_id}. retry in {retry_delay} s.") logging.info(f"({_} of {max_retries}) Waiting for transaction details for {transaction_id}. retry in {retry_delay} s.")
await asyncio.sleep(retry_delay) await asyncio.sleep(retry_delay)
retry_delay *= 1.2 if backoff:
retry_delay = retry_delay * 1.2
return tx_details return tx_details
@ -662,162 +672,174 @@ class SolanaAPI:
return 0 return 0
async def follow_move(self,move): async def follow_move(self,move):
your_balances = await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False) try:
your_balance_info = next((balance for balance in your_balances.values() if balance['address'] == move['token_in']), None) your_balances = await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False)
if your_balance_info is not None: your_balance_info = next((balance for balance in your_balances.values() if balance['address'] == move['token_in']), None)
# Use the balance if your_balance_info is not None:
print(f"Your balance: {your_balance_info['amount']} {move['symbol_in']}") # Use the balance
else: print(f"Your balance: {your_balance_info['amount']} {move['symbol_in']}")
print(f"No ballance found for {move['symbol_in']}. Skipping move.") else:
await telegram_utils.send_telegram_message(f"No ballance found for {move['symbol_in']}. Skipping move.") print(f"No ballance found for {move['symbol_in']}. Skipping move.")
return await telegram_utils.send_telegram_message(f"No ballance found for {move['symbol_in']}. Skipping move.")
return
your_balance = your_balance_info['amount']
your_balance = your_balance_info['amount']
token_info = DEX.TOKENS_INFO.get(move['token_in']) token_info = DEX.TOKENS_INFO.get(move['token_in'])
token_name_in = token_info.get('symbol') or await SAPI.get_token_metadata_symbol(move['token_in']) token_name_in = token_info.get('symbol') or await SAPI.get_token_metadata_symbol(move['token_in'])
token_name_out = DEX.TOKENS_INFO[move['token_out']].get('symbol') or await SAPI.get_token_metadata_symbol(move['token_out']) token_name_out = DEX.TOKENS_INFO[move['token_out']].get('symbol') or await SAPI.get_token_metadata_symbol(move['token_out'])
if not your_balance: if not your_balance:
msg = f"<b>Move not followed:</b>\nNo balance found for token {move['symbol_in']}. Cannot follow move." msg = f"<b>Move not followed:</b>\nNo balance found for token {move['symbol_in']}. Cannot follow move."
logging.warning(msg)
await telegram_utils.send_telegram_message(msg)
return
if FOLLOW_AMOUNT == 'percentage':
# Calculate the amount to swap based on the same percentage as the followed move
amount_to_swap = your_balance * (move['percentage_swapped'] / 100)
elif FOLLOW_AMOUNT == 'exact':
amount_to_swap = move['amount_in']
else:
try:
fixed_amount = float(FOLLOW_AMOUNT) # un USD
fixed_amount_in_token = fixed_amount / move["token_in_price"]
amount_to_swap = min(fixed_amount_in_token, your_balance)
except ValueError:
msg = f"<b>Move not followed:</b>\nInvalid FOLLOW_AMOUNT '{FOLLOW_AMOUNT}'. Must be 'percentage' or a number."
logging.warning(msg) logging.warning(msg)
await telegram_utils.send_telegram_message(msg) await telegram_utils.send_telegram_message(msg)
return return
amount_to_swap = min(amount_to_swap, your_balance) # Ensure we're not trying to swap more than we have if FOLLOW_AMOUNT == 'percentage':
# Calculate the amount to swap based on the same percentage as the followed move
decimals = token_info.get('decimals') if move.get('percentage_swapped') is None:
# Convert to lamports followed_ballances = await DEX.get_wallet_balances(FOLLOWED_WALLET, doGetTokenName=False)
# if decimals is 6, then amount = amount * 1e6; if 9, then amount = amount * 1e9 followed_ballance = next((balance for balance in followed_ballances.values() if balance['address'] == move['token_in']), None)
amount = int(amount_to_swap * 10**decimals) if followed_ballance is not None:
amount = int(amount) # Use the balance
logging.debug(f"Calculated amount in lamports: {amount}") print(f"Followed balance: {followed_ballance['amount']} {move['symbol_in']}")
move['percentage_swapped'] = (move['amount_in']/followed_ballance['amount']) * 100
if your_balance < amount_to_swap: # should not happen amount_to_swap = your_balance * (move['percentage_swapped'] / 100)
msg = (
f"<b>Warning:</b>\n"
f"Insufficient balance: {your_balance:.6f} {token_name_in}. We want to swap {amount_to_swap:.6f}\n({move['symbol_in']}, decimals {token_info.get('decimals')} amount {amount}).\n This will probably fail. But we will try anyway."
)
logging.warning(msg)
await telegram_utils.send_telegram_message(msg)
try:
try:
notification = (
f"<b>Initiating move:</b>\n"
f"Swapping {amount_to_swap:.2f} {token_name_in} for {token_name_out}"
+ (f" ({move['percentage_swapped']:.2f}%)" if 'percentage_swapped' in move else "")
)
# logging.info(notification)
# error_logger.info(notification)
# await telegram_utils.send_telegram_message(notification)
except Exception as e:
logging.error(f"Error sending notification: {e}")
if self.pk is None:
self.pk = await get_pk()
for retry in range(3):
try:
private_key = Keypair.from_bytes(base58.b58decode(self.pk))
async_client = AsyncClient(SOLANA_WS_URL)
jupiter = Jupiter(async_client, private_key)
transaction_data = await jupiter.swap(
input_mint=move['token_in'],
output_mint=move['token_out'],
amount=int(amount),
slippage_bps=300, # Increased to 3%
)
logging.info(f"Initiating move. Transaction data:\n {transaction_data}")
# error_logger.info(f"Initiating move. Transaction data:\n {transaction_data}")
raw_transaction = VersionedTransaction.from_bytes(base64.b64decode(transaction_data))
message = raw_transaction.message
signature = private_key.sign_message( bytes(message) )
# signature = private_key.sign_message(message.to_bytes_versioned())
signed_txn = VersionedTransaction.populate(raw_transaction.message, [signature])
opts = TxOpts(skip_preflight=False, preflight_commitment=Processed)
# send the transaction
result = await async_client.send_raw_transaction(txn=bytes(signed_txn), opts=opts)
transaction_id = json.loads(result.to_json())['result']
print(f"Follow Transaction Sent: https://solscan.io/tx/{transaction_id}")
# append to notification
notification += f"\n\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>{transaction_id}</a>"
await telegram_utils.send_telegram_message(f"Follow Transaction Sent: {transaction_id}")
tx_details = await SAPI.get_transaction_details_with_retry(transaction_id)
if tx_details is not None:
break
else: else:
logging.warning(f"Failed to get transaction details for {transaction_id}. Probably transaction failed. Retrying again...") #fallback to 100 USD
await asyncio.sleep(3) amount_to_swap = 100
except Exception as e:
error_message = f"<b>Move Failed:</b>\n{str(e)}</b>\n{transaction_data}</b>\n{move}"
logging.error(error_message)
# log the errors to /logs/errors.log
# error_logger.error(error_message)
# error_logger.exception(e)
await telegram_utils.send_telegram_message(error_message)
amount = int(amount * 0.75)
await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False)
try:
if tx_details is None:
logging.info(f"Failed to get transaction details for {transaction_id}")
notification = (
f"<b>Move Followed, failed to get transaction details.</b>\n"
f"Swapped {amount_to_swap:.6f} {token_name_in} ({move['token_in']}) "
f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n"
f"\n\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>{transaction_id}</a>"
# log_successful_swap ()
)
else: else:
notification = ( amount_to_swap = your_balance * (move['percentage_swapped'] / 100)
f"<b>Move Followed:</b>\n" elif FOLLOW_AMOUNT == 'exact':
f"Swapped {amount_to_swap:.6f} {token_name_in} ({move['symbol_in']}) " amount_to_swap = move['amount_in']
f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n"
f"for {tx_details['amount_out']:.2f} {token_name_out}"
# f"Amount In USD: {tr_details['amount_in_USD']}\n"
f"\n\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>{transaction_id}</a>"
)
logging.info(notification)
await telegram_utils.send_telegram_message(notification)
except Exception as e:
logging.error(f"Error sending notification: {e}")
except Exception as e:
error_message = f"<b>Swap Follow Error:</b>\n{str(e)}"
logging.error(error_message)
# log the errors to /logs/errors.log
# error_logger.error(error_message)
# error_logger.exception(e)
# if error_message contains 'Program log: Error: insufficient funds'
if 'insufficient funds' in error_message:
await telegram_utils.send_telegram_message("Insufficient funds. Cannot follow move. Please check your balance.")
else: else:
await telegram_utils.send_telegram_message(error_message) try:
fixed_amount = float(FOLLOW_AMOUNT) # un USD
fixed_amount_in_token = fixed_amount / move["token_in_price"]
amount_to_swap = min(fixed_amount_in_token, your_balance)
except ValueError:
msg = f"<b>Move not followed:</b>\nInvalid FOLLOW_AMOUNT '{FOLLOW_AMOUNT}'. Must be 'percentage' or a number."
logging.warning(msg)
await telegram_utils.send_telegram_message(msg)
return
amount_to_swap = min(amount_to_swap, your_balance) # Ensure we're not trying to swap more than we have
decimals = token_info.get('decimals')
# Convert to lamports
# if decimals is 6, then amount = amount * 1e6; if 9, then amount = amount * 1e9
amount_lamports = int(amount_to_swap * 10**decimals)
logging.debug(f"Calculated amount in lamports: {amount_lamports}")
if your_balance < amount_to_swap: # should not happen
msg = (
f"<b>Warning:</b>\n"
f"Insufficient balance: {your_balance:.6f} {token_name_in}. We want to swap {amount_to_swap:.6f}\n({move['symbol_in']}, decimals {token_info.get('decimals')} amount {amount_lamports}).\n This will probably fail. But we will try anyway."
)
logging.warning(msg)
await telegram_utils.send_telegram_message(msg)
try:
try:
notification = (
f"<b>Initiating move:</b>\n"
f"Swapping {amount_to_swap:.2f} {token_name_in} for {token_name_out}"
+ (f" ({move['percentage_swapped']:.2f}%)" if 'percentage_swapped' in move else "")
)
# logging.info(notification)
# error_logger.info(notification)
# await telegram_utils.send_telegram_message(notification)
except Exception as e:
logging.error(f"Error sending notification: {e}")
if self.pk is None:
self.pk = await get_pk()
for retry in range(3):
try:
private_key = Keypair.from_bytes(base58.b58decode(self.pk))
async_client = AsyncClient(SOLANA_WS_URL)
jupiter = Jupiter(async_client, private_key)
transaction_data = await jupiter.swap(
input_mint=move['token_in'],
output_mint=move['token_out'],
amount=amount_lamports,
slippage_bps=300, # Increased to 3%
)
logging.info(f"Initiating move. Transaction data:\n {transaction_data}")
# error_logger.info(f"Initiating move. Transaction data:\n {transaction_data}")
raw_transaction = VersionedTransaction.from_bytes(base64.b64decode(transaction_data))
# message = raw_transaction.message
# signature = private_key.sign_message( bytes(message) )
signature = private_key.sign_message(message.to_bytes_versioned(raw_transaction.message))
signed_txn = VersionedTransaction.populate(raw_transaction.message, [signature])
opts = TxOpts(skip_preflight=False, preflight_commitment=Processed)
# send the transaction
result = await async_client.send_raw_transaction(txn=bytes(signed_txn), opts=opts)
transaction_id = json.loads(result.to_json())['result']
notification = f"Follow Transaction Sent:\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>swapping {amount_to_swap:.2f} {token_name_in}</a>"
logging.info(notification)
await telegram_utils.send_telegram_message(notification)
tx_details = await SAPI.get_transaction_details_with_retry(transaction_id, retry_delay=5, max_retries=6, backoff=False)
if tx_details is not None:
break
else:
logging.warning(f"Failed to get transaction details for {transaction_id}.\n Probably transaction failed. Retrying again...")
await asyncio.sleep(3)
except Exception as e:
decoded_data = ''# base64.b64decode(transaction_data)
error_message = f"<b>Move Failed:</b>\n{str(e)}</b>\n{decoded_data}</b>\n{move}"
logging.error(error_message)
# log the errors to /logs/errors.log
# error_logger.error(error_message)
# error_logger.exception(e)
await telegram_utils.send_telegram_message(error_message)
amount = int(amount * 0.9)
await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False)
try:
if tx_details is None:
logging.info(f"Failed to get transaction details for {transaction_id}")
notification = (
f"<b>Move Followed, failed to get transaction details.</b>\n"
f"Swapped {amount_to_swap:.6f} {token_name_in} ({move['token_in']}) "
f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n"
f"\n\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>solscan.io</a>"
# log_successful_swap ()
)
else:
notification = (
f"<b>Move Followed:</b>\n"
f"Swapped {amount_to_swap:.6f} {token_name_in} ({move['symbol_in']}) "
f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n"
f"for {tx_details['amount_out']:.2f} {token_name_out}"
# f"Amount In USD: {tr_details['amount_in_USD']}\n"
f"\n\n<b>Transaction:</b> <a href='https://solscan.io/tx/{transaction_id}'>solscan.io</a>"
)
logging.info(notification)
await telegram_utils.send_telegram_message(notification)
except Exception as e:
logging.error(f"Error sending notification: {e}")
except Exception as e:
error_message = f"<b>Swap Follow Error:</b>\n{str(e)}"
logging.error(error_message)
# log the errors to /logs/errors.log
# error_logger.error(error_message)
# error_logger.exception(e)
# if error_message contains 'Program log: Error: insufficient funds'
if 'insufficient funds' in error_message:
await telegram_utils.send_telegram_message("Insufficient funds. Cannot follow move. Please check your balance.")
else:
await telegram_utils.send_telegram_message(error_message)
except Exception as e:
logging.error(f"Error following move: {e}")

View File

@ -1,8 +1,16 @@
import asyncio
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from flask import Flask, jsonify, request, render_template, redirect, url_for from flask import Flask, jsonify, request, render_template, redirect, url_for
# from flask_oauthlib.client import OAuth # from flask_oauthlib.client import OAuth
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
import secrets import secrets
import json import json
# from crypto.sol.config import LIQUIDITY_TOKENS
from config import LIQUIDITY_TOKENS
from modules import storage, utils, SolanaAPI from modules import storage, utils, SolanaAPI
from modules.utils import async_safe_call from modules.utils import async_safe_call
import os import os
@ -98,8 +106,10 @@ def init_app(tr_handler=None):
with open( os.path.join(SolanaAPI.root_path, 'logs', f'wh_{current_time}.json') , 'w') as f: with open( os.path.join(SolanaAPI.root_path, 'logs', f'wh_{current_time}.json') , 'w') as f:
json.dump(request_data, f) json.dump(request_data, f)
process_wh(request_data) # await process_wh(request_data)
return jsonify({"status": "Webhook processed"}), 200 # don't wait for the process to finish
asyncio.create_task(process_wh(request_data ))
return jsonify({"status": "OK"}), 200
except Exception as e: except Exception as e:
logging.error(f"Error processing webhook: {e}") logging.error(f"Error processing webhook: {e}")
return jsonify({"error": "Failed to process webhook"}), 500 return jsonify({"error": "Failed to process webhook"}), 500
@ -123,14 +133,40 @@ def init_app(tr_handler=None):
if not token_inputs or not token_outputs: if not token_inputs or not token_outputs:
logging.warning("Missing token inputs or outputs") logging.warning("Missing token inputs or outputs")
return return
tr = {
'token_in': token_inputs[0]['mint'],
'token_out': token_outputs[0]['mint'],
'amount_in': float(token_inputs[0]['rawTokenAmount']['tokenAmount']) / 10**token_inputs[0]['rawTokenAmount']['decimals'],
'amount_out': float(token_outputs[0]['rawTokenAmount']['tokenAmount']) / 10**token_outputs[0]['rawTokenAmount']['decimals'],
}
usdcMint = LIQUIDITY_TOKENS[0]
tr = {}
if not token_inputs or len(token_inputs) == 0:
logging.info("Assumed USDC as first token. BUY transaction detected")
tr["token_in"] = usdcMint
tr["type"] = "BUY"
tr["amount_in"] = await SolanaAPI.DEX.get_token_prices(
token_outputs[0]["mint"],
int(token_outputs[0]["rawTokenAmount"]["tokenAmount"])
)
else:
token_in = token_inputs[0]
tr["token_in"] = token_in["mint"]
tr["token_in_decimals"] = token_in["rawTokenAmount"]["decimals"]
tr["amount_in"] = float(int(token_in["rawTokenAmount"]["tokenAmount"]) / 10**token_in["rawTokenAmount"]["decimals"])
# 'amount_in': float(token_inputs[0]['rawTokenAmount']['tokenAmount']) / 10**token_inputs[0]['rawTokenAmount']['decimals'],
if not token_outputs or len(token_outputs) == 0:
logging.info("Assumed USDC as second token. SELL transaction detected")
tr["token_out"] = usdcMint
tr["type"] = "SELL"
tr["amount_out"] = await SolanaAPI.DEX.get_token_prices(
token_inputs[0]["mint"],
int(token_inputs[0]["rawTokenAmount"]["tokenAmount"])
)
else:
token_out = token_outputs[0]
tr["token_out"] = token_out["mint"]
tr["token_out_decimals"] = token_out["rawTokenAmount"]["decimals"]
tr["amount_out"] = float(int(token_out["rawTokenAmount"]["tokenAmount"]) / 10**token_out["rawTokenAmount"]["decimals"])
#'amount_out': float(token_outputs[0]['rawTokenAmount']['tokenAmount']) / 10**token_outputs[0]['rawTokenAmount']['decimals'],
if not tr["token_in"] or not tr["token_out"] or tr["amount_in"] == 0 or tr["amount_out"] == 0: if not tr["token_in"] or not tr["token_out"] or tr["amount_in"] == 0 or tr["amount_out"] == 0:
logging.warning("Incomplete swap details found in logs. Getting details from transaction") logging.warning("Incomplete swap details found in logs. Getting details from transaction")
tx_signature = data[0].get('signature') tx_signature = data[0].get('signature')
@ -150,7 +186,7 @@ def init_app(tr_handler=None):
tr['value_out_USD'] = prices.get(tr['token_out'], 0) * tr['amount_out'] tr['value_out_USD'] = prices.get(tr['token_out'], 0) * tr['amount_out']
notification = ( notification = (
f"<b>Got WH notification:</b>: {tr['amount_in']} {tr['symbol_in']} swapped for {tr['symbol_out']} \n" f"<b>Got WH notification:</b>: {tr['amount_in']} {tr['symbol_in']} swapped for {tr['amount_out']} {tr['symbol_out']} ${tr['value_out_USD']}\n"
) )
logging.info(notification) logging.info(notification)
await utils.telegram_utils.send_telegram_message(notification) await utils.telegram_utils.send_telegram_message(notification)