Started stutdown and explorer pages.
Bid state can be manually edited.
This commit is contained in:
		
							parent
							
								
									321ec4acb2
								
							
						
					
					
						commit
						4405a130f5
					
				@ -368,22 +368,25 @@ class BasicSwap():
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if self.chain == 'mainnet':
 | 
					        if self.chain == 'mainnet':
 | 
				
			||||||
            self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
 | 
					            self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
 | 
				
			||||||
                self,
 | 
					                self, Coins.PART,
 | 
				
			||||||
                'https://explorer.particl.io/particl-insight-api/'))
 | 
					                'https://explorer.particl.io/particl-insight-api'))
 | 
				
			||||||
            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
 | 
					            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
 | 
				
			||||||
                self,
 | 
					                self, Coins.LTC,
 | 
				
			||||||
                'https://api.bitaps.com/ltc/v1/blockchain'))
 | 
					                'https://api.bitaps.com/ltc/v1/blockchain'))
 | 
				
			||||||
            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerChainz(
 | 
					            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerChainz(
 | 
				
			||||||
                self,
 | 
					                self, Coins.LTC,
 | 
				
			||||||
                'http://chainz.cryptoid.info/ltc/api.dws'))
 | 
					                'http://chainz.cryptoid.info/ltc/api.dws'))
 | 
				
			||||||
        elif self.chain == 'testnet':
 | 
					        elif self.chain == 'testnet':
 | 
				
			||||||
            self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
 | 
					            self.coin_clients[Coins.PART]['explorers'].append(ExplorerInsight(
 | 
				
			||||||
                self,
 | 
					                self, Coins.PART,
 | 
				
			||||||
                'https://explorer-testnet.particl.io/particl-insight-api'))
 | 
					                'https://explorer-testnet.particl.io/particl-insight-api'))
 | 
				
			||||||
            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
 | 
					            self.coin_clients[Coins.LTC]['explorers'].append(ExplorerBitAps(
 | 
				
			||||||
                self,
 | 
					                self, Coins.LTC,
 | 
				
			||||||
                'https://api.bitaps.com/ltc/testnet/v1/blockchain'))
 | 
					                'https://api.bitaps.com/ltc/testnet/v1/blockchain'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            # non-segwit
 | 
				
			||||||
 | 
					            # https://testnet.litecore.io/insight-api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    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
 | 
				
			||||||
@ -593,6 +596,55 @@ class BasicSwap():
 | 
				
			|||||||
        session.close()
 | 
					        session.close()
 | 
				
			||||||
        session.remove()
 | 
					        session.remove()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def activateBid(self, session, bid):
 | 
				
			||||||
 | 
					        if bid.bid_id in self.swaps_in_progress:
 | 
				
			||||||
 | 
					            self.log.debug('Bid %s is already in progress', bid.bid_id.hex())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.log.debug('Loading active bid %s', bid.bid_id.hex())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        offer = session.query(Offer).filter_by(offer_id=bid.offer_id).first()
 | 
				
			||||||
 | 
					        assert(offer), 'Offer not found'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        bid.initiate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.ITX)).first()
 | 
				
			||||||
 | 
					        bid.participate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.PTX)).first()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        self.swaps_in_progress[bid.bid_id] = (bid, offer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        coin_from = Coins(offer.coin_from)
 | 
				
			||||||
 | 
					        coin_to = Coins(offer.coin_to)
 | 
				
			||||||
 | 
					        if bid.initiate_tx and bid.initiate_tx.txid:
 | 
				
			||||||
 | 
					            self.addWatchedOutput(coin_from, bid.bid_id, bid.initiate_tx.txid.hex(), bid.initiate_tx.vout, BidStates.SWAP_INITIATED)
 | 
				
			||||||
 | 
					        if bid.participate_tx and bid.participate_tx.txid:
 | 
				
			||||||
 | 
					            self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_tx.txid.hex(), bid.participate_tx.vout, BidStates.SWAP_PARTICIPATING)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.coin_clients[coin_from]['last_height_checked'] < 1:
 | 
				
			||||||
 | 
					            if bid.initiate_tx and bid.initiate_tx.chain_height:
 | 
				
			||||||
 | 
					                self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_tx.chain_height
 | 
				
			||||||
 | 
					        if self.coin_clients[coin_to]['last_height_checked'] < 1:
 | 
				
			||||||
 | 
					            if bid.participate_tx and bid.participate_tx.chain_height:
 | 
				
			||||||
 | 
					                self.coin_clients[coin_to]['last_height_checked'] = bid.participate_tx.chain_height
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO process addresspool if bid has previously been abandoned
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def deactivateBid(self, offer, bid):
 | 
				
			||||||
 | 
					        # Remove from in progress
 | 
				
			||||||
 | 
					        self.swaps_in_progress.pop(bid.bid_id, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Remove any watched outputs
 | 
				
			||||||
 | 
					        self.removeWatchedOutput(Coins(offer.coin_from), bid.bid_id, None)
 | 
				
			||||||
 | 
					        self.removeWatchedOutput(Coins(offer.coin_to), bid.bid_id, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if bid.state == BidStates.BID_ABANDONED or bid.state == BidStates.SWAP_COMPLETED:
 | 
				
			||||||
 | 
					            # Return unused addrs to pool
 | 
				
			||||||
 | 
					            if bid.getITxState() != TxStates.TX_REDEEMED:
 | 
				
			||||||
 | 
					                self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM)
 | 
				
			||||||
 | 
					            if bid.getITxState() != TxStates.TX_REFUNDED:
 | 
				
			||||||
 | 
					                self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND)
 | 
				
			||||||
 | 
					            if bid.getPTxState() != TxStates.TX_REDEEMED:
 | 
				
			||||||
 | 
					                self.returnAddressToPool(bid_id, TxTypes.PTX_REDEEM)
 | 
				
			||||||
 | 
					            if bid.getPTxState() != TxStates.TX_REFUNDED:
 | 
				
			||||||
 | 
					                self.returnAddressToPool(bid_id, TxTypes.PTX_REFUND)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def loadFromDB(self):
 | 
					    def loadFromDB(self):
 | 
				
			||||||
        self.log.info('Loading data from db')
 | 
					        self.log.info('Loading data from db')
 | 
				
			||||||
        self.mxDB.acquire()
 | 
					        self.mxDB.acquire()
 | 
				
			||||||
@ -600,29 +652,7 @@ class BasicSwap():
 | 
				
			|||||||
            session = scoped_session(self.session_factory)
 | 
					            session = scoped_session(self.session_factory)
 | 
				
			||||||
            for bid in session.query(Bid):
 | 
					            for bid in session.query(Bid):
 | 
				
			||||||
                if bid.state and bid.state > BidStates.BID_RECEIVED and bid.state < BidStates.SWAP_COMPLETED:
 | 
					                if bid.state and bid.state > BidStates.BID_RECEIVED and bid.state < BidStates.SWAP_COMPLETED:
 | 
				
			||||||
                    self.log.debug('Loading active bid %s', bid.bid_id.hex())
 | 
					                    self.activateBid(session, bid)
 | 
				
			||||||
 | 
					 | 
				
			||||||
                    offer = session.query(Offer).filter_by(offer_id=bid.offer_id).first()
 | 
					 | 
				
			||||||
                    assert(offer), 'Offer not found'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    bid.initiate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.ITX)).first()
 | 
					 | 
				
			||||||
                    bid.participate_tx = session.query(SwapTx).filter(sa.and_(SwapTx.bid_id == bid.bid_id, SwapTx.tx_type == TxTypes.PTX)).first()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    self.swaps_in_progress[bid.bid_id] = (bid, offer)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    coin_from = Coins(offer.coin_from)
 | 
					 | 
				
			||||||
                    coin_to = Coins(offer.coin_to)
 | 
					 | 
				
			||||||
                    if bid.initiate_tx and bid.initiate_tx.txid:
 | 
					 | 
				
			||||||
                        self.addWatchedOutput(coin_from, bid.bid_id, bid.initiate_tx.txid.hex(), bid.initiate_tx.vout, BidStates.SWAP_INITIATED)
 | 
					 | 
				
			||||||
                    if bid.participate_tx and bid.participate_tx.txid:
 | 
					 | 
				
			||||||
                        self.addWatchedOutput(coin_to, bid.bid_id, bid.participate_tx.txid.hex(), bid.participate_tx.vout, BidStates.SWAP_PARTICIPATING)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if self.coin_clients[coin_from]['last_height_checked'] < 1:
 | 
					 | 
				
			||||||
                        if bid.initiate_tx and bid.initiate_tx.chain_height:
 | 
					 | 
				
			||||||
                            self.coin_clients[coin_from]['last_height_checked'] = bid.initiate_tx.chain_height
 | 
					 | 
				
			||||||
                    if self.coin_clients[coin_to]['last_height_checked'] < 1:
 | 
					 | 
				
			||||||
                        if bid.participate_tx and bid.participate_tx.chain_height:
 | 
					 | 
				
			||||||
                            self.coin_clients[coin_to]['last_height_checked'] = bid.participate_tx.chain_height
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            session.close()
 | 
					            session.close()
 | 
				
			||||||
@ -1139,44 +1169,49 @@ class BasicSwap():
 | 
				
			|||||||
        pubkey_refund = self.getContractPubkey(bid_date, bid.contract_count)
 | 
					        pubkey_refund = self.getContractPubkey(bid_date, bid.contract_count)
 | 
				
			||||||
        pkhash_refund = getKeyID(pubkey_refund)
 | 
					        pkhash_refund = getKeyID(pubkey_refund)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if offer.lock_type < ABS_LOCK_BLOCKS:
 | 
					        if bid.initiate_tx is not None:
 | 
				
			||||||
            sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
 | 
					            self.log.warning('initiate txn %s already exists for bid %s', bid.initiate_tx.txid, bid_id.hex())
 | 
				
			||||||
            script = buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
 | 
					            txid = bid.initiate_tx.txid
 | 
				
			||||||
 | 
					            script = bid.initiate_tx.script
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            if offer.lock_type == ABS_LOCK_BLOCKS:
 | 
					            if offer.lock_type < ABS_LOCK_BLOCKS:
 | 
				
			||||||
                lock_value = self.callcoinrpc(coin_from, 'getblockchaininfo')['blocks'] + offer.lock_value
 | 
					                sequence = getExpectedSequence(offer.lock_type, offer.lock_value, coin_from)
 | 
				
			||||||
 | 
					                script = buildContractScript(sequence, secret_hash, bid.pkhash_buyer, pkhash_refund)
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                lock_value = int(time.time()) + offer.lock_value
 | 
					                if offer.lock_type == ABS_LOCK_BLOCKS:
 | 
				
			||||||
            self.log.debug('initiate %s lock_value %d %d', coin_from, offer.lock_value, lock_value)
 | 
					                    lock_value = self.callcoinrpc(coin_from, 'getblockchaininfo')['blocks'] + offer.lock_value
 | 
				
			||||||
            script = buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
					                else:
 | 
				
			||||||
 | 
					                    lock_value = int(time.time()) + offer.lock_value
 | 
				
			||||||
 | 
					                self.log.debug('initiate %s lock_value %d %d', coin_from, offer.lock_value, lock_value)
 | 
				
			||||||
 | 
					                script = buildContractScript(lock_value, secret_hash, bid.pkhash_buyer, pkhash_refund, OpCodes.OP_CHECKLOCKTIMEVERIFY)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
 | 
					            p2sh = self.callcoinrpc(Coins.PART, 'decodescript', [script.hex()])['p2sh']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bid.pkhash_seller = pkhash_refund
 | 
					            bid.pkhash_seller = pkhash_refund
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        txn = self.createInitiateTxn(coin_from, bid_id, bid, script)
 | 
					            txn = self.createInitiateTxn(coin_from, bid_id, bid, script)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Store the signed refund txn in case wallet is locked when refund is possible
 | 
					            # Store the signed refund txn in case wallet is locked when refund is possible
 | 
				
			||||||
        refund_txn = self.createRefundTxn(coin_from, txn, offer, bid, script)
 | 
					            refund_txn = self.createRefundTxn(coin_from, txn, offer, bid, script)
 | 
				
			||||||
        bid.initiate_txn_refund = bytes.fromhex(refund_txn)
 | 
					            bid.initiate_txn_refund = bytes.fromhex(refund_txn)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        txid = self.submitTxn(coin_from, txn)
 | 
					            txid = self.submitTxn(coin_from, txn)
 | 
				
			||||||
        self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
 | 
					            self.log.debug('Submitted initiate txn %s to %s chain for bid %s', txid, chainparams[coin_from]['name'], bid_id.hex())
 | 
				
			||||||
        bid.initiate_tx = SwapTx(
 | 
					            bid.initiate_tx = SwapTx(
 | 
				
			||||||
            bid_id=bid_id,
 | 
					                bid_id=bid_id,
 | 
				
			||||||
            tx_type=TxTypes.ITX,
 | 
					                tx_type=TxTypes.ITX,
 | 
				
			||||||
            txid=bytes.fromhex(txid),
 | 
					                txid=bytes.fromhex(txid),
 | 
				
			||||||
            script=script,
 | 
					                script=script,
 | 
				
			||||||
        )
 | 
					            )
 | 
				
			||||||
        bid.setITxState(TxStates.TX_SENT)
 | 
					            bid.setITxState(TxStates.TX_SENT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Check non-bip68 final
 | 
					            # Check non-bip68 final
 | 
				
			||||||
        try:
 | 
					            try:
 | 
				
			||||||
            txid = self.submitTxn(coin_from, bid.initiate_txn_refund.hex())
 | 
					                txid = self.submitTxn(coin_from, bid.initiate_txn_refund.hex())
 | 
				
			||||||
            self.log.error('Submit refund_txn unexpectedly worked: ' + txid)
 | 
					                self.log.error('Submit refund_txn unexpectedly worked: ' + txid)
 | 
				
			||||||
        except Exception as ex:
 | 
					            except Exception as ex:
 | 
				
			||||||
            if 'non-BIP68-final' not in str(ex) and 'non-final' not in str(ex):
 | 
					                if 'non-BIP68-final' not in str(ex) and 'non-final' not in str(ex):
 | 
				
			||||||
                self.log.error('Submit refund_txn unexpected error' + str(ex))
 | 
					                    self.log.error('Submit refund_txn unexpected error' + str(ex))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if txid is not None:
 | 
					        if txid is not None:
 | 
				
			||||||
            msg_buf = BidAcceptMessage()
 | 
					            msg_buf = BidAcceptMessage()
 | 
				
			||||||
@ -1234,22 +1269,7 @@ class BasicSwap():
 | 
				
			|||||||
            bid.setState(BidStates.BID_ABANDONED)
 | 
					            bid.setState(BidStates.BID_ABANDONED)
 | 
				
			||||||
            session.commit()
 | 
					            session.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Remove from in progress
 | 
					            self.deactivateBid(offer, bid)
 | 
				
			||||||
            self.swaps_in_progress.pop(bid_id, None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Remove any watched outputs
 | 
					 | 
				
			||||||
            self.removeWatchedOutput(Coins(offer.coin_from), bid_id, None)
 | 
					 | 
				
			||||||
            self.removeWatchedOutput(Coins(offer.coin_to), bid_id, None)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Return unused addrs to pool
 | 
					 | 
				
			||||||
            if bid.getITxState() != TxStates.TX_REDEEMED:
 | 
					 | 
				
			||||||
                self.returnAddressToPool(bid_id, TxTypes.ITX_REDEEM)
 | 
					 | 
				
			||||||
            if bid.getITxState() != TxStates.TX_REFUNDED:
 | 
					 | 
				
			||||||
                self.returnAddressToPool(bid_id, TxTypes.ITX_REFUND)
 | 
					 | 
				
			||||||
            if bid.getPTxState() != TxStates.TX_REDEEMED:
 | 
					 | 
				
			||||||
                self.returnAddressToPool(bid_id, TxTypes.PTX_REDEEM)
 | 
					 | 
				
			||||||
            if bid.getPTxState() != TxStates.TX_REFUNDED:
 | 
					 | 
				
			||||||
                self.returnAddressToPool(bid_id, TxTypes.PTX_REFUND)
 | 
					 | 
				
			||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            session.close()
 | 
					            session.close()
 | 
				
			||||||
            session.remove()
 | 
					            session.remove()
 | 
				
			||||||
@ -1612,13 +1632,16 @@ class BasicSwap():
 | 
				
			|||||||
        # Seller first mode, buyer participates
 | 
					        # Seller first mode, buyer participates
 | 
				
			||||||
        participate_script = self.deriveParticipateScript(bid_id, bid, offer)
 | 
					        participate_script = self.deriveParticipateScript(bid_id, bid, offer)
 | 
				
			||||||
        if bid.was_sent:
 | 
					        if bid.was_sent:
 | 
				
			||||||
            self.log.debug('Preparing participate txn for bid %s', bid_id.hex())
 | 
					            if bid.participate_tx is not None:
 | 
				
			||||||
 | 
					                self.log.warning('Participate txn %s already exists for bid %s', bid.participate_tx.txid, bid_id.hex())
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                self.log.debug('Preparing participate txn for bid %s', bid_id.hex())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            coin_to = Coins(offer.coin_to)
 | 
					                coin_to = Coins(offer.coin_to)
 | 
				
			||||||
            txn = self.createParticipateTxn(bid_id, bid, offer, participate_script)
 | 
					                txn = self.createParticipateTxn(bid_id, bid, offer, participate_script)
 | 
				
			||||||
            txid = self.submitTxn(coin_to, txn)
 | 
					                txid = self.submitTxn(coin_to, txn)
 | 
				
			||||||
            self.log.debug('Submitted participate txn %s to %s chain for bid %s', txid, chainparams[coin_to]['name'], bid_id.hex())
 | 
					                self.log.debug('Submitted participate txn %s to %s chain for bid %s', txid, chainparams[coin_to]['name'], bid_id.hex())
 | 
				
			||||||
            bid.setPTxState(TxStates.TX_SENT)
 | 
					                bid.setPTxState(TxStates.TX_SENT)
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            bid.participate_tx = SwapTx(
 | 
					            bid.participate_tx = SwapTx(
 | 
				
			||||||
                bid_id=bid_id,
 | 
					                bid_id=bid_id,
 | 
				
			||||||
@ -2326,6 +2349,37 @@ class BasicSwap():
 | 
				
			|||||||
        finally:
 | 
					        finally:
 | 
				
			||||||
            self.mxDB.release()
 | 
					            self.mxDB.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def manualBidUpdate(self, bid_id, data):
 | 
				
			||||||
 | 
					        self.log.info('Manually updating bid %s', bid_id.hex())
 | 
				
			||||||
 | 
					        self.mxDB.acquire()
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            bid, offer = self.getBidAndOffer(bid_id)
 | 
				
			||||||
 | 
					            assert(bid), 'Bid not found {}'.format(bid_id.hex())
 | 
				
			||||||
 | 
					            assert(offer), 'Offer not found {}'.format(bid.offer_id.hex())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            has_changed = False
 | 
				
			||||||
 | 
					            if bid.state != data['bid_state']:
 | 
				
			||||||
 | 
					                bid.setState(data['bid_state'])
 | 
				
			||||||
 | 
					                self.log.debug('Set state to %s', strBidState(bid.state))
 | 
				
			||||||
 | 
					                has_changed = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if has_changed:
 | 
				
			||||||
 | 
					                session = scoped_session(self.session_factory)
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    self.saveBidInSession(session, bid)
 | 
				
			||||||
 | 
					                    session.commit()
 | 
				
			||||||
 | 
					                    if bid.state and bid.state > BidStates.BID_RECEIVED and bid.state < BidStates.SWAP_COMPLETED:
 | 
				
			||||||
 | 
					                        self.activateBid(session, bid)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        self.deactivateBid(offer, bid)
 | 
				
			||||||
 | 
					                finally:
 | 
				
			||||||
 | 
					                    session.close()
 | 
				
			||||||
 | 
					                    session.remove()
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                raise ValueError('No changes')
 | 
				
			||||||
 | 
					        finally:
 | 
				
			||||||
 | 
					            self.mxDB.release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getSummary(self, opts=None):
 | 
					    def getSummary(self, opts=None):
 | 
				
			||||||
        num_watched_outputs = 0
 | 
					        num_watched_outputs = 0
 | 
				
			||||||
        for c, v in self.coin_clients.items():
 | 
					        for c, v in self.coin_clients.items():
 | 
				
			||||||
 | 
				
			|||||||
@ -180,3 +180,14 @@ class SmsgAddress(Base):
 | 
				
			|||||||
    addr_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
 | 
					    addr_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
 | 
				
			||||||
    addr = sa.Column(sa.String)
 | 
					    addr = sa.Column(sa.String)
 | 
				
			||||||
    use_type = sa.Column(sa.Integer)
 | 
					    use_type = sa.Column(sa.Integer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# TODO: Delay responding to automated events
 | 
				
			||||||
 | 
					class EventQueue(Base):
 | 
				
			||||||
 | 
					    __tablename__ = 'eventqueue'
 | 
				
			||||||
 | 
					    addr_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
 | 
				
			||||||
 | 
					    created_at = sa.Column(sa.BigInteger)
 | 
				
			||||||
 | 
					    trigger_at = sa.Column(sa.BigInteger)
 | 
				
			||||||
 | 
					    linked_id = sa.Column(sa.LargeBinary)
 | 
				
			||||||
 | 
					    event_type = sa.Column(sa.Integer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,33 +9,72 @@ import json
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Explorer():
 | 
					class Explorer():
 | 
				
			||||||
    def __init__(self, swapclient, base_url):
 | 
					    def __init__(self, swapclient, coin_type, base_url):
 | 
				
			||||||
        self.swapclient = swapclient
 | 
					        self.swapclient = swapclient
 | 
				
			||||||
 | 
					        self.coin_type = coin_type
 | 
				
			||||||
        self.base_url = base_url
 | 
					        self.base_url = base_url
 | 
				
			||||||
        self.log = self.swapclient.log
 | 
					        self.log = self.swapclient.log
 | 
				
			||||||
 | 
					        self.coin_settings = self.swapclient.coin_clients[self.coin_type]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def readURL(self, url):
 | 
				
			||||||
 | 
					        self.log.debug('Explorer url: {}'.format(url))
 | 
				
			||||||
 | 
					        headers = {'User-Agent': 'Mozilla/5.0'}
 | 
				
			||||||
 | 
					        req = urllib.request.Request(url, headers=headers)
 | 
				
			||||||
 | 
					        return urllib.request.urlopen(req).read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExplorerInsight(Explorer):
 | 
					class ExplorerInsight(Explorer):
 | 
				
			||||||
    def getChainHeight(self):
 | 
					    def getChainHeight(self):
 | 
				
			||||||
        return json.loads(urllib.request.urlopen(self.base_url + '/sync').read())['blockChainHeight']
 | 
					        return json.loads(self.readURL(self.base_url + '/sync'))['blockChainHeight']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getBlock(self, block_hash):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/block/{}'.format(block_hash)))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getTransaction(self, txid):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/tx/{}'.format(txid)))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getBalance(self, address):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/addr/{}/balance'.format(address)))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lookupUnspentByAddress(self, address):
 | 
					    def lookupUnspentByAddress(self, address):
 | 
				
			||||||
        chain_height = self.getChainHeight()
 | 
					        data = json.loads(self.readURL(self.base_url + '/addr/{}/utxo'.format(address)))
 | 
				
			||||||
        self.log.debug('[rm] chain_height %d', chain_height)
 | 
					        rv = []
 | 
				
			||||||
 | 
					        for utxo in data:
 | 
				
			||||||
 | 
					            rv.append({
 | 
				
			||||||
 | 
					                'txid': utxo['txid'],
 | 
				
			||||||
 | 
					                'index': utxo['vout'],
 | 
				
			||||||
 | 
					                'height': utxo['height'],
 | 
				
			||||||
 | 
					                'n_conf': utxo['confirmations'],
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        return rv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExplorerBitAps(Explorer):
 | 
					class ExplorerBitAps(Explorer):
 | 
				
			||||||
    def getChainHeight(self):
 | 
					    def getChainHeight(self):
 | 
				
			||||||
        return json.loads(urllib.request.urlopen(self.base_url + '/block/last').read())['data']['block']['height']
 | 
					        return json.loads(self.readURL(self.base_url + '/block/last'))['data']['block']['height']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getBlock(self, block_hash):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/block/{}'.format(block_hash)))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getTransaction(self, txid):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/transaction/{}'.format(txid)))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getBalance(self, address):
 | 
				
			||||||
 | 
					        data = json.loads(self.readURL(self.base_url + '/address/state/' + address))
 | 
				
			||||||
 | 
					        return data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lookupUnspentByAddress(self, address):
 | 
					    def lookupUnspentByAddress(self, address):
 | 
				
			||||||
        chain_height = self.getChainHeight()
 | 
					        return json.loads(self.readURL(self.base_url + '/address/transactions/' + address))
 | 
				
			||||||
        self.log.debug('[rm] chain_height %d', chain_height)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ExplorerChainz(Explorer):
 | 
					class ExplorerChainz(Explorer):
 | 
				
			||||||
    def getChainHeight(self):
 | 
					    def getChainHeight(self):
 | 
				
			||||||
        return int(urllib.request.urlopen(self.base_url + '?q=getblockcount').read())
 | 
					        return int(self.readURL(self.base_url + '?q=getblockcount'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lookupUnspentByAddress(self, address):
 | 
					    def lookupUnspentByAddress(self, address):
 | 
				
			||||||
        chain_height = self.getChainHeight()
 | 
					        chain_height = self.getChainHeight()
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@ from .util import (
 | 
				
			|||||||
    COIN,
 | 
					    COIN,
 | 
				
			||||||
    format8,
 | 
					    format8,
 | 
				
			||||||
    makeInt,
 | 
					    makeInt,
 | 
				
			||||||
 | 
					    dumpj,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from .chainparams import (
 | 
					from .chainparams import (
 | 
				
			||||||
    chainparams,
 | 
					    chainparams,
 | 
				
			||||||
@ -60,6 +61,34 @@ def listAvailableCoins(swap_client):
 | 
				
			|||||||
    return coins
 | 
					    return coins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def extractDomain(url):
 | 
				
			||||||
 | 
					    return url.split('://', 1)[1].split('/', 1)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def listAvailableExplorers(swap_client):
 | 
				
			||||||
 | 
					    explorers = []
 | 
				
			||||||
 | 
					    for c in Coins:
 | 
				
			||||||
 | 
					        for i, e in enumerate(swap_client.coin_clients[c]['explorers']):
 | 
				
			||||||
 | 
					            explorers.append(('{}_{}'.format(int(c), i), swap_client.coin_clients[c]['name'].capitalize() + ' - ' + extractDomain(e.base_url)))
 | 
				
			||||||
 | 
					    return explorers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def listExplorerActions(swap_client):
 | 
				
			||||||
 | 
					    actions = [('height', 'Chain Height'),
 | 
				
			||||||
 | 
					               ('block', 'Get Block'),
 | 
				
			||||||
 | 
					               ('tx', 'Get Transaction'),
 | 
				
			||||||
 | 
					               ('balance', 'Address Balance'),
 | 
				
			||||||
 | 
					               ('unspent', 'List Unspent')]
 | 
				
			||||||
 | 
					    return actions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def listBidStates():
 | 
				
			||||||
 | 
					    rv = []
 | 
				
			||||||
 | 
					    for s in BidStates:
 | 
				
			||||||
 | 
					        rv.append((int(s), strBidState(s)))
 | 
				
			||||||
 | 
					    return rv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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
 | 
				
			||||||
@ -110,6 +139,12 @@ def html_content_start(title, h2=None, refresh=None):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HttpHandler(BaseHTTPRequestHandler):
 | 
					class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			||||||
 | 
					    def page_info(self, info_str):
 | 
				
			||||||
 | 
					        content = html_content_start('BasicSwap Info') \
 | 
				
			||||||
 | 
					            + '<p>Info: ' + info_str + '</p>' \
 | 
				
			||||||
 | 
					            + '<p><a href=\'/\'>home</a></p></body></html>'
 | 
				
			||||||
 | 
					        return bytes(content, 'UTF-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def page_error(self, error_str):
 | 
					    def page_error(self, error_str):
 | 
				
			||||||
        content = html_content_start('BasicSwap Error') \
 | 
					        content = html_content_start('BasicSwap Error') \
 | 
				
			||||||
            + '<p>Error: ' + error_str + '</p>' \
 | 
					            + '<p>Error: ' + error_str + '</p>' \
 | 
				
			||||||
@ -156,6 +191,50 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
    def js_index(self, url_split):
 | 
					    def js_index(self, url_split):
 | 
				
			||||||
        return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
 | 
					        return bytes(json.dumps(self.server.swap_client.getSummary()), 'UTF-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def page_explorers(self, url_split, post_string):
 | 
				
			||||||
 | 
					        swap_client = self.server.swap_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        result = None
 | 
				
			||||||
 | 
					        explorer = -1
 | 
				
			||||||
 | 
					        action = -1
 | 
				
			||||||
 | 
					        messages = []
 | 
				
			||||||
 | 
					        form_data = self.checkForm(post_string, 'explorers', messages)
 | 
				
			||||||
 | 
					        if form_data:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            explorer = form_data[b'explorer'][0].decode('utf-8')
 | 
				
			||||||
 | 
					            action = form_data[b'action'][0].decode('utf-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            args = '' if not b'args' in form_data else form_data[b'args'][0].decode('utf-8')
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                c, e = explorer.split('_')
 | 
				
			||||||
 | 
					                exp = swap_client.coin_clients[Coins(int(c))]['explorers'][int(e)]
 | 
				
			||||||
 | 
					                if action == 'height':
 | 
				
			||||||
 | 
					                    result = str(exp.getChainHeight())
 | 
				
			||||||
 | 
					                elif action == 'block':
 | 
				
			||||||
 | 
					                    result = dumpj(exp.getBlock(args))
 | 
				
			||||||
 | 
					                elif action == 'tx':
 | 
				
			||||||
 | 
					                    result = dumpj(exp.getTransaction(args))
 | 
				
			||||||
 | 
					                elif action == 'balance':
 | 
				
			||||||
 | 
					                    result = dumpj(exp.getBalance(args))
 | 
				
			||||||
 | 
					                elif action == 'unspent':
 | 
				
			||||||
 | 
					                    result = dumpj(exp.lookupUnspentByAddress(args))
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    result = 'Unknown action'
 | 
				
			||||||
 | 
					            except Exception as ex:
 | 
				
			||||||
 | 
					                result = str(ex)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        template = env.get_template('explorers.html')
 | 
				
			||||||
 | 
					        return bytes(template.render(
 | 
				
			||||||
 | 
					            title=self.server.title,
 | 
				
			||||||
 | 
					            h2=self.server.title,
 | 
				
			||||||
 | 
					            explorers=listAvailableExplorers(swap_client),
 | 
				
			||||||
 | 
					            explorer=explorer,
 | 
				
			||||||
 | 
					            actions=listExplorerActions(swap_client),
 | 
				
			||||||
 | 
					            action=action,
 | 
				
			||||||
 | 
					            result=result,
 | 
				
			||||||
 | 
					            form_id=os.urandom(8).hex(),
 | 
				
			||||||
 | 
					        ), 'UTF-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def page_rpc(self, url_split, post_string):
 | 
					    def page_rpc(self, url_split, post_string):
 | 
				
			||||||
        swap_client = self.server.swap_client
 | 
					        swap_client = self.server.swap_client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -400,7 +479,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
                sort_by = form_data[b'sort_by'][0].decode('utf-8')
 | 
					                sort_by = form_data[b'sort_by'][0].decode('utf-8')
 | 
				
			||||||
                assert(sort_by in ['created_at', 'rate']), 'Invalid sort by'
 | 
					                assert(sort_by in ['created_at', 'rate']), 'Invalid sort by'
 | 
				
			||||||
                filters['sort_by'] = sort_by
 | 
					                filters['sort_by'] = sort_by
 | 
				
			||||||
            if b'sort_dir' in form_data:
 | 
					            elif b'sort_dir' in form_data:
 | 
				
			||||||
                sort_dir = form_data[b'sort_dir'][0].decode('utf-8')
 | 
					                sort_dir = form_data[b'sort_dir'][0].decode('utf-8')
 | 
				
			||||||
                assert(sort_dir in ['asc', 'desc']), 'Invalid sort dir'
 | 
					                assert(sort_dir in ['asc', 'desc']), 'Invalid sort dir'
 | 
				
			||||||
                filters['sort_dir'] = sort_dir
 | 
					                filters['sort_dir'] = sort_dir
 | 
				
			||||||
@ -409,7 +488,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
            filters['page_no'] = int(form_data[b'pageno'][0]) - 1
 | 
					            filters['page_no'] = int(form_data[b'pageno'][0]) - 1
 | 
				
			||||||
            if filters['page_no'] < 1:
 | 
					            if filters['page_no'] < 1:
 | 
				
			||||||
                filters['page_no'] = 1
 | 
					                filters['page_no'] = 1
 | 
				
			||||||
        if form_data and b'pageforwards' in form_data:
 | 
					        elif form_data and b'pageforwards' in form_data:
 | 
				
			||||||
            filters['page_no'] = int(form_data[b'pageno'][0]) + 1
 | 
					            filters['page_no'] = int(form_data[b'pageno'][0]) + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if filters['page_no'] > 1:
 | 
					        if filters['page_no'] > 1:
 | 
				
			||||||
@ -457,6 +536,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        messages = []
 | 
					        messages = []
 | 
				
			||||||
        show_txns = False
 | 
					        show_txns = False
 | 
				
			||||||
 | 
					        edit_bid = False
 | 
				
			||||||
        form_data = self.checkForm(post_string, 'bid', messages)
 | 
					        form_data = self.checkForm(post_string, 'bid', messages)
 | 
				
			||||||
        if form_data:
 | 
					        if form_data:
 | 
				
			||||||
            if b'abandon_bid' in form_data:
 | 
					            if b'abandon_bid' in form_data:
 | 
				
			||||||
@ -464,15 +544,26 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
                    swap_client.abandonBid(bid_id)
 | 
					                    swap_client.abandonBid(bid_id)
 | 
				
			||||||
                    messages.append('Bid abandoned')
 | 
					                    messages.append('Bid abandoned')
 | 
				
			||||||
                except Exception as ex:
 | 
					                except Exception as ex:
 | 
				
			||||||
                    messages.append('Error ' + str(ex))
 | 
					                    messages.append('Abandon failed ' + str(ex))
 | 
				
			||||||
            if b'accept_bid' in form_data:
 | 
					            elif b'accept_bid' in form_data:
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    swap_client.acceptBid(bid_id)
 | 
					                    swap_client.acceptBid(bid_id)
 | 
				
			||||||
                    messages.append('Bid accepted')
 | 
					                    messages.append('Bid accepted')
 | 
				
			||||||
                except Exception as ex:
 | 
					                except Exception as ex:
 | 
				
			||||||
                    messages.append('Error ' + str(ex))
 | 
					                    messages.append('Accept failed ' + str(ex))
 | 
				
			||||||
            if b'show_txns' in form_data:
 | 
					            elif b'show_txns' in form_data:
 | 
				
			||||||
                show_txns = True
 | 
					                show_txns = True
 | 
				
			||||||
 | 
					            elif b'edit_bid' in form_data:
 | 
				
			||||||
 | 
					                edit_bid = True
 | 
				
			||||||
 | 
					            elif b'edit_bid_submit' in form_data:
 | 
				
			||||||
 | 
					                data = {
 | 
				
			||||||
 | 
					                    'bid_state': int(form_data[b'new_state'][0])
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                try:
 | 
				
			||||||
 | 
					                    swap_client.manualBidUpdate(bid_id, data)
 | 
				
			||||||
 | 
					                    messages.append('Bid edited')
 | 
				
			||||||
 | 
					                except Exception as ex:
 | 
				
			||||||
 | 
					                    messages.append('Edit failed ' + str(ex))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bid, offer = swap_client.getBidAndOffer(bid_id)
 | 
					        bid, offer = swap_client.getBidAndOffer(bid_id)
 | 
				
			||||||
        assert(bid), 'Unknown bid ID'
 | 
					        assert(bid), 'Unknown bid ID'
 | 
				
			||||||
@ -533,6 +624,10 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
            'show_txns': show_txns,
 | 
					            'show_txns': show_txns,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if edit_bid:
 | 
				
			||||||
 | 
					            data['bid_state_ind'] = int(bid.state)
 | 
				
			||||||
 | 
					            data['bid_states'] = listBidStates()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if show_txns:
 | 
					        if show_txns:
 | 
				
			||||||
            data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
 | 
					            data['initiate_tx_refund'] = 'None' if not bid.initiate_txn_refund else bid.initiate_txn_refund.hex()
 | 
				
			||||||
            data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
 | 
					            data['participate_tx_refund'] = 'None' if not bid.participate_txn_refund else bid.participate_txn_refund.hex()
 | 
				
			||||||
@ -564,6 +659,7 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
            bid_id=bid_id.hex(),
 | 
					            bid_id=bid_id.hex(),
 | 
				
			||||||
            messages=messages,
 | 
					            messages=messages,
 | 
				
			||||||
            data=data,
 | 
					            data=data,
 | 
				
			||||||
 | 
					            edit_bid=edit_bid,
 | 
				
			||||||
            form_id=os.urandom(8).hex(),
 | 
					            form_id=os.urandom(8).hex(),
 | 
				
			||||||
            old_states=old_states,
 | 
					            old_states=old_states,
 | 
				
			||||||
        ), 'UTF-8')
 | 
					        ), 'UTF-8')
 | 
				
			||||||
@ -594,6 +690,12 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
            watched_outputs=[(wo[1].hex(), getCoinName(wo[0]), wo[2], wo[3], int(wo[4])) for wo in watched_outputs],
 | 
					            watched_outputs=[(wo[1].hex(), getCoinName(wo[0]), wo[2], wo[3], int(wo[4])) for wo in watched_outputs],
 | 
				
			||||||
        ), 'UTF-8')
 | 
					        ), 'UTF-8')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def page_shutdown(self, url_split, post_string):
 | 
				
			||||||
 | 
					        swap_client = self.server.swap_client
 | 
				
			||||||
 | 
					        swap_client.stopRunning()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return self.page_info('Shutting down')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def page_index(self, url_split):
 | 
					    def page_index(self, url_split):
 | 
				
			||||||
        swap_client = self.server.swap_client
 | 
					        swap_client = self.server.swap_client
 | 
				
			||||||
        summary = swap_client.getSummary()
 | 
					        summary = swap_client.getSummary()
 | 
				
			||||||
@ -639,6 +741,8 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
                    return self.page_wallets(url_split, post_string)
 | 
					                    return self.page_wallets(url_split, post_string)
 | 
				
			||||||
                if url_split[1] == 'rpc':
 | 
					                if url_split[1] == 'rpc':
 | 
				
			||||||
                    return self.page_rpc(url_split, post_string)
 | 
					                    return self.page_rpc(url_split, post_string)
 | 
				
			||||||
 | 
					                if url_split[1] == 'explorers':
 | 
				
			||||||
 | 
					                    return self.page_explorers(url_split, post_string)
 | 
				
			||||||
                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':
 | 
				
			||||||
@ -657,6 +761,8 @@ class HttpHandler(BaseHTTPRequestHandler):
 | 
				
			|||||||
                    return self.page_bids(url_split, post_string, sent=True)
 | 
					                    return self.page_bids(url_split, post_string, sent=True)
 | 
				
			||||||
                if url_split[1] == 'watched':
 | 
					                if url_split[1] == 'watched':
 | 
				
			||||||
                    return self.page_watched(url_split, post_string)
 | 
					                    return self.page_watched(url_split, post_string)
 | 
				
			||||||
 | 
					                if url_split[1] == 'shutdown':
 | 
				
			||||||
 | 
					                    return self.page_shutdown(url_split, post_string)
 | 
				
			||||||
            return self.page_index(url_split)
 | 
					            return self.page_index(url_split)
 | 
				
			||||||
        except Exception as ex:
 | 
					        except Exception as ex:
 | 
				
			||||||
            traceback.print_exc()  # TODO: Remove
 | 
					            traceback.print_exc()  # TODO: Remove
 | 
				
			||||||
 | 
				
			|||||||
@ -34,12 +34,33 @@
 | 
				
			|||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
</table>
 | 
					</table>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<form method="post">
 | 
					<form method="post">
 | 
				
			||||||
 | 
					{% if edit_bid %}
 | 
				
			||||||
 | 
					<h4>Edit Bid</h4>
 | 
				
			||||||
 | 
					<table>
 | 
				
			||||||
 | 
					<tr><td>Change Bid State</td><td>
 | 
				
			||||||
 | 
					<select name="new_state">
 | 
				
			||||||
 | 
					{% for s in data.bid_states %}
 | 
				
			||||||
 | 
					<option value="{{ s[0] }}"{% if data.bid_state_ind==s[0] %} selected{% endif %}>{{ s[1] }}</option>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
 | 
					</select></td></tr>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
 | 
					<input name="edit_bid_cancel" type="submit" value="Cancel">
 | 
				
			||||||
 | 
					<input name="edit_bid_submit" type="submit" value="Submit">
 | 
				
			||||||
 | 
					{% else %}
 | 
				
			||||||
{% if data.was_received == 'True' %}
 | 
					{% if data.was_received == 'True' %}
 | 
				
			||||||
<input name="accept_bid" type="submit" value="Accept Bid"><br/>
 | 
					<input name="accept_bid" type="submit" value="Accept Bid"><br/>
 | 
				
			||||||
{% endif %}
 | 
					{% endif %}
 | 
				
			||||||
<input name="abandon_bid" type="submit" value="Abandon Bid">
 | 
					<input name="abandon_bid" type="submit" value="Abandon Bid">
 | 
				
			||||||
 | 
					{% if data.show_txns %}
 | 
				
			||||||
 | 
					<input name="hide_txns" type="submit" value="Hide Info">
 | 
				
			||||||
 | 
					{% else %}
 | 
				
			||||||
<input name="show_txns" type="submit" value="Show More Info">
 | 
					<input name="show_txns" type="submit" value="Show More Info">
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					<input name="edit_bid" type="submit" value="Edit Bid">
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
<input type="hidden" name="formid" value="{{ form_id }}">
 | 
					<input type="hidden" name="formid" value="{{ form_id }}">
 | 
				
			||||||
</form>
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										33
									
								
								basicswap/templates/explorers.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								basicswap/templates/explorers.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					{% include 'header.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<h3>Explorers</h3>
 | 
				
			||||||
 | 
					{% for m in messages %}
 | 
				
			||||||
 | 
					<p>{{ m }}</p>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<form method="post">
 | 
				
			||||||
 | 
					<p>
 | 
				
			||||||
 | 
					<select name="explorer"><option value="-1"{% if explorer==-1 %} selected{% endif %}>-- Select Explorer --</option>
 | 
				
			||||||
 | 
					{% for e in explorers %}
 | 
				
			||||||
 | 
					<option value="{{ e[0] }}"{% if explorer==e[0] %} selected{% endif %}>{{ e[1] }}</option>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
 | 
					</select><br/>
 | 
				
			||||||
 | 
					<select name="action"><option value="-1"{% if action==-1 %} selected{% endif %}>-- Select Action --</option>
 | 
				
			||||||
 | 
					{% for a in actions %}
 | 
				
			||||||
 | 
					<option value="{{ a[0] }}"{% if action==a[0] %} selected{% endif %}>{{ a[1] }}</option>
 | 
				
			||||||
 | 
					{% endfor %}
 | 
				
			||||||
 | 
					</select><br/>
 | 
				
			||||||
 | 
					<input type="text" name="args"><br/>
 | 
				
			||||||
 | 
					<input type="submit" value="Submit">
 | 
				
			||||||
 | 
					<input type="hidden" name="formid" value="{{ form_id }}">
 | 
				
			||||||
 | 
					</p>
 | 
				
			||||||
 | 
					</form>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					{% if result %}
 | 
				
			||||||
 | 
					<textarea id="story" name="story" rows="40" cols="160">
 | 
				
			||||||
 | 
					{{ result }}
 | 
				
			||||||
 | 
					</textarea>
 | 
				
			||||||
 | 
					{% endif %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p><a href="/">home</a></p>
 | 
				
			||||||
 | 
					</body></html>
 | 
				
			||||||
@ -9,6 +9,7 @@ Version: {{ version }}
 | 
				
			|||||||
<p>
 | 
					<p>
 | 
				
			||||||
<a href="/wallets">View Wallets</a><br/>
 | 
					<a href="/wallets">View Wallets</a><br/>
 | 
				
			||||||
<a href="/rpc">RPC Console</a><br/>
 | 
					<a href="/rpc">RPC Console</a><br/>
 | 
				
			||||||
 | 
					<a href="/explorers">Explorers</a><br/>
 | 
				
			||||||
<br/>
 | 
					<br/>
 | 
				
			||||||
<a href="/active">Swaps in progress: {{ summary.num_swapping }}</a><br/>
 | 
					<a href="/active">Swaps in progress: {{ summary.num_swapping }}</a><br/>
 | 
				
			||||||
<a href="/offers">Network Offers: {{ summary.num_network_offers }}</a><br/>
 | 
					<a href="/offers">Network Offers: {{ summary.num_network_offers }}</a><br/>
 | 
				
			||||||
@ -18,7 +19,9 @@ Version: {{ version }}
 | 
				
			|||||||
<a href="/watched">Watched Outputs: {{ summary.num_watched_outputs }}</a><br/>
 | 
					<a href="/watched">Watched Outputs: {{ summary.num_watched_outputs }}</a><br/>
 | 
				
			||||||
</p>
 | 
					</p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<p><a href="/newoffer">New Offer</a><br/></p>
 | 
					<p><a href="/newoffer">New Offer</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<p><a href="/shutdown">Shutdown</a></p>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
</html>
 | 
					</html>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
{% include 'header.html' %}
 | 
					{% include 'header.html' %}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<h3>New Offer</h3>
 | 
					<h3>RPC Console</h3>
 | 
				
			||||||
{% for m in messages %}
 | 
					{% for m in messages %}
 | 
				
			||||||
<p>{{ m }}</p>
 | 
					<p>{{ m }}</p>
 | 
				
			||||||
{% endfor %}
 | 
					{% endfor %}
 | 
				
			||||||
 | 
				
			|||||||
@ -485,6 +485,8 @@ def main():
 | 
				
			|||||||
        'network_key': '7sW2UEcHXvuqEjkpE5mD584zRaQYs6WXYohue4jLFZPTvMSxwvgs',
 | 
					        'network_key': '7sW2UEcHXvuqEjkpE5mD584zRaQYs6WXYohue4jLFZPTvMSxwvgs',
 | 
				
			||||||
        'network_pubkey': '035758c4a22d7dd59165db02a56156e790224361eb3191f02197addcb3bde903d2',
 | 
					        'network_pubkey': '035758c4a22d7dd59165db02a56156e790224361eb3191f02197addcb3bde903d2',
 | 
				
			||||||
        'chainclients': withchainclients,
 | 
					        'chainclients': withchainclients,
 | 
				
			||||||
 | 
					        'auto_reply_delay_min': 5,  # Min delay before sending a response message
 | 
				
			||||||
 | 
					        'auto_reply_delay_max': 50,  # Max delay before sending a response message
 | 
				
			||||||
        'check_progress_seconds': 60,
 | 
					        'check_progress_seconds': 60,
 | 
				
			||||||
        'check_watched_seconds': 60,
 | 
					        'check_watched_seconds': 60,
 | 
				
			||||||
        'check_expired_seconds': 60
 | 
					        'check_expired_seconds': 60
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user