예제 #1
0
 def render(self, template_name, **context_data):
     network = Network.get_by_name(self.installer_settings.network)
     required = RequiredAmounts.from_settings(self.installer_settings)
     context_data.update({
         "network": network,
         "ethereum_required": required.eth,
         "ethereum_required_after_swap": required.eth_after_swap,
         "service_token_required": required.service_token,
         "transfer_token_required": required.transfer_token,
         "eip20_abi": json.dumps(EIP20_ABI),
     })
     return super().render(template_name, **context_data)
예제 #2
0
    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)
예제 #3
0
    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)

        settings = configuration_file.settings
        required = RequiredAmounts.from_settings(settings)
        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({
            "file_name":
            configuration_file.file_name,
            "account":
            to_checksum_address(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,
        })
예제 #4
0
    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)
        )
예제 #5
0
    def get(self, configuration_file_name):
        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"/account/{configuration_file_name}",
            )
            return

        keystore_path = configuration_file.configuration_data["keystore-path"]
        filename = ""
        for file in glob(f"{keystore_path}/UTC--*"):
            file_path = Path(file)
            if file_path.is_file():
                keystore_content = json.loads(file_path.read_text())
                if (to_canonical_address(keystore_content["address"]) ==
                        configuration_file.account.address):
                    filename = os.path.basename(file)
                    break

        w3 = make_web3_provider(
            configuration_file.ethereum_client_rpc_endpoint,
            configuration_file.account)
        required = RequiredAmounts.from_settings(self.installer_settings)
        eth_balance = configuration_file.account.get_ethereum_balance(w3)
        log.info(f"funding tx {configuration_file._initial_funding_txhash}")
        log.info(f"Checking balance {eth_balance} >= {required.eth}")
        if eth_balance >= required.eth:
            configuration_file._initial_funding_txhash = None
            configuration_file.save()

        self.render(
            "account.html",
            configuration_file=configuration_file,
            keystore=filename,
            ramp_api_key=RAMP_API_KEY,
        )
예제 #6
0
    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")

                tx_hash = exchange.buy_tokens(account, token_amount, costs)
                wait_for_transaction(w3, tx_hash)

                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.from_settings(
                    self.installer_settings)
                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 token_ticker == service_token.ticker and service_token_balance > required.service_token:
                    self._deposit_to_udc(w3, account, service_token,
                                         service_token_balance)

                self._redirect_transfer_swap(configuration_file,
                                             transfer_token_balance, required)
            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._redirect_after_swap_error(exc, configuration_file.file_name,
                                            token_ticker)