def _run_funding(self, configuration_file: RaidenConfigurationFile): network = configuration_file.network settings = network_settings[network.name] if not network.FAUCET_AVAILABLE: self._send_error_message( f"Can not run automatic funding for {network.capitalized_name}" ) return account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) self._send_status_update( f"Obtaining {network.capitalized_name} ETH through faucet") network.fund(account) balance = account.wait_for_ethereum_funds( w3=w3, expected_amount=EthereumAmount(0.01)) self._send_status_update(f"Account funded with {balance.formatted}") if settings.service_token.mintable: service_token = Erc20Token.find_by_ticker( settings.service_token.ticker, settings.network) self._send_status_update(f"Minting {service_token.ticker}") mint_tokens(w3, account, service_token) if settings.transfer_token.mintable: transfer_token = Erc20Token.find_by_ticker( settings.transfer_token.ticker, settings.network) self._send_status_update(f"Minting {transfer_token.ticker}") mint_tokens(w3, account, transfer_token)
def setUp(self): self.settings = load_settings("mainnet") self.service_token = Erc20Token.find_by_ticker( self.settings.service_token.ticker, self.settings.network ) self.transfer_token = Erc20Token.find_by_ticker( self.settings.transfer_token.ticker, self.settings.network )
def check_balances(w3, account, settings, check_func): balance = account.get_ethereum_balance(w3) service_token = Erc20Token.find_by_ticker(settings.service_token.ticker, settings.network) udc_balance = get_token_deposit(w3, account, service_token) transfer_token = Erc20Token.find_by_ticker(settings.transfer_token.ticker, settings.network) transfer_token_balance = get_token_balance(w3, account, transfer_token) return (check_func(balance.as_wei) and check_func(udc_balance.as_wei) and check_func(transfer_token_balance.as_wei))
def _run_udc_deposit(self, **kw): try: configuration_file_name = kw.get("configuration_file_name") configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) except (ValueError, KeyError, TypeError) as exc: self._send_error_message(f"Invalid request: {exc}") return try: settings = self.installer_settings required = RequiredAmounts.from_settings(settings) swap_amounts = SwapAmounts.from_settings(settings) service_token = Erc20Token.find_by_ticker( required.service_token.ticker, settings.network) account = configuration_file.account try_unlock(account) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) service_token_balance = get_token_balance(w3, account, service_token) service_token_deposited = get_token_deposit( w3, account, service_token) if service_token_deposited < required.service_token: swap_amount = swap_amounts.service_token if service_token_balance >= swap_amount: deposit = swap_amount - service_token_deposited else: deposit = service_token_balance self._deposit_to_udc(w3, account, service_token, deposit) else: self._send_status_update( f"Service token deposited at UDC: {service_token_deposited.formatted} is enough" ) time.sleep(5) transfer_token = Erc20Token.find_by_ticker( required.transfer_token.ticker, settings.network) transfer_token_balance = get_token_balance(w3, account, transfer_token) self._redirect_transfer_swap(configuration_file, transfer_token_balance, required) except (json.decoder.JSONDecodeError, KeyError, ExchangeError, ValueError) as exc: self._redirect_after_swap_error(exc, configuration_file.file_name, service_token.ticker)
def get(self, configuration_file_name): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) network = configuration_file.network.name account = configuration_file.account try_unlock(account) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) required = RequiredAmounts.for_network(network) service_token = Erc20Token.find_by_ticker( required.service_token.ticker, network) transfer_token = Erc20Token.find_by_ticker( required.transfer_token.ticker, network) service_token_balance = get_total_token_owned( w3=w3, account=configuration_file.account, token=service_token) transfer_token_balance = get_token_balance( w3=w3, account=configuration_file.account, token=transfer_token) eth_balance = configuration_file.account.get_ethereum_balance(w3) def serialize_balance(balance_amount): return ({ "as_wei": balance_amount.as_wei, "formatted": balance_amount.formatted } if balance_amount else None) self.render_json({ "url": self.reverse_url("api-configuration-detail", configuration_file.file_name), "file_name": configuration_file.file_name, "account_page_url": self.reverse_url("account", configuration_file.file_name), "account": configuration_file.account.address, "network": configuration_file.network.name, "balance": { "ETH": serialize_balance(eth_balance), "service_token": serialize_balance(service_token_balance), "transfer_token": serialize_balance(transfer_token_balance), }, "_initial_funding_txhash": configuration_file._initial_funding_txhash, })
def get(self, configuration_file_name, token_ticker): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, configuration_file.account) kyber = Kyber(w3=w3) uniswap = Uniswap(w3=w3) token = Erc20Token.find_by_ticker(token_ticker, configuration_file.network.name) network = configuration_file.network settings = network_settings[network.name] swap_amounts = SwapAmounts.from_settings(settings) if token_ticker == settings.service_token.ticker: swap_amount_1 = swap_amounts.service_token_1 swap_amount_2 = swap_amounts.service_token_2 swap_amount_3 = swap_amounts.service_token_3 elif token_ticker == settings.transfer_token.ticker: swap_amount_1 = swap_amounts.transfer_token_1 swap_amount_2 = swap_amounts.transfer_token_2 swap_amount_3 = swap_amounts.transfer_token_3 self.render( "swap.html", configuration_file=configuration_file, kyber=kyber, uniswap=uniswap, token=token, swap_amount_1=swap_amount_1, swap_amount_2=swap_amount_2, swap_amount_3=swap_amount_3, )
def removeLiquidity(w3, account, router_proxy): pair_address = to_canonical_address(get_pair_address(w3, router_proxy)) liquidity_token = Erc20Token( ticker="UNI-V2", wei_ticker="UNI-V2 WEI", address=pair_address ) amount = get_token_balance(w3, account, liquidity_token) approve(w3, account, router_proxy.address, amount.as_wei, liquidity_token) min_eth = 1 min_tokens = 1 deadline = generateDeadline(w3) transaction_params = { "from": account.address, "gas_price": w3.eth.generateGasPrice(), "gas": GAS_LIMIT, } tx_hash = send_raw_transaction( w3, account, router_proxy.functions.removeLiquidityETH, WIZ_TOKEN.address, amount.as_wei, min_tokens, min_eth, account.address, deadline, **transaction_params, ) wait_for_transaction(w3, tx_hash)
def post(self, configuration_file_name): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) account = configuration_file.account try_unlock(account) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) ex_currency_amt = json_decode(self.request.body) exchange = Exchange.get_by_name(ex_currency_amt["exchange"])(w3=w3) currency = Erc20Token.find_by_ticker(ex_currency_amt["currency"], configuration_file.network) token_amount = TokenAmount(ex_currency_amt["target_amount"], currency) try: exchange_costs = exchange.calculate_transaction_costs( token_amount, account) total_cost = exchange_costs["total"] self.render_json({ "exchange": exchange.name, "currency": currency.ticker, "target_amount": ex_currency_amt["target_amount"], "as_wei": total_cost.as_wei, "formatted": total_cost.formatted, "utc_seconds": int(time.time()), }) except ExchangeError as ex: log.error("There was an error preparing the exchange", exc_info=ex) self.set_status( status_code=409, reason=str(ex), )
def get(self, configuration_file_name, token_ticker): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) if get_passphrase() is None: self.render( "account_unlock.html", keystore_file_path=configuration_file.account. keystore_file_path, return_to=f"/swap/{configuration_file_name}/{token_ticker}", ) return w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, configuration_file.account) kyber = Kyber(w3=w3) uniswap = Uniswap(w3=w3) token = Erc20Token.find_by_ticker(token_ticker, configuration_file.network.name) swap_amounts = SwapAmounts.from_settings(self.installer_settings) if token_ticker == self.installer_settings.service_token.ticker: swap_amount = swap_amounts.service_token elif token_ticker == self.installer_settings.transfer_token.ticker: swap_amount = swap_amounts.transfer_token self.render( "swap.html", configuration_file=configuration_file, kyber=kyber, uniswap=uniswap, token=token, swap_amount=swap_amount, )
def is_listing_token(self, token_ticker: TokenTicker): factory_proxy = self._get_factory_proxy() token = Erc20Token.find_by_ticker(token_ticker, self.network.name) pair_address = to_canonical_address( factory_proxy.functions.getPair(self.weth_address, token.address).call()) return pair_address != NULL_ADDRESS
def _run_launch(self, **kw): configuration_file_name = kw.get("configuration_file_name") configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) network_name = configuration_file.network.name raiden_client = RaidenClient.get_client(network_name) required = RequiredAmounts.for_network(network_name) if not raiden_client.is_installed: self._send_status_update( f"Downloading and installing raiden {raiden_client.release}") raiden_client.install() self._send_status_update("Installation complete") account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) service_token = Erc20Token.find_by_ticker( required.service_token.ticker, network_name) service_token_balance = get_token_balance(w3=w3, account=account, token=service_token) service_token_in_deposit = get_token_deposit(w3=w3, account=account, token=service_token) if service_token_balance.as_wei and service_token_in_deposit < required.service_token: self._send_status_update( f"Making deposit of {service_token_balance.formatted} for Raiden Services" ) deposit_service_tokens(w3=w3, account=account, token=service_token, amount=service_token_balance.as_wei) service_token_deposited = get_token_deposit(w3=w3, account=account, token=service_token) self._send_status_update( f"Amount deposited at UDC: {service_token_deposited.formatted}" ) self._send_status_update( "Launching Raiden, this might take a couple of minutes, do not close the browser" ) if not raiden_client.is_running: raiden_client.launch(configuration_file) try: raiden_client.wait_for_web_ui_ready( status_callback=lambda stat: log.info(str(stat))) self._send_task_complete("Raiden is ready!") self._send_redirect(raiden_client.WEB_UI_INDEX_URL) except (RaidenClientError, RuntimeError) as exc: self._send_error_message(f"Raiden process failed to start: {exc}") raiden_client.kill()
def get(self, configuration_file_name): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) service_token = Erc20Token.find_by_ticker( SERVICE_TOKEN_REQUIRED.ticker) transfer_token = Erc20Token.find_by_ticker( TRANSFER_TOKEN_REQUIRED.ticker) service_token_balance = get_total_token_owned( w3=w3, account=configuration_file.account, token=service_token) transfer_token_balance = get_token_balance( w3=w3, account=configuration_file.account, token=transfer_token) eth_balance = configuration_file.account.get_ethereum_balance(w3) def serialize_balance(balance_amount): return ({ "as_wei": balance_amount.as_wei, "formatted": balance_amount.formatted } if balance_amount else None) self.render_json({ "url": self.reverse_url("api-configuration-detail", configuration_file.file_name), "file_name": configuration_file.file_name, "account_page_url": self.reverse_url("account", configuration_file.file_name), "funding_page_url": self.reverse_url("funding", configuration_file.file_name), "account": configuration_file.account.address, "network": configuration_file.network.name, "balance": { "ETH": serialize_balance(eth_balance), "service_token": serialize_balance(service_token_balance), "transfer_token": serialize_balance(transfer_token_balance), }, })
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 _run_launch(self, **kw): configuration_file_name = kw.get("configuration_file_name") configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) if not RAIDEN_CLIENT.is_installed: self._send_status_update( f"Downloading and installing raiden {RAIDEN_CLIENT.release}") RAIDEN_CLIENT.install() self._send_status_update("Installation complete") account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) service_token = Erc20Token.find_by_ticker( settings.service_token.ticker) service_token_balance = get_token_balance(w3=w3, account=account, token=service_token) service_token_in_deposit = get_token_deposit(w3=w3, account=account, token=service_token) if service_token_balance.as_wei and service_token_in_deposit < SERVICE_TOKEN_REQUIRED: self._send_status_update( f"Making deposit of {service_token_balance.formatted} for Raiden Services" ) deposit_service_tokens(w3=w3, account=account, token=service_token, amount=service_token_balance.as_wei) service_token_deposited = get_token_deposit(w3=w3, account=account, token=service_token) self._send_status_update( f"Amount deposited at UDC: {service_token_deposited.formatted}" ) self._send_status_update( "Launching Raiden, this might take a couple of minutes, do not close the browser" ) if not RAIDEN_CLIENT.is_running: RAIDEN_CLIENT.launch(configuration_file) try: RAIDEN_CLIENT.wait_for_web_ui_ready() self._send_task_complete("Raiden is ready!") self._send_redirect(RAIDEN_CLIENT.WEB_UI_INDEX_URL) except (RaidenClientError, RuntimeError) as exc: self._send_error_message(f"Raiden process failed to start: {exc}") RAIDEN_CLIENT.kill()
def get(self, exchange_name, configuration_file_name, token_ticker): exchange_class = Exchange.get_by_name(exchange_name) configuration_file = RaidenConfigurationFile.get_by_filename(configuration_file_name) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, configuration_file.account ) self.render( "swap.html", exchange=exchange_class(w3=w3), configuration_file=configuration_file, balance=configuration_file.account.get_ethereum_balance(w3), token=Erc20Token.find_by_ticker(token_ticker), )
def get(self, configuration_file_name, token_ticker): configuration_file = RaidenConfigurationFile.get_by_filename(configuration_file_name) w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, configuration_file.account ) kyber = Kyber(w3=w3) uniswap = Uniswap(w3=w3) token = Erc20Token.find_by_ticker(token_ticker) self.render( "swap_options.html", configuration_file=configuration_file, kyber=kyber, uniswap=uniswap, token=token, )
def _deposit(self): network = self._get_network() w3 = self._get_web3() ethereum_balance = self.account.get_ethereum_balance(w3=w3) log.debug(f"Ethereum Balance: {ethereum_balance.formatted}") if not ethereum_balance.as_wei: network.fund(self.account) token = Erc20Token.find_by_ticker(settings.service_token.ticker) token_balance = get_token_balance(w3, self.account, token) log.debug(f"Token Balance: {token_balance.formatted}") if not token_balance.as_wei: mint_tokens(w3, self.account, token) token_balance = get_token_balance(w3, self.account, token) log.debug(f"Tokens minted. New Balance: {token_balance.formatted}") deposit_service_tokens(w3, self.account, token, token_balance.as_wei)
def post(self, configuration_file_name): configuration_file = RaidenConfigurationFile.get_by_filename( configuration_file_name) account = configuration_file.account w3 = make_web3_provider( configuration_file.ethereum_client_rpc_endpoint, account) ex_currency_amt = json_decode(self.request.body) exchange = Exchange.get_by_name(ex_currency_amt["exchange"])(w3=w3) currency = Erc20Token.find_by_ticker(ex_currency_amt["currency"], configuration_file.network) token_amount = TokenAmount(ex_currency_amt["target_amount"], currency) exchange_costs = exchange.calculate_transaction_costs( token_amount, account) total_cost = exchange_costs["total"] self.render_json({ "exchange": exchange.name, "currency": currency.ticker, "target_amount": ex_currency_amt["target_amount"], "as_wei": total_cost.as_wei, "formatted": total_cost.formatted, "utc_seconds": int(time.time()), })
def setUp(self): super().setUp() self.svt_token = Erc20Token.find_by_ticker("SVT", self.NETWORK_NAME)
def test_get_address(self): wiz_token = Erc20Token.find_by_ticker("WIZ", "goerli") self.assertEqual( wiz_token.address, to_canonical_address("0x95b2d84de40a0121061b105e6b54016a49621b44") )
def test_cannot_get_token_on_network_without_deployment(self): with self.assertRaises(TokenError): Erc20Token.find_by_ticker("WIZ", "mainnet")
def test_cannot_initialize_token_without_address(self): with self.assertRaises(TokenError): Erc20Token("RDN", "REI")
def setUp(self): self.one_eth = EthereumAmount(1) self.one_rdn = TokenAmount(1, Erc20Token.find_by_ticker("RDN")) self.one_gwei = EthereumAmount(Wei(10 ** 9)) self.almost_one_eth = EthereumAmount("0.875") self.some_wei = EthereumAmount(Wei(50_000))
from raiden_installer.constants import WEB3_TIMEOUT from raiden_installer.ethereum_rpc import Infura, make_web3_provider from raiden_installer.network import Network from raiden_installer.token_exchange import ExchangeError, Uniswap from raiden_installer.tokens import Erc20Token, EthereumAmount, TokenAmount from raiden_installer.transactions import approve, get_token_balance, mint_tokens from raiden_installer.uniswap.web3 import contracts as uniswap_contracts from raiden_installer.utils import send_raw_transaction, wait_for_transaction from tests.constants import TESTING_KEYSTORE_FOLDER from tests.fixtures import create_account, test_account, test_password from tests.utils import empty_account INFURA_PROJECT_ID = os.getenv("TEST_RAIDEN_INSTALLER_INFURA_PROJECT_ID") NETWORK = Network.get_by_name("goerli") WIZ_TOKEN = Erc20Token.find_by_ticker("WIZ", NETWORK.name) GAS_LIMIT = 120_000 pytestmark = pytest.mark.skipif(not INFURA_PROJECT_ID, reason="missing configuration for infura") def fund_account(account, w3): NETWORK.fund(account) account.wait_for_ethereum_funds(w3, EthereumAmount(0.01)) def generateDeadline(w3): current_timestamp = w3.eth.getBlock('latest')['timestamp'] return current_timestamp + WEB3_TIMEOUT
def _get_RDN(self): return Erc20Token.find_by_ticker("RDN")
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 try_unlock(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") transaction_receipt = exchange.buy_tokens( account, token_amount, costs) wait_for_transaction(w3, transaction_receipt) 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) total_service_token_balance = get_total_token_owned( 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) if total_service_token_balance < required.service_token: raise ExchangeError("Exchange was not successful") elif service_token_balance.as_wei > 0: self._send_status_update( f"Making deposit of {service_token_balance.formatted} to the User Deposit Contract" ) self._send_status_update(f"This might take a few minutes") transaction_receipt = deposit_service_tokens( w3=w3, account=account, token=service_token, amount=service_token_balance.as_wei, ) wait_for_transaction(w3, transaction_receipt) service_token_deposited = get_token_deposit( w3=w3, account=account, token=service_token) self._send_status_update( f"Total amount deposited at UDC: {service_token_deposited.formatted}" ) if transfer_token_balance < required.transfer_token: redirect_url = self.reverse_url( "swap", configuration_file.file_name, transfer_token.ticker) next_page = "Moving on to exchanging DAI ..." else: redirect_url = self.reverse_url( "launch", configuration_file.file_name) next_page = "You are ready to launch Raiden! ..." self._send_summary( ["Congratulations! Swap Successful!", next_page], icon=token_ticker) time.sleep(5) self._send_redirect(redirect_url) 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)) redirect_url = self.reverse_url("swap", configuration_file.file_name, token_ticker) next_page = f"Try again to exchange {token_ticker}..." self._send_summary(["Transaction failed", str(exc), next_page], icon="error") time.sleep(5) self._send_redirect(redirect_url)
def setUp(self): self.one_eth = EthereumAmount(1) self.two_eth = EthereumAmount(2) self.one_rdn = TokenAmount(1, Erc20Token.find_by_ticker("RDN", "mainnet")) self.one_wiz = TokenAmount(1, Erc20Token.find_by_ticker("WIZ", "goerli"))
PORT = "8546" CHAIN_ID = 1337 # Args as specified by the Kyber snapshot documentation GANACHE_COMMAND = [ "node", "node_modules/ganache-cli/cli.js", "--db", "node_modules/kyber-network-workshop/db", "--accounts", "10", "--defaultBalanceEther", "1000", "--mnemonic", "gesture rather obey video awake genuine patient base soon parrot upset lounge", "--networkId", "5777", "--port", PORT ] # Prefilled account from Kyber Ganache snapshot WALLET_PRIVATE_KEY = 0x979d8b20000da5832fc99c547393fdfa5eef980c77bfb1decb17c59738d99471 KNC_TOKEN = Erc20Token(ticker="KNC", wei_ticker="KEI", address=to_canonical_address( kyber_snapshot_addresses.TokenAddress.KNC.value)) def take_snapshot(): body = dict(jsonrpc="2.0", method="evm_snapshot", params=[], id=1) response = requests.post(f"http://localhost:{PORT}", json=body) return response.json()["result"] def revert_to_snapshot(snapshot_id): body = dict(jsonrpc="2.0", method="evm_revert", params=[snapshot_id], id=1) requests.post(f"http://localhost:{PORT}", json=body) @pytest.fixture
def test_can_get_address(self): rdn_token = Erc20Token.find_by_ticker("RDN", "mainnet") self.assertEqual(self.one_rdn.address, rdn_token.address)
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))