defconvert_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 notin routes_functions[multi_address]['functions'].keys():raiseException("Route not available for {} to {} in {}".format(token0_address, token1_address, multi_address))elif routes_functions[multi_address]['functions'][token0_address][0] =='#':raiseException("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 sometimestry: decimal_places =len(str(cost).split('.')[1]) decimal_places = decimal_places if decimal_places <=15else15except (AttributeError,IndexError): tokens_required = tokens_costelse: tokens_required =float(round(tokens_cost, decimal_places))# check if the wallet has enough tokens to convertif tokens_required > (tokens_balance :=get_token_balance(token0_address, account.address)): logging.error("Need {} more tokens".format(tokens_required - tokens_balance))returnFalse# approve the tokens required to convert and determine how many loopsapprove_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 mintsfor i inlist(range(0, loops)):# cancel the rest of this loop if the gas price is too damn highifget_beacon_gas_prices('rapid', beacon_gasnow_cache_seconds)> rapid_gas_fee_limit: logging.warning("Gas fees are too high")returnNoneif 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)exceptExceptionas 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'] ))returnFalsereturnTrue
Description
Load a list of routes
Check if the source token has a route to the desired token
Check if the route is disabled
Check how many tokens are minted in one call
Fix float/decimal amounts
Check if the wallet has enough tokens required to convert
Approve the source token contract with spender as the multi contract address
Determine how many loops and iterations are needed to complete minting
Start the loop
Check if gas prices are reasonable
Get the function to call for the multi contract
Load the multi contract
Create a transaction and call the multi function with the desired amount