Fix tx state display in lists.

selectable address for send_from.
This commit is contained in:
tecnovert 2019-07-28 21:57:20 +02:00
parent 18ee89361a
commit 4bc0ec98eb
No known key found for this signature in database
GPG Key ID: 8ED6D8750C4E3F93
8 changed files with 162 additions and 76 deletions

View File

@ -51,6 +51,7 @@ from .db import (
SwapTx, SwapTx,
PooledAddress, PooledAddress,
SentOffer, SentOffer,
SmsgAddress,
) )
import basicswap.config as cfg import basicswap.config as cfg
import basicswap.segwit_addr as segwit_addr import basicswap.segwit_addr as segwit_addr
@ -467,6 +468,8 @@ class BasicSwap():
self.log.info('Upgrading Database from version %d to %d.', db_version, CURRENT_DB_VERSION) self.log.info('Upgrading Database from version %d to %d.', db_version, CURRENT_DB_VERSION)
raise ValueError('Scripted database upgrade not found.')
def waitForDaemonRPC(self, coin_type): def waitForDaemonRPC(self, coin_type):
for i in range(21): for i in range(21):
if not self.is_running: if not self.is_running:
@ -583,8 +586,7 @@ class BasicSwap():
raise ValueError('Unknown locktype') raise ValueError('Unknown locktype')
def postOffer(self, coin_from, coin_to, amount, rate, min_bid_amount, swap_type, def postOffer(self, coin_from, coin_to, amount, rate, min_bid_amount, swap_type,
lock_type=SEQUENCE_LOCK_TIME, lock_value=48 * 60 * 60, auto_accept_bids=False): lock_type=SEQUENCE_LOCK_TIME, lock_value=48 * 60 * 60, auto_accept_bids=False, addr_send_from=None):
# Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to # Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to
assert(coin_from != coin_to), 'coin_from == coin_to' assert(coin_from != coin_to), 'coin_from == coin_to'
@ -617,8 +619,10 @@ class BasicSwap():
offer_bytes = msg_buf.SerializeToString() offer_bytes = msg_buf.SerializeToString()
payload_hex = str.format('{:02x}', MessageTypes.OFFER) + offer_bytes.hex() payload_hex = str.format('{:02x}', MessageTypes.OFFER) + offer_bytes.hex()
# TODO: reuse address? if addr_send_from is None:
offer_addr = self.callrpc('getnewaddress') offer_addr = self.callrpc('getnewaddress')
else:
offer_addr = addr_send_from
self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg
ro = self.callrpc('smsgsend', [offer_addr, self.network_addr, payload_hex, False, 1, False, False, True]) ro = self.callrpc('smsgsend', [offer_addr, self.network_addr, payload_hex, False, 1, False, False, True])
msg_id = ro['msgid'] msg_id = ro['msgid']
@ -626,7 +630,6 @@ class BasicSwap():
offer_id = bytes.fromhex(msg_id) offer_id = bytes.fromhex(msg_id)
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
offer = Offer( offer = Offer(
offer_id=offer_id, offer_id=offer_id,
@ -646,9 +649,11 @@ class BasicSwap():
was_sent=True, was_sent=True,
auto_accept_bids=auto_accept_bids,) auto_accept_bids=auto_accept_bids,)
offer.setState(OfferStates.OFFER_SENT) offer.setState(OfferStates.OFFER_SENT)
session.add(offer)
session.add(offer)
session.add(SentOffer(offer_id=offer_id)) session.add(SentOffer(offer_id=offer_id))
if addr_send_from is None:
session.add(SmsgAddress(addr=offer_addr, use_type=MessageTypes.OFFER))
session.commit() session.commit()
session.close() session.close()
session.remove() session.remove()
@ -874,79 +879,91 @@ class BasicSwap():
return (sign_for_addr, signature) return (sign_for_addr, signature)
def saveBidInSession(self, bid_id, bid, session):
session.add(bid)
if bid.initiate_tx:
session.add(bid.initiate_tx)
if bid.participate_tx:
session.add(bid.participate_tx)
def saveBid(self, bid_id, bid): def saveBid(self, bid_id, bid):
self.mxDB.acquire() self.mxDB.acquire()
try: try:
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
session.add(bid) self.saveBidInSession(bid_id, bid, session)
if bid.initiate_tx:
session.add(bid.initiate_tx)
if bid.participate_tx:
session.add(bid.participate_tx)
session.commit() session.commit()
session.close() session.close()
session.remove() session.remove()
finally: finally:
self.mxDB.release() self.mxDB.release()
def postBid(self, offer_id, amount): def postBid(self, offer_id, amount, addr_send_from=None):
self.log.debug('postBid %s %s', offer_id.hex(), format8(amount))
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from # Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
self.log.debug('postBid %s %s', offer_id.hex(), format8(amount))
self.mxDB.acquire()
try:
offer = self.getOffer(offer_id)
assert(offer), 'Offer not found: {}.'.format(offer_id.hex())
assert(offer.expire_at > int(time.time())), 'Offer has expired'
offer = self.getOffer(offer_id) msg_buf = BidMessage()
assert(offer), 'Offer not found: {}.'.format(offer_id.hex()) msg_buf.offer_msg_id = offer_id
msg_buf.time_valid = 60 * 10
msg_buf.amount = int(amount) # amount of coin_from
assert(offer.expire_at > int(time.time())), 'Offer has expired' coin_from = Coins(offer.coin_from)
coin_to = Coins(offer.coin_to)
msg_buf = BidMessage() contract_count = self.getNewContractId()
msg_buf.offer_msg_id = offer_id
msg_buf.time_valid = 60 * 10
msg_buf.amount = int(amount) # amount of coin_from
coin_from = Coins(offer.coin_from) now = int(time.time())
coin_to = Coins(offer.coin_to) if offer.swap_type == SwapTypes.SELLER_FIRST:
msg_buf.pkhash_buyer = getKeyID(self.getContractPubkey(dt.datetime.fromtimestamp(now).date(), contract_count))
contract_count = self.getNewContractId() proof_addr, proof_sig = self.getProofOfFunds(coin_to, msg_buf.amount)
msg_buf.proof_address = proof_addr
msg_buf.proof_signature = proof_sig
now = int(time.time()) bid_bytes = msg_buf.SerializeToString()
if offer.swap_type == SwapTypes.SELLER_FIRST: payload_hex = str.format('{:02x}', MessageTypes.BID) + bid_bytes.hex()
msg_buf.pkhash_buyer = getKeyID(self.getContractPubkey(dt.datetime.fromtimestamp(now).date(), contract_count))
proof_addr, proof_sig = self.getProofOfFunds(coin_to, msg_buf.amount) if addr_send_from is None:
msg_buf.proof_address = proof_addr bid_addr = self.callrpc('getnewaddress')
msg_buf.proof_signature = proof_sig else:
bid_addr = addr_send_from
self.callrpc('smsgaddlocaladdress', [bid_addr]) # Enable receiving smsg
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, 1, False, False, True])
msg_id = ro['msgid']
bid_bytes = msg_buf.SerializeToString() bid_id = bytes.fromhex(msg_id)
payload_hex = str.format('{:02x}', MessageTypes.BID) + bid_bytes.hex() bid = Bid(
bid_id=bid_id,
offer_id=offer_id,
amount=msg_buf.amount,
pkhash_buyer=msg_buf.pkhash_buyer,
proof_address=msg_buf.proof_address,
# TODO: reuse address? created_at=now,
bid_addr = self.callrpc('getnewaddress') contract_count=contract_count,
self.callrpc('smsgaddlocaladdress', [bid_addr]) # Enable receiving smsg amount_to=(msg_buf.amount * offer.rate) // COIN,
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, 1, False, False, True]) expire_at=now + msg_buf.time_valid,
msg_id = ro['msgid'] bid_addr=bid_addr,
was_sent=True,
)
bid.setState(BidStates.BID_SENT)
bid_id = bytes.fromhex(msg_id) session = scoped_session(self.session_factory)
bid = Bid( self.saveBidInSession(bid_id, bid, session)
bid_id=bid_id, if addr_send_from is None:
offer_id=offer_id, session.add(SmsgAddress(addr=bid_addr, use_type=MessageTypes.BID))
amount=msg_buf.amount, session.commit()
pkhash_buyer=msg_buf.pkhash_buyer, session.close()
proof_address=msg_buf.proof_address, session.remove()
created_at=now, self.log.info('Sent BID %s', bid_id.hex())
contract_count=contract_count, return bid_id
amount_to=(msg_buf.amount * offer.rate) // COIN, finally:
expire_at=now + msg_buf.time_valid, self.mxDB.release()
bid_addr=bid_addr,
was_sent=True,
)
bid.setState(BidStates.BID_SENT)
self.saveBid(bid_id, bid)
self.log.info('Sent BID %s', bid_id.hex())
return bid_id
def getOffer(self, offer_id, sent=False): def getOffer(self, offer_id, sent=False):
self.mxDB.acquire() self.mxDB.acquire()
@ -2274,13 +2291,19 @@ class BasicSwap():
rv = [] rv = []
now = int(time.time()) now = int(time.time())
session = scoped_session(self.session_factory) session = scoped_session(self.session_factory)
query_str = 'SELECT bids.created_at, bids.bid_id, bids.offer_id, bids.amount, bids.state, bids.was_received, tx1.state, tx2.state FROM bids ' + \
'LEFT JOIN transactions AS tx1 ON tx1.bid_id = bids.bid_id AND tx1.tx_type = {} '.format(TxTypes.ITX) + \
'LEFT JOIN transactions AS tx2 ON tx2.bid_id = bids.bid_id AND tx2.tx_type = {} '.format(TxTypes.PTX)
if offer_id is not None: if offer_id is not None:
q = session.query(Bid).filter(Bid.offer_id == offer_id) query_str += 'WHERE bids.offer_id = x\'{}\' '.format(offer_id.hex())
elif sent: elif sent:
q = session.query(Bid).filter(Bid.was_sent == True) # noqa E712 query_str += 'WHERE bids.was_sent = 1 '
else: else:
q = session.query(Bid).filter(Bid.was_received == True) # noqa E712 query_str += 'WHERE bids.was_received = 1 '
q = q.order_by(Bid.created_at.desc()) query_str += 'ORDER BY bids.created_at DESC'
q = self.engine.execute(query_str)
for row in q: for row in q:
rv.append(row) rv.append(row)
return rv return rv
@ -2313,6 +2336,21 @@ class BasicSwap():
finally: finally:
self.mxDB.release() self.mxDB.release()
def listSmsgAddresses(self, use_type_str):
use_type = MessageTypes.OFFER if use_type_str == 'offer' else MessageTypes.BID
self.mxDB.acquire()
try:
session = scoped_session(self.session_factory)
rv = []
q = self.engine.execute('SELECT addr FROM smsgaddresses WHERE use_type = {} ORDER BY addr_id DESC'.format(use_type))
for row in q:
rv.append(row[0])
return rv
finally:
session.close()
session.remove()
self.mxDB.release()
def callrpc(self, method, params=[], wallet=None): def callrpc(self, method, params=[], wallet=None):
return callrpc(self.coin_clients[Coins.PART]['rpcport'], self.coin_clients[Coins.PART]['rpcauth'], method, params, wallet) return callrpc(self.coin_clients[Coins.PART]['rpcport'], self.coin_clients[Coins.PART]['rpcauth'], method, params, wallet)

View File

@ -9,7 +9,7 @@ import time
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
CURRENT_DB_VERSION = 1 CURRENT_DB_VERSION = 2
Base = declarative_base() Base = declarative_base()
@ -173,3 +173,10 @@ class SentOffer(Base):
__tablename__ = 'sentoffers' __tablename__ = 'sentoffers'
offer_id = sa.Column(sa.LargeBinary, primary_key=True) offer_id = sa.Column(sa.LargeBinary, primary_key=True)
class SmsgAddress(Base):
__tablename__ = 'smsgaddresses'
addr_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
addr = sa.Column(sa.String)
use_type = sa.Column(sa.Integer)

View File

@ -118,6 +118,7 @@ class HttpHandler(BaseHTTPRequestHandler):
bid_id = bytes.fromhex(url_split[3]) bid_id = bytes.fromhex(url_split[3])
assert(len(bid_id) == 28) assert(len(bid_id) == 28)
return bytes(json.dumps(self.server.swap_client.viewBid(bid_id)), 'UTF-8') return bytes(json.dumps(self.server.swap_client.viewBid(bid_id)), 'UTF-8')
assert(False), 'TODO'
return bytes(json.dumps(self.server.swap_client.listBids()), 'UTF-8') return bytes(json.dumps(self.server.swap_client.listBids()), 'UTF-8')
def js_sentbids(self, url_split): def js_sentbids(self, url_split):
@ -245,6 +246,10 @@ class HttpHandler(BaseHTTPRequestHandler):
else: else:
self.server.last_form_id['newoffer'] = form_id self.server.last_form_id['newoffer'] = form_id
addr_from = form_data[b'addr_from'][0].decode('utf-8')
if addr_from == '-1':
addr_from = None
try: try:
coin_from = Coins(int(form_data[b'coin_from'][0])) coin_from = Coins(int(form_data[b'coin_from'][0]))
except Exception: except Exception:
@ -268,7 +273,7 @@ class HttpHandler(BaseHTTPRequestHandler):
else: else:
lock_type = ABS_LOCK_TIME lock_type = ABS_LOCK_TIME
offer_id = swap_client.postOffer(coin_from, coin_to, value_from, rate, min_bid, SwapTypes.SELLER_FIRST, auto_accept_bids=autoaccept, lock_type=lock_type, lock_value=lock_seconds) 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)) messages.append('<a href="/offer/' + offer_id.hex() + '">Sent Offer ' + offer_id.hex() + '</a><br/>Rate: ' + format8(rate))
coins = [] coins = []
@ -282,6 +287,7 @@ class HttpHandler(BaseHTTPRequestHandler):
h2=self.server.title, h2=self.server.title,
messages=messages, messages=messages,
coins=coins, coins=coins,
addrs=swap_client.listSmsgAddresses('offer'),
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
@ -298,6 +304,7 @@ class HttpHandler(BaseHTTPRequestHandler):
messages = [] messages = []
sent_bid_id = None sent_bid_id = None
show_bid_form = None
if post_string != '': if post_string != '':
form_data = urllib.parse.parse_qs(post_string) form_data = urllib.parse.parse_qs(post_string)
form_id = form_data[b'formid'][0].decode('utf-8') form_id = form_data[b'formid'][0].decode('utf-8')
@ -305,7 +312,15 @@ class HttpHandler(BaseHTTPRequestHandler):
messages.append('Prevented double submit for form {}.'.format(form_id)) messages.append('Prevented double submit for form {}.'.format(form_id))
else: else:
self.server.last_form_id['offer'] = form_id self.server.last_form_id['offer'] = form_id
sent_bid_id = swap_client.postBid(offer_id, offer.amount_from).hex()
if b'newbid' in form_data:
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)
@ -325,7 +340,8 @@ class HttpHandler(BaseHTTPRequestHandler):
'addr_from': offer.addr_from, 'addr_from': offer.addr_from,
'created_at': offer.created_at, 'created_at': offer.created_at,
'expired_at': offer.expire_at, 'expired_at': offer.expire_at,
'sent': 'True' if offer.was_sent else 'False' 'sent': 'True' if offer.was_sent else 'False',
'show_bid_form': show_bid_form,
} }
if offer.was_sent: if offer.was_sent:
@ -341,7 +357,8 @@ class HttpHandler(BaseHTTPRequestHandler):
sent_bid_id=sent_bid_id, sent_bid_id=sent_bid_id,
messages=messages, messages=messages,
data=data, data=data,
bids=[(b.bid_id.hex(), format8(b.amount), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.getPTxState())) for b in bids], bids=[(b[1].hex(), format8(b[3]), strBidState(b[4]), strTxState(b[6]), strTxState(b[7])) for b in bids],
addrs=None if show_bid_form is None else swap_client.listSmsgAddresses('bid'),
form_id=os.urandom(8).hex(), form_id=os.urandom(8).hex(),
), 'UTF-8') ), 'UTF-8')
@ -510,8 +527,8 @@ class HttpHandler(BaseHTTPRequestHandler):
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',
bids=[(time.strftime('%Y-%m-%d %H:%M', time.localtime(b.created_at)), bids=[(time.strftime('%Y-%m-%d %H:%M', time.localtime(b[0])),
b.bid_id.hex(), b.offer_id.hex(), strBidState(b.state), strTxState(b.getITxState()), strTxState(b.getPTxState())) for b in bids], b[1].hex(), b[2].hex(), strBidState(b[4]), strTxState(b[6]), strTxState(b[7])) for b in bids],
), 'UTF-8') ), 'UTF-8')
def page_watched(self, url_split, post_string): def page_watched(self, url_split, post_string):

View File

@ -31,6 +31,28 @@
{% endif %} {% endif %}
</table> </table>
<form method="post">
{% if data.show_bid_form %}
<br/><h4>New Bid</h4>
<table>
<tr><td>Send From Address</td><td>
<select name="addr_from">
{% for a in addrs %}
<option value="{{ a }}">{{ a }}</option>
{% endfor %}
<option value="-1">-- New Address --</option>
</select>
</td></tr>
<tr><td><input type="submit" name="sendbid" value="Send Bid"></td></tr>
</table>
{% else %}
<input type="submit" name="newbid" value="New Bid">
{% endif %}
<input type="hidden" name="formid" value="{{ form_id }}">
</form>
<h4>Bids</h4> <h4>Bids</h4>
<table> <table>
<tr><th>Bid ID</th><th>Bid Amount</th><th>Bid Status</th><th>ITX Status</th><th>PTX Status</th></tr> <tr><th>Bid ID</th><th>Bid Amount</th><th>Bid Status</th><th>ITX Status</th><th>PTX Status</th></tr>
@ -39,10 +61,5 @@
{% endfor %} {% endfor %}
</table> </table>
<form method="post">
<input type="submit" value="Send Bid">
<input type="hidden" name="formid" value="{{ form_id }}">
</form>
<p><a href="/">home</a></p> <p><a href="/">home</a></p>
</body></html> </body></html>

View File

@ -8,6 +8,13 @@
<form method="post"> <form method="post">
<table> <table>
<tr><td>Send From Address</td><td><select name="addr_from">
{% for a in addrs %}
<option value="{{ a }}">{{ a }}</option>
{% endfor %}
<option value="-1">-- New Address --</option>
</select></td></tr>
<tr><td>Coin From</td><td> <tr><td>Coin From</td><td>
<select name="coin_from"><option value="-1">-- Select Coin --</option> <select name="coin_from"><option value="-1">-- Select Coin --</option>
{% for c in coins %} {% for c in coins %}

View File

@ -86,4 +86,4 @@ Right click in the directory you want to install into and select 'Git Bash Here'
Open url in browser: Open url in browser:
http://localhost:12700 http://localhost:12700
Shutdown by pressibg ctrl + c in the Git Bash console window. Shutdown by pressing ctrl + c in the Git Bash console window.

View File

@ -342,7 +342,7 @@ class Test(unittest.TestCase):
time.sleep(1) time.sleep(1)
bids = swap_client.listBids() bids = swap_client.listBids()
for bid in bids: for bid in bids:
if bid.bid_id == bid_id and bid.was_received: if bid[1] == bid_id and int(bid[5]) == 1:
return return
raise ValueError('wait_for_bid timed out.') raise ValueError('wait_for_bid timed out.')

View File

@ -338,7 +338,7 @@ class Test(unittest.TestCase):
time.sleep(1) time.sleep(1)
bids = swap_client.listBids() bids = swap_client.listBids()
for bid in bids: for bid in bids:
if bid.bid_id == bid_id and bid.was_received: if bid[1] == bid_id and int(bid[5]) == 1:
return return
raise ValueError('wait_for_bid timed out.') raise ValueError('wait_for_bid timed out.')