From b55042bf07deee0a3c365b6bcd267463e3f43f0a Mon Sep 17 00:00:00 2001 From: tecnovert Date: Sun, 11 Feb 2024 17:55:06 +0200 Subject: [PATCH] ui: Added An Estimate Fee button on XMR wallet page. --- basicswap/interface/xmr.py | 16 +++++-- basicswap/templates/wallet.html | 10 ++++- basicswap/ui/page_wallet.py | 77 +++++++++++++++++++++++---------- doc/release-notes.md | 6 ++- 4 files changed, 80 insertions(+), 29 deletions(-) diff --git a/basicswap/interface/xmr.py b/basicswap/interface/xmr.py index 2bd255b..ab2a67e 100644 --- a/basicswap/interface/xmr.py +++ b/basicswap/interface/xmr.py @@ -231,6 +231,7 @@ class XMRInterface(CoinInterface): rv = {} self.rpc_wallet('refresh') balance_info = self.rpc_wallet('get_balance') + rv['balance'] = self.format_amount(balance_info['unlocked_balance']) rv['unconfirmed_balance'] = self.format_amount(balance_info['balance'] - balance_info['unlocked_balance']) rv['encrypted'] = False if self._wallet_password is None else True @@ -473,7 +474,7 @@ class XMRInterface(CoinInterface): return bytes.fromhex(rv['tx_hash_list'][0]) - def withdrawCoin(self, value: int, addr_to: str, sweepall: bool) -> str: + def withdrawCoin(self, value, addr_to: str, sweepall: bool, estimate_fee: bool = False) -> str: with self._mx_wallet: self.openWallet(self._wallet_filename) self.rpc_wallet('refresh') @@ -482,21 +483,28 @@ class XMRInterface(CoinInterface): balance = self.rpc_wallet('get_balance') if balance['balance'] != balance['unlocked_balance']: raise ValueError('Balance must be fully confirmed to use sweep all.') - self._log.info('XMR withdraw sweep_all.') + self._log.info('XMR {} sweep_all.'.format('estimate fee' if estimate_fee else 'withdraw')) self._log.debug('XMR balance: {}'.format(balance['balance'])) - params = {'address': addr_to} + params = {'address': addr_to, 'do_not_relay': estimate_fee} if self._fee_priority > 0: params['priority'] = self._fee_priority rv = self.rpc_wallet('sweep_all', params) + if estimate_fee: + return {'num_txns': len(rv['fee_list']), 'sum_amount': sum(rv['amount_list']), 'sum_fee': sum(rv['fee_list']), 'sum_weight': sum(rv['weight_list'])} return rv['tx_hash_list'][0] value_sats: int = make_int(value, self.exp()) - params = {'destinations': [{'amount': value_sats, 'address': addr_to}]} + params = {'destinations': [{'amount': value_sats, 'address': addr_to}], 'do_not_relay': estimate_fee} if self._fee_priority > 0: params['priority'] = self._fee_priority rv = self.rpc_wallet('transfer', params) + if estimate_fee: + return {'num_txns': 1, 'sum_amount': rv['amount'], 'sum_fee': rv['fee'], 'sum_weight': rv['weight']} return rv['tx_hash'] + def estimateFee(self, value: int, addr_to: str, sweepall: bool) -> str: + return self.withdrawCoin(value, addr_to, sweepall, estimate_fee=True) + def showLockTransfers(self, kbv, Kbs, restore_height): with self._mx_wallet: try: diff --git a/basicswap/templates/wallet.html b/basicswap/templates/wallet.html index 5fa2c7f..02de308 100644 --- a/basicswap/templates/wallet.html +++ b/basicswap/templates/wallet.html @@ -30,10 +30,15 @@

Manage your {{ w.ticker }} wallet. {% if refresh %} (Page Refresh: {{ refresh }} seconds) {% endif %}

+ {% if w.cid == '6' %} {# XMR #} + + {% endif %} {# / XMR #} {{ circular_arrows_svg | safe }}Refresh
+ @@ -102,7 +107,7 @@ {% else %} -
+
@@ -393,6 +398,9 @@ {{ w.fee_rate }} Est Fee: {{ w.est_fee }} + {% if w.cid == '6' %} {# XMR #} + + {% endif %} {# / XMR #} diff --git a/basicswap/ui/page_wallet.py b/basicswap/ui/page_wallet.py index 17ed173..643b562 100644 --- a/basicswap/ui/page_wallet.py +++ b/basicswap/ui/page_wallet.py @@ -133,27 +133,33 @@ def page_wallet(self, url_split, post_string): page_data = {} messages = [] err_messages = [] - show_utxo_groups = False + show_utxo_groups: bool = False + withdrawal_successful: bool = False + force_refresh: bool = False form_data = self.checkForm(post_string, 'wallet', err_messages) if form_data: cid = str(int(coin_id)) - if bytes('newaddr_' + cid, 'utf-8') in form_data: + estimate_fee: bool = have_data_entry(form_data, 'estfee_' + cid) + withdraw: bool = have_data_entry(form_data, 'withdraw_' + cid) + if have_data_entry(form_data, 'newaddr_' + cid): swap_client.cacheNewAddressForCoin(coin_id) - elif bytes('newmwebaddr_' + cid, 'utf-8') in form_data: + elif have_data_entry(form_data, 'forcerefresh'): + force_refresh = True + elif have_data_entry(form_data, 'newmwebaddr_' + cid): swap_client.cacheNewStealthAddressForCoin(coin_id) - elif bytes('reseed_' + cid, 'utf-8') in form_data: + elif have_data_entry(form_data, 'reseed_' + cid): try: swap_client.reseedWallet(coin_id) messages.append('Reseed complete ' + str(coin_id)) except Exception as ex: err_messages.append('Reseed failed ' + str(ex)) swap_client.updateWalletsInfo(True, coin_id) - elif bytes('withdraw_' + cid, 'utf-8') in form_data: - subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False + elif withdraw or estimate_fee: + subfee = True if have_data_entry(form_data, 'subfee_' + cid) else False page_data['wd_subfee_' + cid] = subfee - sweepall = True if bytes('sweepall_' + cid, 'utf-8') in form_data else False + sweepall = True if have_data_entry(form_data, 'sweepall_' + cid) else False page_data['wd_sweepall_' + cid] = sweepall value = None if not sweepall: @@ -168,6 +174,13 @@ def page_wallet(self, url_split, post_string): except Exception as e: err_messages.append('Missing address') + if estimate_fee and withdraw: + err_messages.append('Estimate fee and withdraw can\'t be used together.') + if estimate_fee and coin_id not in (Coins.XMR, ): + ci = swap_client.ci(coin_id) + ticker: str = ci.ticker() + err_messages.append(f'Estimate fee unavailable for {ticker}.') + if coin_id == Coins.PART: try: type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8') @@ -185,7 +198,7 @@ def page_wallet(self, url_split, post_string): if len(err_messages) == 0: ci = swap_client.ci(coin_id) - ticker = ci.ticker() + ticker: str = ci.ticker() try: if coin_id == Coins.PART: txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee) @@ -194,17 +207,31 @@ def page_wallet(self, url_split, post_string): txid = swap_client.withdrawLTC(type_from, value, address, subfee) messages.append('Withdrew {} {} (from {}) to address {}
In txid: {}'.format(value, ticker, type_from, address, txid)) elif coin_id == Coins.XMR: - txid = swap_client.withdrawCoin(coin_id, value, address, sweepall) - if sweepall: - messages.append('Swept all {} to address {}
In txid: {}'.format(ticker, address, txid)) + if estimate_fee: + fee_estimate = ci.estimateFee(value, address, sweepall) + suffix = 's' if fee_estimate['num_txns'] > 1 else '' + sum_fees = ci.format_amount(fee_estimate['sum_fee']) + value_str = ci.format_amount(fee_estimate['sum_amount']) + messages.append(f'Estimated fee for {value_str} {ticker} to address {address}: {sum_fees} in {fee_estimate["num_txns"]} transaction{suffix}.') + page_data['fee_estimate'] = fee_estimate else: - messages.append('Withdrew {} {} to address {}
In txid: {}'.format(value, ticker, address, txid)) + txid = swap_client.withdrawCoin(coin_id, value, address, sweepall) + if sweepall: + messages.append('Swept all {} to address {}
In txid: {}'.format(ticker, address, txid)) + else: + messages.append('Withdrew {} {} to address {}
In txid: {}'.format(value, ticker, address, txid)) + messages.append('Note: The wallet balance can take a while to update.') else: txid = swap_client.withdrawCoin(coin_id, value, address, subfee) messages.append('Withdrew {} {} to address {}
In txid: {}'.format(value, ticker, address, txid)) + if not estimate_fee: + withdrawal_successful = True except Exception as e: + if swap_client.debug is True: + swap_client.log.error(traceback.format_exc()) err_messages.append(str(e)) - swap_client.updateWalletsInfo(True, coin_id) + if not estimate_fee: + swap_client.updateWalletsInfo(True, only_coin=coin_id) elif have_data_entry(form_data, 'showutxogroups'): show_utxo_groups = True elif have_data_entry(form_data, 'create_utxo'): @@ -214,7 +241,6 @@ def page_wallet(self, url_split, post_string): page_data['utxo_value'] = value ci = swap_client.ci(coin_id) - value_sats = ci.make_int(value) txid, address = ci.createUTXO(value_sats) @@ -224,7 +250,7 @@ def page_wallet(self, url_split, post_string): if swap_client.debug is True: swap_client.log.error(traceback.format_exc()) - swap_client.updateWalletsInfo(only_coin=coin_id, wait_for_complete=True) + swap_client.updateWalletsInfo(force_refresh, only_coin=coin_id, wait_for_complete=True) wallets = swap_client.getCachedWalletsInfo({'coin_id': coin_id}) for k in wallets.keys(): w = wallets[k] @@ -265,17 +291,22 @@ def page_wallet(self, url_split, post_string): if 'wd_type_to_' + cid in page_data: wallet_data['wd_type_to'] = page_data['wd_type_to_' + cid] - if 'wd_value_' + cid in page_data: - wallet_data['wd_value'] = page_data['wd_value_' + cid] - if 'wd_address_' + cid in page_data: - wallet_data['wd_address'] = page_data['wd_address_' + cid] - if 'wd_subfee_' + cid in page_data: - wallet_data['wd_subfee'] = page_data['wd_subfee_' + cid] - if 'wd_sweepall_' + cid in page_data: - wallet_data['wd_sweepall'] = page_data['wd_sweepall_' + cid] if 'utxo_value' in page_data: wallet_data['utxo_value'] = page_data['utxo_value'] + if not withdrawal_successful: + if 'wd_value_' + cid in page_data: + wallet_data['wd_value'] = page_data['wd_value_' + cid] + if 'wd_address_' + cid in page_data: + wallet_data['wd_address'] = page_data['wd_address_' + cid] + if 'wd_subfee_' + cid in page_data: + wallet_data['wd_subfee'] = page_data['wd_subfee_' + cid] + if 'wd_sweepall_' + cid in page_data: + wallet_data['wd_sweepall'] = page_data['wd_sweepall_' + cid] + if 'fee_estimate' in page_data: + wallet_data['est_fee'] = ci.format_amount(page_data['fee_estimate']['sum_fee']) + wallet_data['fee_rate'] = ci.format_amount(page_data['fee_estimate']['sum_fee'] * 1000 // page_data['fee_estimate']['sum_weight']) + if show_utxo_groups: utxo_groups = '' unspent_by_addr = ci.getUnspentsByAddr() diff --git a/doc/release-notes.md b/doc/release-notes.md index f031a8e..6d463de 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -18,7 +18,11 @@ - `rpctimeout`, `walletrpctimeout` and `walletrpctimeoutlong` in the Monero section of basicswap.json. - `wallet_update_timeout` in basicswap.json to set how long the wallet ui page waits for an rpc response. - ui: Renamed unconfirmed balance to pending and include immature balance in pending. -- Fixed LTC create utxo +- Fixed LTC create utxo. +- ui: Changed 'Subtract Fee' option to 'Sweep All' on XMR wallet page. +- ui: Added An Estimate Fee button on XMR wallet page. +- ui: Added a Force Refresh button on XMR wallet page. + - get_balance (if called) at the end of withdrawCoin is correct, subsequent get_balance calls return old balance for a while. 0.12.6