convert_tokens_multi
Function
def convert_tokens_multi(account, multi_address, token0_address, token1_address, iterations, attempts=18):
# check if conversion route exists or is disabled
routes_functions = json.load(open('./data/routes.json'))
if token0_address not in routes_functions[multi_address]['functions'].keys():
raise Exception("Route not available for {} to {} in {}".format(token0_address, token1_address, multi_address))
elif routes_functions[multi_address]['functions'][token0_address][0] == '#':
raise Exception("Route is disabled for {} to {} in {}".format(token0_address, token1_address, multi_address))
# get the cost required to convert tokens
cost = routes_functions[multi_address]['costs'][token0_address]
tokens_cost = cost * iterations * routes_functions[multi_address]['mints']
# python is so stupid sometimes
try:
decimal_places = len(str(cost).split('.')[1])
decimal_places = decimal_places if decimal_places <= 15 else 15
except (AttributeError, IndexError):
tokens_required = tokens_cost
else:
tokens_required = float(round(tokens_cost, decimal_places))
# check if the wallet has enough tokens to convert
if tokens_required > (tokens_balance := get_token_balance(token0_address, account.address)):
logging.error("Need {} more tokens".format(tokens_required - tokens_balance))
return False
# approve the tokens required to convert and determine how many loops
approve_token_spending(account, token0_address, multi_address, get_token_supply(token0_address, True))
loops = math.floor(iterations / routes_functions[multi_address]['max_iterations'])
if iterations % routes_functions[multi_address]['max_iterations'] != 0:
loops += 1
# start calling multi mints
for i in list(range(0, loops)):
# cancel the rest of this loop if the gas price is too damn high
if get_beacon_gas_prices('rapid', beacon_gasnow_cache_seconds) > rapid_gas_fee_limit:
logging.warning("Gas fees are too high")
return None
if i + 1 < loops or iterations == routes_functions[multi_address]['max_iterations']:
# do max iterations during loop
call_iterations = routes_functions[multi_address]['max_iterations']
else:
# on final loop run the remaining iterations
call_iterations = iterations % routes_functions[multi_address]['max_iterations']
# call the multi mint function with iterations based on tokens minted
call_function = routes_functions[multi_address]['functions'][token0_address]
multi_contract = load_contract(multi_address, load_contract_abi(multi_address))
try:
tx = getattr(multi_contract.functions, call_function)(call_iterations).build_transaction({
"from": account.address,
"nonce": get_nonce(account.address)
})
success = broadcast_transaction(account, tx, True, attempts)
except Exception as e:
if error := interpret_exception_message(e):
logging.error("{}. Failed to convert using {}".format(error, routes_functions[multi_address]['label']))
else:
if success:
logging.info("Called {}({}) from {}".format(
call_function,
call_iterations,
routes_functions[multi_address]['label']
))
else:
logging.warning("Failed to call {}({}) from {}".format(
call_function,
call_iterations,
routes_functions[multi_address]['label']
))
return False
return True