From 6ece68314282cafb14867145718ba064da48911d Mon Sep 17 00:00:00 2001 From: Alexander Date: Sat, 13 Jul 2024 08:37:03 -0400 Subject: [PATCH] handle dropped connections better --- bot-buyer.py | 4 ++ bot-seller.py | 7 +++ core.py | 126 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 102 insertions(+), 35 deletions(-) diff --git a/bot-buyer.py b/bot-buyer.py index 0e5e29f..bf2f3ab 100755 --- a/bot-buyer.py +++ b/bot-buyer.py @@ -43,6 +43,10 @@ while True: pdai_sample_result = sample_exchange_rate('PulseX_v2', pdai_address, wpls_address) pusdc_sample_result = sample_exchange_rate('PulseX_v2', pusdc_address, wpls_address) affection_sample_result = sample_exchange_rate('PulseX_v2', affection_address, wpls_address) + if not pdai_sample_result or not pusdc_sample_result or not affection_sample_result: + logging.warning("Failed to sample prices") + log_end_loop(loop_delay) + continue # log the current rate logging.info("pDAI Rate: 1 = {} PLS".format(pdai_sample_result / 10 ** 18)) diff --git a/bot-seller.py b/bot-seller.py index 6cfaee9..d2ef169 100755 --- a/bot-seller.py +++ b/bot-seller.py @@ -56,6 +56,10 @@ while True: pdai_sample_result = sample_exchange_rate('PulseX_v2', pdai_address, wpls_address) pusdc_sample_result = sample_exchange_rate('PulseX_v2', pusdc_address, wpls_address) affection_sample_result = sample_exchange_rate('PulseX_v2', affection_address, wpls_address) + if not pdai_sample_result or not pusdc_sample_result or not affection_sample_result: + logging.warning("Failed to sample prices") + log_end_loop(loop_delay) + continue # log the current rates logging.info("pDAI Rate: 1 = {} PLS".format(pdai_sample_result / 10 ** 18)) @@ -117,6 +121,9 @@ while True: pdai_sample_result = sample_exchange_rate('PulseX_v2', pdai_address, wpls_address) pusdc_sample_result = sample_exchange_rate('PulseX_v2', pusdc_address, wpls_address) affection_sample_result = sample_exchange_rate('PulseX_v2', affection_address, wpls_address) + if not pdai_sample_result or not pusdc_sample_result or not affection_sample_result: + logging.warning("Failed to sample prices") + break else: logging.info("AFFECTION™ price is not within targeted range for selling") break diff --git a/core.py b/core.py index 5dd43bc..7dc3488 100755 --- a/core.py +++ b/core.py @@ -30,13 +30,20 @@ wallet_b_address = os.getenv('WALLET_B_ADDRESS') wallet_c_address = os.getenv('WALLET_C_ADDRESS') -def apply_estimated_gas(tx): - if 'gas' not in tx: - tx['gas'] = web3.eth.estimate_gas(tx) - return tx +def apply_estimated_gas(tx, attempts=18): + while attempts > 0: + try: + if 'gas' not in tx: + tx['gas'] = web3.eth.estimate_gas(tx) + except Exception as e: + logging.debug(e) + attempts -= 1 + time.sleep(1) + else: + return tx -def apply_gas_multiplier(tx, multiplier=None): +def apply_gas_multiplier(tx, multiplier=None, attempts=18): if not multiplier: multiplier = os.getenv('GAS_MULTIPLIER') try: @@ -104,9 +111,12 @@ def broadcast_transaction(account, tx, auto_gas=True, attempts=18): continue elif "already known" in str(e): pass + else: + _attempts -= 1 + time.sleep(1) if not tx_hash: - time.sleep(10) _attempts -= 1 + time.sleep(1) if _attempts != 0: logging.debug("Rebroadcasting TX ... {}".format(attempts - _attempts)) continue @@ -116,11 +126,13 @@ def broadcast_transaction(account, tx, auto_gas=True, attempts=18): except Exception as e: logging.debug(e) _attempts -= 1 + time.sleep(1) if _attempts != 0: logging.debug("Rebroadcasting TX ... {}".format(attempts - _attempts)) else: logging.debug("Confirmed TX: {}".format(tx_receipt)) return tx_receipt + return False def convert_tokens(account, token0_address, token1_address, output_amount, attempts=18): @@ -278,8 +290,7 @@ def estimate_swap_result(router_name, token0_address, token1_address, token0_amo routers = json.load(open('./data/routers.json')) router_contract = load_contract(routers[router_name][0], routers[router_name][1]) token0_info = get_token_info(token0_address) - _attempts = attempts - while _attempts > 0: + while attempts > 0: try: expected_output_amounts = router_contract.functions.getAmountsOut( int(token0_amount * 10 ** token0_info['decimals']), @@ -287,7 +298,8 @@ def estimate_swap_result(router_name, token0_address, token1_address, token0_amo ).call() except Exception as e: logging.debug(e) - _attempts -= 1 + attempts -= 1 + time.sleep(1) else: return expected_output_amounts return [] @@ -311,14 +323,13 @@ def generate_wallet(amount): def get_abi_from_blockscout(address, attempts=18): - _attempts = attempts - while _attempts > 0: + while attempts > 0: try: r = requests.get("https://api.scan.pulsechain.com/api/v2/smart-contracts/{}".format(address)) r.raise_for_status() except RequestException: - _attempts -= 1 - if _attempts > 0: + attempts -= 1 + if attempts > 0: time.sleep(1) continue else: @@ -331,15 +342,38 @@ def get_abi_from_blockscout(address, attempts=18): return [] -def get_average_gas_prices(average='median', tx_amount=100): - latest_block = web3.eth.get_block('latest')['number'] +def get_average_gas_prices(average='median', tx_amount=100, attempts=18): + latest_block = None + _attempts = attempts + while _attempts > 0: + try: + latest_block = web3.eth.get_block('latest')['number'] + except Exception as e: + logging.debug(e) + _attempts -= 1 + time.sleep(1) + else: + break + if not latest_block: + return {} gas_limit = [] gas_prices = [] for block_number in range(latest_block, latest_block - tx_amount, -1): - try: - block = web3.eth.get_block(block_number, full_transactions=True) - except BlockNotFound: - continue + block = None + _attempts = attempts + while _attempts > 0: + try: + block = web3.eth.get_block(block_number, full_transactions=True) + except BlockNotFound: + continue + except Exception as e: + logging.debug(e) + _attempts -= 1 + time.sleep(1) + else: + break + if not block: + return {} for _tx in block['transactions']: gas_limit.append(_tx['gas']) gas_prices.append(_tx['gasPrice']) @@ -356,7 +390,7 @@ def get_average_gas_prices(average='median', tx_amount=100): average_gas_limit = mode(gas_limit[:tx_amount]) average_gas_price = mode(gas_prices[:tx_amount]) case _: - return None + raise Exception('Invalid average type') return { "gas_limit": average_gas_limit, "gas_price": average_gas_price @@ -394,22 +428,45 @@ def get_beacon_gas_prices(speed=None, cache_interval_seconds=10): return {speed: float(web3.from_wei(price, 'gwei')) for speed, price in gas['data'].items() if speed in speeds} -def get_last_block_base_fee(): - latest_block = web3.eth.get_block('latest') - base_fee = latest_block['baseFeePerGas'] - return float(round(web3.from_wei(base_fee, 'gwei'), 2)) +def get_last_block_base_fee(attempts=18): + while attempts > 0: + try: + latest_block = web3.eth.get_block('latest') + except Exception as e: + logging.debug(e) + time.sleep(1) + attempts -= 1 + else: + base_fee = latest_block['baseFeePerGas'] + return float(round(web3.from_wei(base_fee, 'gwei'), 2)) + return -1 -def get_nonce(address): - return web3.eth.get_transaction_count(web3.to_checksum_address(address)) +def get_nonce(address, attempts=18): + while attempts > 0: + try: + return web3.eth.get_transaction_count(web3.to_checksum_address(address)) + except Exception as e: + logging.debug(e) + time.sleep(1) + attempts -= 1 + return -1 -def get_pls_balance(address, decimals=False): - balance = web3.eth.get_balance(address) - if decimals: - return balance - else: - return from_token_decimals(balance, 18) +def get_pls_balance(address, decimals=False, attempts=18): + while attempts > 0: + try: + balance = web3.eth.get_balance(address) + except Exception as e: + logging.debug(e) + time.sleep(1) + attempts -= 1 + else: + if decimals: + return balance + else: + return from_token_decimals(balance, 18) + return -1 def get_token_balance(token_address, wallet_address, decimals=False): @@ -553,11 +610,10 @@ def mint_tokens(account, token_address, amount, attempts=18): def sample_exchange_rate(router_name, token_address, quote_address, attempts=18): - _attempts = attempts - while _attempts > 0: + while attempts > 0: token_result = estimate_swap_result(router_name, token_address, quote_address, 1) if len(token_result) == 0: - _attempts -= 1 + attempts -= 1 time.sleep(1) continue else: