def _calculate_transaction_costs(self, token_amount: TokenAmount, account: Account) -> dict: exchange_rate = self.get_current_rate(token_amount) eth_sold = EthereumAmount(token_amount.value * exchange_rate.value) gas_price = EthereumAmount(Wei(self.w3.eth.gasPrice)) exchange_proxy = self._get_exchange_proxy(token_amount.ticker) latest_block = self.w3.eth.getBlock("latest") deadline = latest_block.timestamp + self.EXCHANGE_TIMEOUT transaction_params = {"from": account.address, "value": eth_sold.as_wei} gas = estimate_gas( self.w3, account, exchange_proxy.functions.ethToTokenSwapOutput, token_amount.as_wei, deadline, **transaction_params, ) gas_cost = EthereumAmount(Wei(gas * gas_price.as_wei)) total = EthereumAmount(gas_cost.value + eth_sold.value) return { "gas_price": gas_price, "gas": gas, "eth_sold": eth_sold, "total": total, "exchange_rate": exchange_rate, }
def _calculate_transaction_costs(self, token_amount: TokenAmount, account: Account) -> dict: exchange_rate = self.get_current_rate(token_amount) eth_sold = EthereumAmount(token_amount.value * exchange_rate.value) max_gas_price = min( self.w3.eth.gasPrice, self.network_contract_proxy.functions.maxGasPrice().call() ) gas_price = EthereumAmount(Wei(max_gas_price)) token_network_address = self.get_token_network_address(token_amount.ticker) transaction_params = {"from": account.address, "value": eth_sold.as_wei} gas = estimate_gas( self.w3, account, self.network_contract_proxy.functions.swapEtherToToken, token_network_address, exchange_rate.as_wei, **transaction_params, ) gas_cost = EthereumAmount(Wei(gas * gas_price.as_wei)) total = EthereumAmount(gas_cost.value + eth_sold.value) return { "gas_price": gas_price, "gas": gas, "eth_sold": eth_sold, "total": total, "exchange_rate": exchange_rate, }
def test_swap(self, ws_client, config, settings, unlocked, mock_get_exchange, mock_deposit_service_tokens, mock_wait_for_transaction): def token_balance(w3, account, token): return (TokenAmount(0, token) if token.ticker == settings.transfer_token.ticker else TokenAmount( 10, token)) eth_balance_patch = patch( "raiden_installer.account.Account.get_ethereum_balance", return_value=EthereumAmount(100)) token_balance_patch = patch("raiden_installer.web.get_token_balance", side_effect=token_balance) total_tokens_patch = patch( "raiden_installer.web.get_total_token_owned", side_effect=lambda w3, account, token: TokenAmount(10, token)) token_deposit_patch = patch( "raiden_installer.shared_handlers.get_token_deposit", side_effect=lambda w3, account, token: TokenAmount(10, token)) with eth_balance_patch, token_balance_patch, total_tokens_patch, token_deposit_patch: mock_exchange = mock_get_exchange()() mock_exchange.calculate_transaction_costs.return_value = { "gas_price": EthereumAmount(Wei(1000000000)), "gas": Wei(500000), "eth_sold": EthereumAmount(0.5), "total": EthereumAmount(0.505), "exchange_rate": EthereumAmount(0.05), } mock_exchange.buy_tokens.return_value = os.urandom(32) mock_exchange.name = "uniswap" data = { "method": "swap", "configuration_file_name": config.file_name, "amount": "10000000000000000000", "token": settings.service_token.ticker, "exchange": "uniswap" } ws_client.write_message(json.dumps(data)) for _ in range(8): message = json.loads((yield ws_client.read_message())) assert message["type"] == "status-update" message = json.loads((yield ws_client.read_message())) assert message["type"] == "summary" message = json.loads((yield ws_client.read_message())) assert message["type"] == "redirect" assert message["redirect_url"] == ( f"/swap/{config.file_name}/{settings.transfer_token.ticker}") mock_exchange.calculate_transaction_costs.assert_called_once() mock_exchange.buy_tokens.assert_called_once() mock_deposit_service_tokens.assert_called_once()
def test_create_swap_amounts(self): swap_amounts = SwapAmounts.from_settings(self.settings) self.assertEqual( swap_amounts.service_token, TokenAmount(Wei(self.settings.service_token.swap_amount), self.service_token) ) self.assertEqual( swap_amounts.transfer_token, TokenAmount(Wei(self.settings.transfer_token.swap_amount), self.transfer_token) )
def calculate_transaction_costs(self, token_amount: TokenAmount, account: Account) -> dict: if not self.is_listing_token(token_amount.ticker): raise ExchangeError( f"Cannot calculate costs because {self.name} is not listing {token_amount.ticker}" ) if token_amount.as_wei <= 0: raise ExchangeError( f"Cannot calculate costs for a swap of {token_amount.formatted}" ) log.debug("calculating exchange rate") exchange_rate = self.get_current_rate(token_amount) eth_sold = EthereumAmount(token_amount.value * exchange_rate.value * Decimal(EXCHANGE_PRICE_MARGIN)) log.debug("calculating gas price") gas_price = self._get_gas_price() transaction_params = { "from": account.address, "value": eth_sold.as_wei, "gasPrice": gas_price.as_wei, } log.debug("estimating gas") gas = self._estimate_gas(token_amount, account, transaction_params, exchange_rate=exchange_rate) block = self.w3.eth.getBlock(self.w3.eth.blockNumber) max_gas_limit = Wei(int(block["gasLimit"] * 0.9)) gas_with_margin = Wei(int(gas * GAS_LIMIT_MARGIN)) gas = min(gas_with_margin, max_gas_limit) gas_cost = EthereumAmount(Wei(gas * gas_price.as_wei)) total = EthereumAmount(gas_cost.value + eth_sold.value) log.debug("transaction cost", gas_price=gas_price, gas=gas, eth=eth_sold) return { "gas_price": gas_price, "gas": gas, "eth_sold": eth_sold, "total": total, "exchange_rate": exchange_rate, }
def get_token_deposit(w3: Web3, account: Account, token: Erc20Token) -> TokenAmount: deposit_proxy = _make_deposit_proxy(w3=w3, token=token) amount = Wei( deposit_proxy.functions.effectiveBalance(account.address).call()) return TokenAmount(amount, token)
def send_raw_transaction(w3, account, contract_function, *args, **kw): transaction_params = { "chainId": w3.eth.chainId, "nonce": w3.eth.getTransactionCount(account.address, "pending"), "gasPrice": kw.pop("gas_price", (w3.eth.generateGasPrice())), "gas": kw.pop("gas", None), "from": to_checksum_address(kw.pop("from", account.address)) } transaction_params.update(**kw) if not transaction_params.get("gas"): transaction_params["gas"] = estimate_gas(w3, account, contract_function, *args, **kw) gas_price = transaction_params["gasPrice"] gas = transaction_params["gas"] value = transaction_params.get("value", 0) estimated_cost = EthereumAmount(Wei((gas * gas_price) + value)) log.debug(f"Estimated cost: {estimated_cost.formatted}") result = contract_function(*args) transaction_data = result.buildTransaction(transaction_params) signed = w3.eth.account.signTransaction(transaction_data, account.private_key) tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction) log.debug(f"transaction hash: {tx_hash.hex()}") return tx_hash
def test_udc_deposit_when_already_deposited(self, ws_client, config, settings, unlocked, mock_deposit_service_tokens): required_deposit = Wei(settings.service_token.amount_required) token_balance_patch = patch( "raiden_installer.web.get_token_balance", side_effect=lambda w3, account, token: TokenAmount(10, token)) token_deposit_patch = patch("raiden_installer.web.get_token_deposit", side_effect=lambda w3, account, token: TokenAmount(required_deposit, token)) with token_balance_patch, token_deposit_patch: data = { "method": "udc_deposit", "configuration_file_name": config.file_name, } ws_client.write_message(json.dumps(data)) message = json.loads((yield ws_client.read_message())) assert message["type"] == "status-update" message = json.loads((yield ws_client.read_message())) assert message["type"] == "summary" message = json.loads((yield ws_client.read_message())) assert message["type"] == "redirect" assert message["redirect_url"] == (f"/launch/{config.file_name}") mock_deposit_service_tokens.assert_not_called()
def deposit_service_tokens(w3: Web3, account: Account, token: Erc20Token, amount: Wei): token_proxy = _make_token_proxy(w3=w3, token=token) deposit_proxy = _make_deposit_proxy(w3=w3, token=token) current_deposit_amount = TokenAmount( Wei(deposit_proxy.functions.total_deposit(account.address).call()), token) new_deposit_amount = TokenAmount(amount, token) total_deposit = current_deposit_amount + new_deposit_amount send_raw_transaction( w3, account, token_proxy.functions.approve, deposit_proxy.address, total_deposit.as_wei, gas=GAS_REQUIRED_FOR_APPROVE, ) return send_raw_transaction( w3, account, deposit_proxy.functions.deposit, account.address, total_deposit.as_wei, gas=GAS_REQUIRED_FOR_DEPOSIT, )
def get_current_rate(self, token_amount: TokenAmount) -> EthereumAmount: amounts_in = self.router_proxy.functions.getAmountsIn( token_amount.as_wei, [self.weth_address, token_amount.address]).call() eth_to_sell = EthereumAmount(Wei(amounts_in[0])) return EthereumAmount(eth_to_sell.value / token_amount.value)
def get(self, configuration_file_name): # Returns the highest estimate of ETH needed to get required service token amount configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) required = RequiredAmounts.for_network(configuration_file.network.name) kyber = Kyber(w3=w3) uniswap = Uniswap(w3=w3) highest_cost = 0 for exchange in (kyber, uniswap): exchange_costs = exchange.calculate_transaction_costs( required.service_token, account) if not exchange_costs: continue total_cost = exchange_costs["total"].as_wei highest_cost = max(highest_cost, total_cost) estimated_cost = EthereumAmount(Wei(highest_cost)) self.render_json({ "dex_swap_RDN": { "as_wei": estimated_cost.as_wei, "formatted": estimated_cost.formatted, } })
def test_can_get_formatted_amount(self): zero_eth = EthereumAmount(0) one_twei = EthereumAmount(Wei(10 ** 12)) one_gwei = EthereumAmount(Wei(10 ** 9)) one_mwei = EthereumAmount(Wei(10 ** 6)) almost_one_eth = EthereumAmount("0.875") some_wei = EthereumAmount(Wei(50_000)) self.assertEqual(self.one_eth.formatted, "1 ETH") self.assertEqual(self.one_rdn.formatted, "1 RDN") self.assertEqual(zero_eth.formatted, "0 ETH") self.assertEqual(one_twei.formatted, "1 TWEI") self.assertEqual(one_gwei.formatted, "1 GWEI") self.assertEqual(one_mwei.formatted, "1 MWEI") self.assertEqual(almost_one_eth.formatted, "0.875 ETH") self.assertEqual(some_wei.formatted, "50000 WEI")
def send_raw_transaction(w3, account, contract_function, *args, **kw): transaction_params = { "chainId": int(w3.net.version), "nonce": w3.eth.getTransactionCount(account.address), "gasPrice": kw.pop("gas_price", (w3.eth.generateGasPrice())), "gas": kw.pop("gas", None), } transaction_params.update(**kw) if not transaction_params.get("gas"): transaction_params["gas"] = estimate_gas(w3, account, contract_function, *args, **kw) gas_price = transaction_params["gasPrice"] gas = transaction_params["gas"] value = transaction_params.get("value", 0) estimated_cost = EthereumAmount(Wei((gas * gas_price) + value)) log.debug(f"Estimated cost: {estimated_cost.formatted}") result = contract_function(*args) transaction_data = result.buildTransaction(transaction_params) signed = w3.eth.account.signTransaction(transaction_data, account.private_key) tx_hash = w3.eth.sendRawTransaction(signed.rawTransaction) log.debug(f"transaction hash: {tx_hash.hex()}") return w3.eth.waitForTransactionReceipt(tx_hash, timeout=WEB3_TIMEOUT)
def get_current_rate(self, token_amount: TokenAmount) -> EthereumAmount: exchange_proxy = self._get_exchange_proxy(token_amount.ticker) eth_to_sell = EthereumAmount( Wei(exchange_proxy.functions.getEthToTokenOutputPrice(token_amount.as_wei).call()) ) return EthereumAmount(eth_to_sell.value / token_amount.value)
def test_swap_without_enough_eth( self, ws_client, config, settings, unlocked, mock_get_exchange, mock_deposit_service_tokens, mock_wait_for_transaction ): with patch( "raiden_installer.account.Account.get_ethereum_balance", return_value=EthereumAmount(0) ): mock_exchange = mock_get_exchange()() mock_exchange.calculate_transaction_costs.return_value = { "gas_price": EthereumAmount(Wei(1000000000)), "gas": Wei(500000), "eth_sold": EthereumAmount(0.5), "total": EthereumAmount(0.505), "exchange_rate": EthereumAmount(0.05), } data = { "method": "swap", "configuration_file_name": config.file_name, "amount": "10000000000000000000", "token": settings.service_token.ticker, "exchange": "uniswap" } ws_client.write_message(json.dumps(data)) message = json.loads((yield ws_client.read_message())) assert message["type"] == "status-update" message = json.loads((yield ws_client.read_message())) assert message["type"] == "summary" message = json.loads((yield ws_client.read_message())) assert message["type"] == "redirect" assert message["redirect_url"] == ( f"/swap/{config.file_name}/{settings.service_token.ticker}" ) mock_exchange.calculate_transaction_costs.assert_called_once() mock_exchange.buy_tokens.assert_not_called() mock_deposit_service_tokens.assert_not_called()
def deposit_service_tokens(w3: Web3, account: Account, token: Erc20Token, amount: Wei): token_proxy = _make_token_proxy(w3=w3, token=token) deposit_proxy = _make_deposit_proxy(w3=w3, token=token) current_deposit_amount = TokenAmount( Wei(deposit_proxy.functions.total_deposit(account.address).call()), token) gas_price = Wei(int(w3.eth.generateGasPrice() * GAS_PRICE_MARGIN)) new_deposit_amount = TokenAmount(amount, token) total_deposit = current_deposit_amount + new_deposit_amount nonce = w3.eth.getTransactionCount(account.address) send_raw_transaction( w3, account, token_proxy.functions.approve, deposit_proxy.address, 0, gas=GAS_REQUIRED_FOR_APPROVE, gas_price=gas_price, nonce=nonce, ) send_raw_transaction( w3, account, token_proxy.functions.approve, deposit_proxy.address, total_deposit.as_wei, gas=GAS_REQUIRED_FOR_APPROVE, gas_price=gas_price, nonce=nonce + 1, ) return send_raw_transaction( w3, account, deposit_proxy.functions.deposit, account.address, total_deposit.as_wei, gas=GAS_REQUIRED_FOR_DEPOSIT, gas_price=gas_price, nonce=nonce + 2, )
def test_create_required_amounts(self): required_amounts = RequiredAmounts.from_settings(self.settings) self.assertEqual( required_amounts.eth, EthereumAmount(Wei(self.settings.ethereum_amount_required)) ) self.assertEqual( required_amounts.eth_after_swap, EthereumAmount(Wei(self.settings.ethereum_amount_required_after_swap)) ) self.assertEqual( required_amounts.service_token, TokenAmount(Wei(self.settings.service_token.amount_required), self.service_token) ) self.assertEqual( required_amounts.transfer_token, TokenAmount(Wei(self.settings.transfer_token.amount_required), self.transfer_token) )
def run_action_swap_kyber(): account = prompt_account_selection() ethereum_rpc_endpoint = prompt_ethereum_rpc_endpoint_selection() w3 = make_web3_provider(ethereum_rpc_endpoint.url, account) kyber = Exchange.get_by_name("kyber")(w3=w3) amount = Wei(5 * (10**18)) kyber.buy_tokens(account, TokenAmount(amount, Erc20Token.find_by_ticker("RDN"))) return main_prompt()
def test_cost_estimation_handler( self, http_client, base_url, config, settings, mock_get_exchange ): exchange = "Kyber" exchange_costs = { "gas_price": EthereumAmount(Wei(1000000000)), "gas": Wei(500000), "eth_sold": EthereumAmount(0.5), "total": EthereumAmount(0.505), "exchange_rate": EthereumAmount(0.05), } mock_exchange = mock_get_exchange()() mock_exchange.name = exchange mock_exchange.calculate_transaction_costs.return_value = exchange_costs currency = settings.transfer_token.ticker target_amount = 3 data = { "exchange": exchange, "currency": currency, "target_amount": target_amount, } request = HTTPRequest( url=f"{base_url}/api/cost-estimation/{config.file_name}", method="POST", body=json.dumps(data) ) response = yield http_client.fetch(request) json_response = json.loads(response.body) assert successful_json_response(response) assert json_response["exchange"] == exchange assert json_response["currency"] == currency assert json_response["target_amount"] == target_amount assert json_response["as_wei"] == exchange_costs["total"].as_wei assert json_response["formatted"] == exchange_costs["total"].formatted
def get_current_rate(self, token_amount: TokenAmount) -> EthereumAmount: eth_address = self.get_token_network_address(TokenTicker("ETH")) token_network_address = self.get_token_network_address( token_amount.ticker) expected_rate, slippage_rate = self.network_contract_proxy.functions.getExpectedRate( token_network_address, eth_address, token_amount.as_wei).call() if expected_rate == 0 or slippage_rate == 0: raise ExchangeError( "Trade not possible at the moment due to lack of liquidity") return EthereumAmount(Wei(max(expected_rate, slippage_rate)))
def _ensure_ethereum_funds(self, ethereum_amount: EthereumAmount): w3 = self._get_web3() current_balance = self.account.get_ethereum_balance(w3) log.debug(f"Current balance: {current_balance.formatted}") network = self._get_network() if current_balance < ethereum_amount: needed_funds = EthereumAmount(Wei(ethereum_amount.as_wei - current_balance.as_wei)) print( f"Please send at least {needed_funds.formatted} to {self.account.address} on " f"{network.capitalized_name}" ) return self._wait_for_ethereum_funds(ethereum_amount=needed_funds)
def _calculate_transaction_costs(self, token_amount: TokenAmount, account: Account) -> dict: exchange_rate = self.get_current_rate(token_amount) eth_sold = EthereumAmount(token_amount.value * exchange_rate.value) gas_price = EthereumAmount(Wei(self.w3.eth.generateGasPrice())) exchange_proxy = self._get_exchange_proxy(token_amount.ticker) latest_block = self.w3.eth.getBlock("latest") deadline = latest_block.timestamp + self.EXCHANGE_TIMEOUT transaction_params = { "from": account.address, "value": eth_sold.as_wei, "gasPrice": gas_price.as_wei, } gas = estimate_gas( self.w3, account, exchange_proxy.functions.ethToTokenSwapOutput, token_amount.as_wei, deadline, **transaction_params, ) max_gas_limit = Wei(int(latest_block["gasLimit"] * 0.9)) gas_with_margin = Wei(int(gas * GAS_LIMIT_MARGIN)) gas = min(gas_with_margin, max_gas_limit) gas_cost = EthereumAmount(Wei(gas * gas_price.as_wei)) total = EthereumAmount(gas_cost.value + eth_sold.value) log.debug("transaction cost", gas_price=gas_price, gas=gas, eth=eth_sold) return { "gas_price": gas_price, "gas": gas, "eth_sold": eth_sold, "total": total, "exchange_rate": exchange_rate, }
def test_goerli_faucet(self): TIMEOUT = 10 INTERVAL = 1 time_remaining = TIMEOUT self.network.fund(self.account) balance = EthereumAmount(Wei(0)) while time_remaining > 0 or balance.as_wei == 0: balance = self.account.get_ethereum_balance(self.w3) time.sleep(INTERVAL) time_remaining -= INTERVAL self.assertTrue(balance.as_wei > 0, f"After {TIMEOUT} seconds, balance was not updated")
def get_token_balance(w3: Web3, account: Account, token: Erc20Token) -> TokenAmount: token_proxy = _make_token_proxy(w3=w3, token=token) amount = Wei(token_proxy.functions.balanceOf(account.address).call()) return TokenAmount(amount, token)
def _run_swap(self, **kw): try: configuration_file_name = kw.get("configuration_file_name") exchange_name = kw["exchange"] token_amount = kw["amount"] token_ticker = kw["token"] except (ValueError, KeyError, TypeError) as exc: self._send_error_message(f"Invalid request: {exc}") return try: configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) network_name = configuration_file.network.name form = TokenExchangeForm({ "network": [network_name], "exchange": [exchange_name], "token_amount": [token_amount], "token_ticker": [token_ticker], }) if form.validate(): account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) token = Erc20Token.find_by_ticker(form.data["token_ticker"], network_name) token_amount = TokenAmount(Wei(form.data["token_amount"]), token) exchange = Exchange.get_by_name(form.data["exchange"])(w3=w3) self._send_status_update(f"Starting swap at {exchange.name}") costs = exchange.calculate_transaction_costs( token_amount, account) needed_funds = costs["total"] exchange_rate = costs["exchange_rate"] balance_before_swap = account.get_ethereum_balance(w3) if needed_funds > balance_before_swap: raise ValueError(( f"Not enough ETH. {balance_before_swap.formatted} available, but " f"{needed_funds.formatted} needed")) self._send_status_update( (f"Best exchange rate found at {exchange.name}: " f"{exchange_rate} / {token_amount.ticker}")) self._send_status_update( f"Trying to acquire {token_amount} at this rate") self._send_status_update( f"maximal costs estimated: {needed_funds} ") transaction_receipt = exchange.buy_tokens( account, token_amount, costs) block_with_transaction = transaction_receipt["blockNumber"] current_block = w3.eth.blockNumber while current_block < block_with_transaction: log.debug("wait for block with transaction to be fetched") current_block = w3.eth.blockNumber time.sleep(1) token_balance = get_token_balance(w3, account, token) balance_after_swap = account.get_ethereum_balance(w3) actual_total_costs = balance_before_swap - balance_after_swap self._send_status_update( f"Swap complete. {token_balance.formatted} available") self._send_status_update(f"Actual costs: {actual_total_costs}") required = RequiredAmounts.for_network(network_name) service_token = Erc20Token.find_by_ticker( required.service_token.ticker, network_name) service_token_balance = get_token_balance( w3, account, service_token) transfer_token = Erc20Token.find_by_ticker( required.transfer_token.ticker, network_name) transfer_token_balance = get_token_balance( w3, account, transfer_token) time.sleep(2) if service_token_balance < required.service_token: self._send_redirect( self.reverse_url("swap", configuration_file.file_name, service_token.ticker)) elif transfer_token_balance < required.transfer_token: self._send_redirect( self.reverse_url("swap", configuration_file.file_name, transfer_token.ticker)) else: self._send_redirect( self.reverse_url("launch", configuration_file.file_name)) else: for key, error_list in form.errors.items(): error_message = f"{key}: {'/'.join(error_list)}" self._send_error_message(error_message) except (json.decoder.JSONDecodeError, KeyError, ExchangeError, ValueError) as exc: self._send_error_message(str(exc))
def get_ethereum_balance(self, w3) -> TokenAmount: return TokenAmount(Wei(w3.eth.getBalance(self.address)), ETH)
def _calculate_transaction_costs(self, token_amount: TokenAmount, account: Account) -> dict: exchange_rate = self.get_current_rate(token_amount) eth_sold = EthereumAmount(token_amount.value * exchange_rate.value * Decimal(1.2)) web3_gas_price = Wei( int(self.w3.eth.generateGasPrice() * self.GAS_PRICE_MARGIN)) kyber_max_gas_price = self.network_contract_proxy.functions.maxGasPrice( ).call() max_gas_price = min(web3_gas_price, kyber_max_gas_price) gas_price = EthereumAmount(Wei(max_gas_price)) log.debug(f"gas price: {gas_price}") token_network_address = self.get_token_network_address( token_amount.ticker) transaction_params = { "from": account.address, "value": eth_sold.as_wei } eth_address = to_checksum_address( kyber_tokens.get_token_network_address(self.chain_id, TokenTicker("ETH"))) gas = estimate_gas( self.w3, account, self.network_contract_proxy.functions.trade, eth_address, eth_sold.as_wei, token_network_address, account.address, token_amount.as_wei, exchange_rate.as_wei, account.address, **transaction_params, ) block = self.w3.eth.getBlock(self.w3.eth.blockNumber) max_gas_limit = Wei(int(block["gasLimit"] * 0.9)) gas_with_margin = Wei(int(gas * self.GAS_PRICE_MARGIN)) gas = min(gas_with_margin, max_gas_limit) log.debug("Gas Limit", gas_with_margin=gas_with_margin, max_gas_limit=max_gas_limit) if max_gas_limit < gas_with_margin: log.debug( f"calculated gas was higher than block's gas limit {max_gas_limit}. Using this limit." ) gas_cost = EthereumAmount(Wei(gas * gas_price.as_wei)) total = EthereumAmount(gas_cost.value + eth_sold.value) log.debug("transaction cost", gas_price=gas_price, gas=gas, eth=eth_sold) return { "gas_price": gas_price, "gas": gas, "eth_sold": eth_sold, "total": total, "exchange_rate": exchange_rate, }
def test_can_multiply_amounts(self): two_eth_in_wei = 2 * self.one_eth.as_wei self.assertEqual(two_eth_in_wei, Wei(2 * 10 ** 18))
def test_can_convert_to_wei(self): self.assertEqual(self.one_eth.as_wei, Wei(10 ** 18))
def get_ethereum_balance(self, w3) -> EthereumAmount: return EthereumAmount(Wei(w3.eth.getBalance(self.address)))