ui: Split wallet page

This commit is contained in:
tecnovert 2022-01-23 14:00:28 +02:00
parent 1c09a8b79e
commit f90a96d9ca
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
11 changed files with 344 additions and 76 deletions

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2021 tecnovert # Copyright (c) 2019-2022 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.
@ -326,6 +326,8 @@ class BasicSwap(BaseApp):
else: else:
self.thread_pool.shutdown() self.thread_pool.shutdown()
self.zmqContext.destroy()
close_all_sessions() close_all_sessions()
self.engine.dispose() self.engine.dispose()
@ -5260,7 +5262,10 @@ class BasicSwap(BaseApp):
# Requires? self.mxDB.acquire() # Requires? self.mxDB.acquire()
try: try:
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
inner_str = 'SELECT coin_id, MAX(created_at) as max_created_at FROM wallets GROUP BY coin_id' where_str = ''
if opts is not None and 'coin_id' in opts:
where_str = 'WHERE coin_id = {}'.format(opts['coin_id'])
inner_str = f'SELECT coin_id, MAX(created_at) as max_created_at FROM wallets {where_str} GROUP BY coin_id'
query_str = 'SELECT a.coin_id, wallet_data, created_at FROM wallets a, ({}) b WHERE a.coin_id = b.coin_id AND a.created_at = b.max_created_at'.format(inner_str) query_str = 'SELECT a.coin_id, wallet_data, created_at FROM wallets a, ({}) b WHERE a.coin_id = b.coin_id AND a.created_at = b.max_created_at'.format(inner_str)
q = session.execute(query_str) q = session.execute(query_str)
@ -5285,6 +5290,9 @@ class BasicSwap(BaseApp):
session.close() session.close()
session.remove() session.remove()
if opts is not None and 'coin_id' in opts:
return rv
for c in Coins: for c in Coins:
if c not in chainparams: if c not in chainparams:
continue continue

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2021 tecnovert # Copyright (c) 2019-2022 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.
@ -207,6 +207,20 @@ chainparams = {
} }
ticker_map = {}
for c, params in chainparams.items():
ticker_map[params['ticker'].lower()] = c
def getCoinIdFromTicker(ticker):
try:
return ticker_map[ticker.lower()]
except Exception:
raise ValueError('Unknown coin')
class CoinInterface: class CoinInterface:
def __init__(self, network): def __init__(self, network):
self.setDefaults() self.setDefaults()
@ -235,6 +249,10 @@ class CoinInterface:
ticker = 'rt' + ticker ticker = 'rt' + ticker
return ticker return ticker
def ticker_mainnet(self):
ticker = chainparams[self.coin_type()]['ticker']
return ticker
def min_amount(self): def min_amount(self):
return chainparams[self.coin_type()][self._network]['min_amount'] return chainparams[self.coin_type()][self._network]['min_amount']

View file

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2019-2021 tecnovert # Copyright (c) 2019-2022 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.
@ -17,11 +17,13 @@ from jinja2 import Environment, PackageLoader
from . import __version__ from . import __version__
from .util import ( from .util import (
dumpj, dumpj,
ensure,
format_timestamp, format_timestamp,
) )
from .chainparams import ( from .chainparams import (
chainparams,
Coins, Coins,
chainparams,
getCoinIdFromTicker,
) )
from .basicswap_util import ( from .basicswap_util import (
SwapTypes, SwapTypes,
@ -370,16 +372,12 @@ class HttpHandler(BaseHTTPRequestHandler):
continue continue
ci = swap_client.ci(k) ci = swap_client.ci(k)
fee_rate, fee_src = swap_client.getFeeRateForCoin(k)
est_fee = swap_client.estimateWithdrawFee(k, fee_rate)
cid = str(int(k)) cid = str(int(k))
wf = { wf = {
'name': w['name'], 'name': w['name'],
'version': w['version'], 'version': w['version'],
'ticker': ci.ticker_mainnet(),
'cid': cid, 'cid': cid,
'fee_rate': ci.format_amount(int(fee_rate * ci.COIN())),
'fee_rate_src': fee_src,
'est_fee': 'Unknown' if est_fee is None else ci.format_amount(int(est_fee * ci.COIN())),
'balance': w['balance'], 'balance': w['balance'],
'blocks': w['blocks'], 'blocks': w['blocks'],
'synced': w['synced'], 'synced': w['synced'],
@ -402,21 +400,6 @@ class HttpHandler(BaseHTTPRequestHandler):
if float(w['anon_pending']) > 0.0: if float(w['anon_pending']) > 0.0:
wf['anon_pending'] = w['anon_pending'] wf['anon_pending'] = w['anon_pending']
elif k == Coins.XMR:
wf['main_address'] = w.get('main_address', 'Refresh necessary')
if 'wd_type_from_' + cid in page_data:
wf['wd_type_from'] = page_data['wd_type_from_' + cid]
if 'wd_type_to_' + cid in page_data:
wf['wd_type_to'] = page_data['wd_type_to_' + cid]
if 'wd_value_' + cid in page_data:
wf['wd_value'] = page_data['wd_value_' + cid]
if 'wd_address_' + cid in page_data:
wf['wd_address'] = page_data['wd_address_' + cid]
if 'wd_subfee_' + cid in page_data:
wf['wd_subfee'] = page_data['wd_subfee_' + cid]
wallets_formatted.append(wf) wallets_formatted.append(wf)
template = env.get_template('wallets.html') template = env.get_template('wallets.html')
@ -428,6 +411,146 @@ class HttpHandler(BaseHTTPRequestHandler):
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
def page_wallet(self, url_split, post_string):
ensure(len(url_split) > 2, 'Wallet not specified')
wallet_ticker = url_split[2]
swap_client = self.server.swap_client
coin_id = getCoinIdFromTicker(wallet_ticker)
page_data = {}
messages = []
form_data = self.checkForm(post_string, 'settings', messages)
if form_data:
cid = str(int(coin_id))
if bytes('newaddr_' + cid, 'utf-8') in form_data:
swap_client.cacheNewAddressForCoin(coin_id)
elif bytes('reseed_' + cid, 'utf-8') in form_data:
try:
swap_client.reseedWallet(coin_id)
messages.append('Reseed complete ' + str(coin_id))
except Exception as ex:
messages.append('Reseed failed ' + str(ex))
swap_client.updateWalletsInfo(True, coin_id)
elif bytes('withdraw_' + cid, 'utf-8') in form_data:
try:
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
page_data['wd_value_' + cid] = value
except Exception as e:
messages.append('Error: Missing value')
try:
address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8')
page_data['wd_address_' + cid] = address
except Exception as e:
messages.append('Error: Missing address')
subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
page_data['wd_subfee_' + cid] = subfee
if coin_id == Coins.PART:
try:
type_from = form_data[bytes('withdraw_type_from_' + cid, 'utf-8')][0].decode('utf-8')
type_to = form_data[bytes('withdraw_type_to_' + cid, 'utf-8')][0].decode('utf-8')
page_data['wd_type_from_' + cid] = type_from
page_data['wd_type_to_' + cid] = type_to
except Exception as e:
messages.append('Error: Missing type')
if len(messages) == 0:
ci = swap_client.ci(coin_id)
ticker = ci.ticker()
if coin_id == Coins.PART:
try:
txid = swap_client.withdrawParticl(type_from, type_to, value, address, subfee)
messages.append('Withdrew {} {} ({} to {}) to address {}<br/>In txid: {}'.format(value, ticker, type_from, type_to, address, txid))
except Exception as e:
messages.append('Error: {}'.format(str(e)))
else:
try:
txid = swap_client.withdrawCoin(coin_id, value, address, subfee)
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
except Exception as e:
messages.append('Error: {}'.format(str(e)))
swap_client.updateWalletsInfo(True, coin_id)
swap_client.updateWalletsInfo()
wallets = swap_client.getCachedWalletsInfo({'coin_id': coin_id})
for k in wallets.keys():
w = wallets[k]
if 'error' in w:
wallet_data = {
'cid': str(int(k)),
'error': w['error']
}
continue
if 'balance' not in w:
wallet_data = {
'name': w['name'],
'havedata': False,
'updating': w['updating'],
}
continue
ci = swap_client.ci(k)
fee_rate, fee_src = swap_client.getFeeRateForCoin(k)
est_fee = swap_client.estimateWithdrawFee(k, fee_rate)
cid = str(int(k))
wallet_data = {
'name': w['name'],
'version': w['version'],
'ticker': ci.ticker_mainnet(),
'cid': cid,
'fee_rate': ci.format_amount(int(fee_rate * ci.COIN())),
'fee_rate_src': fee_src,
'est_fee': 'Unknown' if est_fee is None else ci.format_amount(int(est_fee * ci.COIN())),
'balance': w['balance'],
'blocks': w['blocks'],
'synced': w['synced'],
'deposit_address': w['deposit_address'],
'expected_seed': w['expected_seed'],
'balance_all': float(w['balance']) + float(w['unconfirmed']),
'updating': w['updating'],
'lastupdated': format_timestamp(w['lastupdated']),
'havedata': True,
}
if float(w['unconfirmed']) > 0.0:
wallet_data['unconfirmed'] = w['unconfirmed']
if k == Coins.PART:
wallet_data['stealth_address'] = w['stealth_address']
wallet_data['blind_balance'] = w['blind_balance']
if float(w['blind_unconfirmed']) > 0.0:
wallet_data['blind_unconfirmed'] = w['blind_unconfirmed']
wallet_data['anon_balance'] = w['anon_balance']
if float(w['anon_pending']) > 0.0:
wallet_data['anon_pending'] = w['anon_pending']
elif k == Coins.XMR:
wallet_data['main_address'] = w.get('main_address', 'Refresh necessary')
if 'wd_type_from_' + cid in page_data:
wallet_data['wd_type_from'] = page_data['wd_type_from_' + cid]
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]
template = env.get_template('wallet.html')
return bytes(template.render(
title=self.server.title,
h2=self.server.title,
messages=messages,
w=wallet_data,
form_id=os.urandom(8).hex(),
), 'UTF-8')
def page_settings(self, url_split, post_string): def page_settings(self, url_split, post_string):
swap_client = self.server.swap_client swap_client = self.server.swap_client
@ -764,7 +887,7 @@ class HttpHandler(BaseHTTPRequestHandler):
), 'UTF-8') ), 'UTF-8')
def page_offer(self, url_split, post_string): def page_offer(self, url_split, post_string):
assert(len(url_split) > 2), 'Offer ID not specified' ensure(len(url_split) > 2, 'Offer ID not specified')
try: try:
offer_id = bytes.fromhex(url_split[2]) offer_id = bytes.fromhex(url_split[2])
assert(len(offer_id) == 28) assert(len(offer_id) == 28)
@ -772,7 +895,7 @@ class HttpHandler(BaseHTTPRequestHandler):
raise ValueError('Bad offer ID') raise ValueError('Bad offer ID')
swap_client = self.server.swap_client swap_client = self.server.swap_client
offer, xmr_offer = swap_client.getXmrOffer(offer_id) offer, xmr_offer = swap_client.getXmrOffer(offer_id)
assert(offer), 'Unknown offer ID' ensure(offer, 'Unknown offer ID')
extend_data = { # Defaults extend_data = { # Defaults
'nb_validmins': 10, 'nb_validmins': 10,
@ -928,11 +1051,11 @@ class HttpHandler(BaseHTTPRequestHandler):
if have_data_entry(form_data, 'sort_by'): if have_data_entry(form_data, 'sort_by'):
sort_by = get_data_entry(form_data, 'sort_by') sort_by = get_data_entry(form_data, 'sort_by')
assert(sort_by in ['created_at', 'rate']), 'Invalid sort by' ensure(sort_by in ['created_at', 'rate'], 'Invalid sort by')
filters['sort_by'] = sort_by filters['sort_by'] = sort_by
if have_data_entry(form_data, 'sort_dir'): if have_data_entry(form_data, 'sort_dir'):
sort_dir = get_data_entry(form_data, 'sort_dir') sort_dir = get_data_entry(form_data, 'sort_dir')
assert(sort_dir in ['asc', 'desc']), 'Invalid sort dir' ensure(sort_dir in ['asc', 'desc'], 'Invalid sort dir')
filters['sort_dir'] = sort_dir filters['sort_dir'] = sort_dir
if form_data and have_data_entry(form_data, 'pageback'): if form_data and have_data_entry(form_data, 'pageback'):
@ -973,7 +1096,7 @@ class HttpHandler(BaseHTTPRequestHandler):
), 'UTF-8') ), 'UTF-8')
def page_bid(self, url_split, post_string): def page_bid(self, url_split, post_string):
assert(len(url_split) > 2), 'Bid ID not specified' ensure(len(url_split) > 2, 'Bid ID not specified')
try: try:
bid_id = bytes.fromhex(url_split[2]) bid_id = bytes.fromhex(url_split[2])
assert(len(bid_id) == 28) assert(len(bid_id) == 28)
@ -1023,7 +1146,7 @@ class HttpHandler(BaseHTTPRequestHandler):
show_lock_transfers = True show_lock_transfers = True
bid, xmr_swap, offer, xmr_offer, events = swap_client.getXmrBidAndOffer(bid_id) bid, xmr_swap, offer, xmr_offer, events = swap_client.getXmrBidAndOffer(bid_id)
assert(bid), 'Unknown bid ID' ensure(bid, 'Unknown bid ID')
data = describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, events, edit_bid, show_txns, view_tx_ind, show_lock_transfers=show_lock_transfers) data = describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, events, edit_bid, show_txns, view_tx_ind, show_lock_transfers=show_lock_transfers)
@ -1077,11 +1200,11 @@ class HttpHandler(BaseHTTPRequestHandler):
if form_data and have_data_entry(form_data, 'applyfilters'): if form_data and have_data_entry(form_data, 'applyfilters'):
if have_data_entry(form_data, 'sort_by'): if have_data_entry(form_data, 'sort_by'):
sort_by = get_data_entry(form_data, 'sort_by') sort_by = get_data_entry(form_data, 'sort_by')
assert(sort_by in ['created_at', ]), 'Invalid sort by' ensure(sort_by in ['created_at', ], 'Invalid sort by')
filters['sort_by'] = sort_by filters['sort_by'] = sort_by
if have_data_entry(form_data, 'sort_dir'): if have_data_entry(form_data, 'sort_dir'):
sort_dir = get_data_entry(form_data, 'sort_dir') sort_dir = get_data_entry(form_data, 'sort_dir')
assert(sort_dir in ['asc', 'desc']), 'Invalid sort dir' ensure(sort_dir in ['asc', 'desc'], 'Invalid sort dir')
filters['sort_dir'] = sort_dir filters['sort_dir'] = sort_dir
if form_data and have_data_entry(form_data, 'pageback'): if form_data and have_data_entry(form_data, 'pageback'):
@ -1144,7 +1267,7 @@ class HttpHandler(BaseHTTPRequestHandler):
edit_address_id = int(form_data[b'edit_address_id'][0].decode('utf-8')) edit_address_id = int(form_data[b'edit_address_id'][0].decode('utf-8'))
edit_addr = form_data[b'edit_address'][0].decode('utf-8') edit_addr = form_data[b'edit_address'][0].decode('utf-8')
active_ind = int(form_data[b'active_ind'][0].decode('utf-8')) active_ind = int(form_data[b'active_ind'][0].decode('utf-8'))
assert(active_ind == 0 or active_ind == 1), 'Invalid sort by' ensure(active_ind in (0, 1), 'Invalid sort by')
addressnote = '' if b'addressnote' not in form_data else form_data[b'addressnote'][0].decode('utf-8') addressnote = '' if b'addressnote' not in form_data else form_data[b'addressnote'][0].decode('utf-8')
if not validateTextInput(addressnote, 'Address note', messages, max_length=30): if not validateTextInput(addressnote, 'Address note', messages, max_length=30):
listaddresses = False listaddresses = False
@ -1196,7 +1319,7 @@ class HttpHandler(BaseHTTPRequestHandler):
), 'UTF-8') ), 'UTF-8')
def page_identity(self, url_split, post_string): def page_identity(self, url_split, post_string):
assert(len(url_split) > 2), 'Address not specified' ensure(len(url_split) > 2, 'Address not specified')
identity_address = url_split[2] identity_address = url_split[2]
swap_client = self.server.swap_client swap_client = self.server.swap_client
@ -1333,6 +1456,8 @@ class HttpHandler(BaseHTTPRequestHandler):
return self.page_active(url_split, post_string) return self.page_active(url_split, post_string)
if url_split[1] == 'wallets': if url_split[1] == 'wallets':
return self.page_wallets(url_split, post_string) return self.page_wallets(url_split, post_string)
if url_split[1] == 'wallet':
return self.page_wallet(url_split, post_string)
if url_split[1] == 'settings': if url_split[1] == 'settings':
return self.page_settings(url_split, post_string) return self.page_settings(url_split, post_string)
if url_split[1] == 'rpc': if url_split[1] == 'rpc':

View file

@ -0,0 +1,82 @@
{% include 'header.html' %}
<p><a id="refresh" href="/wallet/{{ w.ticker }}">refresh</a></p>
<p><a id="back" href="/wallets">back</a></p>
<h3>{{ w.name }} Wallet</h3>
{% if refresh %}
<p>Page Refresh: {{ refresh }} seconds</p>
{% endif %}
{% for m in messages %}
<p>{{ m }}</p>
{% endfor %}
<form method="post">
{% if w.updating %}
<h5>Updating</h5>
{% endif %}
{% if w.havedata %}
{% if w.error %}
<p>Error: {{ w.error }}</p>
{% else %}
<table>
<tr><td>Last updated:</td><td>{{ w.lastupdated }}</td></tr>
<tr><td>Version:</td><td>{{ w.version }}</td></tr>
<tr><td>Balance:</td><td>{{ w.balance }}</td>{% if w.unconfirmed %}<td>Unconfirmed:</td><td>{{ w.unconfirmed }}</td>{% endif %}</tr>
{% if w.cid == '1' %}
<tr><td>Blind Balance:</td><td>{{ w.blind_balance }}</td>{% if w.blind_unconfirmed %}<td>Blind Unconfirmed:</td><td>{{ w.blind_unconfirmed }}</td>{% endif %}</tr>
<tr><td>Anon Balance:</td><td>{{ w.anon_balance }}</td>{% if w.anon_pending %}<td>Anon Pending:</td><td>{{ w.anon_pending }}</td>{% endif %}</tr>
{% endif %}
<tr><td>Blocks:</td><td>{{ w.blocks }}</td></tr>
<tr><td>Synced:</td><td>{{ w.synced }}</td></tr>
<tr><td>Expected Seed:</td><td>{{ w.expected_seed }}</td>{% if w.expected_seed != true %}<td><input type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="return confirmReseed();"></td>{% endif %}</tr>
{% if w.cid == '1' %}
<tr><td>Stealth Address</td><td colspan=2>{{ w.stealth_address }}</td></tr>
{% endif %}
{% if w.cid == '6' %}
<tr><td>Main Address</td><td colspan=2>{{ w.main_address }}</td></tr>
<tr><td><input type="submit" name="newaddr_{{ w.cid }}" value="New Subaddress"></td><td colspan=2>{{ w.deposit_address }}</td></tr>
{% else %}
<tr><td><input type="submit" name="newaddr_{{ w.cid }}" value="New Deposit Address"></td><td colspan=2>{{ w.deposit_address }}</td></tr>
{% endif %}
<tr><td><input type="submit" name="withdraw_{{ w.cid }}" value="Withdraw" onclick="return confirmWithdrawal();"></td><td>Amount: <input type="text" name="amt_{{ w.cid }}" value="{{ w.wd_value }}"></td><td>Address: <input type="text" name="to_{{ w.cid }}" value="{{ w.wd_address }}"></td><td>Subtract fee: <input type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked="true"{% endif %}></td></tr>
{% if w.cid == '1' %}
<tr><td>Type From, To</td><td>
<select name="withdraw_type_from_{{ w.cid }}">
<option value="plain"{% if w.wd_type_from == 'plain' %} selected{% endif %}>Plain</option>
<option value="blind"{% if w.wd_type_from == 'blind' %} selected{% endif %}>Blind</option>
<option value="anon"{% if w.wd_type_from == 'anon' %} selected{% endif %}>Anon</option>
</select>
<select name="withdraw_type_to_{{ w.cid }}">
<option value="plain"{% if w.wd_type_to == 'plain' %} selected{% endif %}>Plain</option>
<option value="blind"{% if w.wd_type_to == 'blind' %} selected{% endif %}>Blind</option>
<option value="anon"{% if w.wd_type_to == 'anon' %} selected{% endif %}>Anon</option>
</select></td></tr>
{% endif %}
<tr><td>Fee Rate:</td><td>{{ w.fee_rate }}</td><td>Est Fee:</td><td>{{ w.est_fee }}</td></tr>
</table>
{% endif %}
{% endif %} <!-- havedata -->
<input type="hidden" name="formid" value="{{ form_id }}">
</form>
<p><a href="/">home</a></p>
<script>
function confirmReseed() {
return confirm("Are you sure?\nBackup your wallet before and after.\nWon't detect used keys.\nShould only be used for new wallets.");
}
function confirmWithdrawal() {
return confirm("Are you sure?");
}
</script>
</body></html>

View file

@ -1,6 +1,6 @@
{% include 'header.html' %} {% include 'header.html' %}
<p><a href="/wallets">refresh</a></p> <p><a id="refresh" href="/wallets">refresh</a></p>
<h3>Wallets</h3> <h3>Wallets</h3>
{% if refresh %} {% if refresh %}
@ -35,31 +35,8 @@
<tr><td>Blocks:</td><td>{{ w.blocks }}</td></tr> <tr><td>Blocks:</td><td>{{ w.blocks }}</td></tr>
<tr><td>Synced:</td><td>{{ w.synced }}</td></tr> <tr><td>Synced:</td><td>{{ w.synced }}</td></tr>
<tr><td>Expected Seed:</td><td>{{ w.expected_seed }}</td>{% if w.expected_seed != true %}<td><input type="submit" name="reseed_{{ w.cid }}" value="Reseed wallet" onclick="return confirmReseed();"></td>{% endif %}</tr> <tr><td>Expected Seed:</td><td>{{ w.expected_seed }}</td></tr>
{% if w.cid == '1' %} <tr><td><a href="/wallet/{{ w.ticker }}">Manage</a></td></tr>
<tr><td>Stealth Address</td><td colspan=2>{{ w.stealth_address }}</td></tr>
{% endif %}
{% if w.cid == '6' %}
<tr><td>Main Address</td><td colspan=2>{{ w.main_address }}</td></tr>
<tr><td><input type="submit" name="newaddr_{{ w.cid }}" value="New Subaddress"></td><td colspan=2>{{ w.deposit_address }}</td></tr>
{% else %}
<tr><td><input type="submit" name="newaddr_{{ w.cid }}" value="New Deposit Address"></td><td colspan=2>{{ w.deposit_address }}</td></tr>
{% endif %}
<tr><td><input type="submit" name="withdraw_{{ w.cid }}" value="Withdraw" onclick="return confirmWithdrawal();"></td><td>Amount: <input type="text" name="amt_{{ w.cid }}" value="{{ w.wd_value }}"></td><td>Address: <input type="text" name="to_{{ w.cid }}" value="{{ w.wd_address }}"></td><td>Subtract fee: <input type="checkbox" name="subfee_{{ w.cid }}" {% if w.wd_subfee==true %} checked="true"{% endif %}></td></tr>
{% if w.cid == '1' %}
<tr><td>Type From, To</td><td>
<select name="withdraw_type_from_{{ w.cid }}">
<option value="plain"{% if w.wd_type_from == 'plain' %} selected{% endif %}>Plain</option>
<option value="blind"{% if w.wd_type_from == 'blind' %} selected{% endif %}>Blind</option>
<option value="anon"{% if w.wd_type_from == 'anon' %} selected{% endif %}>Anon</option>
</select>
<select name="withdraw_type_to_{{ w.cid }}">
<option value="plain"{% if w.wd_type_to == 'plain' %} selected{% endif %}>Plain</option>
<option value="blind"{% if w.wd_type_to == 'blind' %} selected{% endif %}>Blind</option>
<option value="anon"{% if w.wd_type_to == 'anon' %} selected{% endif %}>Anon</option>
</select></td></tr>
{% endif %}
<tr><td>Fee Rate:</td><td>{{ w.fee_rate }}</td><td>Est Fee:</td><td>{{ w.est_fee }}</td></tr>
</table> </table>
{% endif %} {% endif %}
{% endif %} <!-- havedata --> {% endif %} <!-- havedata -->

View file

@ -12,6 +12,7 @@ import mmap
import stat import stat
import gnupg import gnupg
import signal import signal
import socket
import hashlib import hashlib
import tarfile import tarfile
import zipfile import zipfile
@ -114,7 +115,12 @@ def downloadFile(url, path):
opener = urllib.request.build_opener() opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')] opener.addheaders = [('User-agent', 'Mozilla/5.0')]
urllib.request.install_opener(opener) urllib.request.install_opener(opener)
# Set one second timeout for urlretrieve connections
old_timeout = socket.getdefaulttimeout()
socket.setdefaulttimeout(1)
urlretrieve(url, path, make_reporthook()) urlretrieve(url, path, make_reporthook())
socket.setdefaulttimeout(old_timeout)
def extractCore(coin, version_pair, settings, bin_dir, release_path): def extractCore(coin, version_pair, settings, bin_dir, release_path):

View file

@ -158,7 +158,7 @@ def runClient(fp, data_dir, chain):
swap_client.start() swap_client.start()
if 'htmlhost' in settings: if 'htmlhost' in settings:
swap_client.log.info('Starting server at %s:%d.' % (settings['htmlhost'], settings['htmlport'])) swap_client.log.info('Starting server at http://%s:%d.' % (settings['htmlhost'], settings['htmlport']))
allow_cors = settings['allowcors'] if 'allowcors' in settings else cfg.DEFAULT_ALLOW_CORS allow_cors = settings['allowcors'] if 'allowcors' in settings else cfg.DEFAULT_ALLOW_CORS
tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'], allow_cors, swap_client) tS1 = HttpThread(fp, settings['htmlhost'], settings['htmlport'], allow_cors, swap_client)
threads.append(tS1) threads.append(tS1)

View file

@ -7,9 +7,9 @@
import os import os
import json import json
import urllib
import signal import signal
import logging import logging
import urllib
from urllib.request import urlopen from urllib.request import urlopen
from basicswap.rpc import callrpc from basicswap.rpc import callrpc

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2020-2021 tecnovert # Copyright (c) 2020-2022 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.
@ -149,18 +149,18 @@ class XmrTestBase(unittest.TestCase):
waitForServer(self.delay_event, 12701) waitForServer(self.delay_event, 12701)
def waitForDepositAddress(): def waitForMainAddress():
for i in range(20): for i in range(20):
if self.delay_event.is_set(): if self.delay_event.is_set():
raise ValueError('Test stopped.') raise ValueError('Test stopped.')
try: try:
wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read())
return wallets['6']['deposit_address'] return wallets['6']['main_address']
except Exception as e: except Exception as e:
print('Waiting for deposit address {}'.format(str(e))) print('Waiting for main address {}'.format(str(e)))
self.delay_event.wait(1) self.delay_event.wait(1)
raise ValueError('waitForDepositAddress timedout') raise ValueError('waitForMainAddress timedout')
xmr_addr1 = waitForDepositAddress() xmr_addr1 = waitForMainAddress()
num_blocks = 100 num_blocks = 100
@ -178,11 +178,15 @@ class XmrTestBase(unittest.TestCase):
for i in range(60): for i in range(60):
if self.delay_event.is_set(): if self.delay_event.is_set():
raise ValueError('Test stopped.') raise ValueError('Test stopped.')
wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read()) try:
particl_blocks = wallets['1']['blocks'] wallets = json.loads(urlopen('http://127.0.0.1:12701/json/wallets').read())
print('particl_blocks', particl_blocks) particl_blocks = wallets['1']['blocks']
if particl_blocks >= num_blocks: print('particl_blocks', particl_blocks)
break if particl_blocks >= num_blocks:
break
except Exception as e:
print('Error reading wallets', str(e))
self.delay_event.wait(1) self.delay_event.wait(1)
assert(particl_blocks >= num_blocks) assert(particl_blocks >= num_blocks)

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Copyright (c) 2021 tecnovert # Copyright (c) 2021-2022 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.
@ -266,7 +266,7 @@ class Test(unittest.TestCase):
wallets = json.loads(urlopen('http://127.0.0.1:{}/json/wallets'.format(UI_PORT + 1)).read()) wallets = json.loads(urlopen('http://127.0.0.1:{}/json/wallets'.format(UI_PORT + 1)).read())
self.xmr_addr = wallets['6']['deposit_address'] self.xmr_addr = wallets['6']['main_address']
num_blocks = 100 num_blocks = 100
if callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks: if callrpc_xmr_na(XMR_BASE_RPC_PORT + 1, 'get_block_count')['count'] < num_blocks:
logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, self.xmr_addr)) logging.info('Mining {} Monero blocks to {}.'.format(num_blocks, self.xmr_addr))

View file

@ -0,0 +1,48 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2022 tecnovert
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""
cd /tmp
wget -4 https://chromedriver.storage.googleapis.com/96.0.4664.45/chromedriver_linux64.zip
7z x chromedriver_linux64.zip
sudo mv chromedriver /opt/chromedriver96
python tests/basicswap/extended/test_xmr_persistent.py
python tests/basicswap/selenium/test_wallets.py
html = driver.page_source
print('html', html)
"""
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
def test_html():
base_url = 'http://localhost:12701'
driver = webdriver.Chrome(service=Service('/opt/chromedriver96'))
url = base_url + '/wallets'
driver.get(url)
time.sleep(1)
driver.refresh()
driver.find_element(By.ID, "refresh").click()
time.sleep(1)
driver.refresh()
driver.close()
if __name__ == '__main__':
test_html()