Offers can be filtered.

This commit is contained in:
tecnovert 2019-07-29 12:14:46 +02:00
parent 4bc0ec98eb
commit 9b95c66605
No known key found for this signature in database
GPG key ID: 8ED6D8750C4E3F93
3 changed files with 168 additions and 125 deletions

View file

@ -604,6 +604,9 @@ class BasicSwap():
self.mxDB.acquire() self.mxDB.acquire()
try: try:
proof_addr, proof_sig = self.getProofOfFunds(coin_from_t, amount)
# TODO: require prrof of funds on offers?
msg_buf = OfferMessage() msg_buf = OfferMessage()
msg_buf.coin_from = int(coin_from) msg_buf.coin_from = int(coin_from)
msg_buf.coin_to = int(coin_to) msg_buf.coin_to = int(coin_to)
@ -2266,7 +2269,7 @@ class BasicSwap():
session.remove() session.remove()
self.mxDB.release() self.mxDB.release()
def listOffers(self, sent=False): def listOffers(self, sent=False, filters={}):
self.mxDB.acquire() self.mxDB.acquire()
try: try:
rv = [] rv = []
@ -2274,9 +2277,18 @@ class BasicSwap():
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
if sent: if sent:
q = session.query(Offer).filter(Offer.was_sent == True).order_by(Offer.created_at.desc()) # noqa E712 q = session.query(Offer).filter(Offer.was_sent == True) # noqa E712
else: else:
q = session.query(Offer).filter(Offer.expire_at > now).order_by(Offer.created_at.desc()) q = session.query(Offer).filter(Offer.expire_at > now)
filter_coin_from = filters.get('coin_from', None)
if filter_coin_from and filter_coin_from > -1:
q = q.filter(Offer.coin_from == int(filter_coin_from))
filter_coin_to = filters.get('coin_to', None)
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())
for row in q: for row in q:
rv.append(row) rv.append(row)
return rv return rv

View file

@ -50,6 +50,14 @@ def getCoinName(c):
return chainparams[c]['name'].capitalize() return chainparams[c]['name'].capitalize()
def listAvailableCoins(swap_client):
coins = []
for k, v in swap_client.coin_clients.items():
if v['connection_type'] == 'rpc':
coins.append((int(k), getCoinName(k)))
return coins
def getTxIdHex(bid, tx_type, prefix): def getTxIdHex(bid, tx_type, prefix):
if tx_type == TxTypes.ITX: if tx_type == TxTypes.ITX:
obj = bid.initiate_tx obj = bid.initiate_tx
@ -98,6 +106,17 @@ class HttpHandler(BaseHTTPRequestHandler):
+ '<p><a href=\'/\'>home</a></p></body></html>' + '<p><a href=\'/\'>home</a></p></body></html>'
return bytes(content, 'UTF-8') return bytes(content, 'UTF-8')
def checkForm(self, post_string, name, messages):
if post_string == '':
return None
form_data = urllib.parse.parse_qs(post_string)
form_id = form_data[b'formid'][0].decode('utf-8')
if self.server.last_form_id.get(name, None) == form_id:
messages.append('Prevented double submit for form {}.'.format(form_id))
else:
self.server.last_form_id[name] = form_id
return form_data
def js_error(self, error_str): def js_error(self, error_str):
error_str_json = json.dumps({'error': error_str}) error_str_json = json.dumps({'error': error_str})
return bytes(error_str_json, 'UTF-8') return bytes(error_str_json, 'UTF-8')
@ -132,35 +151,24 @@ class HttpHandler(BaseHTTPRequestHandler):
result = None result = None
messages = [] messages = []
if post_string != '': form_data = self.checkForm(post_string, 'rpc', messages)
form_data = urllib.parse.parse_qs(post_string) if form_data:
form_id = form_data[b'formid'][0].decode('utf-8') try:
if self.server.last_form_id.get('rpc', None) == form_id: coin_type = Coins(int(form_data[b'coin_type'][0]))
messages.append('Prevented double submit for form {}.'.format(form_id)) except Exception:
else: raise ValueError('Unknown Coin Type')
self.server.last_form_id['newoffer'] = form_id
try: cmd = form_data[b'cmd'][0].decode('utf-8')
coin_type = Coins(int(form_data[b'coin_type'][0])) try:
except Exception: result = swap_client.callcoincli(coin_type, cmd)
raise ValueError('Unknown Coin Type') except Exception as ex:
result = str(ex)
cmd = form_data[b'cmd'][0].decode('utf-8')
try:
result = swap_client.callcoincli(coin_type, cmd)
except Exception as ex:
result = str(ex)
coins = []
for k, v in swap_client.coin_clients.items():
if v['connection_type'] == 'rpc':
coins.append((int(k), getCoinName(k)))
template = env.get_template('rpc.html') template = env.get_template('rpc.html')
return bytes(template.render( return bytes(template.render(
title=self.server.title, title=self.server.title,
h2=self.server.title, h2=self.server.title,
coins=coins, coins=listAvailableCoins(swap_client),
result=result, result=result,
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
@ -181,27 +189,21 @@ class HttpHandler(BaseHTTPRequestHandler):
swap_client = self.server.swap_client swap_client = self.server.swap_client
messages = [] messages = []
if post_string != '': form_data = self.checkForm(post_string, 'wallets', messages)
form_data = urllib.parse.parse_qs(post_string) if form_data:
form_id = form_data[b'formid'][0].decode('utf-8') for c in Coins:
if self.server.last_form_id.get('wallets', None) == form_id: cid = str(int(c))
messages.append('Prevented double submit for form {}.'.format(form_id))
else:
self.server.last_form_id['wallets'] = form_id
for c in Coins: if bytes('newaddr_' + cid, 'utf-8') in form_data:
cid = str(int(c)) swap_client.cacheNewAddressForCoin(c)
if bytes('newaddr_' + cid, 'utf-8') in form_data: if bytes('withdraw_' + cid, 'utf-8') in form_data:
swap_client.cacheNewAddressForCoin(c) value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8')
address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8')
if bytes('withdraw_' + cid, 'utf-8') in form_data: subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False
value = form_data[bytes('amt_' + cid, 'utf-8')][0].decode('utf-8') txid = swap_client.withdrawCoin(c, value, address, subfee)
address = form_data[bytes('to_' + cid, 'utf-8')][0].decode('utf-8') ticker = swap_client.getTicker(c)
subfee = True if bytes('subfee_' + cid, 'utf-8') in form_data else False messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
txid = swap_client.withdrawCoin(c, value, address, subfee)
ticker = swap_client.getTicker(c)
messages.append('Withdrew {} {} to address {}<br/>In txid: {}'.format(value, ticker, address, txid))
wallets = swap_client.getWalletsInfo() wallets = swap_client.getWalletsInfo()
@ -238,55 +240,44 @@ class HttpHandler(BaseHTTPRequestHandler):
swap_client = self.server.swap_client swap_client = self.server.swap_client
messages = [] messages = []
if post_string != '': form_data = self.checkForm(post_string, 'newoffer', messages)
form_data = urllib.parse.parse_qs(post_string) if form_data:
form_id = form_data[b'formid'][0].decode('utf-8') addr_from = form_data[b'addr_from'][0].decode('utf-8')
if self.server.last_form_id.get('newoffer', None) == form_id: if addr_from == '-1':
messages.append('Prevented double submit for form {}.'.format(form_id)) addr_from = None
try:
coin_from = Coins(int(form_data[b'coin_from'][0]))
except Exception:
raise ValueError('Unknown Coin From')
try:
coin_to = Coins(int(form_data[b'coin_to'][0]))
except Exception:
raise ValueError('Unknown Coin To')
value_from = int(float(form_data[b'amt_from'][0]) * COIN)
value_to = int(float(form_data[b'amt_to'][0]) * COIN)
min_bid = int(value_from)
rate = int((value_to / value_from) * COIN)
autoaccept = True if b'autoaccept' in form_data else False
lock_seconds = int(form_data[b'lockhrs'][0]) * 60 * 60
# TODO: More accurate rate
# assert(value_to == (value_from * rate) // COIN)
if swap_client.coin_clients[coin_from]['use_csv'] and swap_client.coin_clients[coin_to]['use_csv']:
lock_type = SEQUENCE_LOCK_TIME
else: else:
self.server.last_form_id['newoffer'] = form_id lock_type = ABS_LOCK_TIME
addr_from = form_data[b'addr_from'][0].decode('utf-8') offer_id = swap_client.postOffer(coin_from, coin_to, value_from, rate, min_bid, SwapTypes.SELLER_FIRST, lock_type=lock_type, lock_value=lock_seconds, auto_accept_bids=autoaccept, addr_send_from=addr_from)
if addr_from == '-1': messages.append('<a href="/offer/' + offer_id.hex() + '">Sent Offer ' + offer_id.hex() + '</a><br/>Rate: ' + format8(rate))
addr_from = None
try:
coin_from = Coins(int(form_data[b'coin_from'][0]))
except Exception:
raise ValueError('Unknown Coin From')
try:
coin_to = Coins(int(form_data[b'coin_to'][0]))
except Exception:
raise ValueError('Unknown Coin From')
value_from = int(float(form_data[b'amt_from'][0]) * COIN)
value_to = int(float(form_data[b'amt_to'][0]) * COIN)
min_bid = int(value_from)
rate = int((value_to / value_from) * COIN)
autoaccept = True if b'autoaccept' in form_data else False
lock_seconds = int(form_data[b'lockhrs'][0]) * 60 * 60
# TODO: More accurate rate
# assert(value_to == (value_from * rate) // COIN)
if swap_client.coin_clients[coin_from]['use_csv'] and swap_client.coin_clients[coin_to]['use_csv']:
lock_type = SEQUENCE_LOCK_TIME
else:
lock_type = ABS_LOCK_TIME
offer_id = swap_client.postOffer(coin_from, coin_to, value_from, rate, min_bid, SwapTypes.SELLER_FIRST, lock_type=lock_type, lock_value=lock_seconds, auto_accept_bids=autoaccept, addr_send_from=addr_from)
messages.append('<a href="/offer/' + offer_id.hex() + '">Sent Offer ' + offer_id.hex() + '</a><br/>Rate: ' + format8(rate))
coins = []
for k, v in swap_client.coin_clients.items():
if v['connection_type'] == 'rpc':
coins.append((int(k), getCoinName(k)))
template = env.get_template('offer_new.html') template = env.get_template('offer_new.html')
return bytes(template.render( return bytes(template.render(
title=self.server.title, title=self.server.title,
h2=self.server.title, h2=self.server.title,
messages=messages, messages=messages,
coins=coins, coins=listAvailableCoins(swap_client),
addrs=swap_client.listSmsgAddresses('offer'), addrs=swap_client.listSmsgAddresses('offer'),
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
@ -305,22 +296,16 @@ class HttpHandler(BaseHTTPRequestHandler):
messages = [] messages = []
sent_bid_id = None sent_bid_id = None
show_bid_form = None show_bid_form = None
if post_string != '': form_data = self.checkForm(post_string, 'offer', messages)
form_data = urllib.parse.parse_qs(post_string) if form_data:
form_id = form_data[b'formid'][0].decode('utf-8') if b'newbid' in form_data:
if self.server.last_form_id.get('offer', None) == form_id: show_bid_form = True
messages.append('Prevented double submit for form {}.'.format(form_id))
else: else:
self.server.last_form_id['offer'] = form_id addr_from = form_data[b'addr_from'][0].decode('utf-8')
if addr_from == '-1':
addr_from = None
if b'newbid' in form_data: sent_bid_id = swap_client.postBid(offer_id, offer.amount_from).hex()
show_bid_form = True
else:
addr_from = form_data[b'addr_from'][0].decode('utf-8')
if addr_from == '-1':
addr_from = None
sent_bid_id = swap_client.postBid(offer_id, offer.amount_from).hex()
coin_from = Coins(offer.coin_from) coin_from = Coins(offer.coin_from)
coin_to = Coins(offer.coin_to) coin_to = Coins(offer.coin_to)
@ -362,17 +347,42 @@ class HttpHandler(BaseHTTPRequestHandler):
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
def page_offers(self, url_split, sent=False): def page_offers(self, url_split, post_string, sent=False):
swap_client = self.server.swap_client swap_client = self.server.swap_client
offers = swap_client.listOffers(sent)
filters = {
'coin_from': -1,
'coin_to': -1,
}
messages = []
form_data = self.checkForm(post_string, 'offers', messages)
if form_data:
coin_from = int(form_data[b'coin_from'][0])
if coin_from > -1:
try:
filters['coin_from'] = Coins(coin_from)
except Exception:
raise ValueError('Unknown Coin From')
coin_to = int(form_data[b'coin_to'][0])
if coin_to > -1:
try:
filters['coin_to'] = Coins(coin_to)
except Exception:
raise ValueError('Unknown Coin From')
offers = swap_client.listOffers(sent, filters)
template = env.get_template('offers.html') template = env.get_template('offers.html')
return bytes(template.render( return bytes(template.render(
title=self.server.title, title=self.server.title,
h2=self.server.title, h2=self.server.title,
page_type='Sent' if sent else 'Received', page_type='Sent' if sent else 'Received',
coins=listAvailableCoins(swap_client),
messages=messages,
filters=filters,
offers=[(time.strftime('%Y-%m-%d %H:%M', time.localtime(o.created_at)), offers=[(time.strftime('%Y-%m-%d %H:%M', time.localtime(o.created_at)),
o.offer_id.hex(), getCoinName(Coins(o.coin_from)), getCoinName(Coins(o.coin_to)), format8(o.amount_from), format8((o.amount_from * o.rate) // COIN), format8(o.rate)) for o in offers], o.offer_id.hex(), getCoinName(Coins(o.coin_from)), getCoinName(Coins(o.coin_to)), format8(o.amount_from), format8((o.amount_from * o.rate) // COIN), format8(o.rate)) for o in offers],
form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
def page_advance(self, url_split, post_string): def page_advance(self, url_split, post_string):
@ -402,27 +412,22 @@ class HttpHandler(BaseHTTPRequestHandler):
messages = [] messages = []
show_txns = False show_txns = False
if post_string != '': form_data = self.checkForm(post_string, 'bid', messages)
form_data = urllib.parse.parse_qs(post_string) if form_data:
form_id = form_data[b'formid'][0].decode('utf-8') if b'abandon_bid' in form_data:
if self.server.last_form_id.get('bid', None) == form_id: try:
messages.append('Prevented double submit for form {}.'.format(form_id)) swap_client.abandonBid(bid_id)
else: messages.append('Bid abandoned')
self.server.last_form_id['bid'] = form_id except Exception as ex:
if b'abandon_bid' in form_data: messages.append('Error ' + str(ex))
try: if b'accept_bid' in form_data:
swap_client.abandonBid(bid_id) try:
messages.append('Bid abandoned') swap_client.acceptBid(bid_id)
except Exception as ex: messages.append('Bid accepted')
messages.append('Error ' + str(ex)) except Exception as ex:
if b'accept_bid' in form_data: messages.append('Error ' + str(ex))
try: if b'show_txns' in form_data:
swap_client.acceptBid(bid_id) show_txns = True
messages.append('Bid accepted')
except Exception as ex:
messages.append('Error ' + str(ex))
if b'show_txns' in form_data:
show_txns = True
bid, offer = swap_client.getBidAndOffer(bid_id) bid, offer = swap_client.getBidAndOffer(bid_id)
assert(bid), 'Unknown bid ID' assert(bid), 'Unknown bid ID'
@ -592,11 +597,11 @@ class HttpHandler(BaseHTTPRequestHandler):
if url_split[1] == 'offer': if url_split[1] == 'offer':
return self.page_offer(url_split, post_string) return self.page_offer(url_split, post_string)
if url_split[1] == 'offers': if url_split[1] == 'offers':
return self.page_offers(url_split) return self.page_offers(url_split, post_string)
if url_split[1] == 'newoffer': if url_split[1] == 'newoffer':
return self.page_newoffer(url_split, post_string) return self.page_newoffer(url_split, post_string)
if url_split[1] == 'sentoffers': if url_split[1] == 'sentoffers':
return self.page_offers(url_split, sent=True) return self.page_offers(url_split, post_string, sent=True)
if url_split[1] == 'advance': if url_split[1] == 'advance':
return self.page_advance(url_split, post_string) return self.page_advance(url_split, post_string)
if url_split[1] == 'bid': if url_split[1] == 'bid':

View file

@ -4,6 +4,32 @@
{% if refresh %} {% if refresh %}
<p>Page Refresh: {{ refresh }} seconds</p> <p>Page Refresh: {{ refresh }} seconds</p>
{% endif %} {% endif %}
{% for m in messages %}
<p>{{ m }}</p>
{% endfor %}
<form method="post">
<table>
<tr><td>Coin From</td><td>
<select name="coin_from"><option value="-1"{% if filters.coin_from==-1 %} selected{% endif %}>-- Any Coin --</option>
{% for c in coins %}
<option value="{{ c[0] }}"{% if filters.coin_from==c[0] %} selected{% endif %}>{{ c[1] }}</option>
{% endfor %}
</select>
</td>
<td>Coin To</td><td>
<select name="coin_to"><option value="-1"{% if filters.coin_to==-1 %} selected{% endif %}>-- Any Coin --</option>
{% for c in coins %}
<option value="{{ c[0] }}"{% if filters.coin_to==c[0] %} selected{% endif %}>{{ c[1] }}</option>
{% endfor %}
</select>
</td></tr>
<tr><td><input type="submit" value="Apply Filters"></td></tr>
</table>
<input type="hidden" name="formid" value="{{ form_id }}">
</form>
<table> <table>
<tr><th>At</th><th>Offer ID</th><th>Coin From</th><th>Coin To</th><th>Amount From</th><th>Amount To</th><th>Rate</th></tr> <tr><th>At</th><th>Offer ID</th><th>Coin From</th><th>Coin To</th><th>Amount From</th><th>Amount To</th><th>Rate</th></tr>