mirror of
https://github.com/basicswap/basicswap.git
synced 2025-01-18 16:44:34 +00:00
refactor: Rename EventQueue table to Action
This commit is contained in:
parent
d47a69c7cb
commit
d909115ea4
8 changed files with 172 additions and 86 deletions
|
@ -77,7 +77,7 @@ from .messages_pb2 import (
|
|||
)
|
||||
from .db import (
|
||||
CURRENT_DB_VERSION,
|
||||
TableTypes,
|
||||
Concepts,
|
||||
Base,
|
||||
DBKVInt,
|
||||
DBKVString,
|
||||
|
@ -87,7 +87,7 @@ from .db import (
|
|||
PooledAddress,
|
||||
SentOffer,
|
||||
SmsgAddress,
|
||||
EventQueue,
|
||||
Action,
|
||||
EventLog,
|
||||
XmrOffer,
|
||||
XmrSwap,
|
||||
|
@ -117,7 +117,7 @@ from .basicswap_util import (
|
|||
BidStates,
|
||||
TxStates,
|
||||
TxTypes,
|
||||
EventTypes,
|
||||
ActionTypes,
|
||||
EventLogTypes,
|
||||
XmrSplitMsgTypes,
|
||||
DebugTypes,
|
||||
|
@ -205,14 +205,14 @@ class BasicSwap(BaseApp):
|
|||
self.check_progress_seconds = self.settings.get('check_progress_seconds', 60)
|
||||
self.check_watched_seconds = self.settings.get('check_watched_seconds', 60)
|
||||
self.check_expired_seconds = self.settings.get('check_expired_seconds', 60 * 5)
|
||||
self.check_events_seconds = self.settings.get('check_events_seconds', 10)
|
||||
self.check_actions_seconds = self.settings.get('check_actions_seconds', 10)
|
||||
self.check_xmr_swaps_seconds = self.settings.get('check_xmr_swaps_seconds', 20)
|
||||
self.startup_tries = self.settings.get('startup_tries', 21) # Seconds waited for will be (x(1 + x+1) / 2
|
||||
self.debug_ui = self.settings.get('debug_ui', False)
|
||||
self._last_checked_progress = 0
|
||||
self._last_checked_watched = 0
|
||||
self._last_checked_expired = 0
|
||||
self._last_checked_events = 0
|
||||
self._last_checked_actions = 0
|
||||
self._last_checked_xmr_swaps = 0
|
||||
self._possibly_revoked_offers = collections.deque([], maxlen=48) # TODO: improve
|
||||
self._updating_wallets_info = {}
|
||||
|
@ -793,9 +793,9 @@ class BasicSwap(BaseApp):
|
|||
|
||||
# Remove any delayed events
|
||||
if self.debug:
|
||||
use_session.execute('UPDATE eventqueue SET active_ind = 2 WHERE linked_id = x\'{}\' '.format(bid.bid_id.hex()))
|
||||
use_session.execute('UPDATE actions SET active_ind = 2 WHERE linked_id = x\'{}\' '.format(bid.bid_id.hex()))
|
||||
else:
|
||||
use_session.execute('DELETE FROM eventqueue WHERE linked_id = x\'{}\' '.format(bid.bid_id.hex()))
|
||||
use_session.execute('DELETE FROM actions WHERE linked_id = x\'{}\' '.format(bid.bid_id.hex()))
|
||||
|
||||
# Unlock locked inputs (TODO)
|
||||
if offer.swap_type == SwapTypes.XMR_SWAP:
|
||||
|
@ -1090,7 +1090,7 @@ class BasicSwap(BaseApp):
|
|||
if automation_id != -1:
|
||||
auto_link = AutomationLink(
|
||||
active_ind=1,
|
||||
linked_type=TableTypes.OFFER,
|
||||
linked_type=Concepts.OFFER,
|
||||
linked_id=offer_id,
|
||||
strategy_id=automation_id,
|
||||
created_at=offer_created_at,
|
||||
|
@ -1549,36 +1549,35 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def createEventInSession(self, delay, event_type, linked_id, session):
|
||||
self.log.debug('createEvent %d %s', event_type, linked_id.hex())
|
||||
def createActionInSession(self, delay, action_type, linked_id, session):
|
||||
self.log.debug('createAction %d %s', action_type, linked_id.hex())
|
||||
now = int(time.time())
|
||||
event = EventQueue(
|
||||
action = Action(
|
||||
active_ind=1,
|
||||
created_at=now,
|
||||
trigger_at=now + delay,
|
||||
event_type=event_type,
|
||||
action_type=action_type,
|
||||
linked_id=linked_id)
|
||||
session.add(event)
|
||||
session.add(action)
|
||||
|
||||
def createEvent(self, delay, event_type, linked_id):
|
||||
# self.log.debug('createEvent %d %s', event_type, linked_id.hex())
|
||||
def createAction(self, delay, action_type, linked_id):
|
||||
# self.log.debug('createAction %d %s', action_type, linked_id.hex())
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
self.createEventInSession(delay, event_type, linked_id, session)
|
||||
self.createActionInSession(delay, action_type, linked_id, session)
|
||||
session.commit()
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def logBidEvent(self, bid_id, event_type, event_msg, session):
|
||||
self.log.debug('logBidEvent %s %s', bid_id.hex(), event_type)
|
||||
def logEvent(self, linked_type, linked_id, event_type, event_msg, session):
|
||||
entry = EventLog(
|
||||
active_ind=1,
|
||||
created_at=int(time.time()),
|
||||
linked_type=TableTypes.BID,
|
||||
linked_id=bid_id,
|
||||
linked_type=linked_type,
|
||||
linked_id=linked_id,
|
||||
event_type=int(event_type),
|
||||
event_msg=event_msg)
|
||||
|
||||
|
@ -1595,10 +1594,27 @@ class BasicSwap(BaseApp):
|
|||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def logBidEvent(self, bid_id, event_type, event_msg, session):
|
||||
self.log.debug('logBidEvent %s %s', bid_id.hex(), event_type)
|
||||
self.logEvent(Concepts.BID, bid_id, event_type, event_msg, session)
|
||||
|
||||
def countBidEvents(self, bid, event_type, session):
|
||||
q = session.execute('SELECT COUNT(*) FROM eventlog WHERE linked_type = {} AND linked_id = x\'{}\' AND event_type = {}'.format(int(TableTypes.BID), bid.bid_id.hex(), int(event_type))).first()
|
||||
q = session.execute('SELECT COUNT(*) FROM eventlog WHERE linked_type = {} AND linked_id = x\'{}\' AND event_type = {}'.format(int(Concepts.BID), bid.bid_id.hex(), int(event_type))).first()
|
||||
return q[0]
|
||||
|
||||
def getEvents(self, linked_type, linked_id):
|
||||
events = []
|
||||
self.mxDB.acquire()
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
for entry in session.query(EventLog).filter(sa.and_(EventLog.linked_type == linked_type, EventLog.linked_id == linked_id)):
|
||||
events.append(entry)
|
||||
return events
|
||||
finally:
|
||||
session.close()
|
||||
session.remove()
|
||||
self.mxDB.release()
|
||||
|
||||
def postBid(self, offer_id, amount, addr_send_from=None, extra_options={}):
|
||||
# Bid to send bid.amount * bid.rate of coin_to in exchange for bid.amount of coin_from
|
||||
self.log.debug('postBid %s', offer_id.hex())
|
||||
|
@ -1838,13 +1854,13 @@ class BasicSwap(BaseApp):
|
|||
|
||||
def list_bid_events(self, bid_id, session):
|
||||
query_str = 'SELECT created_at, event_type, event_msg FROM eventlog ' + \
|
||||
'WHERE active_ind = 1 AND linked_type = {} AND linked_id = x\'{}\' '.format(TableTypes.BID, bid_id.hex())
|
||||
'WHERE active_ind = 1 AND linked_type = {} AND linked_id = x\'{}\' '.format(Concepts.BID, bid_id.hex())
|
||||
q = session.execute(query_str)
|
||||
events = []
|
||||
for row in q:
|
||||
events.append({'at': row[0], 'desc': describeEventEntry(row[1], row[2])})
|
||||
|
||||
query_str = 'SELECT created_at, trigger_at FROM eventqueue ' + \
|
||||
query_str = 'SELECT created_at, trigger_at FROM actions ' + \
|
||||
'WHERE active_ind = 1 AND linked_id = x\'{}\' '.format(bid_id.hex())
|
||||
q = session.execute(query_str)
|
||||
for row in q:
|
||||
|
@ -1962,21 +1978,21 @@ class BasicSwap(BaseApp):
|
|||
ensure(xmr_offer, 'XMR offer not found: {}.'.format(offer_id.hex()))
|
||||
ensure(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)
|
||||
ci_to = self.ci(coin_to)
|
||||
|
||||
valid_for_seconds = extra_options.get('valid_for_seconds', 60 * 10)
|
||||
bid_rate = extra_options.get('bid_rate', offer.rate)
|
||||
self.validateBidAmount(offer, amount, bid_rate)
|
||||
amount_to = int((int(amount) * bid_rate) // ci_from.COIN())
|
||||
|
||||
if not (self.debug and extra_options.get('debug_skip_validation', False)):
|
||||
self.validateBidValidTime(offer.swap_type, offer.coin_from, offer.coin_to, valid_for_seconds)
|
||||
self.validateBidAmount(offer, amount, bid_rate)
|
||||
|
||||
self.checkSynced(coin_from, coin_to)
|
||||
|
||||
amount_to = int((int(amount) * bid_rate) // ci_from.COIN())
|
||||
|
||||
balance_to = ci_to.getSpendableBalance()
|
||||
ensure(balance_to > amount_to, '{} spendable balance is too low: {}'.format(ci_to.coin_name(), ci_to.format_amount(balance_to)))
|
||||
|
||||
|
@ -2954,7 +2970,7 @@ class BasicSwap(BaseApp):
|
|||
if bid.was_sent:
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Sending xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
# bid.setState(BidStates.SWAP_DELAYING)
|
||||
|
||||
if bid_changed:
|
||||
|
@ -3001,7 +3017,7 @@ class BasicSwap(BaseApp):
|
|||
if bid.was_received:
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Releasing xmr script coin lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.SEND_XMR_LOCK_RELEASE, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.SEND_XMR_LOCK_RELEASE, bid_id, session)
|
||||
|
||||
if bid_changed:
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||
|
@ -3018,11 +3034,11 @@ class BasicSwap(BaseApp):
|
|||
except Exception as e:
|
||||
self.log.debug('getrawtransaction lock spend tx failed: %s', str(e))
|
||||
elif state == BidStates.XMR_SWAP_SCRIPT_TX_REDEEMED:
|
||||
if bid.was_received and self.countQueuedEvents(session, bid_id, EventTypes.REDEEM_XMR_SWAP_LOCK_TX_B) < 1:
|
||||
if bid.was_received and self.countQueuedActions(session, bid_id, ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_B) < 1:
|
||||
bid.setState(BidStates.SWAP_DELAYING)
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Redeeming coin b lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.REDEEM_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap)
|
||||
session.commit()
|
||||
elif state == BidStates.XMR_SWAP_NOSCRIPT_TX_REDEEMED:
|
||||
|
@ -3411,7 +3427,7 @@ class BasicSwap(BaseApp):
|
|||
if bid.xmr_b_lock_tx is not None:
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Recovering xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
else:
|
||||
bid.setState(BidStates.XMR_SWAP_FAILED_REFUNDED)
|
||||
|
||||
|
@ -3524,49 +3540,49 @@ class BasicSwap(BaseApp):
|
|||
finally:
|
||||
self.mxDB.release()
|
||||
|
||||
def countQueuedEvents(self, session, bid_id, event_type):
|
||||
q = session.query(EventQueue).filter(sa.and_(EventQueue.active_ind == 1, EventQueue.linked_id == bid_id, EventQueue.event_type == event_type))
|
||||
def countQueuedActions(self, session, bid_id, action_type):
|
||||
q = session.query(Action).filter(sa.and_(Action.active_ind == 1, Action.linked_id == bid_id, Action.action_type == action_type))
|
||||
return q.count()
|
||||
|
||||
def checkEvents(self):
|
||||
def checkQueuedActions(self):
|
||||
self.mxDB.acquire()
|
||||
now = int(time.time())
|
||||
session = None
|
||||
try:
|
||||
session = scoped_session(self.session_factory)
|
||||
|
||||
q = session.query(EventQueue).filter(sa.and_(EventQueue.active_ind == 1, EventQueue.trigger_at <= now))
|
||||
q = session.query(Action).filter(sa.and_(Action.active_ind == 1, Action.trigger_at <= now))
|
||||
for row in q:
|
||||
try:
|
||||
if row.event_type == EventTypes.ACCEPT_BID:
|
||||
if row.action_type == ActionTypes.ACCEPT_BID:
|
||||
self.acceptBid(row.linked_id)
|
||||
elif row.event_type == EventTypes.ACCEPT_XMR_BID:
|
||||
elif row.action_type == ActionTypes.ACCEPT_XMR_BID:
|
||||
self.acceptXmrBid(row.linked_id)
|
||||
elif row.event_type == EventTypes.SIGN_XMR_SWAP_LOCK_TX_A:
|
||||
elif row.action_type == ActionTypes.SIGN_XMR_SWAP_LOCK_TX_A:
|
||||
self.sendXmrBidTxnSigsFtoL(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.SEND_XMR_SWAP_LOCK_TX_A:
|
||||
elif row.action_type == ActionTypes.SEND_XMR_SWAP_LOCK_TX_A:
|
||||
self.sendXmrBidCoinALockTx(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.SEND_XMR_SWAP_LOCK_TX_B:
|
||||
elif row.action_type == ActionTypes.SEND_XMR_SWAP_LOCK_TX_B:
|
||||
self.sendXmrBidCoinBLockTx(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.SEND_XMR_LOCK_RELEASE:
|
||||
elif row.action_type == ActionTypes.SEND_XMR_LOCK_RELEASE:
|
||||
self.sendXmrBidLockRelease(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.REDEEM_XMR_SWAP_LOCK_TX_A:
|
||||
elif row.action_type == ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_A:
|
||||
self.redeemXmrBidCoinALockTx(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.REDEEM_XMR_SWAP_LOCK_TX_B:
|
||||
elif row.action_type == ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_B:
|
||||
self.redeemXmrBidCoinBLockTx(row.linked_id, session)
|
||||
elif row.event_type == EventTypes.RECOVER_XMR_SWAP_LOCK_TX_B:
|
||||
elif row.action_type == ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B:
|
||||
self.recoverXmrBidCoinBLockTx(row.linked_id, session)
|
||||
else:
|
||||
self.log.warning('Unknown event type: %d', row.event_type)
|
||||
except Exception as ex:
|
||||
if self.debug:
|
||||
self.log.error(traceback.format_exc())
|
||||
self.log.error('checkEvents failed: {}'.format(str(ex)))
|
||||
self.log.error('checkQueuedActions failed: {}'.format(str(ex)))
|
||||
|
||||
if self.debug:
|
||||
session.execute('UPDATE eventqueue SET active_ind = 2 WHERE trigger_at <= {}'.format(now))
|
||||
session.execute('UPDATE actions SET active_ind = 2 WHERE trigger_at <= {}'.format(now))
|
||||
else:
|
||||
session.execute('DELETE FROM eventqueue WHERE trigger_at <= {}'.format(now))
|
||||
session.execute('DELETE FROM actions WHERE trigger_at <= {}'.format(now))
|
||||
|
||||
session.commit()
|
||||
finally:
|
||||
|
@ -3778,7 +3794,7 @@ class BasicSwap(BaseApp):
|
|||
self.mxDB.acquire()
|
||||
use_session = scoped_session(self.session_factory)
|
||||
|
||||
link = use_session.query(AutomationLink).filter_by(active_ind=1, linked_type=TableTypes.OFFER, linked_id=offer.offer_id).first()
|
||||
link = use_session.query(AutomationLink).filter_by(active_ind=1, linked_type=Concepts.OFFER, linked_id=offer.offer_id).first()
|
||||
if not link:
|
||||
return False
|
||||
|
||||
|
@ -3787,11 +3803,20 @@ class BasicSwap(BaseApp):
|
|||
|
||||
self.log.debug('Evaluating against strategy {}'.format(strategy.record_id))
|
||||
|
||||
if opts.get('full_amount_only', False) is True:
|
||||
if not offer.amount_negotiable:
|
||||
if bid.amount != offer.amount_from:
|
||||
self.log.info('Not auto accepting bid %s, want exact amount match', bid.bid_id.hex())
|
||||
return False
|
||||
|
||||
if bid.amount < offer.min_bid_amount:
|
||||
self.log.info('Not auto accepting bid %s, bid amount below minimum', bid.bid_id.hex())
|
||||
return False
|
||||
|
||||
if opts.get('exact_rate_only', False) is True:
|
||||
if bid.rate != offer.rate:
|
||||
self.log.info('Not auto accepting bid %s, want exact rate match', bid.bid_id.hex())
|
||||
return False
|
||||
|
||||
max_bids = opts.get('max_bids', 1)
|
||||
# Auto accept bid if set and no other non-abandoned bid for this order exists
|
||||
if self.countAcceptedBids(offer.offer_id) >= max_bids:
|
||||
|
@ -3909,7 +3934,7 @@ class BasicSwap(BaseApp):
|
|||
if self.shouldAutoAcceptBid(offer, bid):
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Auto accepting bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEvent(delay, EventTypes.ACCEPT_BID, bid_id)
|
||||
self.createAction(delay, ActionTypes.ACCEPT_BID, bid_id)
|
||||
|
||||
def processBidAccept(self, msg):
|
||||
self.log.debug('Processing bid accepted msg %s', msg['msgid'])
|
||||
|
@ -4029,7 +4054,7 @@ class BasicSwap(BaseApp):
|
|||
if self.shouldAutoAcceptBid(offer, bid, session):
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Auto accepting xmr bid %s in %d seconds', bid.bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.ACCEPT_XMR_BID, bid.bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.ACCEPT_XMR_BID, bid.bid_id, session)
|
||||
bid.setState(BidStates.SWAP_DELAYING)
|
||||
|
||||
self.saveBidInSession(bid.bid_id, bid, session, xmr_swap)
|
||||
|
@ -4087,7 +4112,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Responding to xmr bid accept %s in %d seconds', bid.bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.SIGN_XMR_SWAP_LOCK_TX_A, bid.bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.SIGN_XMR_SWAP_LOCK_TX_A, bid.bid_id, session)
|
||||
|
||||
def processXmrBid(self, msg):
|
||||
# MSG1L
|
||||
|
@ -4437,7 +4462,7 @@ class BasicSwap(BaseApp):
|
|||
if num_retries < 5 and (ci_to.is_transient_error(ex) or self.is_transient_error(ex)):
|
||||
delay = random.randrange(self.min_delay_retry, self.max_delay_retry)
|
||||
self.log.info('Retrying sending xmr swap chain B lock tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.SEND_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
else:
|
||||
self.setBidError(bid_id, bid, 'publishBLockTx failed: ' + str(ex), save_bid=False)
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
||||
|
@ -4585,7 +4610,7 @@ class BasicSwap(BaseApp):
|
|||
if num_retries < 100 and (ci_to.is_transient_error(ex) or self.is_transient_error(ex)):
|
||||
delay = random.randrange(self.min_delay_retry, self.max_delay_retry)
|
||||
self.log.info('Retrying sending xmr swap chain B spend tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.REDEEM_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
else:
|
||||
self.setBidError(bid_id, bid, 'spendBLockTx failed: ' + str(ex), save_bid=False)
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
||||
|
@ -4644,7 +4669,7 @@ class BasicSwap(BaseApp):
|
|||
if num_retries < 100 and (ci_to.is_transient_error(ex) or self.is_transient_error(ex)):
|
||||
delay = random.randrange(self.min_delay_retry, self.max_delay_retry)
|
||||
self.log.info('Retrying sending xmr swap chain B refund tx for bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEventInSession(delay, EventTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
self.createActionInSession(delay, ActionTypes.RECOVER_XMR_SWAP_LOCK_TX_B, bid_id, session)
|
||||
else:
|
||||
self.setBidError(bid_id, bid, 'spendBLockTx for refund failed: ' + str(ex), save_bid=False)
|
||||
self.saveBidInSession(bid_id, bid, session, xmr_swap, save_in_progress=offer)
|
||||
|
@ -4710,7 +4735,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Sending coin A lock tx for xmr bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEvent(delay, EventTypes.SEND_XMR_SWAP_LOCK_TX_A, bid_id)
|
||||
self.createAction(delay, ActionTypes.SEND_XMR_SWAP_LOCK_TX_A, bid_id)
|
||||
|
||||
bid.setState(BidStates.SWAP_DELAYING)
|
||||
self.saveBid(bid_id, bid, xmr_swap=xmr_swap)
|
||||
|
@ -4829,7 +4854,7 @@ class BasicSwap(BaseApp):
|
|||
|
||||
delay = random.randrange(self.min_delay_event, self.max_delay_event)
|
||||
self.log.info('Redeeming coin A lock tx for xmr bid %s in %d seconds', bid_id.hex(), delay)
|
||||
self.createEvent(delay, EventTypes.REDEEM_XMR_SWAP_LOCK_TX_A, bid_id)
|
||||
self.createAction(delay, ActionTypes.REDEEM_XMR_SWAP_LOCK_TX_A, bid_id)
|
||||
|
||||
bid.setState(BidStates.XMR_SWAP_LOCK_RELEASED)
|
||||
self.saveBid(bid_id, bid, xmr_swap=xmr_swap)
|
||||
|
@ -4866,6 +4891,12 @@ class BasicSwap(BaseApp):
|
|||
self.log.error('processMsg %s', str(ex))
|
||||
if self.debug:
|
||||
self.log.error(traceback.format_exc())
|
||||
self.logEvent(Concepts.NETWORK_MESSAGE,
|
||||
bytes.fromhex(msg['msgid']),
|
||||
EventLogTypes.ERROR,
|
||||
str(ex),
|
||||
None)
|
||||
|
||||
finally:
|
||||
self.mxDB.release()
|
||||
|
||||
|
@ -4940,9 +4971,9 @@ class BasicSwap(BaseApp):
|
|||
self.expireMessages()
|
||||
self._last_checked_expired = now
|
||||
|
||||
if now - self._last_checked_events >= self.check_events_seconds:
|
||||
self.checkEvents()
|
||||
self._last_checked_events = now
|
||||
if now - self._last_checked_actions >= self.check_actions_seconds:
|
||||
self.checkQueuedActions()
|
||||
self._last_checked_actions = now
|
||||
|
||||
if now - self._last_checked_xmr_swaps >= self.check_xmr_swaps_seconds:
|
||||
self.checkXmrSwaps()
|
||||
|
|
|
@ -122,7 +122,7 @@ class TxTypes(IntEnum):
|
|||
XMR_SWAP_B_LOCK = auto()
|
||||
|
||||
|
||||
class EventTypes(IntEnum):
|
||||
class ActionTypes(IntEnum):
|
||||
ACCEPT_BID = auto()
|
||||
ACCEPT_XMR_BID = auto()
|
||||
SIGN_XMR_SWAP_LOCK_TX_A = auto()
|
||||
|
@ -155,6 +155,7 @@ class EventLogTypes(IntEnum):
|
|||
LOCK_TX_B_SPEND_TX_PUBLISHED = auto()
|
||||
LOCK_TX_A_REFUND_TX_SEEN = auto()
|
||||
LOCK_TX_A_REFUND_SPEND_TX_SEEN = auto()
|
||||
ERROR = auto()
|
||||
|
||||
|
||||
class XmrSplitMsgTypes(IntEnum):
|
||||
|
@ -331,6 +332,8 @@ def describeEventEntry(event_type, event_msg):
|
|||
return 'Lock tx A refund spend tx seen in chain'
|
||||
if event_type == EventLogTypes.SYSTEM_WARNING:
|
||||
return 'Warning: ' + event_msg
|
||||
if event_type == EventLogTypes.ERROR:
|
||||
return 'Error: ' + event_msg
|
||||
|
||||
|
||||
def getVoutByAddress(txjs, p2sh):
|
||||
|
|
|
@ -17,16 +17,19 @@ CURRENT_DB_DATA_VERSION = 1
|
|||
Base = declarative_base()
|
||||
|
||||
|
||||
class TableTypes(IntEnum):
|
||||
class Concepts(IntEnum):
|
||||
OFFER = auto()
|
||||
BID = auto()
|
||||
NETWORK_MESSAGE = auto()
|
||||
|
||||
|
||||
def strTableTypes(state):
|
||||
if state == TableTypes.OFFER:
|
||||
def strConcepts(state):
|
||||
if state == Concepts.OFFER:
|
||||
return 'Offer'
|
||||
if state == TableTypes.BID:
|
||||
if state == Concepts.BID:
|
||||
return 'Bid'
|
||||
if state == Concepts.NETWORK_MESSAGE:
|
||||
return 'Network Message'
|
||||
return 'Unknown'
|
||||
|
||||
|
||||
|
@ -245,16 +248,16 @@ class SmsgAddress(Base):
|
|||
note = sa.Column(sa.String)
|
||||
|
||||
|
||||
class EventQueue(Base):
|
||||
__tablename__ = 'eventqueue'
|
||||
class Action(Base):
|
||||
__tablename__ = 'actions'
|
||||
|
||||
event_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
action_id = sa.Column(sa.Integer, primary_key=True, autoincrement=True)
|
||||
active_ind = sa.Column(sa.Integer)
|
||||
created_at = sa.Column(sa.BigInteger)
|
||||
trigger_at = sa.Column(sa.BigInteger)
|
||||
linked_id = sa.Column(sa.LargeBinary)
|
||||
event_type = sa.Column(sa.Integer)
|
||||
event_data = sa.Column(sa.LargeBinary)
|
||||
action_type = sa.Column(sa.Integer)
|
||||
action_data = sa.Column(sa.LargeBinary)
|
||||
|
||||
|
||||
class EventLog(Base):
|
||||
|
|
|
@ -8,7 +8,7 @@ import json
|
|||
|
||||
from sqlalchemy.orm import scoped_session
|
||||
from .db import (
|
||||
TableTypes,
|
||||
Concepts,
|
||||
AutomationStrategy,
|
||||
CURRENT_DB_VERSION,
|
||||
CURRENT_DB_DATA_VERSION)
|
||||
|
@ -27,15 +27,15 @@ def upgradeDatabaseData(self, data_version):
|
|||
session.add(AutomationStrategy(
|
||||
active_ind=1,
|
||||
label='Accept All',
|
||||
type_ind=TableTypes.OFFER,
|
||||
data=json.dumps({'full_amount_only': True,
|
||||
type_ind=Concepts.OFFER,
|
||||
data=json.dumps({'exact_rate_only': True,
|
||||
'max_bids': 1}).encode('utf-8'),
|
||||
only_known_identities=False))
|
||||
session.add(AutomationStrategy(
|
||||
active_ind=1,
|
||||
label='Accept Known',
|
||||
type_ind=TableTypes.OFFER,
|
||||
data=json.dumps({'full_amount_only': True,
|
||||
type_ind=Concepts.OFFER,
|
||||
data=json.dumps({'exact_rate_only': True,
|
||||
'max_bids': 1}).encode('utf-8'),
|
||||
only_known_identities=True,
|
||||
note='Accept bids from identities with previously successful swaps only'))
|
||||
|
@ -168,6 +168,7 @@ def upgradeDatabase(self, db_version):
|
|||
|
||||
session.execute('ALTER TABLE wallets ADD COLUMN active_ind INTEGER')
|
||||
session.execute('ALTER TABLE knownidentities ADD COLUMN active_ind INTEGER')
|
||||
session.execute('ALTER TABLE eventqueue RENAME TO actions')
|
||||
|
||||
if current_version != db_version:
|
||||
self.db_version = db_version
|
||||
|
|
|
@ -16,7 +16,7 @@ from basicswap.util import (
|
|||
ensure,
|
||||
)
|
||||
from basicswap.db import (
|
||||
strTableTypes,
|
||||
strConcepts,
|
||||
)
|
||||
|
||||
|
||||
|
@ -48,7 +48,7 @@ def page_automation_strategies(self, url_split, post_string):
|
|||
|
||||
formatted_strategies = []
|
||||
for s in swap_client.listAutomationStrategies(filters):
|
||||
formatted_strategies.append((s[0], s[1], strTableTypes(s[2])))
|
||||
formatted_strategies.append((s[0], s[1], strConcepts(s[2])))
|
||||
|
||||
template = server.env.get_template('automation_strategies.html')
|
||||
return bytes(template.render(
|
||||
|
@ -93,7 +93,7 @@ def page_automation_strategy(self, url_split, post_string):
|
|||
|
||||
formatted_strategy = {
|
||||
'label': strategy.label,
|
||||
'type': strTableTypes(strategy.type_ind),
|
||||
'type': strConcepts(strategy.type_ind),
|
||||
'only_known_identities': 'True' if strategy.only_known_identities is True else 'False',
|
||||
'data': strategy.data,
|
||||
'note': strategy.note,
|
||||
|
|
|
@ -19,7 +19,7 @@ from .util import (
|
|||
set_pagination_filters,
|
||||
)
|
||||
from basicswap.db import (
|
||||
TableTypes,
|
||||
Concepts,
|
||||
)
|
||||
from basicswap.util import (
|
||||
ensure,
|
||||
|
@ -305,7 +305,7 @@ def page_newoffer(self, url_split, post_string):
|
|||
|
||||
automation_filters = {}
|
||||
automation_filters['sort_by'] = 'label'
|
||||
automation_filters['type_ind'] = TableTypes.OFFER
|
||||
automation_filters['type_ind'] = Concepts.OFFER
|
||||
automation_strategies = swap_client.listAutomationStrategies(automation_filters)
|
||||
|
||||
return bytes(template.render(
|
||||
|
@ -454,7 +454,7 @@ def page_offer(self, url_split, post_string):
|
|||
|
||||
if offer.was_sent:
|
||||
try:
|
||||
strategy = swap_client.getLinkedStrategy(TableTypes.OFFER, offer_id)
|
||||
strategy = swap_client.getLinkedStrategy(Concepts.OFFER, offer_id)
|
||||
data['automation_strat_id'] = strategy[0]
|
||||
data['automation_strat_label'] = strategy[1]
|
||||
except Exception:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2020-2021 tecnovert
|
||||
# Copyright (c) 2020-2022 tecnovert
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file LICENSE.txt or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
|
@ -140,6 +140,19 @@ def wait_for_bid_tx_state(delay_event, swap_client, bid_id, initiate_state, part
|
|||
raise ValueError('wait_for_bid_tx_state timed out.')
|
||||
|
||||
|
||||
def wait_for_event(delay_event, swap_client, linked_type, linked_id, wait_for=20):
|
||||
logging.info('wait_for_event')
|
||||
|
||||
for i in range(wait_for):
|
||||
if delay_event.is_set():
|
||||
raise ValueError('Test stopped.')
|
||||
delay_event.wait(1)
|
||||
rv = swap_client.getEvents(linked_type, linked_id)
|
||||
if len(rv) > 0:
|
||||
return rv
|
||||
raise ValueError('wait_for_event timed out.')
|
||||
|
||||
|
||||
def wait_for_offer(delay_event, swap_client, offer_id, wait_for=20):
|
||||
logging.info('wait_for_offer %s', offer_id.hex())
|
||||
for i in range(wait_for):
|
||||
|
|
|
@ -19,6 +19,9 @@ import subprocess
|
|||
from urllib.request import urlopen
|
||||
|
||||
import basicswap.config as cfg
|
||||
from basicswap.db import (
|
||||
Concepts,
|
||||
)
|
||||
from basicswap.basicswap import (
|
||||
BasicSwap,
|
||||
Coins,
|
||||
|
@ -61,6 +64,7 @@ from tests.basicswap.common import (
|
|||
checkForks,
|
||||
stopDaemons,
|
||||
wait_for_bid,
|
||||
wait_for_event,
|
||||
wait_for_offer,
|
||||
wait_for_no_offer,
|
||||
wait_for_none_active,
|
||||
|
@ -845,7 +849,9 @@ class Test(BaseTest):
|
|||
def test_09_auto_accept(self):
|
||||
logging.info('---------- Test BTC to XMR auto accept')
|
||||
swap_clients = self.swap_clients
|
||||
offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, 11 * COIN, 101 * XMR_COIN, 10 * COIN, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
amt_swap = make_int(random.uniform(0.01, 11.0), scale=8, r=1)
|
||||
rate_swap = make_int(random.uniform(10.0, 101.0), scale=12, r=1)
|
||||
offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, amt_swap, rate_swap, amt_swap, SwapTypes.XMR_SWAP, auto_accept_bids=True)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].listOffers(filters={'offer_id': offer_id})[0]
|
||||
|
||||
|
@ -853,6 +859,35 @@ class Test(BaseTest):
|
|||
wait_for_bid(test_delay_event, swap_clients[0], bid_id, BidStates.SWAP_COMPLETED, wait_for=180)
|
||||
wait_for_bid(test_delay_event, swap_clients[1], bid_id, BidStates.SWAP_COMPLETED, sent=True)
|
||||
|
||||
def test_09_1_auto_accept_multiple(self):
|
||||
logging.info('---------- Test BTC to XMR auto accept multiple bids')
|
||||
swap_clients = self.swap_clients
|
||||
amt_swap = make_int(10, scale=8, r=1)
|
||||
rate_swap = make_int(100, scale=12, r=1)
|
||||
min_bid = make_int(1, scale=8, r=1)
|
||||
|
||||
extra_options = {
|
||||
'amount_negotiable': True,
|
||||
'automation_id': 1,
|
||||
}
|
||||
offer_id = swap_clients[0].postOffer(Coins.BTC, Coins.XMR, amt_swap, rate_swap, min_bid, SwapTypes.XMR_SWAP, extra_options=extra_options)
|
||||
wait_for_offer(test_delay_event, swap_clients[1], offer_id)
|
||||
offer = swap_clients[1].listOffers(filters={'offer_id': offer_id})[0]
|
||||
|
||||
below_min_bid = min_bid - 1
|
||||
try:
|
||||
bid_id = swap_clients[1].postBid(offer_id, below_min_bid)
|
||||
except Exception as e:
|
||||
assert('Bid amount below minimum' in str(e))
|
||||
extra_bid_options = {
|
||||
'debug_skip_validation': True,
|
||||
}
|
||||
bid_id = swap_clients[1].postBid(offer_id, below_min_bid, extra_options=extra_bid_options)
|
||||
|
||||
events = wait_for_event(test_delay_event, swap_clients[0], Concepts.NETWORK_MESSAGE, bid_id)
|
||||
assert('Bid amount below minimum' in events[0].event_msg)
|
||||
# TODO
|
||||
|
||||
def test_10_locked_refundtx(self):
|
||||
logging.info('---------- Test Refund tx is locked')
|
||||
swap_clients = self.swap_clients
|
||||
|
|
Loading…
Reference in a new issue