mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-03 17:29:26 +00:00
ui: Expose bid valid for.
Set smsgsregtestadjust to false in tests. Fix offer smsg valid for. Set active_ind on bid records. api: All times returned should be in unix-time.
This commit is contained in:
parent
1953820cd1
commit
5beb1d17b9
15 changed files with 145 additions and 73 deletions
|
@ -100,12 +100,6 @@ import basicswap.network as bsn
|
|||
import basicswap.protocols.atomic_swap_1 as atomic_swap_1
|
||||
|
||||
|
||||
MIN_OFFER_VALID_TIME = 60 * 10
|
||||
MAX_OFFER_VALID_TIME = 60 * 60 * 48
|
||||
MIN_BID_VALID_TIME = 60 * 10
|
||||
MAX_BID_VALID_TIME = 60 * 60 * 48
|
||||
|
||||
|
||||
class MessageTypes(IntEnum):
|
||||
OFFER = auto()
|
||||
BID = auto()
|
||||
|
@ -228,9 +222,6 @@ class DebugTypes(IntEnum):
|
|||
MAKE_INVALID_PTX = auto()
|
||||
|
||||
|
||||
INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
||||
|
||||
|
||||
def strOfferState(state):
|
||||
if state == OfferStates.OFFER_SENT:
|
||||
return 'Sent'
|
||||
|
@ -477,7 +468,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
self.swaps_in_progress = dict()
|
||||
|
||||
self.SMSG_SECONDS_IN_HOUR = 60 * 2 if self.chain == 'regtest' else 60 * 60
|
||||
self.SMSG_SECONDS_IN_HOUR = 60 * 60 # Note: Set smsgsregtestadjust=0 for regtest
|
||||
|
||||
self.delay_event = threading.Event()
|
||||
self.threads = []
|
||||
|
@ -1102,12 +1093,20 @@ class BasicSwap(BaseApp):
|
|||
else:
|
||||
raise ValueError('Unknown locktype')
|
||||
|
||||
def validateOfferValidTime(self, coin_from, coin_to, valid_for_seconds):
|
||||
if valid_for_seconds < 60 * 60: # SMSG_MIN_TTL
|
||||
def validateOfferValidTime(self, offer_type, coin_from, coin_to, valid_for_seconds):
|
||||
# TODO: adjust
|
||||
if valid_for_seconds < 10 * 60:
|
||||
raise ValueError('Offer TTL too low')
|
||||
if valid_for_seconds > 48 * 60 * 60:
|
||||
raise ValueError('Offer TTL too high')
|
||||
|
||||
def validateBidValidTime(self, offer_type, coin_from, coin_to, valid_for_seconds):
|
||||
# TODO: adjust
|
||||
if valid_for_seconds < 10 * 60:
|
||||
raise ValueError('Bid TTL too low')
|
||||
if valid_for_seconds > 24 * 60 * 60:
|
||||
raise ValueError('Bid TTL too high')
|
||||
|
||||
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, addr_send_from=None, extra_options={}):
|
||||
# Offer to send offer.amount_from of coin_from in exchange for offer.amount_from * offer.rate of coin_to
|
||||
|
@ -1129,7 +1128,7 @@ class BasicSwap(BaseApp):
|
|||
self.validateSwapType(coin_from_t, coin_to_t, swap_type)
|
||||
self.validateOfferAmounts(coin_from_t, coin_to_t, amount, rate, min_bid_amount)
|
||||
self.validateOfferLockValue(coin_from_t, coin_to_t, lock_type, lock_value)
|
||||
self.validateOfferValidTime(coin_from_t, coin_to_t, valid_for_seconds)
|
||||
self.validateOfferValidTime(swap_type, coin_from_t, coin_to_t, valid_for_seconds)
|
||||
|
||||
self.mxDB.acquire()
|
||||
session = None
|
||||
|
@ -1196,7 +1195,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
self.callrpc('smsgaddlocaladdress', [offer_addr]) # Enable receiving smsg
|
||||
options = {'decodehex': True, 'ttl_is_seconds': True}
|
||||
msg_valid = self.SMSG_SECONDS_IN_HOUR * 1
|
||||
msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds)
|
||||
ro = self.callrpc('smsgsend', [offer_addr, self.network_addr, payload_hex, False, msg_valid, False, options])
|
||||
msg_id = ro['msgid']
|
||||
|
||||
|
@ -1725,13 +1724,16 @@ class BasicSwap(BaseApp):
|
|||
assert(offer.expire_at > int(time.time())), 'Offer has expired'
|
||||
|
||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||
return self.postXmrBid(offer_id, amount, addr_send_from)
|
||||
return self.postXmrBid(offer_id, amount, addr_send_from, extra_options)
|
||||
|
||||
valid_for_seconds = extra_options.get('valid_for_seconds', 60 * 10)
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, valid_for_seconds)
|
||||
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
msg_buf = BidMessage()
|
||||
msg_buf.offer_msg_id = offer_id
|
||||
msg_buf.time_valid = extra_options.get('time_valid', 60 * 10)
|
||||
msg_buf.time_valid = valid_for_seconds
|
||||
msg_buf.amount = int(amount) # amount of coin_from
|
||||
|
||||
coin_from = Coins(offer.coin_from)
|
||||
|
@ -1762,12 +1764,13 @@ class BasicSwap(BaseApp):
|
|||
bid_addr = addr_send_from
|
||||
self.callrpc('smsgaddlocaladdress', [bid_addr]) # Enable receiving smsg
|
||||
options = {'decodehex': True, 'ttl_is_seconds': True}
|
||||
msg_valid = self.SMSG_SECONDS_IN_HOUR * 1
|
||||
msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds)
|
||||
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options])
|
||||
msg_id = ro['msgid']
|
||||
|
||||
bid_id = bytes.fromhex(msg_id)
|
||||
bid = Bid(
|
||||
active_ind=1,
|
||||
bid_id=bid_id,
|
||||
offer_id=offer_id,
|
||||
amount=msg_buf.amount,
|
||||
|
@ -2031,7 +2034,7 @@ class BasicSwap(BaseApp):
|
|||
self.saveBid(bid_id, bid)
|
||||
self.swaps_in_progress[bid_id] = (bid, offer)
|
||||
|
||||
def postXmrBid(self, offer_id, amount, addr_send_from=None):
|
||||
def postXmrBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
||||
# Bid to send bid.amount * offer.rate of coin_to in exchange for bid.amount of coin_from
|
||||
# Send MSG1L F -> L
|
||||
self.log.debug('postXmrBid %s', offer_id.hex())
|
||||
|
@ -2044,6 +2047,9 @@ class BasicSwap(BaseApp):
|
|||
assert(xmr_offer), 'XMR offer not found: {}.'.format(offer_id.hex())
|
||||
assert(offer.expire_at > int(time.time())), 'Offer has expired'
|
||||
|
||||
valid_for_seconds = extra_options.get('valid_for_seconds', 60 * 10)
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, valid_for_seconds)
|
||||
|
||||
coin_from = Coins(offer.coin_from)
|
||||
coin_to = Coins(offer.coin_to)
|
||||
ci_from = self.ci(coin_from)
|
||||
|
@ -2053,7 +2059,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
msg_buf = XmrBidMessage()
|
||||
msg_buf.offer_msg_id = offer_id
|
||||
msg_buf.time_valid = 60 * 10
|
||||
msg_buf.time_valid = valid_for_seconds
|
||||
msg_buf.amount = int(amount) # Amount of coin_from
|
||||
|
||||
address_out = self.getReceiveAddressFromPool(coin_from, offer_id, TxTypes.XMR_SWAP_A_LOCK)
|
||||
|
@ -2110,7 +2116,7 @@ class BasicSwap(BaseApp):
|
|||
bid_addr = addr_send_from
|
||||
self.callrpc('smsgaddlocaladdress', [bid_addr]) # Enable receiving smsg
|
||||
options = {'decodehex': True, 'ttl_is_seconds': True}
|
||||
msg_valid = self.SMSG_SECONDS_IN_HOUR * 1
|
||||
msg_valid = max(self.SMSG_SECONDS_IN_HOUR * 1, valid_for_seconds)
|
||||
ro = self.callrpc('smsgsend', [bid_addr, offer.addr_from, payload_hex, False, msg_valid, False, options])
|
||||
xmr_swap.bid_id = bytes.fromhex(ro['msgid'])
|
||||
|
||||
|
@ -2138,6 +2144,7 @@ class BasicSwap(BaseApp):
|
|||
xmr_swap.bid_msg_id3 = bytes.fromhex(ro['msgid'])
|
||||
|
||||
bid = Bid(
|
||||
active_ind=1,
|
||||
bid_id=xmr_swap.bid_id,
|
||||
offer_id=offer_id,
|
||||
amount=msg_buf.amount,
|
||||
|
@ -3135,7 +3142,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
# Bid times out if buyer doesn't see tx in chain within INITIATE_TX_TIMEOUT seconds
|
||||
if bid.initiate_tx is None and \
|
||||
bid.state_time + INITIATE_TX_TIMEOUT < int(time.time()):
|
||||
bid.state_time + atomic_swap_1.INITIATE_TX_TIMEOUT < int(time.time()):
|
||||
self.log.info('Swap timed out waiting for initiate tx for bid %s', bid_id.hex())
|
||||
bid.setState(BidStates.SWAP_TIMEDOUT, 'Timed out waiting for initiate tx')
|
||||
self.saveBid(bid_id, bid)
|
||||
|
@ -3630,9 +3637,8 @@ class BasicSwap(BaseApp):
|
|||
self.validateSwapType(coin_from, coin_to, offer_data.swap_type)
|
||||
self.validateOfferAmounts(coin_from, coin_to, offer_data.amount_from, offer_data.rate, offer_data.min_bid_amount)
|
||||
self.validateOfferLockValue(coin_from, coin_to, offer_data.lock_type, offer_data.lock_value)
|
||||
self.validateOfferValidTime(coin_from, coin_to, offer_data.time_valid)
|
||||
self.validateOfferValidTime(offer_data.swap_type, coin_from, coin_to, offer_data.time_valid)
|
||||
|
||||
assert(offer_data.time_valid >= MIN_OFFER_VALID_TIME and offer_data.time_valid <= MAX_OFFER_VALID_TIME), 'Invalid time_valid'
|
||||
assert(msg['sent'] + offer_data.time_valid >= now), 'Offer expired'
|
||||
|
||||
if offer_data.swap_type == SwapTypes.SELLER_FIRST:
|
||||
|
@ -3752,17 +3758,17 @@ class BasicSwap(BaseApp):
|
|||
|
||||
# Validate data
|
||||
assert(len(bid_data.offer_msg_id) == 28), 'Bad offer_id length'
|
||||
assert(bid_data.time_valid >= MIN_BID_VALID_TIME and bid_data.time_valid <= MAX_BID_VALID_TIME), 'Invalid time_valid'
|
||||
|
||||
offer_id = bid_data.offer_msg_id
|
||||
offer = self.getOffer(offer_id, sent=True)
|
||||
assert(offer and offer.was_sent), 'Unknown offerid'
|
||||
assert(offer and offer.was_sent), 'Unknown offer'
|
||||
|
||||
assert(offer.state == OfferStates.OFFER_RECEIVED), 'Bad offer state'
|
||||
assert(msg['to'] == offer.addr_from), 'Received on incorrect address'
|
||||
assert(now <= offer.expire_at), 'Offer expired'
|
||||
assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum'
|
||||
assert(bid_data.amount <= offer.amount_from), 'Bid amount above offer amount'
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, bid_data.time_valid)
|
||||
assert(now <= msg['sent'] + bid_data.time_valid), 'Bid expired'
|
||||
|
||||
# TODO: Allow higher bids
|
||||
|
@ -3800,6 +3806,7 @@ class BasicSwap(BaseApp):
|
|||
bid = self.getBid(bid_id)
|
||||
if bid is None:
|
||||
bid = Bid(
|
||||
active_ind=1,
|
||||
bid_id=bid_id,
|
||||
offer_id=offer_id,
|
||||
amount=bid_data.amount,
|
||||
|
@ -3885,7 +3892,7 @@ class BasicSwap(BaseApp):
|
|||
if offer.lock_type == ABS_LOCK_BLOCKS:
|
||||
self.log.warning('TODO: validate absolute lock values')
|
||||
else:
|
||||
assert(script_lock_value <= bid.created_at + offer.lock_value + INITIATE_TX_TIMEOUT), 'script lock time too high'
|
||||
assert(script_lock_value <= bid.created_at + offer.lock_value + atomic_swap_1.INITIATE_TX_TIMEOUT), 'script lock time too high'
|
||||
assert(script_lock_value >= bid.created_at + offer.lock_value), 'script lock time too low'
|
||||
|
||||
assert(len(scriptvalues[3]) == 40), 'pkhash_refund bad length'
|
||||
|
@ -4033,12 +4040,12 @@ class BasicSwap(BaseApp):
|
|||
|
||||
# Validate data
|
||||
assert(len(bid_data.offer_msg_id) == 28), 'Bad offer_id length'
|
||||
assert(bid_data.time_valid >= MIN_BID_VALID_TIME and bid_data.time_valid <= MAX_BID_VALID_TIME), 'Invalid time_valid'
|
||||
|
||||
offer_id = bid_data.offer_msg_id
|
||||
offer, xmr_offer = self.getXmrOffer(offer_id, sent=True)
|
||||
assert(offer and offer.was_sent), 'Offer not found: {}.'.format(offer_id.hex())
|
||||
assert(xmr_offer), 'XMR offer not found: {}.'.format(offer_id.hex())
|
||||
|
||||
ci_from = self.ci(offer.coin_from)
|
||||
ci_to = self.ci(offer.coin_to)
|
||||
|
||||
|
@ -4047,10 +4054,9 @@ class BasicSwap(BaseApp):
|
|||
assert(now <= offer.expire_at), 'Offer expired'
|
||||
assert(bid_data.amount >= offer.min_bid_amount), 'Bid amount below minimum'
|
||||
assert(bid_data.amount <= offer.amount_from), 'Bid amount above offer amount'
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, bid_data.time_valid)
|
||||
assert(now <= msg['sent'] + bid_data.time_valid), 'Bid expired'
|
||||
|
||||
self.log.debug('TODO: xmr bid validation')
|
||||
|
||||
assert(ci_to.verifyKey(bid_data.kbvf))
|
||||
assert(ci_from.verifyPubkey(bid_data.pkaf))
|
||||
|
||||
|
@ -4059,6 +4065,7 @@ class BasicSwap(BaseApp):
|
|||
bid, xmr_swap = self.getXmrBid(bid_id)
|
||||
if bid is None:
|
||||
bid = Bid(
|
||||
active_ind=1,
|
||||
bid_id=bid_id,
|
||||
offer_id=offer_id,
|
||||
amount=bid_data.amount,
|
||||
|
@ -4839,6 +4846,8 @@ class BasicSwap(BaseApp):
|
|||
|
||||
if now - self._last_checked_watched >= self.check_watched_seconds:
|
||||
for k, c in self.coin_clients.items():
|
||||
if k == Coins.PART_ANON:
|
||||
continue
|
||||
if len(c['watched_outputs']) > 0:
|
||||
self.checkForSpends(k, c)
|
||||
self._last_checked_watched = now
|
||||
|
@ -5132,25 +5141,29 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def listBids(self, sent=False, offer_id=None, for_html=False):
|
||||
def listBids(self, sent=False, offer_id=None, for_html=False, filters={}):
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
rv = []
|
||||
now = int(time.time())
|
||||
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, offers.coin_from FROM bids ' + \
|
||||
query_str = 'SELECT bids.created_at, bids.expire_at, bids.bid_id, bids.offer_id, bids.amount, bids.state, bids.was_received, tx1.state, tx2.state, offers.coin_from FROM bids ' + \
|
||||
'LEFT JOIN offers ON offers.offer_id = bids.offer_id ' + \
|
||||
'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)
|
||||
|
||||
query_str += 'WHERE bids.active_ind = 1 '
|
||||
filter_bid_id = filters.get('bid_id', None)
|
||||
if filter_bid_id is not None:
|
||||
query_str += 'AND bids.bid_id = x\'{}\' '.format(filter_bid_id.hex())
|
||||
if offer_id is not None:
|
||||
query_str += 'WHERE bids.offer_id = x\'{}\' '.format(offer_id.hex())
|
||||
query_str += 'AND bids.offer_id = x\'{}\' '.format(offer_id.hex())
|
||||
elif sent:
|
||||
query_str += 'WHERE bids.was_sent = 1 '
|
||||
query_str += 'AND bids.was_sent = 1 '
|
||||
else:
|
||||
query_str += 'WHERE bids.was_received = 1 '
|
||||
query_str += 'ORDER BY bids.created_at DESC'
|
||||
query_str += 'AND bids.was_received = 1 '
|
||||
query_str += ' ORDER BY bids.created_at DESC'
|
||||
|
||||
q = session.execute(query_str)
|
||||
for row in q:
|
||||
|
|
|
@ -633,6 +633,9 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
offer, xmr_offer = swap_client.getXmrOffer(offer_id)
|
||||
assert(offer), 'Unknown offer ID'
|
||||
|
||||
extend_data = { # Defaults
|
||||
'nb_validmins': 10,
|
||||
}
|
||||
messages = []
|
||||
sent_bid_id = None
|
||||
show_bid_form = None
|
||||
|
@ -643,15 +646,26 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
swap_client.revokeOffer(offer_id)
|
||||
messages.append('Offer revoked')
|
||||
except Exception as ex:
|
||||
messages.append('Revoke offer failed ' + str(ex))
|
||||
messages.append('Revoke offer failed: ' + str(ex))
|
||||
elif b'newbid' in form_data:
|
||||
show_bid_form = True
|
||||
elif b'sendbid' in form_data:
|
||||
try:
|
||||
addr_from = form_data[b'addr_from'][0].decode('utf-8')
|
||||
extend_data['nb_addr_from'] = addr_from
|
||||
if addr_from == '-1':
|
||||
addr_from = None
|
||||
|
||||
sent_bid_id = swap_client.postBid(offer_id, offer.amount_from, addr_send_from=addr_from).hex()
|
||||
minutes_valid = int(form_data[b'validmins'][0].decode('utf-8'))
|
||||
extend_data['nb_validmins'] = minutes_valid
|
||||
|
||||
extra_options = {
|
||||
'valid_for_seconds': minutes_valid * 60,
|
||||
}
|
||||
sent_bid_id = swap_client.postBid(offer_id, offer.amount_from, addr_send_from=addr_from, extra_options=extra_options).hex()
|
||||
except Exception as ex:
|
||||
messages.append('Error: Send bid failed: ' + str(ex))
|
||||
show_bid_form = True
|
||||
|
||||
ci_from = swap_client.ci(Coins(offer.coin_from))
|
||||
ci_to = swap_client.ci(Coins(offer.coin_to))
|
||||
|
@ -674,6 +688,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
'was_revoked': 'True' if offer.active_ind == 2 else 'False',
|
||||
'show_bid_form': show_bid_form,
|
||||
}
|
||||
data.update(extend_data)
|
||||
|
||||
if xmr_offer:
|
||||
int_fee_rate_now, fee_source = ci_from.get_fee_rate()
|
||||
|
@ -700,7 +715,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
sent_bid_id=sent_bid_id,
|
||||
messages=messages,
|
||||
data=data,
|
||||
bids=[(b[1].hex(), ci_from.format_amount(b[3]), strBidState(b[4]), strTxState(b[6]), strTxState(b[7])) for b in bids],
|
||||
bids=[(b[2].hex(), ci_from.format_amount(b[4]), strBidState(b[5]), strTxState(b[7]), strTxState(b[8])) for b in bids],
|
||||
addrs=None if show_bid_form is None else swap_client.listSmsgAddresses('bid'),
|
||||
form_id=os.urandom(8).hex(),
|
||||
), 'UTF-8')
|
||||
|
@ -875,7 +890,7 @@ class HttpHandler(BaseHTTPRequestHandler):
|
|||
h2=self.server.title,
|
||||
page_type='Sent' if sent else 'Received',
|
||||
bids=[(format_timestamp(b[0]),
|
||||
b[1].hex(), b[2].hex(), strBidState(b[4]), strTxState(b[6]), strTxState(b[7])) for b in bids],
|
||||
b[2].hex(), b[3].hex(), strBidState(b[5]), strTxState(b[7]), strTxState(b[8])) for b in bids],
|
||||
), 'UTF-8')
|
||||
|
||||
def page_watched(self, url_split, post_string):
|
||||
|
|
|
@ -9,7 +9,6 @@ import urllib.parse
|
|||
|
||||
from .util import (
|
||||
toBool,
|
||||
format_timestamp,
|
||||
)
|
||||
from .basicswap import (
|
||||
strBidState,
|
||||
|
@ -131,7 +130,8 @@ def js_offers(self, url_split, post_string, is_json, sent=False):
|
|||
ci_to = self.server.swap_client.ci(o.coin_to)
|
||||
rv.append({
|
||||
'offer_id': o.offer_id.hex(),
|
||||
'created_at': format_timestamp(o.created_at),
|
||||
'created_at': o.created_at,
|
||||
'expire_at': o.expire_at,
|
||||
'coin_from': ci_from.coin_name(),
|
||||
'coin_to': ci_to.coin_name(),
|
||||
'amount_from': ci_from.format_amount(o.amount_from),
|
||||
|
@ -173,10 +173,20 @@ def js_bids(self, url_split, post_string, is_json):
|
|||
if addr_from == '-1':
|
||||
addr_from = None
|
||||
|
||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||
bid_id = swap_client.postXmrBid(offer_id, amount_from, addr_send_from=addr_from)
|
||||
if have_data_entry(post_data, 'validmins'):
|
||||
valid_for_seconds = int(get_data_entry(post_data, 'validmins')) * 60
|
||||
elif have_data_entry(post_data, 'valid_for_seconds'):
|
||||
valid_for_seconds = int(get_data_entry(post_data, 'valid_for_seconds'))
|
||||
else:
|
||||
bid_id = swap_client.postBid(offer_id, amount_from, addr_send_from=addr_from)
|
||||
valid_for_seconds = 10 * 60
|
||||
|
||||
extra_options = {
|
||||
'valid_for_seconds': valid_for_seconds,
|
||||
}
|
||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||
bid_id = swap_client.postXmrBid(offer_id, amount_from, addr_send_from=addr_from, extra_options=extra_options)
|
||||
else:
|
||||
bid_id = swap_client.postBid(offer_id, amount_from, addr_send_from=addr_from, extra_options=extra_options)
|
||||
|
||||
if have_data_entry(post_data, 'debugind'):
|
||||
swap_client.setBidDebugInd(bid_id, int(get_data_entry(post_data, 'debugind')))
|
||||
|
@ -203,18 +213,18 @@ def js_bids(self, url_split, post_string, is_json):
|
|||
|
||||
edit_bid = False
|
||||
show_txns = False
|
||||
data = describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, events, edit_bid, show_txns)
|
||||
|
||||
data = describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, events, edit_bid, show_txns, for_api=True)
|
||||
return bytes(json.dumps(data), 'UTF-8')
|
||||
|
||||
bids = swap_client.listBids()
|
||||
return bytes(json.dumps([{
|
||||
'bid_id': b[1].hex(),
|
||||
'offer_id': b[2].hex(),
|
||||
'created_at': format_timestamp(b[0]),
|
||||
'coin_from': b[8],
|
||||
'amount_from': swap_client.ci(b[8]).format_amount(b[3]),
|
||||
'bid_state': strBidState(b[4])
|
||||
'bid_id': b[2].hex(),
|
||||
'offer_id': b[3].hex(),
|
||||
'created_at': b[0],
|
||||
'expire_at': b[1],
|
||||
'coin_from': b[9],
|
||||
'amount_from': swap_client.ci(b[9]).format_amount(b[4]),
|
||||
'bid_state': strBidState(b[5])
|
||||
} for b in bids]), 'UTF-8')
|
||||
|
||||
|
||||
|
|
|
@ -12,6 +12,9 @@ from basicswap.script import (
|
|||
)
|
||||
|
||||
|
||||
INITIATE_TX_TIMEOUT = 40 * 60 # TODO: make variable per coin
|
||||
|
||||
|
||||
def buildContractScript(lock_val, secret_hash, pkh_redeem, pkh_refund, op_lock=OpCodes.OP_CHECKSEQUENCEVERIFY):
|
||||
script = bytearray([
|
||||
OpCodes.OP_IF,
|
||||
|
|
|
@ -52,11 +52,12 @@
|
|||
<tr><td>Send From Address</td><td>
|
||||
<select name="addr_from">
|
||||
{% for a in addrs %}
|
||||
<option value="{{ a }}">{{ a }}</option>
|
||||
<option value="{{ a }}" {% if data.nb_addr_from==a %} selected{% endif %}>{{ a }}</option>
|
||||
{% endfor %}
|
||||
<option value="-1">-- New Address --</option>
|
||||
<option value="-1" {% if data.nb_addr_from=="-1" %} selected{% endif %}>-- New Address --</option>
|
||||
</select>
|
||||
</td></tr>
|
||||
<tr><td>Minutes valid</td><td><input type="number" name="validmins" min="10" max="1440" value="{{ data.nb_validmins }}"></td></tr>
|
||||
|
||||
<tr><td><input type="submit" name="sendbid" value="Send Bid"><input type="submit" name="cancel" value="Cancel"></td></tr>
|
||||
</table>
|
||||
|
|
|
@ -127,7 +127,7 @@ def listBidStates():
|
|||
return rv
|
||||
|
||||
|
||||
def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_bid, show_txns, view_tx_ind=None):
|
||||
def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_bid, show_txns, view_tx_ind=None, for_api=False):
|
||||
ci_from = swap_client.ci(Coins(offer.coin_from))
|
||||
ci_to = swap_client.ci(Coins(offer.coin_to))
|
||||
ticker_from = ci_from.ticker()
|
||||
|
@ -176,8 +176,8 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
'offer_id': bid.offer_id.hex(),
|
||||
'addr_from': bid.bid_addr,
|
||||
'addr_fund_proof': bid.proof_address,
|
||||
'created_at': format_timestamp(bid.created_at, with_seconds=True),
|
||||
'expired_at': format_timestamp(bid.expire_at, with_seconds=True),
|
||||
'created_at': bid.created_at if for_api else format_timestamp(bid.created_at, with_seconds=True),
|
||||
'expired_at': bid.expire_at if for_api else format_timestamp(bid.expire_at, with_seconds=True),
|
||||
'was_sent': 'True' if bid.was_sent else 'False',
|
||||
'was_received': 'True' if bid.was_received else 'False',
|
||||
'initiate_tx': getTxIdHex(bid, TxTypes.ITX, ' ' + ticker_from),
|
||||
|
@ -226,7 +226,6 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b
|
|||
data['participate_tx_spend'] = getTxSpendHex(bid, TxTypes.PTX)
|
||||
|
||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||
|
||||
data['coin_a_lock_refund_tx_est_final'] = 'None'
|
||||
if bid.xmr_a_lock_tx and bid.xmr_a_lock_tx.block_time:
|
||||
if offer.lock_type == SEQUENCE_LOCK_TIME:
|
||||
|
|
|
@ -61,13 +61,13 @@ def prepareDataDir(datadir, node_id, conf_file, dir_prefix, base_p2p_port=BASE_P
|
|||
fp.write('acceptnonstdtxn=0\n')
|
||||
fp.write('txindex=1\n')
|
||||
fp.write('wallet=wallet.dat\n')
|
||||
|
||||
fp.write('findpeers=0\n')
|
||||
# minstakeinterval=5 # Using walletsettings stakelimit instead
|
||||
fp.write('stakethreadconddelayms=1000\n')
|
||||
|
||||
if base_p2p_port == BASE_PORT: # Particl
|
||||
fp.write('zmqpubsmsg=tcp://127.0.0.1:{}\n'.format(BASE_ZMQ_PORT + node_id))
|
||||
# minstakeinterval=5 # Using walletsettings stakelimit instead
|
||||
fp.write('stakethreadconddelayms=1000\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
|
||||
for i in range(0, num_nodes):
|
||||
if node_id == i:
|
||||
|
@ -109,10 +109,15 @@ def wait_for_bid(delay_event, swap_client, bid_id, state=None, sent=False, wait_
|
|||
if delay_event.is_set():
|
||||
raise ValueError('Test stopped.')
|
||||
delay_event.wait(1)
|
||||
bids = swap_client.listBids(sent=sent)
|
||||
|
||||
filters = {
|
||||
'bid_id': bid_id,
|
||||
}
|
||||
bids = swap_client.listBids(sent=sent, filters=filters)
|
||||
assert(len(bids) < 2)
|
||||
for bid in bids:
|
||||
if bid[1] == bid_id:
|
||||
if state is not None and state != bid[4]:
|
||||
if bid[2] == bid_id:
|
||||
if state is not None and state != bid[5]:
|
||||
continue
|
||||
return
|
||||
raise ValueError('wait_for_bid timed out.')
|
||||
|
@ -235,7 +240,6 @@ def wait_for_balance(delay_event, url, balance_key, expect_amount, iterations=20
|
|||
i = 0
|
||||
while not delay_event.is_set():
|
||||
rv_js = json.loads(urlopen(url).read())
|
||||
print("[rm] rv_js", rv_js)
|
||||
if float(rv_js[balance_key]) >= expect_amount:
|
||||
break
|
||||
delay_event.wait(delay_time)
|
||||
|
|
|
@ -99,6 +99,7 @@ class XmrTestBase(unittest.TestCase):
|
|||
fp.write('listenonion=0\n')
|
||||
fp.write('upnp=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
for ip in range(3):
|
||||
if ip != i:
|
||||
fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020 tecnovert
|
||||
# Copyright (c) 2020-2021 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -218,7 +218,9 @@ class Test(unittest.TestCase):
|
|||
rpc('walletsettings', ['stakingoptions', {'stakecombinethreshold': 100, 'stakesplitthreshold': 200}])
|
||||
|
||||
for i in range(NUM_BTC_NODES):
|
||||
prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT)
|
||||
data_dir = prepareDataDir(TEST_DIR, i, 'bitcoin.conf', 'btc_', base_p2p_port=BTC_BASE_PORT, base_rpc_port=BTC_BASE_RPC_PORT)
|
||||
if os.path.exists(os.path.join(cfg.BITCOIN_BINDIR, 'bitcoin-wallet')):
|
||||
callrpc_cli(cfg.BITCOIN_BINDIR, data_dir, 'regtest', '-wallet=wallet.dat create', 'bitcoin-wallet')
|
||||
|
||||
cls.btc_daemons.append(startDaemon(os.path.join(TEST_DIR, 'btc_' + str(i)), cfg.BITCOIN_BINDIR, cfg.BITCOIND))
|
||||
logging.info('Started %s %d', cfg.BITCOIND, cls.part_daemons[-1].pid)
|
||||
|
|
|
@ -125,6 +125,7 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey):
|
|||
|
||||
fp.write('acceptnonstdtxn=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
|
||||
for i in range(0, NUM_NODES):
|
||||
if nodeId == i:
|
||||
|
|
|
@ -99,6 +99,7 @@ class Test(unittest.TestCase):
|
|||
fp.write('listenonion=0\n')
|
||||
fp.write('upnp=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
for ip in range(3):
|
||||
if ip != i:
|
||||
fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip))
|
||||
|
|
|
@ -180,6 +180,7 @@ class Test(unittest.TestCase):
|
|||
fp.write('listenonion=0\n')
|
||||
fp.write('upnp=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
salt = generate_salt(16)
|
||||
fp.write('rpcauth={}:{}${}\n'.format('test_part_' + str(i), salt, password_to_hmac(salt, 'test_part_pwd_' + str(i))))
|
||||
for ip in range(NUM_NODES):
|
||||
|
|
|
@ -103,6 +103,7 @@ class Test(unittest.TestCase):
|
|||
fp.write('listenonion=0\n')
|
||||
fp.write('upnp=0\n')
|
||||
fp.write('minstakeinterval=5\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
for ip in range(3):
|
||||
if ip != i:
|
||||
fp.write('connect=127.0.0.1:{}\n'.format(PARTICL_PORT_BASE + ip))
|
||||
|
|
|
@ -135,6 +135,7 @@ def prepareDir(datadir, nodeId, network_key, network_pubkey):
|
|||
|
||||
fp.write('acceptnonstdtxn=0\n')
|
||||
fp.write('minstakeinterval=2\n')
|
||||
fp.write('smsgsregtestadjust=0\n')
|
||||
fp.write('stakethreadconddelayms=1000\n')
|
||||
|
||||
for i in range(0, NUM_NODES):
|
||||
|
|
|
@ -68,11 +68,29 @@ class Test(XmrTestBase):
|
|||
offers = json.loads(urlopen('http://127.0.0.1:12701/json/offers').read())
|
||||
offer = offers[0]
|
||||
|
||||
data = parse.urlencode({
|
||||
data = {
|
||||
'offer_id': offer['offer_id'],
|
||||
'amount_from': offer['amount_from']}).encode()
|
||||
'amount_from': offer['amount_from']}
|
||||
|
||||
bid_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=data).read())
|
||||
data['valid_for_seconds'] = 24 * 60 * 60 + 1
|
||||
bid = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(data).encode()).read())
|
||||
assert(bid['error'] == 'Bid TTL too high')
|
||||
del data['valid_for_seconds']
|
||||
data['validmins'] = 24 * 60 + 1
|
||||
bid = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(data).encode()).read())
|
||||
assert(bid['error'] == 'Bid TTL too high')
|
||||
|
||||
del data['validmins']
|
||||
data['valid_for_seconds'] = 10
|
||||
bid = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(data).encode()).read())
|
||||
assert(bid['error'] == 'Bid TTL too low')
|
||||
del data['valid_for_seconds']
|
||||
data['validmins'] = 1
|
||||
bid = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(data).encode()).read())
|
||||
assert(bid['error'] == 'Bid TTL too low')
|
||||
|
||||
data['validmins'] = 60
|
||||
bid_id = json.loads(urlopen('http://127.0.0.1:12701/json/bids/new', data=parse.urlencode(data).encode()).read())
|
||||
|
||||
waitForNumBids(self.delay_event, 12700, 1)
|
||||
|
||||
|
@ -82,6 +100,7 @@ class Test(XmrTestBase):
|
|||
if bid['bid_state'] == 'Received':
|
||||
break
|
||||
self.delay_event.wait(1)
|
||||
assert(bid['expire_at'] == bid['created_at'] + data['validmins'] * 60)
|
||||
|
||||
data = parse.urlencode({
|
||||
'accept': True
|
||||
|
|
Loading…
Reference in a new issue