mirror of
https://github.com/basicswap/basicswap.git
synced 2024-12-31 15:59:28 +00:00
Variable bid amount and rate.
This commit is contained in:
parent
8a9f4f9e38
commit
99534756de
8 changed files with 215 additions and 52 deletions
|
@ -984,6 +984,14 @@ class BasicSwap(BaseApp):
|
|||
if valid_for_seconds > 24 * 60 * 60:
|
||||
raise ValueError('Bid TTL too high')
|
||||
|
||||
def validateBidAmount(self, offer, bid_amount, bid_rate):
|
||||
ensure(bid_amount >= offer.min_bid_amount, 'Bid amount below minimum')
|
||||
ensure(bid_amount <= offer.amount_from, 'Bid amount above offer amount')
|
||||
if not offer.amount_negotiable:
|
||||
ensure(offer.amount_from == bid_amount, 'Bid amount must match offer amount.')
|
||||
if not offer.rate_negotiable:
|
||||
ensure(offer.rate == bid_rate, 'Bid rate must match offer rate.')
|
||||
|
||||
def getOfferAddressTo(self, extra_options):
|
||||
if 'addr_send_to' in extra_options:
|
||||
return extra_options['addr_send_to']
|
||||
|
@ -1613,7 +1621,7 @@ class BasicSwap(BaseApp):
|
|||
return q[0]
|
||||
|
||||
def postBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
||||
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
||||
# Bid to send bid.amount * bid.rate of coin_to in exchange for bid.amount of coin_from
|
||||
self.log.debug('postBid %s', offer_id.hex())
|
||||
|
||||
offer = self.getOffer(offer_id)
|
||||
|
@ -1627,10 +1635,7 @@ class BasicSwap(BaseApp):
|
|||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, valid_for_seconds)
|
||||
|
||||
bid_rate = extra_options.get('bid_rate', offer.rate)
|
||||
if not offer.amount_negotiable:
|
||||
ensure(offer.amount_from == int(amount), 'Bid amount must match offer amount.')
|
||||
if not offer.rate_negotiable:
|
||||
ensure(offer.rate == bid_rate, 'Bid rate must match offer rate.')
|
||||
self.validateBidAmount(offer, amount, bid_rate)
|
||||
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
|
@ -1650,7 +1655,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
contract_count = self.getNewContractId()
|
||||
|
||||
amount_to = int((msg_buf.amount * offer.rate) // self.ci(coin_from).COIN())
|
||||
amount_to = int((msg_buf.amount * bid_rate) // self.ci(coin_from).COIN())
|
||||
|
||||
now = int(time.time())
|
||||
if offer.swap_type == SwapTypes.SELLER_FIRST:
|
||||
|
@ -1958,7 +1963,7 @@ class BasicSwap(BaseApp):
|
|||
self.swaps_in_progress[bid_id] = (bid, offer)
|
||||
|
||||
def postXmrBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
||||
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
||||
# Bid to send bid.amount * bid.rate of coin_to in exchange for bid.amount of coin_from
|
||||
# Send MSG1L F -> L
|
||||
self.log.debug('postXmrBid %s', offer_id.hex())
|
||||
|
||||
|
@ -1979,10 +1984,7 @@ class BasicSwap(BaseApp):
|
|||
ci_to = self.ci(coin_to)
|
||||
|
||||
bid_rate = extra_options.get('bid_rate', offer.rate)
|
||||
if not offer.amount_negotiable:
|
||||
ensure(offer.amount_from == int(amount), 'Bid amount must match offer amount.')
|
||||
if not offer.rate_negotiable:
|
||||
ensure(offer.rate == bid_rate, 'Bid rate must match offer rate.')
|
||||
self.validateBidAmount(offer, amount, bid_rate)
|
||||
|
||||
self.checkSynced(coin_from, coin_to)
|
||||
|
||||
|
@ -2080,7 +2082,7 @@ class BasicSwap(BaseApp):
|
|||
rate=msg_buf.rate,
|
||||
created_at=bid_created_at,
|
||||
contract_count=xmr_swap.contract_count,
|
||||
amount_to=(msg_buf.amount * offer.rate) // ci_from.COIN(),
|
||||
amount_to=(msg_buf.amount * msg_buf.rate) // ci_from.COIN(),
|
||||
expire_at=bid_created_at + msg_buf.time_valid,
|
||||
bid_addr=bid_addr,
|
||||
was_sent=True,
|
||||
|
@ -2397,7 +2399,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
amount_to = bid.amount_to
|
||||
# Check required?
|
||||
assert(amount_to == (bid.amount * offer.rate) // self.ci(offer.coin_from).COIN())
|
||||
assert(amount_to == (bid.amount * bid.rate) // self.ci(offer.coin_from).COIN())
|
||||
|
||||
if bid.debug_ind == DebugTypes.MAKE_INVALID_PTX:
|
||||
amount_to -= 1
|
||||
|
@ -3773,15 +3775,9 @@ class BasicSwap(BaseApp):
|
|||
ensure(offer.state == OfferStates.OFFER_RECEIVED, 'Bad offer state')
|
||||
ensure(msg['to'] == offer.addr_from, 'Received on incorrect address')
|
||||
ensure(now <= offer.expire_at, 'Offer expired')
|
||||
ensure(bid_data.amount >= offer.min_bid_amount, 'Bid amount below minimum')
|
||||
ensure(bid_data.amount <= offer.amount_from, 'Bid amount above offer amount')
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, bid_data.time_valid)
|
||||
ensure(now <= msg['sent'] + bid_data.time_valid, 'Bid expired')
|
||||
|
||||
if not offer.amount_negotiable:
|
||||
ensure(offer.amount_from == bid_data.amount, 'Bid amount must match offer amount.')
|
||||
if not offer.rate_negotiable:
|
||||
ensure(offer.rate == bid_data.rate, 'Bid rate must match offer rate.')
|
||||
self.validateBidAmount(offer, bid_data.amount, bid_data.rate)
|
||||
|
||||
# TODO: Allow higher bids
|
||||
# assert(bid_data.rate != offer['data'].rate), 'Bid rate mismatch'
|
||||
|
@ -3790,7 +3786,7 @@ class BasicSwap(BaseApp):
|
|||
ci_from = self.ci(offer.coin_from)
|
||||
ci_to = self.ci(coin_to)
|
||||
|
||||
amount_to = int((bid_data.amount * offer.rate) // ci_from.COIN())
|
||||
amount_to = int((bid_data.amount * bid_data.rate) // ci_from.COIN())
|
||||
swap_type = offer.swap_type
|
||||
if swap_type == SwapTypes.SELLER_FIRST:
|
||||
ensure(len(bid_data.pkhash_buyer) == 20, 'Bad pkhash_buyer length')
|
||||
|
@ -4067,15 +4063,10 @@ class BasicSwap(BaseApp):
|
|||
raise ValueError('Bad offer state')
|
||||
ensure(msg['to'] == offer.addr_from, 'Received on incorrect address')
|
||||
ensure(now <= offer.expire_at, 'Offer expired')
|
||||
ensure(bid_data.amount >= offer.min_bid_amount, 'Bid amount below minimum')
|
||||
ensure(bid_data.amount <= offer.amount_from, 'Bid amount above offer amount')
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, bid_data.time_valid)
|
||||
ensure(now <= msg['sent'] + bid_data.time_valid, 'Bid expired')
|
||||
|
||||
if not offer.amount_negotiable:
|
||||
ensure(offer.amount_from == bid_data.amount, 'Bid amount must match offer amount.')
|
||||
if not offer.rate_negotiable:
|
||||
ensure(offer.rate == bid_data.rate, 'Bid rate must match offer rate.')
|
||||
self.validateBidAmount(offer, bid_data.amount, bid_data.rate)
|
||||
|
||||
ensure(ci_to.verifyKey(bid_data.kbvf), 'Invalid chain B follower view key')
|
||||
ensure(ci_from.verifyPubkey(bid_data.pkaf), 'Invalid chain A follower public key')
|
||||
|
@ -4092,7 +4083,7 @@ class BasicSwap(BaseApp):
|
|||
amount=bid_data.amount,
|
||||
rate=bid_data.rate,
|
||||
created_at=msg['sent'],
|
||||
amount_to=(bid_data.amount * offer.rate) // ci_from.COIN(),
|
||||
amount_to=(bid_data.amount * bid_data.rate) // ci_from.COIN(),
|
||||
expire_at=msg['sent'] + bid_data.time_valid,
|
||||
bid_addr=msg['from'],
|
||||
was_received=True,
|
||||
|
@ -5525,24 +5516,75 @@ class BasicSwap(BaseApp):
|
|||
return self._network.get_info()
|
||||
|
||||
def lookupRates(self, coin_from, coin_to):
|
||||
self.log.debug('lookupRates {}, {}'.format(coin_from, coin_to))
|
||||
rv = {}
|
||||
ci_from = self.ci(int(coin_from))
|
||||
ci_to = self.ci(int(coin_to))
|
||||
|
||||
name_from = ci_from.coin_name().lower()
|
||||
name_to = ci_to.coin_name().lower()
|
||||
headers = {'Connection': 'close'}
|
||||
name_from = ci_from.chainparams()['name']
|
||||
name_to = ci_to.chainparams()['name']
|
||||
url = 'https://api.coingecko.com/api/v3/simple/price?ids={},{}&vs_currencies=usd'.format(name_from, name_to)
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
start = time.time()
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js = json.loads(urllib.request.urlopen(req).read())
|
||||
js = json.loads(urllib.request.urlopen(req, timeout=10).read())
|
||||
js['time_taken'] = time.time() - start
|
||||
rate = float(js[name_from]['usd']) / float(js[name_to]['usd'])
|
||||
js['rate'] = ci_to.format_amount(rate, conv_int=True, r=1)
|
||||
js['rate_inferred'] = ci_to.format_amount(rate, conv_int=True, r=1)
|
||||
rv['coingecko'] = js
|
||||
|
||||
url = 'https://api.bittrex.com/api/v1.1/public/getticker?market={}-{}'.format(ci_from.ticker(), ci_to.ticker())
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js = json.loads(urllib.request.urlopen(req).read())
|
||||
rv['bittrex'] = js
|
||||
ticker_from = ci_from.chainparams()['ticker']
|
||||
ticker_to = ci_to.chainparams()['ticker']
|
||||
if ci_from.coin_type() == Coins.BTC:
|
||||
pair = '{}-{}'.format(ticker_from, ticker_to)
|
||||
url = 'https://api.bittrex.com/api/v1.1/public/getticker?market=' + pair
|
||||
start = time.time()
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js = json.loads(urllib.request.urlopen(req, timeout=10).read())
|
||||
js['time_taken'] = time.time() - start
|
||||
js['pair'] = pair
|
||||
|
||||
try:
|
||||
rate_inverted = ci_from.make_int(1.0 / float(js['result']['Last']), r=1)
|
||||
js['rate_inferred'] = ci_to.format_amount(rate_inverted)
|
||||
except Exception as e:
|
||||
self.log.warning('lookupRates error: %s', str(e))
|
||||
js['rate_inferred'] = 'error'
|
||||
|
||||
rv['bittrex'] = js
|
||||
elif ci_to.coin_type() == Coins.BTC:
|
||||
pair = '{}-{}'.format(ticker_to, ticker_from)
|
||||
url = 'https://api.bittrex.com/api/v1.1/public/getticker?market=' + pair
|
||||
start = time.time()
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js = json.loads(urllib.request.urlopen(req, timeout=10).read())
|
||||
js['time_taken'] = time.time() - start
|
||||
js['pair'] = pair
|
||||
js['rate_last'] = js['result']['Last']
|
||||
rv['bittrex'] = js
|
||||
else:
|
||||
pair = 'BTC-{}'.format(ticker_from)
|
||||
url = 'https://api.bittrex.com/api/v1.1/public/getticker?market=' + pair
|
||||
start = time.time()
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js_from = json.loads(urllib.request.urlopen(req, timeout=10).read())
|
||||
js_from['time_taken'] = time.time() - start
|
||||
js_from['pair'] = pair
|
||||
|
||||
pair = 'BTC-{}'.format(ticker_to)
|
||||
url = 'https://api.bittrex.com/api/v1.1/public/getticker?market=' + pair
|
||||
start = time.time()
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js_to = json.loads(urllib.request.urlopen(req, timeout=10).read())
|
||||
js_to['time_taken'] = time.time() - start
|
||||
js_to['pair'] = pair
|
||||
|
||||
try:
|
||||
rate_inferred = float(js_from['result']['Last']) / float(js_to['result']['Last'])
|
||||
rate_inferred = ci_to.format_amount(rate, conv_int=True, r=1)
|
||||
except Exception as e:
|
||||
rate_inferred = 'error'
|
||||
|
||||
rv['bittrex'] = {'from': js_from, 'to': js_to, 'rate_inferred': rate_inferred}
|
||||
|
||||
return rv
|
||||
|
|
|
@ -497,7 +497,9 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
try:
|
||||
page_data['amt_from'] = get_data_entry(form_data, 'amt_from')
|
||||
parsed_data['amt_from'] = inputAmount(page_data['amt_from'], ci_from)
|
||||
parsed_data['min_bid'] = int(parsed_data['amt_from'])
|
||||
|
||||
# TODO: Add min_bid to the ui
|
||||
parsed_data['min_bid'] = ci_from.chainparams_network()['min_amount']
|
||||
except Exception:
|
||||
errors.append('Amount From')
|
||||
|
||||
|
@ -516,6 +518,10 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
page_data['rate_var'] = True if have_data_entry(form_data, 'rate_var') else False
|
||||
parsed_data['rate_var'] = page_data['rate_var']
|
||||
|
||||
# Change default autoaccept to false
|
||||
if page_data['amt_var'] or page_data['rate_var']:
|
||||
page_data['autoaccept'] = False
|
||||
|
||||
if b'step1' in form_data:
|
||||
if len(errors) == 0 and b'continue' in form_data:
|
||||
page_data['step2'] = True
|
||||
|
@ -717,6 +723,14 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
sent_bid_id = None
|
||||
show_bid_form = None
|
||||
form_data = self.checkForm(post_string, 'offer', messages)
|
||||
|
||||
ci_from = swap_client.ci(Coins(offer.coin_from))
|
||||
ci_to = swap_client.ci(Coins(offer.coin_to))
|
||||
|
||||
# Set defaults
|
||||
bid_amount = ci_from.format_amount(offer.amount_from)
|
||||
bid_rate = ci_to.format_amount(offer.rate)
|
||||
|
||||
if form_data:
|
||||
if b'revoke_offer' in form_data:
|
||||
try:
|
||||
|
@ -739,20 +753,29 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
extra_options = {
|
||||
'valid_for_seconds': minutes_valid * 60,
|
||||
}
|
||||
sent_bid_id = swap_client.postBid(offer_id, offer.amount_from, addr_send_from=addr_from, extra_options=extra_options).hex()
|
||||
if have_data_entry(form_data, 'bid_rate'):
|
||||
bid_rate = get_data_entry(form_data, 'bid_rate')
|
||||
extra_options['bid_rate'] = ci_to.make_int(bid_rate, r=1)
|
||||
|
||||
if have_data_entry(form_data, 'bid_amount'):
|
||||
bid_amount = get_data_entry(form_data, 'bid_amount')
|
||||
amount_from = inputAmount(bid_amount, ci_from)
|
||||
else:
|
||||
amount_from = offer.amount_from
|
||||
|
||||
sent_bid_id = swap_client.postBid(offer_id, amount_from, addr_send_from=addr_from, extra_options=extra_options).hex()
|
||||
except Exception as ex:
|
||||
messages.append('Error: Send bid failed: ' + str(ex))
|
||||
show_bid_form = True
|
||||
|
||||
ci_from = swap_client.ci(Coins(offer.coin_from))
|
||||
ci_to = swap_client.ci(Coins(offer.coin_to))
|
||||
|
||||
data = {
|
||||
'tla_from': ci_from.ticker(),
|
||||
'tla_to': ci_to.ticker(),
|
||||
'state': strOfferState(offer.state),
|
||||
'coin_from': ci_from.coin_name(),
|
||||
'coin_to': ci_to.coin_name(),
|
||||
'coin_from_ind': int(ci_from.coin_type()),
|
||||
'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()),
|
||||
'rate': ci_to.format_amount(offer.rate),
|
||||
|
@ -767,6 +790,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
'show_bid_form': show_bid_form,
|
||||
'amount_negotiable': offer.amount_negotiable,
|
||||
'rate_negotiable': offer.rate_negotiable,
|
||||
'bid_amount': bid_amount,
|
||||
'bid_rate': bid_rate,
|
||||
}
|
||||
data.update(extend_data)
|
||||
|
||||
|
@ -1097,6 +1122,13 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
|
||||
def page_shutdown(self, url_split, post_string):
|
||||
swap_client = self.server.swap_client
|
||||
|
||||
if len(url_split) > 2:
|
||||
token = url_split[2]
|
||||
expect_token = self.server.session_tokens.get('shutdown', None)
|
||||
if token != expect_token:
|
||||
return self.page_info('Unexpected token, still running.')
|
||||
|
||||
swap_client.stopRunning()
|
||||
|
||||
return self.page_info('Shutting down')
|
||||
|
@ -1105,13 +1137,17 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
swap_client = self.server.swap_client
|
||||
summary = swap_client.getSummary()
|
||||
|
||||
shutdown_token = os.urandom(8).hex()
|
||||
self.server.session_tokens['shutdown'] = shutdown_token
|
||||
|
||||
template = env.get_template('index.html')
|
||||
return bytes(template.render(
|
||||
title=self.server.title,
|
||||
refresh=30,
|
||||
h2=self.server.title,
|
||||
version=__version__,
|
||||
summary=summary
|
||||
summary=summary,
|
||||
shutdown_token=shutdown_token
|
||||
), 'UTF-8')
|
||||
|
||||
def page_404(self, url_split):
|
||||
|
@ -1249,6 +1285,7 @@ class HttpThread(threading.Thread, HTTPServer):
|
|||
self.swap_client = swap_client
|
||||
self.title = 'BasicSwap, ' + self.swap_client.chain
|
||||
self.last_form_id = dict()
|
||||
self.session_tokens = dict()
|
||||
|
||||
self.timeout = 60
|
||||
HTTPServer.__init__(self, (self.host_name, self.port_no), HttpHandler)
|
||||
|
|
|
@ -23,7 +23,7 @@ Version: {{ version }}
|
|||
|
||||
<p><a href="/newoffer">New Offer</a></p>
|
||||
|
||||
<p><a href="/shutdown">Shutdown</a></p>
|
||||
<p><a href="/shutdown/{{ shutdown_token }}">Shutdown</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<form method="post">
|
||||
{% if data.show_bid_form %}
|
||||
<br/><h4>New Bid</h4>
|
||||
<p>You will send {{ data.amt_to }} {{ data.tla_to }} and receive {{ data.amt_from }} {{ data.tla_from }}
|
||||
<p>You will send <span id="bid_amt_to">{{ data.amt_to }}</span> {{ data.tla_to }} and receive <span id="bid_amt_from">{{ data.amt_from }}</span> {{ data.tla_from }}
|
||||
{% if data.xmr_type == true %}
|
||||
(excluding {{ data.amt_from_lock_spend_tx_fee }} {{ data.tla_from }} in tx fees).
|
||||
{% else %}
|
||||
|
@ -62,24 +62,37 @@
|
|||
</td></tr>
|
||||
|
||||
{% if data.amount_negotiable == true %}
|
||||
<tr><td>Amount</td><td><input type="text" name="bid_amount" value="{{ data.amt_from }}"></td></tr>
|
||||
<tr><td>Amount</td><td><input type="text" id="bid_amount" name="bid_amount" value="{{ data.bid_amount }}" onchange="updateBidParams('amount');"></td></tr>
|
||||
{% endif %}
|
||||
{% if data.rate_negotiable == true %}
|
||||
<tr><td>Rate</td><td><input type="text" name="bid_rate" value="{{ data.rate }}"></td></tr>
|
||||
<tr><td>Rate</td><td><input type="text" id="bid_rate" name="bid_rate" value="{{ data.bid_rate }}" onchange="updateBidParams('rate');"></td></tr>
|
||||
{% endif %}
|
||||
|
||||
<tr><td>Minutes valid</td><td><input type="number" name="validmins" min="10" max="1440" value="{{ data.nb_validmins }}"></td></tr>
|
||||
<tr><td><input type="submit" name="sendbid" value="Send Bid"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
||||
<tr><td>
|
||||
<input type="submit" name="sendbid" value="Send Bid">
|
||||
<input type="submit" name="cancel" value="Cancel">
|
||||
<input name="check_rates" type="button" value="Lookup Rates" onclick='lookup_rates();'>
|
||||
</td></tr>
|
||||
</table>
|
||||
{% else %}
|
||||
<input type="submit" name="newbid" value="New Bid">
|
||||
{% if data.sent == 'True' and data.was_revoked != true %}
|
||||
<input name="revoke_offer" type="submit" value="Revoke Offer" onclick="return confirmPopup();">
|
||||
{% endif %}
|
||||
<input name="check_rates" type="button" value="Lookup Rates" onclick='lookup_rates();'>
|
||||
{% endif %}
|
||||
<input type="hidden" id="coin_from" value="{{ data.coin_from_ind }}">
|
||||
<input type="hidden" id="coin_to" value="{{ data.coin_to_ind }}">
|
||||
<input type="hidden" id="amt_var" value="{{ data.amount_negotiable }}">
|
||||
<input type="hidden" id="rate_var" value="{{ data.rate_negotiable }}">
|
||||
<input type="hidden" id="amount_from" value="{{ data.amt_from }}">
|
||||
<input type="hidden" id="offer_rate" value="{{ data.rate }}">
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
</form>
|
||||
|
||||
<p id="rates_display"></p>
|
||||
|
||||
<h4>Bids</h4>
|
||||
<table>
|
||||
<tr><th>Bid ID</th><th>Bid Amount</th><th>Bid Rate</th><th>Bid Status</th><th>Identity From</th></tr>
|
||||
|
@ -91,8 +104,72 @@
|
|||
<p><a href="/">home</a></p>
|
||||
|
||||
<script>
|
||||
const xhr_rates = new XMLHttpRequest();
|
||||
xhr_rates.onload = () => {
|
||||
if (xhr_rates.status == 200) {
|
||||
const obj = JSON.parse(xhr_rates.response);
|
||||
|
||||
inner_html = '<h4>Rates</h4><pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>';
|
||||
document.getElementById('rates_display').innerHTML = inner_html;
|
||||
}
|
||||
}
|
||||
|
||||
function lookup_rates() {
|
||||
const coin_from = document.getElementById('coin_from').value;
|
||||
const coin_to = document.getElementById('coin_to').value;
|
||||
|
||||
if (coin_from == '-1' || coin_to == '-1') {
|
||||
alert('Coins from and to must be set first.');
|
||||
return;
|
||||
}
|
||||
|
||||
inner_html = '<h4>Rates</h4><p>Updating...</p>';
|
||||
document.getElementById('rates_display').innerHTML = inner_html;
|
||||
|
||||
xhr_rates.open('POST', '/json/rates');
|
||||
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr_rates.send('coin_from='+coin_from+'&coin_to='+coin_to);
|
||||
}
|
||||
|
||||
const xhr_bid_params = new XMLHttpRequest();
|
||||
xhr_bid_params.onload = () => {
|
||||
if (xhr_bid_params.status == 200) {
|
||||
const obj = JSON.parse(xhr_bid_params.response);
|
||||
document.getElementById('bid_amt_to').innerHTML = obj['amount_to'];
|
||||
}
|
||||
}
|
||||
|
||||
function updateBidParams(value_changed) {
|
||||
const coin_from = document.getElementById('coin_from').value;
|
||||
const coin_to = document.getElementById('coin_to').value;
|
||||
const amt_var = document.getElementById('amt_var').value;
|
||||
const rate_var = document.getElementById('rate_var').value;
|
||||
|
||||
let amt_from = '';
|
||||
let rate = '';
|
||||
if (amt_var) {
|
||||
amt_from = document.getElementById('bid_amount').value;
|
||||
} else {
|
||||
amt_from = document.getElementById('amount_from').value;
|
||||
}
|
||||
if (rate_var) {
|
||||
rate = document.getElementById('bid_rate').value;
|
||||
} else {
|
||||
rate = document.getElementById('offer_rate').value;
|
||||
}
|
||||
|
||||
if (value_changed == 'amount') {
|
||||
document.getElementById('bid_amt_from').innerHTML = amt_from;
|
||||
}
|
||||
|
||||
xhr_bid_params.open('POST', '/json/rate');
|
||||
xhr_bid_params.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr_bid_params.send('coin_from='+coin_from+'&coin_to='+coin_to+'&rate='+rate+'&amt_from='+amt_from);
|
||||
}
|
||||
|
||||
function confirmPopup() {
|
||||
return confirm("Are you sure?");
|
||||
}
|
||||
|
||||
</script>
|
||||
</body></html>
|
||||
|
|
|
@ -57,7 +57,7 @@ xhr_rates.onload = () => {
|
|||
if (xhr_rates.status == 200) {
|
||||
const obj = JSON.parse(xhr_rates.response);
|
||||
|
||||
inner_html = '<pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>';
|
||||
inner_html = '<h4>Rates</h4><pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>';
|
||||
document.getElementById('rates_display').innerHTML = inner_html;
|
||||
}
|
||||
}
|
||||
|
@ -88,6 +88,9 @@ function lookup_rates() {
|
|||
return;
|
||||
}
|
||||
|
||||
inner_html = '<h4>Rates</h4><p>Updating...</p>';
|
||||
document.getElementById('rates_display').innerHTML = inner_html;
|
||||
|
||||
xhr_rates.open('POST', '/json/rates');
|
||||
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr_rates.send('coin_from='+coin_from+'&coin_to='+coin_to);
|
||||
|
@ -106,7 +109,7 @@ function set_rate(value_changed) {
|
|||
}
|
||||
|
||||
params = 'coin_from='+coin_from+'&coin_to='+coin_to;
|
||||
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from')) {
|
||||
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from') || (amt_to == '' && value_changed == 'amt_from')) {
|
||||
if (amt_from == '' || rate == '') {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -206,7 +206,7 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
'coin_from': ci_from.coin_name(),
|
||||
'coin_to': ci_to.coin_name(),
|
||||
'amt_from': ci_from.format_amount(bid.amount),
|
||||
'amt_to': ci_to.format_amount((bid.amount * offer.rate) // ci_from.COIN()),
|
||||
'amt_to': ci_to.format_amount((bid.amount * bid.rate) // ci_from.COIN()),
|
||||
'bid_rate': ci_to.format_amount(bid.rate),
|
||||
'ticker_from': ticker_from,
|
||||
'ticker_to': ticker_to,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
- Track failed and successful swaps by address.
|
||||
- Added rate lookup helper when creating offer.
|
||||
- Prevent old shutdown link from shutting down a new session.
|
||||
|
||||
|
||||
0.0.26
|
||||
|
|
|
@ -497,6 +497,9 @@ class BaseTest(unittest.TestCase):
|
|||
class Test(BaseTest):
|
||||
__test__ = True
|
||||
|
||||
def notest_00_delay(self):
|
||||
test_delay_event.wait(100000)
|
||||
|
||||
def test_01_part_xmr(self):
|
||||
logging.info('---------- Test PART to XMR')
|
||||
swap_clients = self.swap_clients
|
||||
|
|
Loading…
Reference in a new issue