mirror of
https://github.com/basicswap/basicswap.git
synced 2024-12-23 03:49:25 +00:00
html: More offer filtering.
This commit is contained in:
parent
8731c9796a
commit
da9f95fd61
10 changed files with 128 additions and 15 deletions
|
@ -6,7 +6,7 @@ stages:
|
||||||
- lint
|
- lint
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- TEST_DIR=/tmp/test_basicswap/
|
- TEST_DIR=~/test_basicswap2/
|
||||||
- PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/
|
- PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/
|
||||||
- BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/
|
- BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/
|
||||||
- LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/
|
- LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/
|
||||||
|
@ -22,9 +22,9 @@ script:
|
||||||
- export PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/
|
- export PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/
|
||||||
- export BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/
|
- export BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/
|
||||||
- export LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/
|
- export LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/
|
||||||
- TEST_DIR=/tmp/test_basicswap/
|
- export DATADIRS=~/test_basicswap2/
|
||||||
- mkdir -p ${TEST_DIR}/bin/{particl,bitcoin}
|
- mkdir -p ${DATADIRS}/bin/{particl,bitcoin}
|
||||||
- cp /opt/binaries/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz ${TEST_DIR}/bin/bitcoin
|
- cp /opt/binaries/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz ${DATADIRS}/bin/bitcoin
|
||||||
- python setup.py test
|
- python setup.py test
|
||||||
after_success:
|
after_success:
|
||||||
- echo "End test"
|
- echo "End test"
|
||||||
|
|
|
@ -54,6 +54,8 @@ from .db import (
|
||||||
SentOffer,
|
SentOffer,
|
||||||
SmsgAddress,
|
SmsgAddress,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz
|
||||||
import basicswap.config as cfg
|
import basicswap.config as cfg
|
||||||
import basicswap.segwit_addr as segwit_addr
|
import basicswap.segwit_addr as segwit_addr
|
||||||
|
|
||||||
|
@ -361,6 +363,24 @@ class BasicSwap():
|
||||||
for c in Coins:
|
for c in Coins:
|
||||||
self.setCoinConnectParams(c)
|
self.setCoinConnectParams(c)
|
||||||
|
|
||||||
|
if self.chain == 'mainnet':
|
||||||
|
self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
|
||||||
|
self,
|
||||||
|
'https://explorer.particl.io/particl-insight-api/'))
|
||||||
|
self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
|
||||||
|
self,
|
||||||
|
'https://api.bitaps.com/ltc/v1/blockchain'))
|
||||||
|
self.coin_clients[Coins.LTC]['explorers'].append(ExplorerChainz(
|
||||||
|
self,
|
||||||
|
'http://chainz.cryptoid.info/ltc/api.dws'))
|
||||||
|
elif self.chain == 'testnet':
|
||||||
|
self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
|
||||||
|
self,
|
||||||
|
'https://explorer-testnet.particl.io/particl-insight-api'))
|
||||||
|
self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
|
||||||
|
self,
|
||||||
|
'https://api.bitaps.com/ltc/testnet/v1/blockchain'))
|
||||||
|
|
||||||
def prepareLogging(self):
|
def prepareLogging(self):
|
||||||
self.log = logging.getLogger(self.log_name)
|
self.log = logging.getLogger(self.log_name)
|
||||||
self.log.propagate = False
|
self.log.propagate = False
|
||||||
|
@ -425,9 +445,13 @@ class BasicSwap():
|
||||||
'use_csv': chain_client_settings.get('use_csv', True),
|
'use_csv': chain_client_settings.get('use_csv', True),
|
||||||
'core_version_group': chain_client_settings.get('core_version_group', 0),
|
'core_version_group': chain_client_settings.get('core_version_group', 0),
|
||||||
'pid': None,
|
'pid': None,
|
||||||
|
'explorers': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
def setDaemonPID(self, name, pid):
|
def setDaemonPID(self, name, pid):
|
||||||
|
if isinstance(name, Coins):
|
||||||
|
self.coin_clients[name]['pid'] = pid
|
||||||
|
return
|
||||||
for c, v in self.coin_clients.items():
|
for c, v in self.coin_clients.items():
|
||||||
if v['name'] == name:
|
if v['name'] == name:
|
||||||
v['pid'] = pid
|
v['pid'] = pid
|
||||||
|
@ -2379,7 +2403,12 @@ class BasicSwap():
|
||||||
if filter_coin_to and filter_coin_to > -1:
|
if filter_coin_to and filter_coin_to > -1:
|
||||||
q = q.filter(Offer.coin_to == int(filter_coin_to))
|
q = q.filter(Offer.coin_to == int(filter_coin_to))
|
||||||
|
|
||||||
q = q.order_by(Offer.created_at.desc())
|
order_dir = filters.get('sort_dir', 'desc')
|
||||||
|
order_by = filters.get('order_by', 'created_at')
|
||||||
|
if order_by == 'created_at':
|
||||||
|
q = q.order_by(Offer.created_at.desc() if order_dir == 'desc' else Offer.created_at.asc())
|
||||||
|
elif order_by == 'rate':
|
||||||
|
q = q.order_by(Offer.rate.desc() if order_dir == 'desc' else Offer.rate.asc())
|
||||||
|
|
||||||
limit = filters.get('limit', None)
|
limit = filters.get('limit', None)
|
||||||
if limit is not None:
|
if limit is not None:
|
||||||
|
|
42
basicswap/explorers.py
Normal file
42
basicswap/explorers.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright (c) 2019 tecnovert
|
||||||
|
# Distributed under the MIT software license, see the accompanying
|
||||||
|
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
import urllib.request
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Explorer():
|
||||||
|
def __init__(self, swapclient, base_url):
|
||||||
|
self.swapclient = swapclient
|
||||||
|
self.base_url = base_url
|
||||||
|
self.log = self.swapclient.log
|
||||||
|
|
||||||
|
|
||||||
|
class ExplorerInsight(Explorer):
|
||||||
|
def getChainHeight(self):
|
||||||
|
return json.loads(urllib.request.urlopen(self.base_url + '/sync').read())['blockChainHeight']
|
||||||
|
|
||||||
|
def lookupUnspentByAddress(self, address):
|
||||||
|
chain_height = self.getChainHeight()
|
||||||
|
self.log.debug('[rm] chain_height %d', chain_height)
|
||||||
|
|
||||||
|
|
||||||
|
class ExplorerBitAps(Explorer):
|
||||||
|
def getChainHeight(self):
|
||||||
|
return json.loads(urllib.request.urlopen(self.base_url + '/block/last').read())['data']['block']['height']
|
||||||
|
|
||||||
|
def lookupUnspentByAddress(self, address):
|
||||||
|
chain_height = self.getChainHeight()
|
||||||
|
self.log.debug('[rm] chain_height %d', chain_height)
|
||||||
|
|
||||||
|
|
||||||
|
class ExplorerChainz(Explorer):
|
||||||
|
def getChainHeight(self):
|
||||||
|
return int(urllib.request.urlopen(self.base_url + '?q=getblockcount').read())
|
||||||
|
|
||||||
|
def lookupUnspentByAddress(self, address):
|
||||||
|
chain_height = self.getChainHeight()
|
||||||
|
self.log.debug('[rm] chain_height %d', chain_height)
|
|
@ -45,6 +45,7 @@ def format_timestamp(value):
|
||||||
|
|
||||||
env = Environment(loader=PackageLoader('basicswap', 'templates'))
|
env = Environment(loader=PackageLoader('basicswap', 'templates'))
|
||||||
env.filters['formatts'] = format_timestamp
|
env.filters['formatts'] = format_timestamp
|
||||||
|
PAGE_LIMIT = 50
|
||||||
|
|
||||||
|
|
||||||
def getCoinName(c):
|
def getCoinName(c):
|
||||||
|
@ -373,6 +374,10 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
filters = {
|
filters = {
|
||||||
'coin_from': -1,
|
'coin_from': -1,
|
||||||
'coin_to': -1,
|
'coin_to': -1,
|
||||||
|
'page_no': 1,
|
||||||
|
'limit': PAGE_LIMIT,
|
||||||
|
'sort_by': 'created_at',
|
||||||
|
'sort_dir': 'desc',
|
||||||
}
|
}
|
||||||
messages = []
|
messages = []
|
||||||
form_data = self.checkForm(post_string, 'offers', messages)
|
form_data = self.checkForm(post_string, 'offers', messages)
|
||||||
|
@ -390,6 +395,25 @@ class HttpHandler(BaseHTTPRequestHandler):
|
||||||
except Exception:
|
except Exception:
|
||||||
raise ValueError('Unknown Coin From')
|
raise ValueError('Unknown Coin From')
|
||||||
|
|
||||||
|
if b'sort_by' in form_data:
|
||||||
|
sort_by = form_data[b'sort_by'][0].decode('utf-8')
|
||||||
|
assert(sort_by in ['created_at', 'rate']), 'Invalid sort by'
|
||||||
|
filters['sort_by'] = sort_by
|
||||||
|
if b'sort_dir' in form_data:
|
||||||
|
sort_dir = form_data[b'sort_dir'][0].decode('utf-8')
|
||||||
|
assert(sort_dir in ['asc', 'desc']), 'Invalid sort dir'
|
||||||
|
filters['sort_dir'] = sort_dir
|
||||||
|
|
||||||
|
if form_data and b'pageback' in form_data:
|
||||||
|
filters['page_no'] = int(form_data[b'pageno'][0]) - 1
|
||||||
|
if filters['page_no'] < 1:
|
||||||
|
filters['page_no'] = 1
|
||||||
|
if form_data and b'pageforwards' in form_data:
|
||||||
|
filters['page_no'] = int(form_data[b'pageno'][0]) + 1
|
||||||
|
|
||||||
|
if filters['page_no'] > 1:
|
||||||
|
filters['offset'] = (filters['page_no'] - 1) * PAGE_LIMIT
|
||||||
|
|
||||||
offers = swap_client.listOffers(sent, filters)
|
offers = swap_client.listOffers(sent, filters)
|
||||||
|
|
||||||
template = env.get_template('offers.html')
|
template = env.get_template('offers.html')
|
||||||
|
|
|
@ -25,9 +25,22 @@
|
||||||
</select>
|
</select>
|
||||||
</td></tr>
|
</td></tr>
|
||||||
|
|
||||||
|
<tr><td>Sort By</td><td>
|
||||||
|
<select name="sort_by">
|
||||||
|
<option value="created_at"{% if filters.sort_by=='created_at' %} selected{% endif %}>Created At</option>
|
||||||
|
<option value="rate"{% if filters.sort_by=='rate' %} selected{% endif %}>Rate</option>
|
||||||
|
</select>
|
||||||
|
<select name="sort_dir">
|
||||||
|
<option value="asc"{% if filters.sort_dir=='asc' %} selected{% endif %}>Ascending</option>
|
||||||
|
<option value="desc"{% if filters.sort_dir=='desc' %} selected{% endif %}>Descending</option>
|
||||||
|
</select>
|
||||||
|
</td></tr>
|
||||||
|
|
||||||
<tr><td><input type="submit" name='applyfilters' value="Apply Filters"></td><td><input type="submit" name='clearfilters' value="Clear Filters"></td></tr>
|
<tr><td><input type="submit" name='applyfilters' value="Apply Filters"></td><td><input type="submit" name='clearfilters' value="Clear Filters"></td></tr>
|
||||||
|
<tr><td><input type="submit" name='pageback' value="Page Back"></td><td>Page: {{ filters.page_no }}</td><td><input type="submit" name='pageforwards' value="Page Forwards"></td></tr>
|
||||||
</table>
|
</table>
|
||||||
<input type="hidden" name="formid" value="{{ form_id }}">
|
<input type="hidden" name="formid" value="{{ form_id }}">
|
||||||
|
<input type="hidden" name="pageno" value="{{ filters.page_no }}">
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -271,12 +271,6 @@ def make_rpc_func(bin_dir, data_dir, chain):
|
||||||
nonlocal data_dir
|
nonlocal data_dir
|
||||||
nonlocal chain
|
nonlocal chain
|
||||||
|
|
||||||
# Debug ci
|
|
||||||
try:
|
|
||||||
os.system('cat ' + os.path.join(data_dir, 'debug.log'))
|
|
||||||
except Exception as ex:
|
|
||||||
logger.error(ex)
|
|
||||||
|
|
||||||
return callrpc_cli(bin_dir, data_dir, chain, cmd, cfg.PARTICL_CLI)
|
return callrpc_cli(bin_dir, data_dir, chain, cmd, cfg.PARTICL_CLI)
|
||||||
return rpc_func
|
return rpc_func
|
||||||
|
|
||||||
|
|
|
@ -257,6 +257,9 @@ class Test(unittest.TestCase):
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
|
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
|
||||||
cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
|
cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.BTC, cls.daemons[0].pid)
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.NMC, cls.daemons[1].pid)
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
|
||||||
cls.swap_clients[-1].start()
|
cls.swap_clients[-1].start()
|
||||||
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
|
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
|
||||||
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
|
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
|
||||||
|
|
|
@ -33,7 +33,7 @@ class Test(unittest.TestCase):
|
||||||
super(Test, self).tearDownClass()
|
super(Test, self).tearDownClass()
|
||||||
|
|
||||||
def test(self):
|
def test(self):
|
||||||
testargs = ['basicswap-prepare', '-datadir=' + test_path, '-particl_mnemonic=none'] # Why won't the daemon run in travis-ci?
|
testargs = ['basicswap-prepare', '-datadir=' + test_path]
|
||||||
with patch.object(sys, 'argv', testargs):
|
with patch.object(sys, 'argv', testargs):
|
||||||
prepareSystem.main()
|
prepareSystem.main()
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import threading
|
||||||
|
|
||||||
import bin.basicswap_prepare as prepareSystem
|
import bin.basicswap_prepare as prepareSystem
|
||||||
import bin.basicswap_run as runSystem
|
import bin.basicswap_run as runSystem
|
||||||
test_path = os.path.expanduser('/tmp/test_basicswap')
|
test_path = os.path.expanduser('~/test_basicswap1')
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
logger.level = logging.DEBUG
|
logger.level = logging.DEBUG
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
basicswap]$ python setup.py test
|
basicswap]$ python setup.py test
|
||||||
|
|
||||||
Run one test:
|
Run one test:
|
||||||
$ python setup.py test -s tests.test_run.Test.test_04_ltc_btc
|
$ python setup.py test -s tests.basicswap.test_run.Test.test_04_ltc_btc
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -259,6 +259,9 @@ class Test(unittest.TestCase):
|
||||||
settings = json.load(fs)
|
settings = json.load(fs)
|
||||||
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
|
fp = open(os.path.join(basicswap_dir, 'basicswap.log'), 'w')
|
||||||
cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
|
cls.swap_clients.append(BasicSwap(fp, basicswap_dir, settings, 'regtest', log_name='BasicSwap{}'.format(i)))
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.BTC, cls.daemons[0].pid)
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.LTC, cls.daemons[1].pid)
|
||||||
|
cls.swap_clients[-1].setDaemonPID(Coins.PART, cls.daemons[2 + i].pid)
|
||||||
cls.swap_clients[-1].start()
|
cls.swap_clients[-1].start()
|
||||||
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
|
cls.swap_clients[0].callrpc('extkeyimportmaster', ['abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb'])
|
||||||
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
|
cls.swap_clients[1].callrpc('extkeyimportmaster', ['pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true'])
|
||||||
|
@ -558,11 +561,16 @@ class Test(unittest.TestCase):
|
||||||
def pass_99_delay(self):
|
def pass_99_delay(self):
|
||||||
global stop_test
|
global stop_test
|
||||||
logging.info('Delay')
|
logging.info('Delay')
|
||||||
for i in range(60 * 5):
|
for i in range(60 * 10):
|
||||||
if stop_test:
|
if stop_test:
|
||||||
break
|
break
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print('delay', i)
|
print('delay', i)
|
||||||
|
if i % 2 == 0:
|
||||||
|
offer_id = self.swap_clients[0].postOffer(Coins.BTC, Coins.LTC, 0.001 * (i + 1) * COIN, 1.0 * (i + 1) * COIN, 0.001 * (i + 1) * COIN, SwapTypes.SELLER_FIRST)
|
||||||
|
else:
|
||||||
|
offer_id = self.swap_clients[1].postOffer(Coins.LTC, Coins.BTC, 0.001 * (i + 1) * COIN, 1.0 * (i + 1) * COIN, 0.001 * COIN, SwapTypes.SELLER_FIRST)
|
||||||
|
|
||||||
stop_test = True
|
stop_test = True
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue