From 1ee2db137ba83c7e100b1913c7ffbc9773ef95e7 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Sun, 31 Jul 2022 23:40:58 +0200 Subject: [PATCH] ui: Expose min bid amount. --- basicswap/http_server.py | 5 ++++ basicswap/static/css/simple/style.css | 10 +++++++ basicswap/static/js/new_offer.js | 27 +++++++++++++++++ basicswap/templates/header.html | 3 +- basicswap/templates/offer.html | 4 +++ basicswap/templates/offer_confirm.html | 5 ++++ basicswap/templates/offer_new_1.html | 8 +++-- basicswap/templates/offer_new_2.html | 5 ++++ basicswap/ui/page_offers.py | 41 ++++++++++++++++++-------- doc/install.md | 4 +-- 10 files changed, 95 insertions(+), 17 deletions(-) create mode 100644 basicswap/static/js/new_offer.js diff --git a/basicswap/http_server.py b/basicswap/http_server.py index 593f61a..7e3f5b6 100644 --- a/basicswap/http_server.py +++ b/basicswap/http_server.py @@ -704,6 +704,11 @@ class HttpHandler(BaseHTTPRequestHandler): with open(os.path.join(static_path, 'css', filename), 'rb') as fp: self.putHeaders(status_code, 'text/css; charset=utf-8') return fp.read() + elif len(url_split) > 3 and url_split[2] == 'js': + filename = os.path.join(*url_split[3:]) + with open(os.path.join(static_path, 'js', filename), 'rb') as fp: + self.putHeaders(status_code, 'application/javascript') + return fp.read() else: self.putHeaders(status_code, 'text/html') return self.page_404(url_split) diff --git a/basicswap/static/css/simple/style.css b/basicswap/static/css/simple/style.css index dbf3da9..d650ab3 100644 --- a/basicswap/static/css/simple/style.css +++ b/basicswap/static/css/simple/style.css @@ -22,3 +22,13 @@ margin: 0; width:calc(33.33% - 25px); } + +.error +{ + background:#ff5b5b; +} + +.error_msg +{ + color:red; +} diff --git a/basicswap/static/js/new_offer.js b/basicswap/static/js/new_offer.js new file mode 100644 index 0000000..c8c28d2 --- /dev/null +++ b/basicswap/static/js/new_offer.js @@ -0,0 +1,27 @@ + +window.addEventListener('DOMContentLoaded', (event) => { + let err_msgs = document.querySelectorAll('p.error_msg'); + for (let i=0; i < err_msgs.length; i++) { + err_msg = err_msgs[i].innerText + if (err_msg.indexOf('coin_to') >= 0 || err_msg.indexOf('Coin To') >= 0) { + e = document.getElementById('coin_to'); + e.classList.add('error'); + } + if (err_msg.indexOf('Coin From') >= 0) { + e = document.getElementById('coin_from'); + e.classList.add('error'); + } + if (err_msg.indexOf('Amount From') >= 0) { + e = document.getElementById('amt_from'); + e.classList.add('error'); + } + if (err_msg.indexOf('Amount To') >= 0) { + e = document.getElementById('amt_to'); + e.classList.add('error'); + } + if (err_msg.indexOf('Minimum Bid Amount') >= 0) { + e = document.getElementById('amt_bid_min'); + e.classList.add('error'); + } + } +}); diff --git a/basicswap/templates/header.html b/basicswap/templates/header.html index f761188..f9bd560 100644 --- a/basicswap/templates/header.html +++ b/basicswap/templates/header.html @@ -19,6 +19,7 @@ floating_div = document.createElement('div'); floating_div.classList.add('floatright'); messages = document.createElement('ul'); + messages.setAttribute('id', 'ul_updates'); ws.onmessage = function (event) { let json = JSON.parse(event.data); @@ -33,7 +34,7 @@ event_message = 'Bid accepted'; } - let messages = document.getElementsByTagName('ul')[0], + let messages = document.getElementById('ul_updates'), message = document.createElement('li'); message.innerHTML = event_message; messages.appendChild(message); diff --git a/basicswap/templates/offer.html b/basicswap/templates/offer.html index 135a30f..e47e6c7 100644 --- a/basicswap/templates/offer.html +++ b/basicswap/templates/offer.html @@ -10,6 +10,9 @@ {% for m in messages %}

{{ m }}

{% endfor %} +{% for m in err_messages %} +

Error: {{ m }}

+{% endfor %} {% if sent_bid_id %}

Sent Bid {{ sent_bid_id }}

@@ -21,6 +24,7 @@ Coin To{{ data.coin_to }} Amount From{{ data.amt_from }} {{ data.tla_from }} Amount To{{ data.amt_to }} {{ data.tla_to }} +Minimum Bid Amount{{ data.amt_bid_min }} {{ data.tla_from }} Rate{{ data.rate }} Amount Swapped{{ data.amt_swapped }} {{ data.tla_from }} Amount Variable{{ data.amount_negotiable }} diff --git a/basicswap/templates/offer_confirm.html b/basicswap/templates/offer_confirm.html index 00b486b..0d82855 100644 --- a/basicswap/templates/offer_confirm.html +++ b/basicswap/templates/offer_confirm.html @@ -4,6 +4,9 @@ {% for m in messages %}

{{ m }}

{% endfor %} +{% for m in err_messages %} +

Error: {{ m }}

+{% endfor %}
@@ -59,6 +62,7 @@ {% endif %} +Minimum Bid Amount Rate Amount Variable Rate Variable @@ -97,5 +101,6 @@ {% endif %}
+ diff --git a/basicswap/templates/offer_new_1.html b/basicswap/templates/offer_new_1.html index 7083ce2..b5f79f5 100644 --- a/basicswap/templates/offer_new_1.html +++ b/basicswap/templates/offer_new_1.html @@ -4,6 +4,9 @@ {% for m in messages %}

{{ m }}

{% endfor %} +{% for m in err_messages %} +

Error: {{ m }}

+{% endfor %}
@@ -36,8 +39,9 @@ {% endfor %} Amount ToThe amount you will receive. - +Minimum Bid Amount RateLock Rate: + Amount Variable Rate Variable @@ -131,6 +135,6 @@ function set_rate(value_changed) { xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr_rate.send(params); } - + diff --git a/basicswap/templates/offer_new_2.html b/basicswap/templates/offer_new_2.html index e3836a0..b2782d5 100644 --- a/basicswap/templates/offer_new_2.html +++ b/basicswap/templates/offer_new_2.html @@ -4,6 +4,9 @@ {% for m in messages %}

{{ m }}

{% endfor %} +{% for m in err_messages %} +

Error: {{ m }}

+{% endfor %} @@ -56,6 +59,7 @@ {% endif %} +Minimum Bid Amount Rate Amount Variable Rate Variable @@ -92,4 +96,5 @@ {% endif %}
+ diff --git a/basicswap/ui/page_offers.py b/basicswap/ui/page_offers.py index 5269844..ae26e80 100644 --- a/basicswap/ui/page_offers.py +++ b/basicswap/ui/page_offers.py @@ -22,6 +22,7 @@ from basicswap.db import ( ) from basicswap.util import ( ensure, + format_amount, format_timestamp, ) from basicswap.basicswap_util import ( @@ -44,7 +45,7 @@ def value_or_none(v): return v -def parseOfferFormData(swap_client, form_data, page_data): +def parseOfferFormData(swap_client, form_data, page_data, options={}): errors = [] parsed_data = {} @@ -88,12 +89,24 @@ def parseOfferFormData(swap_client, form_data, page_data): try: page_data['amt_from'] = get_data_entry(form_data, 'amt_from') parsed_data['amt_from'] = inputAmount(page_data['amt_from'], ci_from) - - # TODO: Add min_bid to the ui - parsed_data['min_bid'] = ci_from.chainparams_network()['min_amount'] except Exception: errors.append('Amount From') + try: + if 'amt_bid_min' not in page_data: + if options.get('add_min_bid_amt', False) is True: + parsed_data['amt_bid_min'] = ci_from.chainparams_network()['min_amount'] + else: + raise ValueError('missing') + else: + page_data['amt_bid_min'] = get_data_entry(form_data, 'amt_bid_min') + parsed_data['amt_bid_min'] = inputAmount(page_data['amt_bid_min'], ci_from) + + if parsed_data['amt_bid_min'] < 0 or parsed_data['amt_bid_min'] > parsed_data['amt_from']: + errors.append('Minimum Bid Amount out of range') + except Exception: + errors.append('Minimum Bid Amount') + try: page_data['amt_to'] = get_data_entry(form_data, 'amt_to') parsed_data['amt_to'] = inputAmount(page_data['amt_to'], ci_to) @@ -235,7 +248,7 @@ def postNewOfferFromParsed(swap_client, parsed_data): parsed_data['coin_to'], parsed_data['amt_from'], parsed_data['rate'], - parsed_data['min_bid'], + parsed_data['amt_bid_min'], swap_type, lock_type=lock_type, lock_value=parsed_data['lock_seconds'], @@ -246,7 +259,7 @@ def postNewOfferFromParsed(swap_client, parsed_data): def postNewOffer(swap_client, form_data): page_data = {} - parsed_data, errors = parseOfferFormData(swap_client, form_data, page_data) + parsed_data, errors = parseOfferFormData(swap_client, form_data, page_data, options={'add_min_bid_amt': True}) if len(errors) > 0: raise ValueError('Parse errors: ' + ' '.join(errors)) return postNewOfferFromParsed(swap_client, parsed_data) @@ -257,6 +270,7 @@ def page_newoffer(self, url_split, post_string): swap_client = server.swap_client messages = [] + err_messages = [] page_data = { # Set defaults 'addr_to': -1, @@ -267,20 +281,21 @@ def page_newoffer(self, url_split, post_string): 'lockmins': 30, # used in debug mode 'debug_ui': swap_client.debug_ui, 'automation_strat_id': -1, + 'amt_bid_min': format_amount(1000, 8), } - form_data = self.checkForm(post_string, 'newoffer', messages) + form_data = self.checkForm(post_string, 'newoffer', err_messages) if form_data: try: parsed_data, errors = parseOfferFormData(swap_client, form_data, page_data) for e in errors: - messages.append('Error: {}'.format(str(e))) + err_messages.append(str(e)) except Exception as e: if swap_client.debug is True: swap_client.log.error(traceback.format_exc()) - messages.append('Error: {}'.format(str(e))) + err_messages.append(str(e)) - if len(messages) == 0 and 'submit_offer' in page_data: + if len(err_messages) == 0 and 'submit_offer' in page_data: try: offer_id = postNewOfferFromParsed(swap_client, parsed_data) messages.append('Sent Offer {}'.format(offer_id.hex())) @@ -288,9 +303,9 @@ def page_newoffer(self, url_split, post_string): except Exception as e: if swap_client.debug is True: swap_client.log.error(traceback.format_exc()) - messages.append('Error: {}'.format(str(e))) + err_messages.append(str(e)) - if len(messages) == 0 and 'check_offer' in page_data: + if len(err_messages) == 0 and 'check_offer' in page_data: template = server.env.get_template('offer_confirm.html') elif 'step2' in page_data: template = server.env.get_template('offer_new_2.html') @@ -309,6 +324,7 @@ def page_newoffer(self, url_split, post_string): return self.render_template(template, { 'messages': messages, + 'err_messages': err_messages, 'coins_from': coins_from, 'coins': coins_to, 'addrs': swap_client.listSmsgAddresses('offer_send_from'), @@ -401,6 +417,7 @@ def page_offer(self, url_split, post_string): 'coin_to_ind': int(ci_to.coin_type()), 'amt_from': ci_from.format_amount(offer.amount_from), 'amt_to': ci_to.format_amount((offer.amount_from * offer.rate) // ci_from.COIN()), + 'amt_bid_min': ci_from.format_amount(offer.min_bid_amount), 'rate': ci_to.format_amount(offer.rate), 'lock_type': getLockName(offer.lock_type), 'lock_value': offer.lock_value, diff --git a/doc/install.md b/doc/install.md index 47c4a63..0083e96 100644 --- a/doc/install.md +++ b/doc/install.md @@ -57,14 +57,14 @@ Append `--usebtcfastsync` to the below command to optionally initialise the Bitc Setup with a local Monero daemon (recommended): export COINDATA_PATH=/var/data/coinswaps - docker run --rm -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT + docker run --rm -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT To instead use Monero public nodes and not run a local Monero daemon
(it can be difficult to find reliable public nodes): Set XMR_RPC_HOST and BASE_XMR_RPC_PORT to a public XMR node. export COINDATA_PATH=/var/data/coinswaps - docker run --rm -e XMR_RPC_HOST="node.xmr.to" -e BASE_XMR_RPC_PORT=18081 -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT + docker run --rm -e XMR_RPC_HOST="node.xmr.to" -e BASE_XMR_RPC_PORT=18081 -t --name swap_prepare -v $COINDATA_PATH:/coindata i_swapclient basicswap-prepare --datadir=/coindata --withcoins=monero --htmlhost="0.0.0.0" --wshost="0.0.0.0" --xmrrestoreheight=$CURRENT_XMR_HEIGHT **Record the mnemonic from the output of the above command.**