ui: Expose min bid amount.
This commit is contained in:
		
							parent
							
								
									1c4f208d27
								
							
						
					
					
						commit
						1ee2db137b
					
				@ -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)
 | 
			
		||||
 | 
			
		||||
@ -22,3 +22,13 @@
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  width:calc(33.33% - 25px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.error
 | 
			
		||||
{
 | 
			
		||||
  background:#ff5b5b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.error_msg
 | 
			
		||||
{
 | 
			
		||||
  color:red;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								basicswap/static/js/new_offer.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								basicswap/static/js/new_offer.js
									
									
									
									
									
										Normal file
									
								
							@ -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');
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@ -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 = '<a href=/bid/' + json['bid_id'] + '>Bid accepted</a>';
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let messages = document.getElementsByTagName('ul')[0],
 | 
			
		||||
        let messages = document.getElementById('ul_updates'),
 | 
			
		||||
            message = document.createElement('li');
 | 
			
		||||
        message.innerHTML = event_message;
 | 
			
		||||
        messages.appendChild(message);
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,9 @@
 | 
			
		||||
{% for m in messages %}
 | 
			
		||||
<p>{{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% for m in err_messages %}
 | 
			
		||||
<p class="error_msg">Error: {{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
 | 
			
		||||
{% if sent_bid_id %}
 | 
			
		||||
<p><a href="/bid/{{ sent_bid_id }}">Sent Bid {{ sent_bid_id }}</a></p>
 | 
			
		||||
@ -21,6 +24,7 @@
 | 
			
		||||
<tr><td>Coin To</td><td>{{ data.coin_to }}</td></tr>
 | 
			
		||||
<tr><td>Amount From</td><td>{{ data.amt_from }} {{ data.tla_from }}</td></tr>
 | 
			
		||||
<tr><td>Amount To</td><td>{{ data.amt_to }} {{ data.tla_to }}</td></tr>
 | 
			
		||||
<tr><td>Minimum Bid Amount</td><td>{{ data.amt_bid_min }} {{ data.tla_from }}</td></tr>
 | 
			
		||||
<tr><td>Rate</td><td>{{ data.rate }}</td></tr>
 | 
			
		||||
<tr><td title="Total coin-from value of completed bids, that this node is involved in">Amount Swapped</td><td>{{ data.amt_swapped }} {{ data.tla_from }}</td></tr>
 | 
			
		||||
<tr><td title="If bids can be sent with a different amount">Amount Variable</td><td>{{ data.amount_negotiable }}</td></tr>
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,9 @@
 | 
			
		||||
{% for m in messages %}
 | 
			
		||||
<p>{{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% for m in err_messages %}
 | 
			
		||||
<p class="error_msg">Error: {{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
 | 
			
		||||
<form method="post">
 | 
			
		||||
 | 
			
		||||
@ -59,6 +62,7 @@
 | 
			
		||||
<option value="100"{% if data.fee_to_extra==100 %} selected{% endif %}>100%</option>
 | 
			
		||||
</select></td></tr>
 | 
			
		||||
{% endif %}
 | 
			
		||||
<tr><td>Minimum Bid Amount</td><td><input type="text" id="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly></td></tr>
 | 
			
		||||
<tr><td>Rate</td><td><input type="text" id="rate" name="rate" value="{{ data.rate }}" readonly></td></tr>
 | 
			
		||||
<tr><td>Amount Variable</td><td colspan=3><input type="checkbox" id="amt_var" name="amt_var_" value="av" {% if data.amt_var==true %} checked=checked{% endif %} disabled></td></tr>
 | 
			
		||||
<tr><td>Rate Variable</td><td colspan=3><input type="checkbox" id="rate_var" name="rate_var_" value="rv" {% if data.rate_var==true %} checked=checked{% endif %} disabled></td></tr>
 | 
			
		||||
@ -97,5 +101,6 @@
 | 
			
		||||
<input type="hidden" name="rate_var" value="rv">
 | 
			
		||||
{% endif %}
 | 
			
		||||
</form>
 | 
			
		||||
<script src="static/js/new_offer.js"></script>
 | 
			
		||||
 | 
			
		||||
</body></html>
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,9 @@
 | 
			
		||||
{% for m in messages %}
 | 
			
		||||
<p>{{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% for m in err_messages %}
 | 
			
		||||
<p class="error_msg">Error: {{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
 | 
			
		||||
<form method="post">
 | 
			
		||||
 | 
			
		||||
@ -36,8 +39,9 @@
 | 
			
		||||
{% endfor %}
 | 
			
		||||
</select>
 | 
			
		||||
</td><td>Amount To</td><td><input type="text" id="amt_to" name="amt_to" value="{{ data.amt_to }}" onchange="set_rate('amt_to');"></td><td>The amount you will receive.</td></tr>
 | 
			
		||||
 | 
			
		||||
<tr><td>Minimum Bid Amount</td><td><input type="text" id="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded"></td></tr>
 | 
			
		||||
<tr><td>Rate</td><td><input type="text" id="rate" name="rate" value="{{ data.rate }}" onchange="set_rate('rate');"></td><td>Lock Rate: <input type="checkbox" id="rate_lock" name="rate_lock" value="rl" checked=checked></td></tr>
 | 
			
		||||
 | 
			
		||||
<tr><td>Amount Variable</td><td><input type="checkbox" id="amt_var" name="amt_var" value="av" {% if data.amt_var==true %} checked=checked{% endif %}></td></tr>
 | 
			
		||||
<tr><td>Rate Variable</td><td><input type="checkbox" id="rate_var" name="rate_var" value="rv" {% if data.rate_var==true %} checked=checked{% endif %}></td></tr>
 | 
			
		||||
</table>
 | 
			
		||||
@ -131,6 +135,6 @@ function set_rate(value_changed) {
 | 
			
		||||
    xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
 | 
			
		||||
    xhr_rate.send(params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
<script src="static/js/new_offer.js"></script>
 | 
			
		||||
</body></html>
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,9 @@
 | 
			
		||||
{% for m in messages %}
 | 
			
		||||
<p>{{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
{% for m in err_messages %}
 | 
			
		||||
<p class="error_msg">Error: {{ m }}</p>
 | 
			
		||||
{% endfor %}
 | 
			
		||||
 | 
			
		||||
<form method="post">
 | 
			
		||||
 | 
			
		||||
@ -56,6 +59,7 @@
 | 
			
		||||
<option value="100"{% if data.fee_to_extra==100 %} selected{% endif %}>100%</option>
 | 
			
		||||
</select></td></tr>
 | 
			
		||||
{% endif %}
 | 
			
		||||
<tr><td>Minimum Bid Amount</td><td><input type="text" id="amt_bid_min" name="amt_bid_min" value="{{ data.amt_bid_min }}" title="Bids with an amount below the minimum bid value will be discarded" readonly></td></tr>
 | 
			
		||||
<tr><td>Rate</td><td><input type="text" id="rate" name="rate" value="{{ data.rate }}" readonly></td></tr>
 | 
			
		||||
<tr><td>Amount Variable</td><td colspan=3><input type="checkbox" id="amt_var" name="amt_var_" value="av" {% if data.amt_var==true %} checked=checked{% endif %} disabled></td></tr>
 | 
			
		||||
<tr><td>Rate Variable</td><td colspan=3><input type="checkbox" id="rate_var" name="rate_var_" value="rv" {% if data.rate_var==true %} checked=checked{% endif %} disabled></td></tr>
 | 
			
		||||
@ -92,4 +96,5 @@
 | 
			
		||||
{% endif %}
 | 
			
		||||
</form>
 | 
			
		||||
 | 
			
		||||
<script src="static/js/new_offer.js"></script>
 | 
			
		||||
</body></html>
 | 
			
		||||
 | 
			
		||||
@ -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('<a href="/offer/' + offer_id.hex() + '">Sent Offer {}</a>'.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,
 | 
			
		||||
 | 
			
		||||
@ -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<br>(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.**
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user