ui: Add rate lookup helper when creating offers.
This commit is contained in:
parent
54ad0e496c
commit
8a9f4f9e38
@ -14,6 +14,7 @@ import base64
|
||||
import random
|
||||
import shutil
|
||||
import struct
|
||||
import urllib.request
|
||||
import hashlib
|
||||
import secrets
|
||||
import datetime as dt
|
||||
@ -1036,6 +1037,9 @@ class BasicSwap(BaseApp):
|
||||
msg_buf.amount_negotiable = extra_options.get('amount_negotiable', False)
|
||||
msg_buf.rate_negotiable = extra_options.get('rate_negotiable', False)
|
||||
|
||||
if msg_buf.amount_negotiable or msg_buf.rate_negotiable:
|
||||
ensure(auto_accept_bids is False, 'Auto-accept unavailable when amount or rate are variable')
|
||||
|
||||
if 'from_fee_override' in extra_options:
|
||||
msg_buf.fee_rate_from = make_int(extra_options['from_fee_override'], self.ci(coin_from).exp())
|
||||
else:
|
||||
@ -5519,3 +5523,26 @@ class BasicSwap(BaseApp):
|
||||
if not self._network:
|
||||
return {'Error': 'Not Initialised'}
|
||||
return self._network.get_info()
|
||||
|
||||
def lookupRates(self, 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()
|
||||
url = 'https://api.coingecko.com/api/v3/simple/price?ids={},{}&vs_currencies=usd'.format(name_from, name_to)
|
||||
headers = {'User-Agent': 'Mozilla/5.0'}
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
js = json.loads(urllib.request.urlopen(req).read())
|
||||
rate = float(js[name_from]['usd']) / float(js[name_to]['usd'])
|
||||
js['rate'] = 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
|
||||
|
||||
return rv
|
||||
|
@ -1,11 +1,11 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2019 tecnovert
|
||||
# Copyright (c) 2019-2021 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
import urllib.request
|
||||
import json
|
||||
import urllib.request
|
||||
|
||||
|
||||
class Explorer():
|
||||
|
@ -42,6 +42,8 @@ from .js_server import (
|
||||
js_network,
|
||||
js_revokeoffer,
|
||||
js_smsgaddresses,
|
||||
js_rates,
|
||||
js_rate,
|
||||
js_index,
|
||||
)
|
||||
from .ui import (
|
||||
@ -507,6 +509,12 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
|
||||
if 'amt_to' in parsed_data and 'amt_from' in parsed_data:
|
||||
parsed_data['rate'] = ci_from.make_int(parsed_data['amt_to'] / parsed_data['amt_from'], r=1)
|
||||
page_data['rate'] = ci_to.format_amount(parsed_data['rate'])
|
||||
|
||||
page_data['amt_var'] = True if have_data_entry(form_data, 'amt_var') else False
|
||||
parsed_data['amt_var'] = page_data['amt_var']
|
||||
page_data['rate_var'] = True if have_data_entry(form_data, 'rate_var') else False
|
||||
parsed_data['rate_var'] = page_data['rate_var']
|
||||
|
||||
if b'step1' in form_data:
|
||||
if len(errors) == 0 and b'continue' in form_data:
|
||||
@ -616,6 +624,11 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
if 'addr_to' in parsed_data:
|
||||
extra_options['addr_send_to'] = parsed_data['addr_to']
|
||||
|
||||
if parsed_data.get('amt_var', False):
|
||||
extra_options['amount_negotiable'] = parsed_data['amt_var']
|
||||
if parsed_data.get('rate_var', False):
|
||||
extra_options['rate_negotiable'] = parsed_data['rate_var']
|
||||
|
||||
offer_id = swap_client.postOffer(
|
||||
parsed_data['coin_from'],
|
||||
parsed_data['coin_to'],
|
||||
@ -1129,6 +1142,8 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||
'network': js_network,
|
||||
'revokeoffer': js_revokeoffer,
|
||||
'smsgaddresses': js_smsgaddresses,
|
||||
'rate': js_rate,
|
||||
'rates': js_rates,
|
||||
}.get(url_split[2], js_index)
|
||||
return func(self, url_split, post_string, is_json)
|
||||
except Exception as ex:
|
||||
|
@ -19,6 +19,7 @@ from .chainparams import (
|
||||
)
|
||||
from .ui import (
|
||||
PAGE_LIMIT,
|
||||
getCoinType,
|
||||
inputAmount,
|
||||
describeBid,
|
||||
setCoinFilter,
|
||||
@ -245,10 +246,6 @@ def js_revokeoffer(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps({'revoked_offer': offer_id.hex()}), 'UTF-8')
|
||||
|
||||
|
||||
def js_index(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
|
||||
|
||||
|
||||
def js_smsgaddresses(self, url_split, post_string, is_json):
|
||||
swap_client = self.server.swap_client
|
||||
if len(url_split) > 3:
|
||||
@ -276,3 +273,61 @@ def js_smsgaddresses(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps({'edited_address': address}), 'UTF-8')
|
||||
|
||||
return bytes(json.dumps(swap_client.listAllSMSGAddresses()), 'UTF-8')
|
||||
|
||||
|
||||
def js_rates(self, url_split, post_string, is_json):
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
sc = self.server.swap_client
|
||||
coin_from = get_data_entry(post_data, 'coin_from')
|
||||
coin_to = get_data_entry(post_data, 'coin_to')
|
||||
return bytes(json.dumps(sc.lookupRates(coin_from, coin_to)), 'UTF-8')
|
||||
|
||||
|
||||
def js_rate(self, url_split, post_string, is_json):
|
||||
if post_string == '':
|
||||
raise ValueError('No post data')
|
||||
if is_json:
|
||||
post_data = json.loads(post_string)
|
||||
post_data['is_json'] = True
|
||||
else:
|
||||
post_data = urllib.parse.parse_qs(post_string)
|
||||
|
||||
sc = self.server.swap_client
|
||||
coin_from = getCoinType(get_data_entry(post_data, 'coin_from'))
|
||||
ci_from = sc.ci(coin_from)
|
||||
coin_to = getCoinType(get_data_entry(post_data, 'coin_to'))
|
||||
ci_to = sc.ci(coin_to)
|
||||
|
||||
# Set amount to if rate is provided
|
||||
rate = get_data_entry_or(post_data, 'rate', None)
|
||||
if rate is not None:
|
||||
amt_from_str = get_data_entry_or(post_data, 'amt_from', None)
|
||||
amt_to_str = get_data_entry_or(post_data, 'amt_to', None)
|
||||
|
||||
if amt_from_str is not None:
|
||||
rate = ci_to.make_int(rate, r=1)
|
||||
amt_from = inputAmount(amt_from_str, ci_from)
|
||||
amount_to = ci_to.format_amount(int((amt_from * rate) // ci_from.COIN()), r=1)
|
||||
return bytes(json.dumps({'amount_to': amount_to}), 'UTF-8')
|
||||
if amt_to_str is not None:
|
||||
rate = ci_from.make_int(1.0 / float(rate), r=1)
|
||||
amt_to = inputAmount(amt_to_str, ci_to)
|
||||
amount_from = ci_from.format_amount(int((amt_to * rate) // ci_to.COIN()), r=1)
|
||||
return bytes(json.dumps({'amount_from': amount_from}), 'UTF-8')
|
||||
|
||||
amt_from = inputAmount(get_data_entry(post_data, 'amt_from'), ci_from)
|
||||
amt_to = inputAmount(get_data_entry(post_data, 'amt_to'), ci_to)
|
||||
|
||||
rate = ci_to.format_amount(ci_from.make_int(amt_to / amt_from, r=1))
|
||||
return bytes(json.dumps({'rate': rate}), 'UTF-8')
|
||||
|
||||
|
||||
def js_index(self, url_split, post_string, is_json):
|
||||
return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
|
||||
|
@ -60,8 +60,15 @@
|
||||
<option value="-1" {% if data.nb_addr_from=="-1" %} selected{% endif %}>-- New Address --</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
<tr><td>Minutes valid</td><td><input type="number" name="validmins" min="10" max="1440" value="{{ data.nb_validmins }}"></td></tr>
|
||||
|
||||
{% if data.amount_negotiable == true %}
|
||||
<tr><td>Amount</td><td><input type="text" name="bid_amount" value="{{ data.amt_from }}"></td></tr>
|
||||
{% endif %}
|
||||
{% if data.rate_negotiable == true %}
|
||||
<tr><td>Rate</td><td><input type="text" name="bid_rate" value="{{ data.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>
|
||||
</table>
|
||||
{% else %}
|
||||
|
@ -59,10 +59,13 @@
|
||||
<option value="100"{% if data.fee_to_extra==100 %} selected{% endif %}>100%</option>
|
||||
</select></td></tr>
|
||||
{% endif %}
|
||||
</td><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="true"{% 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="true"{% endif %} disabled></td></tr>
|
||||
|
||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}" readonly></td></tr>
|
||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="64" value="{{ data.lockhrs }}" readonly></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept_" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %} disabled></td></tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" id="autoaccept" name="autoaccept_" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %} disabled></td></tr>
|
||||
</table>
|
||||
|
||||
<input name="submit_offer" type="submit" value="Confirm Offer">
|
||||
@ -77,6 +80,12 @@
|
||||
{% if data.autoaccept==true %}
|
||||
<input type="hidden" name="autoaccept" value="aa">
|
||||
{% endif %}
|
||||
{% if data.amt_var==true %}
|
||||
<input type="hidden" name="amt_var" value="av">
|
||||
{% endif %}
|
||||
{% if data.rate_var==true %}
|
||||
<input type="hidden" name="rate_var" value="rv">
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
</body></html>
|
||||
|
@ -22,26 +22,112 @@
|
||||
</select></td></tr>
|
||||
|
||||
<tr><td>Coin From</td><td>
|
||||
<select name="coin_from"><option value="-1">-- Select Coin --</option>
|
||||
<select id="coin_from" name="coin_from" onchange="set_rate('coin_from');"><option value="-1">-- Select Coin --</option>
|
||||
{% for c in coins %}
|
||||
<option{% if data.coin_from==c[0] %} selected{% endif %} value="{{ c[0] }}">{{ c[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td><td>Amount From</td><td><input type="text" name="amt_from" value="{{ data.amt_from }}"></td><td>The amount you will send.</td></tr>
|
||||
</td><td>Amount From</td><td><input type="text" id="amt_from" name="amt_from" value="{{ data.amt_from }}" onchange="set_rate('amt_from');"></td><td>The amount you will send.</td></tr>
|
||||
|
||||
<tr><td>Coin To</td><td>
|
||||
<select name="coin_to"><option value="-1">-- Select Coin --</option>
|
||||
<select id="coin_to" name="coin_to" onchange="set_rate('coin_to');"><option value="-1">-- Select Coin --</option>
|
||||
{% for c in coins %}
|
||||
<option{% if data.coin_to==c[0] %} selected{% endif %} value="{{ c[0] }}">{{ c[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</td><td>Amount To</td><td><input type="text" name="amt_to" value="{{ data.amt_to }}"></td><td>The amount you will receive.</td></tr>
|
||||
</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>
|
||||
</td><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"></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="true"{% 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="true"{% endif %}></td></tr>
|
||||
</table>
|
||||
|
||||
<input name="continue" type="submit" value="Continue">
|
||||
<input name="check_rates" type="button" value="Lookup Rates" onclick='lookup_rates();'>
|
||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||
<input type="hidden" name="step1" value="a">
|
||||
</form>
|
||||
|
||||
<p id="rates_display"></p>
|
||||
|
||||
<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 = '<pre><code>' + JSON.stringify(obj, null, ' ') + '</code></pre>';
|
||||
document.getElementById('rates_display').innerHTML = inner_html;
|
||||
}
|
||||
}
|
||||
|
||||
const xhr_rate = new XMLHttpRequest();
|
||||
xhr_rate.onload = () => {
|
||||
if (xhr_rate.status == 200) {
|
||||
const obj = JSON.parse(xhr_rate.response);
|
||||
|
||||
if (obj.hasOwnProperty('rate')) {
|
||||
document.getElementById('rate').value = obj['rate'];
|
||||
} else
|
||||
if (obj.hasOwnProperty('amount_to')) {
|
||||
document.getElementById('amt_to').value = obj['amount_to'];
|
||||
} else
|
||||
if (obj.hasOwnProperty('amount_from')) {
|
||||
document.getElementById('amt_from').value = obj['amount_from'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
function set_rate(value_changed) {
|
||||
const coin_from = document.getElementById('coin_from').value;
|
||||
const coin_to = document.getElementById('coin_to').value;
|
||||
const amt_from = document.getElementById('amt_from').value;
|
||||
const amt_to = document.getElementById('amt_to').value;
|
||||
const rate = document.getElementById('rate').value;
|
||||
const lock_rate = document.getElementById('rate_lock').checked;
|
||||
|
||||
if (coin_from == '-1' || coin_to == '-1') {
|
||||
return;
|
||||
}
|
||||
|
||||
params = 'coin_from='+coin_from+'&coin_to='+coin_to;
|
||||
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from')) {
|
||||
if (amt_from == '' || rate == '') {
|
||||
return;
|
||||
}
|
||||
params += '&rate='+rate+'&amt_from='+amt_from;
|
||||
} else
|
||||
if (lock_rate && value_changed == 'amt_to') {
|
||||
if (amt_to == '' || rate == '') {
|
||||
return;
|
||||
}
|
||||
params += '&amt_to='+amt_to+'&rate='+rate;
|
||||
} else {
|
||||
if (amt_from == '' || amt_to == '') {
|
||||
return;
|
||||
}
|
||||
params += '&amt_from='+amt_from+'&amt_to='+amt_to;
|
||||
}
|
||||
|
||||
xhr_rate.open('POST', '/json/rate');
|
||||
xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
xhr_rate.send(params);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body></html>
|
||||
|
@ -56,10 +56,15 @@
|
||||
<option value="100"{% if data.fee_to_extra==100 %} selected{% endif %}>100%</option>
|
||||
</select></td></tr>
|
||||
{% endif %}
|
||||
</td><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="true"{% 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="true"{% endif %} disabled></td></tr>
|
||||
|
||||
|
||||
<tr class="padded_row"><td>Offer valid (hrs)</td><td><input type="number" name="validhrs" min="1" max="48" value="{{ data.validhrs }}"></td></tr>
|
||||
<tr><td>Contract locked (hrs)</td><td><input type="number" name="lockhrs" min="1" max="96" value="{{ data.lockhrs }}"></td>{% if data.swap_style != 'xmr' %}<td colspan=2>Participate txn will be locked for half the time.</td>{% endif %}</tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" name="autoaccept" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %}></td></tr>
|
||||
<tr><td>Auto Accept Bids</td><td colspan=3><input type="checkbox" id="autoaccept" name="autoaccept" value="aa" {% if data.autoaccept==true %} checked="true"{% endif %}></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<input name="check_offer" type="submit" value="Continue">
|
||||
@ -69,6 +74,12 @@
|
||||
<input type="hidden" name="addr_from" value="{{ data.addr_from }}">
|
||||
<input type="hidden" name="coin_from" value="{{ data.coin_from }}">
|
||||
<input type="hidden" name="coin_to" value="{{ data.coin_to }}">
|
||||
{% if data.amt_var==true %}
|
||||
<input type="hidden" name="amt_var" value="true">
|
||||
{% endif %}
|
||||
{% if data.rate_var==true %}
|
||||
<input type="hidden" name="rate_var" value="true">
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
</body></html>
|
||||
|
@ -313,7 +313,7 @@ def prepareCore(coin, version_pair, settings, data_dir):
|
||||
extractCore(coin, version_pair, settings, bin_dir, release_path)
|
||||
|
||||
|
||||
def prepareDataDir(coin, settings, chain, particl_mnemonic, use_containers=False)):
|
||||
def prepareDataDir(coin, settings, chain, particl_mnemonic, use_containers=False):
|
||||
core_settings = settings['chainclients'][coin]
|
||||
bin_dir = core_settings['bindir']
|
||||
data_dir = core_settings['datadir']
|
||||
|
@ -2,21 +2,22 @@
|
||||
0.0.27
|
||||
==============
|
||||
|
||||
- Track failed and successful swaps by address
|
||||
- Track failed and successful swaps by address.
|
||||
- Added rate lookup helper when creating offer.
|
||||
|
||||
|
||||
0.0.26
|
||||
==============
|
||||
|
||||
- Added protocol version to order and bid messages
|
||||
- Added protocol version to order and bid messages.
|
||||
- Moved chain start heights to bid.
|
||||
- Avoid scantxoutset for decred style swaps
|
||||
- xmr: spend chain B lock tx will look for existing spends
|
||||
- Avoid scantxoutset for decred style swaps.
|
||||
- xmr: spend chain B lock tx will look for existing spends.
|
||||
- xmrswaps:
|
||||
- Setting state to 'Script tx redeemed' will trigger an attempt to redeem the scriptless lock tx.
|
||||
- Node will wait for the chain B lock tx to reach a spendable depth before attempting to spend.
|
||||
- ui: Sort settings page by coin name.
|
||||
- ui, xmr: List of candidate remote XMR daemon urls can be set through the http ui
|
||||
- ui, xmr: List of candidate remote XMR daemon urls can be set through the http ui.
|
||||
|
||||
|
||||
0.0.25
|
||||
@ -24,8 +25,8 @@
|
||||
|
||||
- Fix extra 33 bytes in lock spend fee calculation.
|
||||
- XMR swaps use watchonly addresses to save the lock tx to the wallet
|
||||
- Instead of scantxoutset
|
||||
- Add missing check of leader's lock refund tx signature result
|
||||
- Instead of scantxoutset.
|
||||
- Add missing check of leader's lock refund tx signature result.
|
||||
- Blind part -> XMR swaps are possible:
|
||||
- The sha256 hash of the chain b view private key is used as the nonce for transactions requiring cooperation to sign.
|
||||
- Follower sends a public key in xmr_swap.dest_af.
|
||||
@ -45,14 +46,14 @@
|
||||
0.0.23
|
||||
==============
|
||||
|
||||
- Enables private offers
|
||||
- Enables private offers.
|
||||
|
||||
|
||||
0.0.22
|
||||
==============
|
||||
|
||||
- Improved wallets page
|
||||
- Consistent wallet order
|
||||
- Consistent wallet order.
|
||||
- Separated RPC calls into threads.
|
||||
|
||||
|
||||
@ -67,5 +68,5 @@
|
||||
0.0.6
|
||||
==============
|
||||
|
||||
- Experimental support for XMR swaps.
|
||||
- Single direction only, scriptless -> XMR
|
||||
- Experimental support for XMR swaps
|
||||
- Single direction only, scriptless -> XMR.
|
||||
|
@ -29,10 +29,10 @@ from basicswap.basicswap_util import (
|
||||
SEQUENCE_LOCK_BLOCKS,
|
||||
SEQUENCE_LOCK_TIME)
|
||||
from basicswap.util import (
|
||||
SerialiseNum,
|
||||
DeserialiseNum,
|
||||
make_int,
|
||||
SerialiseNum,
|
||||
format_amount,
|
||||
DeserialiseNum,
|
||||
validate_amount)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user