also get token names

This commit is contained in:
Dobromir Popov 2024-10-05 23:00:20 +03:00
parent 405445e6a8
commit 2a15df144c

View File

@ -34,6 +34,19 @@ import re
load_dotenv() load_dotenv()
app = Flask(__name__) app = Flask(__name__)
ENV_FILE = '.env'
async def save_subscription_id(subscription_id):
# storing subscription id in .env file disabled
#set_key(ENV_FILE, "SUBSCRIPTION_ID", str(subscription_id))
logger.info(f"Saved subscription ID: {subscription_id}")
async def load_subscription_id():
subscription_id = os.getenv("SUBSCRIPTION_ID")
return int(subscription_id) if subscription_id else None
# Function to find the latest log file # Function to find the latest log file
def get_latest_log_file(): def get_latest_log_file():
log_dir = './logs' log_dir = './logs'
@ -103,35 +116,6 @@ async def send_telegram_message(message):
logging.error(f"Error sending Telegram message: {str(e)}") logging.error(f"Error sending Telegram message: {str(e)}")
# async def get_token_prices(token_addresses: List[str]) -> Dict[str, float]:
# url = "https://api.coingecko.com/api/v3/simple/token_price/solana"
# params = {
# "contract_addresses": ",".join(token_addresses),
# "vs_currencies": DISPLAY_CURRENCY.lower()
# }
# prices = {}
# async with aiohttp.ClientSession() as session:
# async with session.get(url, params=params) as response:
# if response.status == 200:
# data = await response.json()
# for address, price_info in data.items():
# if DISPLAY_CURRENCY.lower() in price_info:
# prices[address] = price_info[DISPLAY_CURRENCY.lower()]
# else:
# logging.error(f"Failed to get token prices. Status: {response.status}")
# # For tokens not found in CoinGecko, try to get price from a DEX or set a default value
# missing_tokens = set(token_addresses) - set(prices.keys())
# for token in missing_tokens:
# # You might want to implement a fallback method here, such as:
# # prices[token] = await get_price_from_dex(token)
# # For now, we'll set a default value
# prices[token] = 0.0
# logging.warning(f"Price not found for token {token}. Setting to 0.")
# return prices
async def get_token_prices(token_addresses: List[str]) -> Dict[str, float]: async def get_token_prices(token_addresses: List[str]) -> Dict[str, float]:
coingecko_prices = await get_prices_from_coingecko(token_addresses) coingecko_prices = await get_prices_from_coingecko(token_addresses)
@ -237,33 +221,6 @@ async def convert_balances_to_currency(balances, token_prices, sol_price):
return converted_balances return converted_balances
async def get_token_balance(wallet_address, token_address):
try:
response = await solana_client.get_token_accounts_by_owner_json_parsed(
Pubkey.from_string(wallet_address),
opts=TokenAccountOpts(
mint=Pubkey.from_string(token_address),
# program_id=Pubkey.from_string("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
),
commitment=Confirmed
)
if response['result']['value']:
balance = await solana_client.get_token_account_balance(
response['result']['value'][0]['pubkey']
)
amount = float(balance['result']['value']['uiAmount'])
logging.debug(f"Balance for {token_address} in {wallet_address}: {amount}")
return amount
else:
logging.debug(f"No account found for {token_address} in {wallet_address}")
return 0
except Exception as e:
logging.error(f"Error getting balance for {token_address} in {wallet_address}: {str(e)} \r\n {e}")
return 0
async def get_token_balance_rpc(wallet_address, token_address): async def get_token_balance_rpc(wallet_address, token_address):
url = SOLANA_HTTP_URL url = SOLANA_HTTP_URL
headers = {"Content-Type": "application/json"} headers = {"Content-Type": "application/json"}
@ -313,16 +270,8 @@ async def get_token_balance_rpc(wallet_address, token_address):
except requests.exceptions.RequestException as e: except requests.exceptions.RequestException as e:
logging.error(f"Error getting balance for {token_address} in {wallet_address}: {str(e)} \r\n {e}") logging.error(f"Error getting balance for {token_address} in {wallet_address}: {str(e)} \r\n {e}")
return 0 return 0
ENV_FILE = '.env'
async def save_subscription_id(subscription_id):
# storing subscription id in .env file disabled
#set_key(ENV_FILE, "SUBSCRIPTION_ID", str(subscription_id))
logger.info(f"Saved subscription ID: {subscription_id}")
async def load_subscription_id():
subscription_id = os.getenv("SUBSCRIPTION_ID")
return int(subscription_id) if subscription_id else None
async def get_token_name(mint_address): async def get_token_name(mint_address):
@ -356,15 +305,23 @@ async def get_wallet_balances(wallet_address):
mint = info['mint'] mint = info['mint']
amount = float(info['tokenAmount']['uiAmount']) amount = float(info['tokenAmount']['uiAmount'])
if amount > 0: if amount > 0:
token_name = await get_token_name(mint) or mint token_name = await get_token_name(mint) or 'Unknown'
balances[f"{token_name} ({mint})"] = amount balances[mint] = {
'name': token_name,
'address': mint,
'amount': amount
}
logging.debug(f"Balance for {token_name} ({mint}): {amount}") logging.debug(f"Balance for {token_name} ({mint}): {amount}")
else: else:
logging.warning(f"Unexpected data format for account: {account}") logging.warning(f"Unexpected data format for account: {account}")
sol_balance = await solana_client.get_balance(Pubkey.from_string(wallet_address)) sol_balance = await solana_client.get_balance(Pubkey.from_string(wallet_address))
if sol_balance.value is not None: if sol_balance.value is not None:
balances['SOL'] = sol_balance.value / 1e9 balances['SOL'] = {
'name': 'SOL',
'address': 'SOL',
'amount': sol_balance.value / 1e9
}
else: else:
logging.warning(f"SOL balance response missing for wallet: {wallet_address}") logging.warning(f"SOL balance response missing for wallet: {wallet_address}")
@ -386,6 +343,49 @@ async def list_initial_wallet_states():
followed_converted_balances = await convert_balances_to_currency(followed_wallet_balances, token_prices, sol_price) followed_converted_balances = await convert_balances_to_currency(followed_wallet_balances, token_prices, sol_price)
your_converted_balances = await convert_balances_to_currency(your_wallet_balances, token_prices, sol_price) your_converted_balances = await convert_balances_to_currency(your_wallet_balances, token_prices, sol_price)
TOKEN_ADDRESSES = {token: balance['amount'] for token, balance in {**followed_converted_balances, **your_converted_balances}.items() if balance['amount'] is not None and balance['amount'] > 0}
logging.info(f"Monitoring balances for tokens: {[balance['name'] for balance in TOKEN_ADDRESSES.values()]}")
followed_wallet_state = []
FOLLOWED_WALLET_VALUE = 0
for token, balance in followed_converted_balances.items():
if balance['amount'] is not None and balance['amount'] > 0:
followed_wallet_state.append(f"{balance['name']} ({balance['address']}): {balance['amount']:.2f} {DISPLAY_CURRENCY}")
FOLLOWED_WALLET_VALUE += balance['amount']
your_wallet_state = []
YOUR_WALLET_VALUE = 0
for token, balance in your_converted_balances.items():
if balance['amount'] is not None and balance['amount'] > 0:
your_wallet_state.append(f"{balance['name']} ({balance['address']}): {balance['amount']:.2f} {DISPLAY_CURRENCY}")
YOUR_WALLET_VALUE += balance['amount']
message = (
f"<b>Initial Wallet States (All balances in {DISPLAY_CURRENCY}):</b>\n\n"
f"<b>Followed Wallet ({FOLLOWED_WALLET}):</b>\n"
f"{chr(10).join(followed_wallet_state)}\n"
f"<b>Total Value:</b> {FOLLOWED_WALLET_VALUE:.2f} {DISPLAY_CURRENCY}\n\n"
f"<b>Your Wallet ({YOUR_WALLET}):</b>\n"
f"{chr(10).join(your_wallet_state)}\n"
f"<b>Total Value:</b> {YOUR_WALLET_VALUE:.2f} {DISPLAY_CURRENCY}\n\n"
f"<b>Monitored Tokens:</b>\n"
f"{', '.join([balance['name'] for balance in TOKEN_ADDRESSES.values()])}"
)
logging.info(message)
await send_telegram_message(message)
global TOKEN_ADDRESSES, FOLLOWED_WALLET_VALUE, YOUR_WALLET_VALUE
followed_wallet_balances = await get_wallet_balances(FOLLOWED_WALLET)
your_wallet_balances = await get_wallet_balances(YOUR_WALLET)
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()
followed_converted_balances = await convert_balances_to_currency(followed_wallet_balances, token_prices, sol_price)
your_converted_balances = await convert_balances_to_currency(your_wallet_balances, token_prices, sol_price)
TOKEN_ADDRESSES = {token: amount for token, amount in {**followed_converted_balances, **your_converted_balances}.items() if amount is not None and amount > 0} TOKEN_ADDRESSES = {token: amount for token, amount in {**followed_converted_balances, **your_converted_balances}.items() if amount is not None and amount > 0}
logging.info(f"Monitoring balances for tokens: {TOKEN_ADDRESSES.keys()}") logging.info(f"Monitoring balances for tokens: {TOKEN_ADDRESSES.keys()}")
@ -574,7 +574,16 @@ async def parse_swap_logs(logs):
async def follow_move(move): async def follow_move(move):
your_balances = await get_wallet_balances(YOUR_WALLET) your_balances = await get_wallet_balances(YOUR_WALLET)
your_balance = your_balances.get(move['token_in'], 0) your_balance_info = your_balances.get(move['token_in'])
if not your_balance_info:
message = f"<b>Move Failed:</b>\nNo balance found for token {move['token_in']}"
logging.warning(message)
await send_telegram_message(message)
return
your_balance = your_balance_info['amount']
token_name = your_balance_info['name']
# Calculate the amount to swap based on the same percentage as the followed move # Calculate the amount to swap based on the same percentage as the followed move
amount_to_swap = your_balance * (move['percentage_swapped'] / 100) amount_to_swap = your_balance * (move['percentage_swapped'] / 100)
@ -599,11 +608,14 @@ async def follow_move(move):
result = await async_client.send_raw_transaction(txn=bytes(signed_txn), opts=opts) result = await async_client.send_raw_transaction(txn=bytes(signed_txn), opts=opts)
transaction_id = json.loads(result.to_json())['result'] transaction_id = json.loads(result.to_json())['result']
output_token_info = your_balances.get(move['token_out'], {'name': 'Unknown'})
output_token_name = output_token_info['name']
message = ( message = (
f"<b>Move Followed:</b>\n" f"<b>Move Followed:</b>\n"
f"Swapped {amount_to_swap:.6f} {move['token_in']} " f"Swapped {amount_to_swap:.6f} {token_name} ({move['token_in']}) "
f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n" f"(same {move['percentage_swapped']:.2f}% as followed wallet)\n"
f"for {transaction_data['outputAmount'] / 1e6:.6f} {move['token_out']}" f"for {transaction_data['outputAmount'] / 1e6:.6f} {output_token_name} ({move['token_out']})"
) )
logging.info(message) logging.info(message)
await send_telegram_message(message) await send_telegram_message(message)
@ -614,11 +626,10 @@ async def follow_move(move):
else: else:
message = ( message = (
f"<b>Move Failed:</b>\n" f"<b>Move Failed:</b>\n"
f"Insufficient balance to swap {amount_to_swap:.6f} {move['token_in']}" f"Insufficient balance to swap {amount_to_swap:.6f} {token_name} ({move['token_in']})"
) )
logging.warning(message) logging.warning(message)
await send_telegram_message(message) await send_telegram_message(message)
# Helper functions (implement these according to your needs) # Helper functions (implement these according to your needs)