diff --git a/basicswap/basicswap.py b/basicswap/basicswap.py index 22106b5..a562bcd 100644 --- a/basicswap/basicswap.py +++ b/basicswap/basicswap.py @@ -1825,6 +1825,15 @@ class BasicSwap(BaseApp): session.remove() self.mxDB.release() + def setTxBlockInfoFromHeight(self, ci, tx, height): + try: + tx.block_height = height + block_header = ci.getBlockHeaderFromHeight(height) + tx.block_hash = bytes.fromhex(block_header['hash']) + tx.block_time = block_header['time'] # Or median_time? + except Exception as e: + self.log.warning(f'setTxBlockInfoFromHeight failed {e}') + def loadBidTxns(self, bid, session): bid.txns = {} for stx in session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id)): @@ -3009,11 +3018,7 @@ class BasicSwap(BaseApp): if not bid.xmr_a_lock_tx.chain_height and lock_tx_chain_info['height'] != 0: self.logBidEvent(bid.bid_id, EventLogTypes.LOCK_TX_A_SEEN, '', session) - - block_header = ci_from.getBlockHeaderFromHeight(lock_tx_chain_info['height']) - bid.xmr_a_lock_tx.block_hash = bytes.fromhex(block_header['hash']) - bid.xmr_a_lock_tx.block_height = block_header['height'] - bid.xmr_a_lock_tx.block_time = block_header['time'] # Or median_time? + self.setTxBlockInfoFromHeight(ci_from, bid.xmr_a_lock_tx, lock_tx_chain_info['height']) bid_changed = True if bid.xmr_a_lock_tx.chain_height != lock_tx_chain_info['height'] and lock_tx_chain_info['height'] != 0: @@ -3121,10 +3126,7 @@ class BasicSwap(BaseApp): lock_refund_tx_chain_info = ci_from.getLockTxHeight(refund_tx.txid, refund_tx_addr, 0, bid.chain_a_height_start) if lock_refund_tx_chain_info is not None and lock_refund_tx_chain_info.get('height', 0) > 0: - block_header = ci_from.getBlockHeaderFromHeight(lock_refund_tx_chain_info['height']) - refund_tx.block_hash = bytes.fromhex(block_header['hash']) - refund_tx.block_height = block_header['height'] - refund_tx.block_time = block_header['time'] # Or median_time? + self.setTxBlockInfoFromHeight(ci_from, refund_tx, lock_refund_tx_chain_info['height']) self.saveBidInSession(bid_id, bid, session, xmr_swap) session.commit() @@ -3167,6 +3169,7 @@ class BasicSwap(BaseApp): index = None tx_height = None last_initiate_txn_conf = bid.initiate_tx.conf + ci_from = self.ci(coin_from) if coin_from == Coins.PART: # Has txindex try: initiate_txn = self.callcoinrpc(coin_from, 'getrawtransaction', [initiate_txnid_hex, True]) @@ -3190,7 +3193,6 @@ class BasicSwap(BaseApp): else: addr = p2sh - ci_from = self.ci(coin_from) found = ci_from.getLockTxHeight(bytes.fromhex(initiate_txnid_hex), addr, bid.amount, bid.chain_a_height_start, find_index=True) if found: bid.initiate_tx.conf = found['depth'] @@ -3207,6 +3209,8 @@ class BasicSwap(BaseApp): bid.initiate_tx.vout = index # Start checking for spends of initiate_txn before fully confirmed bid.initiate_tx.chain_height = self.setLastHeightChecked(coin_from, tx_height) + self.setTxBlockInfoFromHeight(ci_from, bid.initiate_tx, tx_height) + self.addWatchedOutput(coin_from, bid_id, initiate_txnid_hex, bid.initiate_tx.vout, BidStates.SWAP_INITIATED) if bid.getITxState() is None or bid.getITxState() < TxStates.TX_SENT: bid.setITxState(TxStates.TX_SENT) @@ -3243,6 +3247,8 @@ class BasicSwap(BaseApp): self.addParticipateTxn(bid_id, bid, coin_to, found['txid'], found['index'], found['height']) bid.setPTxState(TxStates.TX_SENT) save_bid = True + if found['height'] > 0 and bid.participate_tx.block_height is None: + self.setTxBlockInfoFromHeight(ci_to, bid.participate_tx, found['height']) if bid.participate_tx.conf is not None: self.log.debug('participate txid %s confirms %d', bid.participate_tx.txid.hex(), bid.participate_tx.conf) diff --git a/basicswap/js_server.py b/basicswap/js_server.py index a5ce8ff..4f736a7 100644 --- a/basicswap/js_server.py +++ b/basicswap/js_server.py @@ -241,6 +241,7 @@ def js_bids(self, url_split, post_string, is_json): bid_id = bytes.fromhex(url_split[3]) assert (len(bid_id) == 28) + show_txns = False if post_string != '': if is_json: post_data = json.loads(post_string) @@ -252,6 +253,9 @@ def js_bids(self, url_split, post_string, is_json): elif have_data_entry(post_data, 'debugind'): swap_client.setBidDebugInd(bid_id, int(get_data_entry(post_data, 'debugind'))) + if have_data_entry(post_data, 'show_extra'): + show_txns = True + bid, xmr_swap, offer, xmr_offer, events = swap_client.getXmrBidAndOffer(bid_id) assert (bid), 'Unknown bid ID' @@ -267,7 +271,6 @@ def js_bids(self, url_split, post_string, is_json): return bytes(json.dumps(old_states), 'UTF-8') edit_bid = False - show_txns = False 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') diff --git a/basicswap/ui/util.py b/basicswap/ui/util.py index 4411f49..11ceb14 100644 --- a/basicswap/ui/util.py +++ b/basicswap/ui/util.py @@ -356,6 +356,16 @@ def describeBid(swap_client, bid, xmr_swap, offer, xmr_offer, bid_events, edit_b if 'view_tx_hex' in data: data['view_tx_desc'] = json.dumps(ci_from.describeTx(data['view_tx_hex']), indent=4) + else: + if offer.lock_type == TxLockTypes.SEQUENCE_LOCK_TIME: + if bid.initiate_tx and bid.initiate_tx.block_time is not None: + raw_sequence = ci_from.getExpectedSequence(offer.lock_type, offer.lock_value) + seconds_locked = ci_from.decodeSequence(raw_sequence) + data['itx_refund_tx_est_final'] = bid.initiate_tx.block_time + seconds_locked + if bid.participate_tx and bid.participate_tx.block_time is not None: + raw_sequence = ci_to.getExpectedSequence(offer.lock_type, offer.lock_value // 2) + seconds_locked = ci_to.decodeSequence(raw_sequence) + data['ptx_refund_tx_est_final'] = bid.participate_tx.block_time + seconds_locked return data diff --git a/doc/api.md b/doc/api.md new file mode 100644 index 0000000..f79c3d5 --- /dev/null +++ b/doc/api.md @@ -0,0 +1,8 @@ + + +Examples: + + curl --header "Content-Type: application/json" \ + --request POST \ + --data '{"show_extra":true}' \ + http://localhost:12701/json/bids/00000000636ab87a5c8950b66684e86b5ed3684f175c8d05a8f0bfb6