swap stable again
This commit is contained in:
parent
1b0c72dc08
commit
69241b1498
@ -24,7 +24,7 @@ TELEGRAM_BOT_TOKEN="6749075936:AAHUHiPTDEIu6JH7S2fQdibwsu6JVG3FNG0"
|
|||||||
DISPLAY_CURRENCY=USD
|
DISPLAY_CURRENCY=USD
|
||||||
#FOLLOW_AMOUNT=3
|
#FOLLOW_AMOUNT=3
|
||||||
# proportional, xx%,
|
# proportional, xx%,
|
||||||
FOLLOW_AMOUNT=5%
|
FOLLOW_AMOUNT=2%
|
||||||
|
|
||||||
LIQUIDITY_TOKENS=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,So11111111111111111111111111111111111111112
|
LIQUIDITY_TOKENS=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v,So11111111111111111111111111111111111111112
|
||||||
|
|
||||||
|
@ -14,17 +14,18 @@ from jupiter_python_sdk.jupiter import Jupiter, Jupiter_DCA
|
|||||||
from dexscreener import DexscreenerClient
|
from dexscreener import DexscreenerClient
|
||||||
from solana.rpc.types import TokenAccountOpts, TxOpts
|
from solana.rpc.types import TokenAccountOpts, TxOpts
|
||||||
from solana.rpc.async_api import AsyncClient
|
from solana.rpc.async_api import AsyncClient
|
||||||
from solana.transaction import Signature
|
|
||||||
from solana.rpc.websocket_api import connect
|
from solana.rpc.websocket_api import connect
|
||||||
from solana.rpc.commitment import Confirmed, Processed
|
from solana.rpc.commitment import Confirmed, Processed
|
||||||
from solana.transaction import Transaction
|
from solana.rpc.async_api import AsyncClient
|
||||||
|
from solana.rpc.types import TxOpts
|
||||||
|
from solana.rpc.commitment import Confirmed, Finalized, Processed
|
||||||
|
from solana.rpc.core import RPCException
|
||||||
|
|
||||||
|
from solana.transaction import Signature, Transaction
|
||||||
from spl.token.client import Token
|
from spl.token.client import Token
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
import base58
|
import base58
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from solana.rpc.async_api import AsyncClient
|
|
||||||
from solana.rpc.types import TxOpts
|
|
||||||
from solana.rpc.commitment import Confirmed, Finalized, Processed
|
|
||||||
|
|
||||||
|
|
||||||
from solders.rpc.requests import GetTransaction
|
from solders.rpc.requests import GetTransaction
|
||||||
@ -304,7 +305,9 @@ class SolanaAPI:
|
|||||||
finally:
|
finally:
|
||||||
receive_task.cancel()
|
receive_task.cancel()
|
||||||
process_task.cancel()
|
process_task.cancel()
|
||||||
|
except asyncio.CancelledError:
|
||||||
|
logging.info("Websocket connection cancelled, attempting to reconnect...")
|
||||||
|
await asyncio.sleep(5) # Wait before reconnecting
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"An unexpected error occurred: {e}")
|
logger.error(f"An unexpected error occurred: {e}")
|
||||||
logger.error("".join(traceback.format_exception(None, e, e.__traceback__)))
|
logger.error("".join(traceback.format_exception(None, e, e.__traceback__)))
|
||||||
@ -361,7 +364,7 @@ class SolanaAPI:
|
|||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
async def get_token_metadata_symbol(self, mint_address):
|
async def get_token_metadata_symbol(self, mint_address):
|
||||||
if mint_address in DEX.TOKENS_INFO and 'symbol' in DEX.TOKENS_INFO[mint_address]:
|
if mint_address in DEX.TOKENS_INFO and DEX.TOKENS_INFO[mint_address] is not None:
|
||||||
return DEX.TOKENS_INFO[mint_address].get('symbol')
|
return DEX.TOKENS_INFO[mint_address].get('symbol')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -370,6 +373,8 @@ class SolanaAPI:
|
|||||||
account_data_data = account_data_result['value']['data']
|
account_data_data = account_data_result['value']['data']
|
||||||
if 'parsed' in account_data_data and 'info' in account_data_data['parsed']:
|
if 'parsed' in account_data_data and 'info' in account_data_data['parsed']:
|
||||||
account_data_info = account_data_data['parsed']['info']
|
account_data_info = account_data_data['parsed']['info']
|
||||||
|
if DEX.TOKENS_INFO[mint_address] is None:
|
||||||
|
DEX.TOKENS_INFO[mint_address] = {}
|
||||||
if 'decimals' in account_data_info:
|
if 'decimals' in account_data_info:
|
||||||
if mint_address in DEX.TOKENS_INFO:
|
if mint_address in DEX.TOKENS_INFO:
|
||||||
DEX.TOKENS_INFO[mint_address]['decimals'] = account_data_info['decimals']
|
DEX.TOKENS_INFO[mint_address]['decimals'] = account_data_info['decimals']
|
||||||
@ -780,10 +785,10 @@ class SolanaAPI:
|
|||||||
# )
|
# )
|
||||||
# response_data = response.json()
|
# response_data = response.json()
|
||||||
|
|
||||||
result = response_data['swapTransaction']
|
|
||||||
try:
|
try:
|
||||||
response_data['swapTransaction']
|
result = response_data['swapTransaction']
|
||||||
return response_data['swapTransaction']
|
return (response_data['swapTransaction'], response_data['lastValidBlockHeight'])
|
||||||
except:
|
except:
|
||||||
raise Exception(response_data['error'])
|
raise Exception(response_data['error'])
|
||||||
# Return the serialized transaction
|
# Return the serialized transaction
|
||||||
@ -793,15 +798,16 @@ class SolanaAPI:
|
|||||||
async def follow_move(self,move):
|
async def follow_move(self,move):
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
|
your_balance = 0
|
||||||
your_balances = await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False)
|
your_balances = await DEX.get_wallet_balances(YOUR_WALLET, doGetTokenName=False)
|
||||||
your_balance_info = next((balance for balance in your_balances.values() if balance['address'] == move['token_in']), None)
|
your_balance_info = next((balance for balance in your_balances.values() if balance['address'] == move['token_in']), None)
|
||||||
if your_balance_info is not None:
|
if your_balance_info is not None and 'amount' in your_balance_info and float(your_balance_info['amount']) > 0:
|
||||||
# Use the balance
|
# Use the balance
|
||||||
print(f"Your balance: {your_balance_info['amount']} {move['symbol_in']}")
|
print(f"Your balance: {your_balance_info['amount']} {move['symbol_in']}")
|
||||||
# else:
|
else:
|
||||||
# print(f"No ballance found for {move['symbol_in']}. Skipping move.")
|
print(f"No ballance found for {move['symbol_in']}. Skipping move.")
|
||||||
# await telegram_utils.send_telegram_message(f"No ballance found for {move['symbol_in']}. Skipping move.")
|
await telegram_utils.send_telegram_message(f"No ballance found for {move['symbol_in']}. Skipping move.")
|
||||||
# return
|
return
|
||||||
|
|
||||||
your_balance = your_balance_info['amount']
|
your_balance = your_balance_info['amount']
|
||||||
|
|
||||||
@ -812,7 +818,7 @@ class SolanaAPI:
|
|||||||
return
|
return
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error fetching your balance: {e}")
|
logging.error(f"Error fetching your balance: {str(e)}", exc_info=True)
|
||||||
if FOLLOW_AMOUNT == 'proportional':
|
if FOLLOW_AMOUNT == 'proportional':
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -898,7 +904,7 @@ class SolanaAPI:
|
|||||||
|
|
||||||
# https://station.jup.ag/api-v6/post-swap
|
# https://station.jup.ag/api-v6/post-swap
|
||||||
#transaction_data = await jupiter.swap(
|
#transaction_data = await jupiter.swap(
|
||||||
transaction_data = await self.swap_on_jupiter(
|
(transaction_data, block) = await self.swap_on_jupiter(
|
||||||
input_mint=move['token_in'],
|
input_mint=move['token_in'],
|
||||||
output_mint=move['token_out'],
|
output_mint=move['token_out'],
|
||||||
amount=amount_lamports,
|
amount=amount_lamports,
|
||||||
@ -933,6 +939,32 @@ class SolanaAPI:
|
|||||||
else:
|
else:
|
||||||
logging.warning(f"Failed to get transaction details for {transaction_id}.\n Probably transaction failed. Retrying again...")
|
logging.warning(f"Failed to get transaction details for {transaction_id}.\n Probably transaction failed. Retrying again...")
|
||||||
await asyncio.sleep(3)
|
await asyncio.sleep(3)
|
||||||
|
except RPCException as rpce:
|
||||||
|
# Convert to string and parse for key information
|
||||||
|
error_str = str(rpce)
|
||||||
|
|
||||||
|
# Get the main error message
|
||||||
|
if "Error processing Instruction" in error_str:
|
||||||
|
# Check for common errors
|
||||||
|
if "insufficient funds" in error_str:
|
||||||
|
logging.error("Transaction failed: Insufficient funds")
|
||||||
|
elif "custom program error: 0x28" in error_str:
|
||||||
|
logging.error("Transaction failed: Custom program error 40 (0x28) - Likely insufficient funds")
|
||||||
|
|
||||||
|
# Parse logs if available
|
||||||
|
try:
|
||||||
|
logs = rpce.data.result.logs
|
||||||
|
if logs:
|
||||||
|
# Get the last error message from logs
|
||||||
|
error_logs = [log for log in logs if "Error:" in log]
|
||||||
|
if error_logs:
|
||||||
|
logging.error(f"Program error: {error_logs[-1]}")
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Full debug logging
|
||||||
|
logging.debug(f"Full RPC error: {error_str}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# decode transacion data (try base58/64)
|
# decode transacion data (try base58/64)
|
||||||
# decoded_data = base58.b58decode(transaction_data).decode('utf-8')
|
# decoded_data = base58.b58decode(transaction_data).decode('utf-8')
|
||||||
@ -1070,7 +1102,8 @@ class SolanaDEX:
|
|||||||
if 'symbol' not in token_info:
|
if 'symbol' not in token_info:
|
||||||
token_info['symbol'] = await SAPI.get_token_metadata_symbol(token)
|
token_info['symbol'] = await SAPI.get_token_metadata_symbol(token)
|
||||||
token_info['price'] = price
|
token_info['price'] = price
|
||||||
token_info['lastUpdated'] = datetime.now().isoformat()
|
token_info['lastUpdated'] = datetime.now().isoformat()
|
||||||
|
token_info['address'] = token
|
||||||
|
|
||||||
return prices
|
return prices
|
||||||
|
|
||||||
@ -1225,6 +1258,9 @@ class SolanaDEX:
|
|||||||
)
|
)
|
||||||
|
|
||||||
if response.value:
|
if response.value:
|
||||||
|
|
||||||
|
if self.TOKENS_INFO is None:
|
||||||
|
self.TOKENS_INFO = {}
|
||||||
for account in response.value:
|
for account in response.value:
|
||||||
try:
|
try:
|
||||||
parsed_data = account.account.data.parsed
|
parsed_data = account.account.data.parsed
|
||||||
@ -1237,7 +1273,7 @@ class SolanaDEX:
|
|||||||
# amount = float(info['tokenAmount']['amount'])
|
# amount = float(info['tokenAmount']['amount'])
|
||||||
# amount = float(amount / 10**decimals)
|
# amount = float(amount / 10**decimals)
|
||||||
token_name = None
|
token_name = None
|
||||||
if mint in self.TOKENS_INFO:
|
if mint in self.TOKENS_INFO and isinstance(self.TOKENS_INFO[mint], dict):
|
||||||
token_name = self.TOKENS_INFO[mint].get('symbol')
|
token_name = self.TOKENS_INFO[mint].get('symbol')
|
||||||
elif doGetTokenName:
|
elif doGetTokenName:
|
||||||
token_name = await SAPI.get_token_metadata_symbol(mint)
|
token_name = await SAPI.get_token_metadata_symbol(mint)
|
||||||
@ -1252,27 +1288,31 @@ class SolanaDEX:
|
|||||||
self.TOKENS_INFO[mint] = self.TOKENS_INFO[mint].update(balances[mint])
|
self.TOKENS_INFO[mint] = self.TOKENS_INFO[mint].update(balances[mint])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logging.debug(f"Account balance for {token_name or "N/A"} ({mint}): {amount}")
|
logging.debug(f"Account balance for {token_name or 'N/A'} ({mint}): {amount}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error logging account balance: {str(e)}")
|
logging.error(f"Error logging account balance: {str(e)}", exc_info=True)
|
||||||
else:
|
else:
|
||||||
logging.warning(f"Unexpected data format for account: {account}")
|
logging.warning(f"Unexpected data format for account: {account}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error parsing account data: {str(e)}")
|
logging.error(f"Error parsing account data: {str(e)}", exc_info=True)
|
||||||
self.TOKENS_INFO["lastUpdated"] = datetime.now().isoformat()
|
self.TOKENS_INFO["lastUpdated"] = datetime.now().isoformat()
|
||||||
|
|
||||||
# sol_balance = await self.solana_client.get_balance(Pubkey.from_string(wallet_address))
|
sol_balance = await self.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'] = {
|
mint = 'So11111111111111111111111111111111111111112'
|
||||||
# 'name': 'SOL',
|
balances[mint] = {
|
||||||
# 'address': 'SOL',
|
'name': 'SOL',
|
||||||
# 'amount': sol_balance.value / 1e9
|
'address': mint,
|
||||||
# }
|
'amount': sol_balance.value / 1e9,
|
||||||
# else:
|
'decimals': 9
|
||||||
# logging.warning(f"SOL balance response missing for wallet: {wallet_address}")
|
}
|
||||||
|
self.TOKENS_INFO[mint] = {'symbol': token_name}
|
||||||
|
self.TOKENS_INFO[mint] = self.TOKENS_INFO[mint].update(balances[mint])
|
||||||
|
else:
|
||||||
|
logging.warning(f"SOL balance response missing for wallet: {wallet_address}")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(f"Error getting wallet balances: {str(e)} {e.error_msg}")
|
logging.error(f"Error getting wallet balances: {str(e)}", exc_info=True)
|
||||||
if response and response.value:
|
if response and response.value:
|
||||||
logging.info(f"Found {len(response.value)} ({len(balances)} non zero) token accounts for wallet: {wallet_address}")
|
logging.info(f"Found {len(response.value)} ({len(balances)} non zero) token accounts for wallet: {wallet_address}")
|
||||||
else:
|
else:
|
||||||
|
@ -335,13 +335,15 @@ def init_app(tr_handler=None):
|
|||||||
tr["token_out"]
|
tr["token_out"]
|
||||||
)
|
)
|
||||||
# ToDo - optimize
|
# ToDo - optimize
|
||||||
# prices = await SolanaAPI.DEX.get_token_prices(
|
prices = await SolanaAPI.DEX.get_token_prices(
|
||||||
# [tr["token_in"], tr["token_out"]]
|
[tr["token_in"], tr["token_out"]]
|
||||||
# )
|
)
|
||||||
# tr["token_in_price"] = prices.get(tr["token_in"], 0)
|
await SolanaAPI.DEX.save_token_info()
|
||||||
# tr["token_out_price"] = prices.get(tr["token_out"], 0)
|
|
||||||
# tr["value_in_USD"] = prices.get(tr["token_in"], 0) * tr["amount_in"]
|
tr["token_in_price"] = prices.get(tr["token_in"], 0)
|
||||||
# tr["value_out_USD"] = prices.get(tr["token_out"], 0) * tr["amount_out"]
|
tr["token_out_price"] = prices.get(tr["token_out"], 0)
|
||||||
|
tr["value_in_USD"] = prices.get(tr["token_in"], 0) * tr["amount_in"]
|
||||||
|
tr["value_out_USD"] = prices.get(tr["token_out"], 0) * tr["amount_out"]
|
||||||
|
|
||||||
# notification = f"<b>Got WH notification:</b>: {tr['amount_in']} {tr['symbol_in'] or tr["token_in"]} swapped for {tr['amount_out']} {tr['symbol_out']} ${tr['value_out_USD']}\n"
|
# notification = f"<b>Got WH notification:</b>: {tr['amount_in']} {tr['symbol_in'] or tr["token_in"]} swapped for {tr['amount_out']} {tr['symbol_out']} ${tr['value_out_USD']}\n"
|
||||||
# logging.info(notification)
|
# logging.info(notification)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user