@@ -1151,9 +1151,8 @@ def get_onchain_history(self, *, domain=None):
1151
1151
'date' : timestamp_to_datetime (hist_item .tx_mined_status .timestamp ),
1152
1152
'label' : self .get_label_for_txid (hist_item .txid ),
1153
1153
'txpos_in_block' : hist_item .tx_mined_status .txpos ,
1154
+ 'wanted_height' : hist_item .tx_mined_status .wanted_height ,
1154
1155
}
1155
- if wanted_height := hist_item .tx_mined_status .wanted_height :
1156
- d ['wanted_height' ] = wanted_height
1157
1156
yield d
1158
1157
1159
1158
def create_invoice (self , * , outputs : List [PartialTxOutput ], message , pr , URI ) -> Invoice :
@@ -1412,6 +1411,7 @@ def sort_key(x):
1412
1411
parent ['date' ] = timestamp_to_datetime (tx_item ['timestamp' ])
1413
1412
parent ['height' ] = tx_item ['height' ]
1414
1413
parent ['confirmations' ] = tx_item ['confirmations' ]
1414
+ parent ['wanted_height' ] = tx_item .get ('wanted_height' )
1415
1415
parent ['children' ].append (tx_item )
1416
1416
1417
1417
now = time .time ()
@@ -3320,8 +3320,10 @@ def add_sweep_info(self, sweep_info: 'SweepInfo'):
3320
3320
# early return if it is spent, because self.processing is not persisted
3321
3321
prevout = txin .prevout .to_str ()
3322
3322
prev_txid , index = prevout .split (':' )
3323
- if self .adb .db .get_spent_outpoint (prev_txid , int (index )):
3324
- return
3323
+ if spender_txid := self .adb .db .get_spent_outpoint (prev_txid , int (index )):
3324
+ tx_mined_status = self .adb .get_tx_height (spender_txid )
3325
+ if tx_mined_status .height not in [TX_HEIGHT_LOCAL , TX_HEIGHT_FUTURE ]:
3326
+ return
3325
3327
self .processing .add (txin .prevout )
3326
3328
self .logger .info (f'add_sweep_info: { sweep_info .name } { sweep_info .txin .prevout .to_str ()} ' )
3327
3329
self .batch_inputs [txin .prevout ] = sweep_info
@@ -3338,10 +3340,21 @@ def to_pay_after(self, tx):
3338
3340
return [x for x in self .batch_payments if x not in tx .outputs ()]
3339
3341
3340
3342
def to_sweep_after (self , tx ):
3341
- if not tx :
3342
- return self .batch_inputs
3343
- tx_prevouts = set (txin .prevout for txin in tx .inputs ())
3344
- return dict ((k ,v ) for k ,v in self .batch_inputs .items () if k not in tx_prevouts )
3343
+ tx_prevouts = set (txin .prevout for txin in tx .inputs ()) if tx else set ()
3344
+ result = []
3345
+ for k ,v in self .batch_inputs .items ():
3346
+ prevout = v .txin .prevout
3347
+ prev_txid , index = prevout .to_str ().split (':' )
3348
+ if not self .adb .db .get_transaction (prev_txid ):
3349
+ continue
3350
+ if spender_txid := self .adb .db .get_spent_outpoint (prev_txid , int (index )):
3351
+ tx_mined_status = self .adb .get_tx_height (spender_txid )
3352
+ if tx_mined_status .height not in [TX_HEIGHT_LOCAL , TX_HEIGHT_FUTURE ]:
3353
+ continue
3354
+ if prevout in tx_prevouts :
3355
+ continue
3356
+ result .append ((k ,v ))
3357
+ return dict (result )
3345
3358
3346
3359
def should_bump_fee (self , base_tx ):
3347
3360
# fixme: since batch_txs is not persisted, we do not bump after a restart
@@ -3401,7 +3414,13 @@ async def manage_batch_payments(self):
3401
3414
base_tx = self .batch_txs [- 1 ] if self .batch_txs else None
3402
3415
to_pay = self .to_pay_after (base_tx )
3403
3416
to_sweep = self .to_sweep_after (base_tx )
3404
- to_sweep_now = dict ([(k ,v ) for k ,v in to_sweep .items () if self .can_broadcast (v )[0 ] is True ])
3417
+ to_sweep_now = {}
3418
+ for k , v in to_sweep .items ():
3419
+ can_broadcast , wanted_height = self .can_broadcast (v )
3420
+ if can_broadcast :
3421
+ to_sweep_now [k ] = v
3422
+ else :
3423
+ self .add_future_tx (v , wanted_height )
3405
3424
if not to_pay and not to_sweep_now and not self .should_bump_fee (base_tx ):
3406
3425
continue
3407
3426
try :
@@ -3505,6 +3524,38 @@ async def maybe_broadcast_legacy_htlc_txs(self):
3505
3524
self .adb .add_transaction (tx )
3506
3525
self .batch_inputs .pop (sweep_info .txin .prevout )
3507
3526
3527
+ def add_future_tx (self , sweep_info , wanted_height ):
3528
+ """ add local tx to provide user feedback """
3529
+ txin = copy .deepcopy (sweep_info .txin )
3530
+ prevout = txin .prevout .to_str ()
3531
+ prev_txid , index = prevout .split (':' )
3532
+ if self .adb .db .get_spent_outpoint (prev_txid , int (index )):
3533
+ return
3534
+ name = sweep_info .name
3535
+ prevout = txin .prevout .to_str ()
3536
+ new_tx = self .create_transaction (
3537
+ inputs = [txin ],
3538
+ outputs = [],
3539
+ password = None ,
3540
+ fee = 0 ,
3541
+ )
3542
+ # we may have a tx with a different fee, in which case it will be replaced
3543
+ try :
3544
+ tx_was_added = self .adb .add_transaction (new_tx )#, is_new=(old_tx is None))
3545
+ except Exception as e :
3546
+ self .logger .info (f'could not add future tx: { name } . prevout: { prevout } { str (e )} ' )
3547
+ tx_was_added = False
3548
+ if tx_was_added :
3549
+ self .logger .info (f'added future tx: { name } . prevout: { prevout } ' )
3550
+
3551
+ # set future tx regardless of tx_was_added, because it is not persisted
3552
+ # (and wanted_height can change if input of CSV was not mined before)
3553
+ self .adb .set_future_tx (new_tx .txid (), wanted_height = wanted_height )
3554
+ if tx_was_added :
3555
+ self .set_label (new_tx .txid (), name )
3556
+ #if old_tx and old_tx.txid() != new_tx.txid():
3557
+ # self.lnworker.wallet.set_label(old_tx.txid(), None)
3558
+ util .trigger_callback ('wallet_updated' , self .lnworker .wallet )
3508
3559
3509
3560
class Simple_Wallet (Abstract_Wallet ):
3510
3561
# wallet with a single keystore
0 commit comments