html: More offer filtering.

This commit is contained in:
tecnovert 2019-08-01 18:21:23 +02:00
parent 8731c9796a
commit da9f95fd61
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
10 changed files with 128 additions and 15 deletions

View file

@ -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"

View file

@ -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
View 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)

View file

@ -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')

View file

@ -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>

View file

@ -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

View file

@ -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'])

View file

@ -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()

View file

@ -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

View file

@ -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