mirror of
https://github.com/basicswap/basicswap.git
synced 2024-11-16 15:58:17 +00:00
ui: Added An Estimate Fee button on XMR wallet page.
This commit is contained in:
parent
9be4bd28fd
commit
b55042bf07
4 changed files with 80 additions and 29 deletions
|
@ -231,6 +231,7 @@ class XMRInterface(CoinInterface):
|
||||||
rv = {}
|
rv = {}
|
||||||
self.rpc_wallet('refresh')
|
self.rpc_wallet('refresh')
|
||||||
balance_info = self.rpc_wallet('get_balance')
|
balance_info = self.rpc_wallet('get_balance')
|
||||||
|
|
||||||
rv['balance'] = self.format_amount(balance_info['unlocked_balance'])
|
rv['balance'] = self.format_amount(balance_info['unlocked_balance'])
|
||||||
rv['unconfirmed_balance'] = self.format_amount(balance_info['balance'] - 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
|
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])
|
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:
|
with self._mx_wallet:
|
||||||
self.openWallet(self._wallet_filename)
|
self.openWallet(self._wallet_filename)
|
||||||
self.rpc_wallet('refresh')
|
self.rpc_wallet('refresh')
|
||||||
|
@ -482,21 +483,28 @@ class XMRInterface(CoinInterface):
|
||||||
balance = self.rpc_wallet('get_balance')
|
balance = self.rpc_wallet('get_balance')
|
||||||
if balance['balance'] != balance['unlocked_balance']:
|
if balance['balance'] != balance['unlocked_balance']:
|
||||||
raise ValueError('Balance must be fully confirmed to use sweep all.')
|
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']))
|
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:
|
if self._fee_priority > 0:
|
||||||
params['priority'] = self._fee_priority
|
params['priority'] = self._fee_priority
|
||||||
rv = self.rpc_wallet('sweep_all', params)
|
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]
|
return rv['tx_hash_list'][0]
|
||||||
|
|
||||||
value_sats: int = make_int(value, self.exp())
|
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:
|
if self._fee_priority > 0:
|
||||||
params['priority'] = self._fee_priority
|
params['priority'] = self._fee_priority
|
||||||
rv = self.rpc_wallet('transfer', params)
|
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']
|
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):
|
def showLockTransfers(self, kbv, Kbs, restore_height):
|
||||||
with self._mx_wallet:
|
with self._mx_wallet:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -30,10 +30,15 @@
|
||||||
<p class="font-normal text-coolGray-200 dark:text-white pl-2 pt-5">Manage your {{ w.ticker }} wallet. {% if refresh %} (Page Refresh: {{ refresh }} seconds) {% endif %}</p>
|
<p class="font-normal text-coolGray-200 dark:text-white pl-2 pt-5">Manage your {{ w.ticker }} wallet. {% if refresh %} (Page Refresh: {{ refresh }} seconds) {% endif %}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
|
<div class="w-full md:w-1/2 p-3 p-6 container flex flex-wrap items-center justify-end items-center mx-auto">
|
||||||
|
{% if w.cid == '6' %} {# XMR #}
|
||||||
|
<button type="submit" form="main_form" class="flex flex-wrap justify-center px-4 py-2.5 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="forcerefresh" name="forcerefresh" value="Force Refresh">
|
||||||
|
{{ circular_arrows_svg | safe }} Force Refresh</button>
|
||||||
|
{% endif %} {# / XMR #}
|
||||||
<a class="rounded-full mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/wallet/{{ w.ticker }}">
|
<a class="rounded-full mr-5 flex flex-wrap justify-center px-5 py-3 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border dark:bg-gray-500 dark:hover:bg-gray-700 border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" id="refresh" href="/wallet/{{ w.ticker }}">
|
||||||
{{ circular_arrows_svg | safe }}<span>Refresh</span>
|
{{ circular_arrows_svg | safe }}<span>Refresh</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -102,7 +107,7 @@
|
||||||
|
|
||||||
{% else %}
|
{% else %}
|
||||||
|
|
||||||
<form method="post" autocomplete="off">
|
<form method="post" autocomplete="off" id="main_form">
|
||||||
<section>
|
<section>
|
||||||
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
|
<div class="pl-6 pr-6 pt-0 pb-0 mt-5 h-full overflow-hidden">
|
||||||
<div class="pb-6 border-coolGray-100">
|
<div class="pb-6 border-coolGray-100">
|
||||||
|
@ -393,6 +398,9 @@
|
||||||
<td class="py-3 px-6 bold">{{ w.fee_rate }}</td>
|
<td class="py-3 px-6 bold">{{ w.fee_rate }}</td>
|
||||||
<td class="py-3 px-6">
|
<td class="py-3 px-6">
|
||||||
<b>Est Fee:</b> {{ w.est_fee }}
|
<b>Est Fee:</b> {{ w.est_fee }}
|
||||||
|
{% if w.cid == '6' %} {# XMR #}
|
||||||
|
<button type="submit" class="flex flex-wrap justify-center py-2 px-4 bg-blue-500 hover:bg-blue-600 font-medium text-sm text-white border border-blue-500 rounded-md shadow-button focus:ring-0 focus:outline-none" name="estfee_{{ w.cid }}" value="Estimate Fee">Estimate Fee</button>
|
||||||
|
{% endif %} {# / XMR #}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
@ -133,27 +133,33 @@ def page_wallet(self, url_split, post_string):
|
||||||
page_data = {}
|
page_data = {}
|
||||||
messages = []
|
messages = []
|
||||||
err_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)
|
form_data = self.checkForm(post_string, 'wallet', err_messages)
|
||||||
if form_data:
|
if form_data:
|
||||||
cid = str(int(coin_id))
|
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)
|
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)
|
swap_client.cacheNewStealthAddressForCoin(coin_id)
|
||||||
elif bytes('reseed_' + cid, 'utf-8') in form_data:
|
elif have_data_entry(form_data, 'reseed_' + cid):
|
||||||
try:
|
try:
|
||||||
swap_client.reseedWallet(coin_id)
|
swap_client.reseedWallet(coin_id)
|
||||||
messages.append('Reseed complete ' + str(coin_id))
|
messages.append('Reseed complete ' + str(coin_id))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
err_messages.append('Reseed failed ' + str(ex))
|
err_messages.append('Reseed failed ' + str(ex))
|
||||||
swap_client.updateWalletsInfo(True, coin_id)
|
swap_client.updateWalletsInfo(True, coin_id)
|
||||||
elif bytes('withdraw_' + cid, 'utf-8') in form_data:
|
elif withdraw or estimate_fee:
|
||||||
subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
|
subfee = True if have_data_entry(form_data, 'subfee_' + cid) else False
|
||||||
page_data['wd_subfee_' + cid] = subfee
|
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
|
page_data['wd_sweepall_' + cid] = sweepall
|
||||||
value = None
|
value = None
|
||||||
if not sweepall:
|
if not sweepall:
|
||||||
|
@ -168,6 +174,13 @@ def page_wallet(self, url_split, post_string):
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
err_messages.append('Missing address')
|
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:
|
if coin_id == Coins.PART:
|
||||||
try:
|
try:
|
||||||
type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8')
|
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:
|
if len(err_messages) == 0:
|
||||||
ci = swap_client.ci(coin_id)
|
ci = swap_client.ci(coin_id)
|
||||||
ticker = ci.ticker()
|
ticker: str = ci.ticker()
|
||||||
try:
|
try:
|
||||||
if coin_id == Coins.PART:
|
if coin_id == Coins.PART:
|
||||||
txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
|
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)
|
txid = swap_client.withdrawLTC(type_from, value, address, subfee)
|
||||||
messages.append('Withdrew {} {} (from {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, address, txid))
|
messages.append('Withdrew {} {} (from {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, address, txid))
|
||||||
elif coin_id == Coins.XMR:
|
elif coin_id == Coins.XMR:
|
||||||
txid = swap_client.withdrawCoin(coin_id, value, address, sweepall)
|
if estimate_fee:
|
||||||
if sweepall:
|
fee_estimate = ci.estimateFee(value, address, sweepall)
|
||||||
messages.append('Swept all {} to address {}<br/>In txid: {}'.format(ticker, address, txid))
|
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:
|
else:
|
||||||
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
txid = swap_client.withdrawCoin(coin_id, value, address, sweepall)
|
||||||
|
if sweepall:
|
||||||
|
messages.append('Swept all {} to address {}<br/>In txid: {}'.format(ticker, address, txid))
|
||||||
|
else:
|
||||||
|
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
||||||
|
messages.append('Note: The wallet balance can take a while to update.')
|
||||||
else:
|
else:
|
||||||
txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
|
txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
|
||||||
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
|
||||||
|
if not estimate_fee:
|
||||||
|
withdrawal_successful = True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if swap_client.debug is True:
|
||||||
|
swap_client.log.error(traceback.format_exc())
|
||||||
err_messages.append(str(e))
|
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'):
|
elif have_data_entry(form_data, 'showutxogroups'):
|
||||||
show_utxo_groups = True
|
show_utxo_groups = True
|
||||||
elif have_data_entry(form_data, 'create_utxo'):
|
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
|
page_data['utxo_value'] = value
|
||||||
|
|
||||||
ci = swap_client.ci(coin_id)
|
ci = swap_client.ci(coin_id)
|
||||||
|
|
||||||
value_sats = ci.make_int(value)
|
value_sats = ci.make_int(value)
|
||||||
|
|
||||||
txid, address = ci.createUTXO(value_sats)
|
txid, address = ci.createUTXO(value_sats)
|
||||||
|
@ -224,7 +250,7 @@ def page_wallet(self, url_split, post_string):
|
||||||
if swap_client.debug is True:
|
if swap_client.debug is True:
|
||||||
swap_client.log.error(traceback.format_exc())
|
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})
|
wallets = swap_client.getCachedWalletsInfo({'coin_id': coin_id})
|
||||||
for k in wallets.keys():
|
for k in wallets.keys():
|
||||||
w = wallets[k]
|
w = wallets[k]
|
||||||
|
@ -265,17 +291,22 @@ def page_wallet(self, url_split, post_string):
|
||||||
if 'wd_type_to_' + cid in page_data:
|
if 'wd_type_to_' + cid in page_data:
|
||||||
wallet_data['wd_type_to'] = page_data['wd_type_to_' + cid]
|
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:
|
if 'utxo_value' in page_data:
|
||||||
wallet_data['utxo_value'] = page_data['utxo_value']
|
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:
|
if show_utxo_groups:
|
||||||
utxo_groups = ''
|
utxo_groups = ''
|
||||||
unspent_by_addr = ci.getUnspentsByAddr()
|
unspent_by_addr = ci.getUnspentsByAddr()
|
||||||
|
|
|
@ -18,7 +18,11 @@
|
||||||
- `rpctimeout`, `walletrpctimeout` and `walletrpctimeoutlong` in the Monero section of basicswap.json.
|
- `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.
|
- `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.
|
- 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
|
0.12.6
|
||||||
|
|
Loading…
Reference in a new issue