ui: Display count of locked UTXOs on wallet page.
This commit is contained in:
parent
30a5ea1652
commit
9ee6669179
@ -6522,6 +6522,9 @@ class BasicSwap(BaseApp):
|
|||||||
'locked': walletinfo['locked'],
|
'locked': walletinfo['locked'],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if 'locked_utxos' in walletinfo:
|
||||||
|
rv['locked_utxos'] = walletinfo['locked_utxos']
|
||||||
|
|
||||||
if coin == Coins.PART:
|
if coin == Coins.PART:
|
||||||
rv['stealth_address'] = self.getCachedStealthAddressForCoin(Coins.PART)
|
rv['stealth_address'] = self.getCachedStealthAddressForCoin(Coins.PART)
|
||||||
rv['anon_balance'] = walletinfo['anon_balance']
|
rv['anon_balance'] = walletinfo['anon_balance']
|
||||||
|
@ -300,6 +300,7 @@ class BTCInterface(CoinInterface):
|
|||||||
rv = self.rpc_wallet('getwalletinfo')
|
rv = self.rpc_wallet('getwalletinfo')
|
||||||
rv['encrypted'] = 'unlocked_until' in rv
|
rv['encrypted'] = 'unlocked_until' in rv
|
||||||
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
||||||
|
rv['locked_utxos'] = len(self.rpc_wallet('listlockunspent'))
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def walletRestoreHeight(self) -> int:
|
def walletRestoreHeight(self) -> int:
|
||||||
|
@ -33,9 +33,7 @@ class LTCInterface(BTCInterface):
|
|||||||
return self.rpc_wallet('sendtoaddress', params)
|
return self.rpc_wallet('sendtoaddress', params)
|
||||||
|
|
||||||
def getWalletInfo(self):
|
def getWalletInfo(self):
|
||||||
rv = self.rpc_wallet('getwalletinfo')
|
rv = super(LTCInterface, self).getWalletInfo()
|
||||||
rv['encrypted'] = 'unlocked_until' in rv
|
|
||||||
rv['locked'] = rv.get('unlocked_until', 1) <= 0
|
|
||||||
|
|
||||||
mweb_info = self.rpc_wallet_mweb('getwalletinfo')
|
mweb_info = self.rpc_wallet_mweb('getwalletinfo')
|
||||||
rv['mweb_balance'] = mweb_info['balance']
|
rv['mweb_balance'] = mweb_info['balance']
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2020-2023 tecnovert
|
# Copyright (c) 2020-2024 tecnovert
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@
|
|||||||
<div class="px-6">
|
<div class="px-6">
|
||||||
<div class="flex flex-wrap justify-end">
|
<div class="flex flex-wrap justify-end">
|
||||||
<div class="w-full md:w-auto p-1.5 ml-2">
|
<div class="w-full md:w-auto p-1.5 ml-2">
|
||||||
<button name="" value="Apply" type="submit" class="flex flex-wrap justify-center w-full 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">
|
<button name="apply" value="Apply" type="submit" class="flex flex-wrap justify-center w-full 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">
|
||||||
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
<svg class="text-gray-500 w-5 h-5 mr-2" xmlns="http://www.w3.org/2000/svg" height="24" width="24" viewBox="0 0 24 24">
|
||||||
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
|
<g stroke-linecap="round" stroke-width="2" fill="none" stroke="#ffffff" stroke-linejoin="round">
|
||||||
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
|
<polyline points=" 6,12 10,16 18,8 " stroke="#ffffff"></polyline>
|
||||||
@ -160,7 +160,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
<tr class="opacity-100 text-gray-500 dark:text-gray-100">
|
||||||
<td class="py-3 px-6">
|
<td class="py-3 px-6">
|
||||||
<textarea class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" rows="20">{{ result }}</textarea>
|
<textarea name="result" class="hover:border-blue-500 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-50 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 focus:ring-0" rows="20">{{ result }}</textarea>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -172,6 +172,12 @@
|
|||||||
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }} (<span class="usd-value"></span>) {% if w.mweb_pending %} <span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Pending: +{{ w.mweb_pending }} {{ w.ticker }}</span>{% endif %}</td>
|
<td class="py-3 px-6 bold coinname-value" data-coinname="{{ w.name }}">{{ w.mweb_balance }} {{ w.ticker }} (<span class="usd-value"></span>) {% if w.mweb_pending %} <span class="inline-block py-1 px-2 rounded-full bg-green-100 text-green-500 dark:bg-gray-500 dark:text-green-500">Pending: +{{ w.mweb_pending }} {{ w.ticker }}</span>{% endif %}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %} {# / LTC #}
|
{% endif %} {# / LTC #}
|
||||||
|
{% if w.locked_utxos %}
|
||||||
|
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
||||||
|
<td class="py-3 px-6 bold">Locked Outputs:</td>
|
||||||
|
<td id='locked_utxos' class="py-3 px-6">{{ w.locked_utxos }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %} {# / locked_utxos #}
|
||||||
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
<tr class="opacity-100 text-gray-500 dark:text-gray-100 hover:bg-coolGray-200 dark:hover:bg-gray-600">
|
||||||
<td class="py-3 px-6 bold">Blocks:</td>
|
<td class="py-3 px-6 bold">Blocks:</td>
|
||||||
<td class="py-3 px-6">{{ w.blocks }} {% if w.known_block_count %} / {{ w.known_block_count }} {% endif %}</td>
|
<td class="py-3 px-6">{{ w.blocks }} {% if w.known_block_count %} / {{ w.known_block_count }} {% endif %}</td>
|
||||||
|
@ -41,6 +41,8 @@ def format_wallet_data(swap_client, ci, w):
|
|||||||
wf['bootstrapping'] = True
|
wf['bootstrapping'] = True
|
||||||
if 'known_block_count' in w:
|
if 'known_block_count' in w:
|
||||||
wf['known_block_count'] = w['known_block_count']
|
wf['known_block_count'] = w['known_block_count']
|
||||||
|
if 'locked_utxos' in w:
|
||||||
|
wf['locked_utxos'] = w['locked_utxos']
|
||||||
|
|
||||||
if 'balance' in w and 'unconfirmed' in w:
|
if 'balance' in w and 'unconfirmed' in w:
|
||||||
wf['balance_all'] = float(w['balance']) + float(w['unconfirmed'])
|
wf['balance_all'] = float(w['balance']) + float(w['unconfirmed'])
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2022-2023 tecnovert
|
# Copyright (c) 2022-2024 tecnovert
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@ -10,7 +10,9 @@ import time
|
|||||||
|
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
from selenium.webdriver.common.by import By
|
from selenium.webdriver.common.by import By
|
||||||
|
from selenium.webdriver.support.select import Select
|
||||||
from util import get_driver
|
from util import get_driver
|
||||||
|
from basicswap.util import dumpje
|
||||||
|
|
||||||
|
|
||||||
def test_wallets(driver):
|
def test_wallets(driver):
|
||||||
@ -72,6 +74,50 @@ def test_wallets(driver):
|
|||||||
e = elements[0]
|
e = elements[0]
|
||||||
assert ('Withdrew 10 rtPART (plain to plain) to address' in e.text)
|
assert ('Withdrew 10 rtPART (plain to plain) to address' in e.text)
|
||||||
|
|
||||||
|
print('Locking UTXO')
|
||||||
|
driver.get(base_url + '/rpc')
|
||||||
|
el = driver.find_element(By.NAME, 'coin_type')
|
||||||
|
for option in el.find_elements(By.TAG_NAME, 'option'):
|
||||||
|
if option.text == 'Particl':
|
||||||
|
option.click()
|
||||||
|
break
|
||||||
|
driver.find_element(By.NAME, 'cmd').send_keys('listunspent')
|
||||||
|
driver.find_element(By.NAME, 'apply').click()
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
text_value = driver.find_element(By.NAME, 'result').text
|
||||||
|
utxos = json.loads(text_value.split('\n', 1)[1])
|
||||||
|
|
||||||
|
lock_utxos = [{'txid': utxos[0]['txid'], 'vout': utxos[0]['vout']}]
|
||||||
|
driver.find_element(By.NAME, 'cmd').send_keys('lockunspent false "{}"'.format(dumpje(lock_utxos)))
|
||||||
|
driver.find_element(By.NAME, 'apply').click()
|
||||||
|
|
||||||
|
print('Check for locked UTXO count')
|
||||||
|
driver.get(base_url + '/wallet/PART')
|
||||||
|
found = False
|
||||||
|
for i in range(5):
|
||||||
|
try:
|
||||||
|
el = driver.find_element(By.ID, 'locked_utxos')
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
driver.find_element(By.ID, 'refresh').click()
|
||||||
|
time.sleep(2)
|
||||||
|
found = True
|
||||||
|
assert (found)
|
||||||
|
driver.refresh()
|
||||||
|
|
||||||
|
print('Unlocking UTXO')
|
||||||
|
driver.get(base_url + '/rpc')
|
||||||
|
el = driver.find_element(By.NAME, 'coin_type')
|
||||||
|
for option in el.find_elements(By.TAG_NAME, 'option'):
|
||||||
|
if option.text == 'Particl':
|
||||||
|
option.click()
|
||||||
|
break
|
||||||
|
driver.find_element(By.NAME, 'cmd').send_keys('lockunspent true "{}"'.format(dumpje(lock_utxos)))
|
||||||
|
driver.find_element(By.NAME, 'apply').click()
|
||||||
|
|
||||||
print('Test Passed!')
|
print('Test Passed!')
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,6 +182,9 @@ class Test(BaseTest):
|
|||||||
sx_addr = read_json_api(1800, 'wallets/part/newstealthaddress')
|
sx_addr = read_json_api(1800, 'wallets/part/newstealthaddress')
|
||||||
assert (callnoderpc(0, 'getaddressinfo', [sx_addr, ])['isstealthaddress'] is True)
|
assert (callnoderpc(0, 'getaddressinfo', [sx_addr, ])['isstealthaddress'] is True)
|
||||||
|
|
||||||
|
rv = read_json_api(1800, 'wallets/part')
|
||||||
|
assert ('locked_utxos' in rv)
|
||||||
|
|
||||||
def test_004_validateSwapType(self):
|
def test_004_validateSwapType(self):
|
||||||
logging.info('---------- Test validateSwapType')
|
logging.info('---------- Test validateSwapType')
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2020-2023 tecnovert
|
# Copyright (c) 2020-2024 tecnovert
|
||||||
# Distributed under the MIT software license, see the accompanying
|
# Distributed under the MIT software license, see the accompanying
|
||||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
@ -107,6 +107,7 @@ XMR_BASE_RPC_PORT = 21792
|
|||||||
XMR_BASE_ZMQ_PORT = 22792
|
XMR_BASE_ZMQ_PORT = 22792
|
||||||
XMR_BASE_WALLET_RPC_PORT = 23792
|
XMR_BASE_WALLET_RPC_PORT = 23792
|
||||||
|
|
||||||
|
signal_event = threading.Event() # Set if test was cancelled
|
||||||
test_delay_event = threading.Event()
|
test_delay_event = threading.Event()
|
||||||
RESET_TEST = make_boolean(os.getenv('RESET_TEST', 'true'))
|
RESET_TEST = make_boolean(os.getenv('RESET_TEST', 'true'))
|
||||||
|
|
||||||
@ -255,6 +256,7 @@ def ltcCli(cmd, node_id=0):
|
|||||||
|
|
||||||
def signal_handler(sig, frame):
|
def signal_handler(sig, frame):
|
||||||
logging.info('signal {} detected.'.format(sig))
|
logging.info('signal {} detected.'.format(sig))
|
||||||
|
signal_event.set()
|
||||||
test_delay_event.set()
|
test_delay_event.set()
|
||||||
|
|
||||||
|
|
||||||
@ -336,6 +338,8 @@ class BaseTest(unittest.TestCase):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
|
if signal_event.is_set():
|
||||||
|
raise ValueError('Test has been cancelled.')
|
||||||
test_delay_event.clear()
|
test_delay_event.clear()
|
||||||
random.seed(time.time())
|
random.seed(time.time())
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user