mirror of
https://github.com/basicswap/basicswap.git
synced 2025-02-25 20:40:41 +00:00
ui: auto set blank amount from using amount to and rate.
Fix btc get unspents, 'solvable'.
This commit is contained in:
parent
f64b2c1030
commit
47f7b4545e
7 changed files with 104 additions and 42 deletions
basicswap
doc
tests/basicswap
|
@ -444,10 +444,10 @@ class BasicSwap(BaseApp):
|
||||||
if connection_type == 'rpc':
|
if connection_type == 'rpc':
|
||||||
if 'rpcauth' in chain_client_settings:
|
if 'rpcauth' in chain_client_settings:
|
||||||
rpcauth = chain_client_settings['rpcauth']
|
rpcauth = chain_client_settings['rpcauth']
|
||||||
self.log.debug('Read %s rpc credentials from json settings', coin)
|
self.log.debug(f'Read {Coins(coin).name} rpc credentials from json settings')
|
||||||
elif 'rpcpassword' in chain_client_settings:
|
elif 'rpcpassword' in chain_client_settings:
|
||||||
rpcauth = chain_client_settings['rpcuser'] + ':' + chain_client_settings['rpcpassword']
|
rpcauth = chain_client_settings['rpcuser'] + ':' + chain_client_settings['rpcpassword']
|
||||||
self.log.debug('Read %s rpc credentials from json settings', coin)
|
self.log.debug(f'Read {Coins(coin).name} rpc credentials from json settings')
|
||||||
|
|
||||||
session = scoped_session(self.session_factory)
|
session = scoped_session(self.session_factory)
|
||||||
try:
|
try:
|
||||||
|
@ -698,7 +698,7 @@ class BasicSwap(BaseApp):
|
||||||
pidfilename += 'd'
|
pidfilename += 'd'
|
||||||
|
|
||||||
pidfilepath = os.path.join(self.getChainDatadirPath(coin), pidfilename + '.pid')
|
pidfilepath = os.path.join(self.getChainDatadirPath(coin), pidfilename + '.pid')
|
||||||
self.log.debug('Reading %s rpc credentials from auth cookie %s', coin, authcookiepath)
|
self.log.debug('Reading %s rpc credentials from auth cookie %s', Coins(coin).name, authcookiepath)
|
||||||
# Wait for daemon to start
|
# Wait for daemon to start
|
||||||
# Test pids to ensure authcookie is read for the correct process
|
# Test pids to ensure authcookie is read for the correct process
|
||||||
datadir_pid = -1
|
datadir_pid = -1
|
||||||
|
@ -1948,7 +1948,7 @@ class BasicSwap(BaseApp):
|
||||||
return txid
|
return txid
|
||||||
|
|
||||||
def cacheNewAddressForCoin(self, coin_type):
|
def cacheNewAddressForCoin(self, coin_type):
|
||||||
self.log.debug('cacheNewAddressForCoin %s', coin_type)
|
self.log.debug('cacheNewAddressForCoin %s', Coins(coin_type).name)
|
||||||
key_str = 'receive_addr_' + self.ci(coin_type).coin_name().lower()
|
key_str = 'receive_addr_' + self.ci(coin_type).coin_name().lower()
|
||||||
addr = self.getReceiveAddressForCoin(coin_type)
|
addr = self.getReceiveAddressForCoin(coin_type)
|
||||||
self.setStringKV(key_str, addr)
|
self.setStringKV(key_str, addr)
|
||||||
|
@ -2012,7 +2012,7 @@ class BasicSwap(BaseApp):
|
||||||
raise ValueError('Wallet seed doesn\'t match expected.')
|
raise ValueError('Wallet seed doesn\'t match expected.')
|
||||||
|
|
||||||
def getCachedAddressForCoin(self, coin_type):
|
def getCachedAddressForCoin(self, coin_type):
|
||||||
self.log.debug('getCachedAddressForCoin %s', coin_type)
|
self.log.debug('getCachedAddressForCoin %s', Coins(coin_type).name)
|
||||||
# TODO: auto refresh after used
|
# TODO: auto refresh after used
|
||||||
|
|
||||||
ci = self.ci(coin_type)
|
ci = self.ci(coin_type)
|
||||||
|
@ -2032,7 +2032,7 @@ class BasicSwap(BaseApp):
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def cacheNewStealthAddressForCoin(self, coin_type):
|
def cacheNewStealthAddressForCoin(self, coin_type):
|
||||||
self.log.debug('cacheNewStealthAddressForCoin %s', coin_type)
|
self.log.debug('cacheNewStealthAddressForCoin %s', Coins(coin_type).name)
|
||||||
|
|
||||||
if coin_type == Coins.LTC_MWEB:
|
if coin_type == Coins.LTC_MWEB:
|
||||||
coin_type = Coins.LTC
|
coin_type = Coins.LTC
|
||||||
|
@ -2043,7 +2043,7 @@ class BasicSwap(BaseApp):
|
||||||
return addr
|
return addr
|
||||||
|
|
||||||
def getCachedStealthAddressForCoin(self, coin_type):
|
def getCachedStealthAddressForCoin(self, coin_type):
|
||||||
self.log.debug('getCachedStealthAddressForCoin %s', coin_type)
|
self.log.debug('getCachedStealthAddressForCoin %s', Coins(coin_type).name)
|
||||||
|
|
||||||
if coin_type == Coins.LTC_MWEB:
|
if coin_type == Coins.LTC_MWEB:
|
||||||
coin_type = Coins.LTC
|
coin_type = Coins.LTC
|
||||||
|
@ -2546,7 +2546,7 @@ class BasicSwap(BaseApp):
|
||||||
lock_value = self.callcoinrpc(coin_from, 'getblockcount') + offer.lock_value
|
lock_value = self.callcoinrpc(coin_from, 'getblockcount') + offer.lock_value
|
||||||
else:
|
else:
|
||||||
lock_value = self.getTime() + offer.lock_value
|
lock_value = self.getTime() + offer.lock_value
|
||||||
self.log.debug('Initiate %s lock_value %d %d', coin_from, offer.lock_value, lock_value)
|
self.log.debug('Initiate %s lock_value %d %d', ci_from.coin_name(), offer.lock_value, lock_value)
|
||||||
script = atomic_swap_1.buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
script = atomic_swap_1.buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||||
|
|
||||||
p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
|
p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
|
||||||
|
@ -3161,12 +3161,12 @@ class BasicSwap(BaseApp):
|
||||||
cblock_hash = block_header_at['hash']
|
cblock_hash = block_header_at['hash']
|
||||||
cblock_height = block_header_at['height']
|
cblock_height = block_header_at['height']
|
||||||
|
|
||||||
self.log.debug('Setting lock value from height of block %s %s', coin_to, cblock_hash)
|
self.log.debug('Setting lock value from height of block %s %s', Coins(coin_to).name, cblock_hash)
|
||||||
contract_lock_value = cblock_height + lock_value
|
contract_lock_value = cblock_height + lock_value
|
||||||
else:
|
else:
|
||||||
self.log.debug('Setting lock value from time of block %s %s', coin_from, initiate_tx_block_hash)
|
self.log.debug('Setting lock value from time of block %s %s', Coins(coin_from).name, initiate_tx_block_hash)
|
||||||
contract_lock_value = initiate_tx_block_time + lock_value
|
contract_lock_value = initiate_tx_block_time + lock_value
|
||||||
self.log.debug('participate %s lock_value %d %d', coin_to, lock_value, contract_lock_value)
|
self.log.debug('participate %s lock_value %d %d', Coins(coin_to).name, lock_value, contract_lock_value)
|
||||||
participate_script = atomic_swap_1.buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
participate_script = atomic_swap_1.buildContractScript(contract_lock_value, secret_hash, pkhash_seller, pkhash_buyer_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
|
||||||
return participate_script
|
return participate_script
|
||||||
|
|
||||||
|
@ -3965,7 +3965,7 @@ class BasicSwap(BaseApp):
|
||||||
bid.participate_tx.conf = found['depth']
|
bid.participate_tx.conf = found['depth']
|
||||||
index = found['index']
|
index = found['index']
|
||||||
if bid.participate_tx is None or bid.participate_tx.txid is None:
|
if bid.participate_tx is None or bid.participate_tx.txid is None:
|
||||||
self.log.debug('Found bid %s participate txn %s in chain %s', bid_id.hex(), found['txid'], coin_to)
|
self.log.debug('Found bid %s participate txn %s in chain %s', bid_id.hex(), found['txid'], Coins(coin_to).name)
|
||||||
self.addParticipateTxn(bid_id, bid, coin_to, found['txid'], found['index'], found['height'])
|
self.addParticipateTxn(bid_id, bid, coin_to, found['txid'], found['index'], found['height'])
|
||||||
bid.setPTxState(TxStates.TX_SENT)
|
bid.setPTxState(TxStates.TX_SENT)
|
||||||
save_bid = True
|
save_bid = True
|
||||||
|
@ -4265,7 +4265,7 @@ class BasicSwap(BaseApp):
|
||||||
|
|
||||||
def checkForSpends(self, coin_type, c):
|
def checkForSpends(self, coin_type, c):
|
||||||
# assert (self.mxDB.locked())
|
# assert (self.mxDB.locked())
|
||||||
self.log.debug('checkForSpends %s', coin_type)
|
self.log.debug('checkForSpends %s', Coins(coin_type).name)
|
||||||
|
|
||||||
# TODO: Check for spends on watchonly txns where possible
|
# TODO: Check for spends on watchonly txns where possible
|
||||||
|
|
||||||
|
@ -7375,7 +7375,7 @@ class BasicSwap(BaseApp):
|
||||||
return self._is_encrypted, self._is_locked
|
return self._is_encrypted, self._is_locked
|
||||||
|
|
||||||
def lookupRates(self, coin_from, coin_to, output_array=False):
|
def lookupRates(self, coin_from, coin_to, output_array=False):
|
||||||
self.log.debug('lookupRates {}, {}'.format(coin_from, coin_to))
|
self.log.debug('lookupRates {}, {}'.format(coin_from, Coins(coin_to).name))
|
||||||
|
|
||||||
rate_sources = self.settings.get('rate_sources', {})
|
rate_sources = self.settings.get('rate_sources', {})
|
||||||
ci_from = self.ci(int(coin_from))
|
ci_from = self.ci(int(coin_from))
|
||||||
|
|
|
@ -1378,8 +1378,6 @@ class BTCInterface(CoinInterface):
|
||||||
for u in unspent:
|
for u in unspent:
|
||||||
if u.get('spendable', False) is False:
|
if u.get('spendable', False) is False:
|
||||||
continue
|
continue
|
||||||
if u.get('solveable', False) is False:
|
|
||||||
continue
|
|
||||||
if 'address' not in u:
|
if 'address' not in u:
|
||||||
continue
|
continue
|
||||||
if 'desc' in u:
|
if 'desc' in u:
|
||||||
|
@ -1411,7 +1409,6 @@ class BTCInterface(CoinInterface):
|
||||||
def getProofOfFunds(self, amount_for, extra_commit_bytes):
|
def getProofOfFunds(self, amount_for, extra_commit_bytes):
|
||||||
# TODO: Lock unspent and use same output/s to fund bid
|
# TODO: Lock unspent and use same output/s to fund bid
|
||||||
unspent_addr = self.getUnspentsByAddr()
|
unspent_addr = self.getUnspentsByAddr()
|
||||||
|
|
||||||
sign_for_addr = None
|
sign_for_addr = None
|
||||||
for addr, value in unspent_addr.items():
|
for addr, value in unspent_addr.items():
|
||||||
if value >= amount_for:
|
if value >= amount_for:
|
||||||
|
|
|
@ -51,6 +51,31 @@ class LTCInterface(BTCInterface):
|
||||||
rv['mweb_immature'] = mweb_info['immature_balance']
|
rv['mweb_immature'] = mweb_info['immature_balance']
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
def getUnspentsByAddr(self):
|
||||||
|
unspent_addr = dict()
|
||||||
|
unspent = self.rpc_wallet('listunspent')
|
||||||
|
for u in unspent:
|
||||||
|
if u.get('spendable', False) is False:
|
||||||
|
continue
|
||||||
|
if u.get('solvable', False) is False: # Filter out mweb outputs
|
||||||
|
continue
|
||||||
|
if 'address' not in u:
|
||||||
|
continue
|
||||||
|
if 'desc' in u:
|
||||||
|
desc = u['desc']
|
||||||
|
if self.using_segwit:
|
||||||
|
if self.use_p2shp2wsh():
|
||||||
|
if not desc.startswith('sh(wpkh'):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if not desc.startswith('wpkh'):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if not desc.startswith('pkh'):
|
||||||
|
continue
|
||||||
|
unspent_addr[u['address']] = unspent_addr.get(u['address'], 0) + self.make_int(u['amount'], r=1)
|
||||||
|
return unspent_addr
|
||||||
|
|
||||||
|
|
||||||
class LTCInterfaceMWEB(LTCInterface):
|
class LTCInterfaceMWEB(LTCInterface):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
<option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
|
<option{% if data.addr_from==a[0] %} selected{% endif %} value="{{ a[0] }}">{{ a[0] }} {{ a[1] }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<option{% if data.addr_from=="-1" %} selected{% endif %} value="-1">New Address</option>
|
<option{% if data.addr_from=="-1" %} selected{% endif %} value="-1">New Address</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -149,7 +149,7 @@
|
||||||
<div class="flex flex-wrap -m-3">
|
<div class="flex flex-wrap -m-3">
|
||||||
<div class="w-full md:w-1/2 p-3">
|
<div class="w-full md:w-1/2 p-3">
|
||||||
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Select Coin You Send</p>
|
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Select Coin You Send</p>
|
||||||
<div class="custom-select">
|
<div class="custom-select">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
{{ input_down_arrow_offer_svg | safe }}
|
{{ input_down_arrow_offer_svg | safe }}
|
||||||
<select class="select hover:border-blue-500 pl-10 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 bold focus:ring-0" id="coin_from" name="coin_from" onchange="set_rate('coin_from');">
|
<select class="select hover:border-blue-500 pl-10 bg-gray-50 text-gray-900 appearance-none pr-10 dark:bg-gray-500 dark:text-white border border-gray-300 dark:border-gray-400 dark:text-gray-50 dark:placeholder-gray-400 text-sm rounded-lg outline-none focus:ring-blue-500 focus:border-blue-500 block w-full p-5 bold focus:ring-0" id="coin_from" name="coin_from" onchange="set_rate('coin_from');">
|
||||||
|
@ -182,7 +182,7 @@
|
||||||
<div class="w-full md:flex-1 p-3">
|
<div class="w-full md:flex-1 p-3">
|
||||||
<div class="flex flex-wrap -m-3">
|
<div class="flex flex-wrap -m-3">
|
||||||
<div class="w-full md:w-1/2 p-3">
|
<div class="w-full md:w-1/2 p-3">
|
||||||
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Select Coin You Get</p>
|
<p class="mb-1.5 font-medium text-base text-coolGray-800 dark:text-white">Select Coin You Get</p>
|
||||||
<div class="custom-select">
|
<div class="custom-select">
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
{{ input_down_arrow_offer_svg | safe }}
|
{{ input_down_arrow_offer_svg | safe }}
|
||||||
|
@ -343,22 +343,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookup_rates() {
|
function lookup_rates() {
|
||||||
const coin_from = document.getElementById('coin_from').value;
|
const coin_from = document.getElementById('coin_from').value;
|
||||||
const coin_to = document.getElementById('coin_to').value;
|
const coin_to = document.getElementById('coin_to').value;
|
||||||
|
|
||||||
if (coin_from === '-1' || coin_to === '-1') {
|
if (coin_from === '-1' || coin_to === '-1') {
|
||||||
alert('Coins from and to must be set first.');
|
alert('Coins from and to must be set first.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedCoin = (coin_from === '15') ? '3' : coin_from;
|
const selectedCoin = (coin_from === '15') ? '3' : coin_from;
|
||||||
|
|
||||||
inner_html = '<p>Updating...</p>';
|
inner_html = '<p>Updating...</p>';
|
||||||
document.getElementById('rates_display').innerHTML = inner_html;
|
document.getElementById('rates_display').innerHTML = inner_html;
|
||||||
document.querySelector(".pricejsonhidden").classList.remove("hidden");
|
document.querySelector(".pricejsonhidden").classList.remove("hidden");
|
||||||
|
|
||||||
const xhr_rates = new XMLHttpRequest();
|
const xhr_rates = new XMLHttpRequest();
|
||||||
xhr_rates.onreadystatechange = function() {
|
xhr_rates.onreadystatechange = function() {
|
||||||
if (xhr_rates.readyState === XMLHttpRequest.DONE) {
|
if (xhr_rates.readyState === XMLHttpRequest.DONE) {
|
||||||
|
@ -369,19 +369,19 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr_rates.open('POST', '/json/rates');
|
xhr_rates.open('POST', '/json/rates');
|
||||||
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||||
xhr_rates.send('coin_from=' + selectedCoin + '&coin_to=' + coin_to);
|
xhr_rates.send('coin_from=' + selectedCoin + '&coin_to=' + coin_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getRateInferred(event) {
|
function getRateInferred(event) {
|
||||||
event.preventDefault(); // Prevent default form submission behavior
|
event.preventDefault(); // Prevent default form submission behavior
|
||||||
|
|
||||||
const coin_from = document.getElementById('coin_from').value;
|
const coin_from = document.getElementById('coin_from').value;
|
||||||
const coin_to = document.getElementById('coin_to').value;
|
const coin_to = document.getElementById('coin_to').value;
|
||||||
const params = 'coin_from=' + encodeURIComponent(coin_from) + '&coin_to=' + encodeURIComponent(coin_to);
|
const params = 'coin_from=' + encodeURIComponent(coin_from) + '&coin_to=' + encodeURIComponent(coin_to);
|
||||||
|
|
||||||
const xhr_rates = new XMLHttpRequest();
|
const xhr_rates = new XMLHttpRequest();
|
||||||
xhr_rates.onreadystatechange = function() {
|
xhr_rates.onreadystatechange = function() {
|
||||||
if (xhr_rates.readyState === XMLHttpRequest.DONE) {
|
if (xhr_rates.readyState === XMLHttpRequest.DONE) {
|
||||||
|
@ -400,14 +400,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
xhr_rates.open('POST', '/json/rates');
|
xhr_rates.open('POST', '/json/rates');
|
||||||
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
xhr_rates.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||||
xhr_rates.send(params);
|
xhr_rates.send(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('get_rate_inferred_button').addEventListener('click', getRateInferred);
|
document.getElementById('get_rate_inferred_button').addEventListener('click', getRateInferred);
|
||||||
|
|
||||||
function set_swap_type_enabled(coin_from, coin_to, swap_type) {
|
function set_swap_type_enabled(coin_from, coin_to, swap_type) {
|
||||||
const adaptor_sig_only_coins = ['6' /* XMR */, '8' /* PART_ANON */, '7' /* PART_BLIND */, '13' /* FIRO */];
|
const adaptor_sig_only_coins = ['6' /* XMR */, '8' /* PART_ANON */, '7' /* PART_BLIND */, '13' /* FIRO */];
|
||||||
const secret_hash_only_coins = ['11' /* PIVX */, '12' /* DASH */];
|
const secret_hash_only_coins = ['11' /* PIVX */, '12' /* DASH */];
|
||||||
|
@ -442,7 +442,7 @@
|
||||||
swap_type_hidden.parentNode.removeChild(swap_type_hidden);
|
swap_type_hidden.parentNode.removeChild(swap_type_hidden);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_rate(value_changed) {
|
function set_rate(value_changed) {
|
||||||
const coin_from = document.getElementById('coin_from').value;
|
const coin_from = document.getElementById('coin_from').value;
|
||||||
const coin_to = document.getElementById('coin_to').value;
|
const coin_to = document.getElementById('coin_to').value;
|
||||||
|
@ -450,19 +450,26 @@
|
||||||
const amt_to = document.getElementById('amt_to').value;
|
const amt_to = document.getElementById('amt_to').value;
|
||||||
const rate = document.getElementById('rate').value;
|
const rate = document.getElementById('rate').value;
|
||||||
const lock_rate = rate == '' ? false : document.getElementById('rate_lock').checked;
|
const lock_rate = rate == '' ? false : document.getElementById('rate_lock').checked;
|
||||||
|
|
||||||
const swap_type = document.getElementById('swap_type');
|
const swap_type = document.getElementById('swap_type');
|
||||||
set_swap_type_enabled(coin_from, coin_to, swap_type);
|
set_swap_type_enabled(coin_from, coin_to, swap_type);
|
||||||
|
|
||||||
if (coin_from == '-1' || coin_to == '-1') {
|
if (coin_from == '-1' || coin_to == '-1') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params = 'coin_from=' + coin_from + '&coin_to=' + coin_to;
|
params = 'coin_from=' + coin_from + '&coin_to=' + coin_to;
|
||||||
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from') || (amt_to == '' && value_changed == 'amt_from')) {
|
if (value_changed == 'rate' || (lock_rate && value_changed == 'amt_from') || (amt_to == '' && value_changed == 'amt_from')) {
|
||||||
if (amt_from == '' || rate == '') {
|
if (rate == '' || (amt_from == '' && amt_to == '')) {
|
||||||
return;
|
return;
|
||||||
|
} else
|
||||||
|
if (amt_from == '' && amt_to != '') {
|
||||||
|
if (value_changed == 'amt_from') { // Don't try and set a value just cleared
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
params += '&rate=' + rate + '&amt_to=' + amt_to;
|
||||||
|
} else {
|
||||||
|
params += '&rate=' + rate + '&amt_from=' + amt_from;
|
||||||
}
|
}
|
||||||
params += '&rate=' + rate + '&amt_from=' + amt_from;
|
|
||||||
} else
|
} else
|
||||||
if (lock_rate && value_changed == 'amt_to') {
|
if (lock_rate && value_changed == 'amt_to') {
|
||||||
if (amt_to == '' || rate == '') {
|
if (amt_to == '' || rate == '') {
|
||||||
|
@ -479,7 +486,7 @@
|
||||||
xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
xhr_rate.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||||
xhr_rate.send(params);
|
xhr_rate.send(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const coin_from = document.getElementById('coin_from').value;
|
const coin_from = document.getElementById('coin_from').value;
|
||||||
const coin_to = document.getElementById('coin_to').value;
|
const coin_to = document.getElementById('coin_to').value;
|
||||||
|
@ -492,4 +499,4 @@
|
||||||
{% include 'footer.html' %}
|
{% include 'footer.html' %}
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
- All for all known coins.
|
- All for all known coins.
|
||||||
- Comma separated list of coin tickers to show.
|
- Comma separated list of coin tickers to show.
|
||||||
- basicswap-run will rewrite litecoin.conf file to add config required to run Litecoin 0.21.3 in pruned mode.
|
- basicswap-run will rewrite litecoin.conf file to add config required to run Litecoin 0.21.3 in pruned mode.
|
||||||
|
- On new offers page a blank amount-from is auto-filled from amount-to and rate.
|
||||||
|
|
||||||
|
|
||||||
0.12.7
|
0.12.7
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright (c) 2023 tecnovert
|
# Copyright (c) 2023-2024 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.
|
||||||
|
|
||||||
|
@ -29,8 +29,39 @@ def test_offer(driver):
|
||||||
select = Select(driver.find_element(By.ID, 'coin_to'))
|
select = Select(driver.find_element(By.ID, 'coin_to'))
|
||||||
select.select_by_visible_text('Monero')
|
select.select_by_visible_text('Monero')
|
||||||
|
|
||||||
driver.find_element(By.NAME, 'amt_from').send_keys('1')
|
amt_from = driver.find_element(By.NAME, 'amt_from')
|
||||||
driver.find_element(By.NAME, 'amt_to').send_keys('2')
|
amt_to = driver.find_element(By.NAME, 'amt_to')
|
||||||
|
rate = driver.find_element(By.ID, 'rate')
|
||||||
|
amt_from.send_keys('1')
|
||||||
|
amt_to.send_keys('2')
|
||||||
|
amt_from.click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
rate_value = rate.get_attribute('value')
|
||||||
|
assert (float(rate_value) == 2.0)
|
||||||
|
|
||||||
|
rate.clear()
|
||||||
|
rate.send_keys('3')
|
||||||
|
amt_from.click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
amt_to_value = amt_to.get_attribute('value')
|
||||||
|
assert (float(amt_to_value) == 3.0)
|
||||||
|
|
||||||
|
amt_from.clear()
|
||||||
|
amt_from.send_keys('2')
|
||||||
|
amt_to.click()
|
||||||
|
time.sleep(0.5)
|
||||||
|
amt_to_value = amt_to.get_attribute('value')
|
||||||
|
assert (float(amt_to_value) == 6.0)
|
||||||
|
|
||||||
|
amt_from.clear()
|
||||||
|
amt_to.clear()
|
||||||
|
rate.clear()
|
||||||
|
amt_to.send_keys('2')
|
||||||
|
rate.send_keys('2')
|
||||||
|
amt_to.click()
|
||||||
|
time.sleep(0.2)
|
||||||
|
amt_from_value = amt_from.get_attribute('value')
|
||||||
|
assert (float(amt_from_value) == 1.0)
|
||||||
|
|
||||||
driver.find_element(By.NAME, 'continue').click()
|
driver.find_element(By.NAME, 'continue').click()
|
||||||
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
|
WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.NAME, 'check_offer'))).click()
|
||||||
|
|
|
@ -182,6 +182,7 @@ class TestLTC(BasicSwapTest):
|
||||||
|
|
||||||
require_amount: int = ci1.make_int(1)
|
require_amount: int = ci1.make_int(1)
|
||||||
unspent_addr = ci1.getUnspentsByAddr()
|
unspent_addr = ci1.getUnspentsByAddr()
|
||||||
|
assert (len(unspent_addr) > 0)
|
||||||
for addr, _ in unspent_addr.items():
|
for addr, _ in unspent_addr.items():
|
||||||
if 'mweb1' in addr:
|
if 'mweb1' in addr:
|
||||||
raise ValueError('getUnspentsByAddr should exclude mweb UTXOs.')
|
raise ValueError('getUnspentsByAddr should exclude mweb UTXOs.')
|
||||||
|
|
Loading…
Reference in a new issue