diff --git a/jmclient/jmclient/client_protocol.py b/jmclient/jmclient/client_protocol.py index 80d4a65..164c37d 100644 --- a/jmclient/jmclient/client_protocol.py +++ b/jmclient/jmclient/client_protocol.py @@ -72,6 +72,8 @@ class JMTakerClientProtocol(amp.AMP): to daemon, request message channel initialization with relevant config data for our message channels """ + if self.taker.aborted: + return #needed only for naming convention in IRC currently blockchain_source = jm_single().config.get("BLOCKCHAIN", "blockchain_source") diff --git a/jmclient/jmclient/taker.py b/jmclient/jmclient/taker.py index 196b9e5..ee373b6 100644 --- a/jmclient/jmclient/taker.py +++ b/jmclient/jmclient/taker.py @@ -647,6 +647,9 @@ class Taker(object): def confirm_callback(self, txd, txid, confirmations): self.waiting_for_conf = False + if self.aborted: + #do not trigger on_finished processing (abort whole schedule) + return jlog.debug("Confirmed callback in taker, confs: " + str(confirmations)) fromtx=False if self.schedule_index + 1 == len(self.schedule) else True waittime = self.schedule[self.schedule_index][4] diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index 1575529..6a68949 100644 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -305,7 +305,10 @@ class SpendTab(QWidget): self.tumbler_options = None #signals from client backend to GUI self.jmclient_obj = QtCore.QObject() + #timer for waiting for confirmation on restart self.restartTimer = QtCore.QTimer() + #timer for wait for next transaction + self.nextTxTimer = None #This signal/callback requires user acceptance decision. self.jmclient_obj.connect(self.jmclient_obj, QtCore.SIGNAL('JMCLIENT:offers'), self.checkOffers) @@ -857,8 +860,14 @@ class SpendTab(QWidget): if self.taker_finished_res: w.statusBar().showMessage("Transaction confirmed: " + self.taker.txid) #singleShot argument is in milliseconds - QtCore.QTimer.singleShot(int(self.taker_finished_waittime*60*1000), - self.startNextTransaction) + if self.nextTxTimer: + self.nextTxTimer.stop() + self.nextTxTimer = QtCore.QTimer() + self.nextTxTimer.setSingleShot(True) + self.nextTxTimer.timeout.connect(self.startNextTransaction) + self.nextTxTimer.start(int(self.taker_finished_waittime*60*1000)) + #QtCore.QTimer.singleShot(int(self.taker_finished_waittime*60*1000), + # self.startNextTransaction) #see note above re multiple/tumble duplication if self.spendstate.typestate == 'multiple' and \ not self.tumbler_options: @@ -942,6 +951,11 @@ class SpendTab(QWidget): def cleanUp(self): """Reset state to 'ready' """ + #Qt specific: because schedules can restart in same app instance, + #we must clean up any existing delayed actions via singleShot. + #Currently this should only happen via self.abortTransactions. + if self.nextTxTimer: + self.nextTxTimer.stop() self.spendstate.reset() self.tumbler_options = None self.tumbler_destaddrs = None