From da9f95fd61ea86d4962d7a8102ddbaf6fa5903b9 Mon Sep 17 00:00:00 2001 From: tecnovert Date: Thu, 1 Aug 2019 18:21:23 +0200 Subject: [PATCH] html: More offer filtering. --- .travis.yml | 8 +++---- basicswap/basicswap.py | 31 +++++++++++++++++++++++- basicswap/explorers.py | 42 +++++++++++++++++++++++++++++++++ basicswap/http_server.py | 24 +++++++++++++++++++ basicswap/templates/offers.html | 13 ++++++++++ bin/basicswap_prepare.py | 6 ----- tests/basicswap/test_nmc.py | 3 +++ tests/basicswap/test_prepare.py | 2 +- tests/basicswap/test_reload.py | 2 +- tests/basicswap/test_run.py | 12 ++++++++-- 10 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 basicswap/explorers.py diff --git a/.travis.yml b/.travis.yml index 2215ba2..c1c2f5f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ stages: - lint env: global: - - TEST_DIR=/tmp/test_basicswap/ + - TEST_DIR=~/test_basicswap2/ - PARTICL_BINDIR=/opt/binaries/particl-0.18.0.12/bin/ - BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/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 BITCOIN_BINDIR=/opt/binaries/bitcoin-0.18.0/bin/ - export LITECOIN_BINDIR=/opt/binaries/litecoin-0.17.1/bin/ - - TEST_DIR=/tmp/test_basicswap/ - - mkdir -p ${TEST_DIR}/bin/{particl,bitcoin} - - cp /opt/binaries/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz ${TEST_DIR}/bin/bitcoin + - export DATADIRS=~/test_basicswap2/ + - mkdir -p ${DATADIRS}/bin/{particl,bitcoin} + - cp /opt/binaries/bitcoin-0.18.0-x86_64-linux-gnu.tar.gz ${DATADIRS}/bin/bitcoin - python setup.py test after_success: - echo "End test" diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index c8926c9..661c35e 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -54,6 +54,8 @@ from .db import ( SentOffer, SmsgAddress, ) + +from .explorers import ExplorerInsight, ExplorerBitAps, ExplorerChainz import basicswap.config as cfg import basicswap.segwit_addr as segwit_addr @@ -361,6 +363,24 @@ class BasicSwap(): for c in Coins: 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): self.log = logging.getLogger(self.log_name) self.log.propagate = False @@ -425,9 +445,13 @@ class BasicSwap(): 'use_csv': chain_client_settings.get('use_csv', True), 'core_version_group': chain_client_settings.get('core_version_group', 0), 'pid': None, + 'explorers': [], } def setDaemonPID(self, name, pid): + if isinstance(name, Coins): + self.coin_clients[name]['pid'] = pid + return for c, v in self.coin_clients.items(): if v['name'] == name: v['pid'] = pid @@ -2379,7 +2403,12 @@ class BasicSwap(): if filter_coin_to and filter_coin_to > -1: 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) if limit is not None: diff --git a/basicswap/explorers.py b/basicswap/explorers.py new file mode 100644 index 0000000..6039799 --- /dev/null +++ b/basicswap/explorers.py @@ -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) diff --git a/basicswap/http_server.py b/basicswap/http_server.py index 92de1f0..aa3a853 100644 --- a/basicswap/http_server.py +++ b/basicswap/http_server.py @@ -45,6 +45,7 @@ def format_timestamp(value): env = Environment(loader=PackageLoader('basicswap', 'templates')) env.filters['formatts'] = format_timestamp +PAGE_LIMIT = 50 def getCoinName(c): @@ -373,6 +374,10 @@ class HttpHandler(BaseHTTPRequestHandler): filters = { 'coin_from': -1, 'coin_to': -1, + 'page_no': 1, + 'limit': PAGE_LIMIT, + 'sort_by': 'created_at', + 'sort_dir': 'desc', } messages = [] form_data = self.checkForm(post_string, 'offers', messages) @@ -390,6 +395,25 @@ class HttpHandler(BaseHTTPRequestHandler): except Exception: 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) template = env.get_template('offers.html') diff --git a/basicswap/templates/offers.html b/basicswap/templates/offers.html index ac2dad4..648960e 100644 --- a/basicswap/templates/offers.html +++ b/basicswap/templates/offers.html @@ -25,9 +25,22 @@ +Sort By + + + + +Page: {{ filters.page_no }} + diff --git a/bin/basicswap_prepare.py b/bin/basicswap_prepare.py index 3e609fd..35d445e 100644 --- a/bin/basicswap_prepare.py +++ b/bin/basicswap_prepare.py @@ -271,12 +271,6 @@ def make_rpc_func(bin_dir, data_dir, chain): nonlocal data_dir 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 rpc_func diff --git a/tests/basicswap/test_nmc.py b/tests/basicswap/test_nmc.py index 0293ee8..c028f64 100644 --- a/tests/basicswap/test_nmc.py +++ b/tests/basicswap/test_nmc.py @@ -257,6 +257,9 @@ class Test(unittest.TestCase): settings = json.load(fs) 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[-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[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']) diff --git a/tests/basicswap/test_prepare.py b/tests/basicswap/test_prepare.py index 2df4e0a..2c21de7 100644 --- a/tests/basicswap/test_prepare.py +++ b/tests/basicswap/test_prepare.py @@ -33,7 +33,7 @@ class Test(unittest.TestCase): super(Test, self).tearDownClass() 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): prepareSystem.main() diff --git a/tests/basicswap/test_reload.py b/tests/basicswap/test_reload.py index 6cb88fe..a07d142 100644 --- a/tests/basicswap/test_reload.py +++ b/tests/basicswap/test_reload.py @@ -26,7 +26,7 @@ import threading import bin.basicswap_prepare as prepareSystem 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.level = logging.DEBUG diff --git a/tests/basicswap/test_run.py b/tests/basicswap/test_run.py index 18d9fc1..3c719fc 100644 --- a/tests/basicswap/test_run.py +++ b/tests/basicswap/test_run.py @@ -9,7 +9,7 @@ basicswap]$ python setup.py 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) 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[-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[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']) @@ -558,11 +561,16 @@ class Test(unittest.TestCase): def pass_99_delay(self): global stop_test logging.info('Delay') - for i in range(60 * 5): + for i in range(60 * 10): if stop_test: break time.sleep(1) 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