convert_tokens

Function

def convert_tokens(account, token0_address, token1_address, output_amount, attempts=18):
    # check if conversion route exists
    routes_functions = json.load(open('./data/routes.json'))
    if token0_address not in routes_functions[token1_address]['functions'].keys():
        raise Exception("Route not available for {} to {}".format(token0_address, token1_address))

    # get the cost required to convert tokens
    cost = routes_functions[token1_address]['costs'][token0_address]
    tokens_required = cost * output_amount
    if (tokens_balance := get_token_balance(token0_address, account.address)) < tokens_required:
        logging.error("Need {} more tokens".format(tokens_required - tokens_balance))
        return False

    # call the buy function with amount or default to no args
    call_function = routes_functions[token1_address]['functions'][token0_address]
    approve_token_spending(account, token0_address, token1_address, get_token_supply(token0_address, True))
    token1_contract = load_contract(token1_address, load_contract_abi(token1_address))
    amount = to_token_decimals(output_amount, token1_contract.functions.decimals().call())
    try:
        tx = getattr(token1_contract.functions, call_function)(int(amount)).build_transaction({
            "from": account.address,
            "nonce": get_nonce(account.address)
        })
    except Web3ValidationError as e:
        if 'positional arguments with type(s) `int`' in str(e):
            for i in range(0, amount):
                # 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
                try:
                    tx = getattr(token1_contract.functions, call_function)().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[token1_address]['label']))
                else:
                    if success:
                        logging.info("Called {}({}) from {}".format(
                            call_function,
                            amount,
                            routes_functions[token1_address]['label']
                        ))
                    else:
                        logging.warning("Failed to call {}({}) from {}".format(
                            call_function,
                            amount,
                            routes_functions[token1_address]['label']
                        ))
                        return False
        else:
            raise Web3ValidationError(e)
        return True
    else:
        try:
            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[token1_address]['label']))
            return False
        else:
            if success:
                logging.info("Called {}({}) from {}".format(
                    call_function,
                    amount,
                    routes_functions[token1_address]['label']
                ))
                return True
            else:
                logging.warning("Failed to call {}({}) from {}".format(
                    call_function,
                    amount,
                    routes_functions[token1_address]['label']
                ))
                return False

Description

  • Load a list of routes

  • Check if the source token has a route to the desired token

  • Estimate the cost of token0 required to convert to token1

  • Get the buy function to call for the token contract

  • Approve the source token contract with spender as your desired token contract address

  • Load the contract for your desired token

  • Create a transaction and call the buy function with the desired amount

  • Broadcast and return True/False

    \