@@ -150,6 +150,10 @@ class SwapWatcherService {
150150 if (receiveAddress == null ) {
151151 throw Exception ('Receive address is null' );
152152 }
153+
154+ // Unsubscribe BEFORE claiming to prevent race condition with WebSocket updates
155+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
156+
153157 String claimTxId;
154158 try {
155159 claimTxId = await _boltzRepo.claimLightningToBitcoinSwap (
@@ -178,8 +182,9 @@ class SwapWatcherService {
178182 fees: swap.fees? .copyWith (claimFee: swap.fees! .claimFee),
179183 );
180184 await _boltzRepo.updateSwap (swap: updatedSwap);
181- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
182185 } catch (e, st) {
186+ // Re-subscribe on error so watcher continues monitoring
187+ _boltzRepo.subscribeToSwaps ([swap.id]);
183188 log.severe (
184189 '{"swapId": "${swap .id }", "function": "_processReceiveLnToBitcoinClaim"}' ,
185190 error: e,
@@ -198,6 +203,10 @@ class SwapWatcherService {
198203 if (receiveAddress == null ) {
199204 throw Exception ('Receive address is null' );
200205 }
206+
207+ // Unsubscribe BEFORE claiming to prevent race condition with WebSocket updates
208+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
209+
201210 String claimTxId;
202211 log.fine (
203212 '{"swapId": "${swap .id }", "function": "_processReceiveLnToLiquidClaim", "action": "coop_claim_started", "timestamp": "${DateTime .now ().toIso8601String ()}"}' ,
@@ -229,9 +238,10 @@ class SwapWatcherService {
229238 fees: swap.fees? .copyWith (claimFee: swap.fees! .claimFee),
230239 );
231240 await _boltzRepo.updateSwap (swap: updatedSwap);
232- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
233241 _swapStreamController.add (updatedSwap);
234242 } catch (e, st) {
243+ // Re-subscribe on error so watcher continues monitoring
244+ _boltzRepo.subscribeToSwaps ([swap.id]);
235245 log.severe (
236246 '{"swapId": "${swap .id }", "function": "_processReceiveLnToLiquidClaim"}' ,
237247 error: e,
@@ -343,6 +353,10 @@ class SwapWatcherService {
343353 swapType: swap.type,
344354 );
345355 final absoluteFeeOptions = networkFee.toAbsolute (txSize);
356+
357+ // Unsubscribe BEFORE refunding to prevent race condition with WebSocket updates
358+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
359+
346360 String refundTxid;
347361 int actualFeesUsed;
348362 log.fine (
@@ -383,8 +397,9 @@ class SwapWatcherService {
383397 fees: swap.fees? .copyWith (claimFee: actualFeesUsed),
384398 );
385399 await _boltzRepo.updateSwap (swap: updatedSwap);
386- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
387400 } catch (e, st) {
401+ // Re-subscribe on error so watcher continues monitoring
402+ _boltzRepo.subscribeToSwaps ([swap.id]);
388403 log.severe (
389404 '{"swapId": "${swap .id }", "function": "_processSendLiquidToLnRefund"}' ,
390405 error: e,
@@ -422,6 +437,10 @@ class SwapWatcherService {
422437 swapType: swap.type,
423438 );
424439 final absoluteFeeOptions = networkFee.toAbsolute (txSize);
440+
441+ // Unsubscribe BEFORE refunding to prevent race condition with WebSocket updates
442+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
443+
425444 String refundTxid;
426445 int actualFeesUsed;
427446 log.fine (
@@ -462,8 +481,9 @@ class SwapWatcherService {
462481 fees: swap.fees? .copyWith (claimFee: actualFeesUsed),
463482 );
464483 await _boltzRepo.updateSwap (swap: updatedSwap);
465- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
466484 } catch (e, st) {
485+ // Re-subscribe on error so watcher continues monitoring
486+ _boltzRepo.subscribeToSwaps ([swap.id]);
467487 log.severe (
468488 '{"swapId": "${swap .id }", "function": "_processSendBitcoinToLnRefund"}' ,
469489 error: e,
@@ -506,6 +526,9 @@ class SwapWatcherService {
506526 finalClaimAddress = swap.receiveAddress! ;
507527 }
508528 }
529+ // Unsubscribe BEFORE claiming to prevent race condition with WebSocket updates
530+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
531+
509532 String claimTxid;
510533 log.fine (
511534 '{"swapId": "${swap .id }", "function": "_processChainLiquidToBitcoinClaim", "action": "coop_claim_started", "timestamp": "${DateTime .now ().toIso8601String ()}"}' ,
@@ -537,8 +560,9 @@ class SwapWatcherService {
537560 fees: swap.fees? .copyWith (claimFee: swap.fees! .claimFee),
538561 );
539562 await _boltzRepo.updateSwap (swap: updatedSwap);
540- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
541563 } catch (e, st) {
564+ // Re-subscribe on error so watcher continues monitoring
565+ _boltzRepo.subscribeToSwaps ([swap.id]);
542566 log.severe (
543567 '{"swapId": "${swap .id }", "function": "_processChainLiquidToBitcoinClaim"' ,
544568 error: e,
@@ -584,6 +608,9 @@ class SwapWatcherService {
584608 }
585609 }
586610
611+ // Unsubscribe BEFORE claiming to prevent race condition with WebSocket updates
612+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
613+
587614 String claimTxid;
588615 log.fine (
589616 '{"swapId": "${swap .id }", "function": "_processChainBitcoinToLiquidClaim", "action": "coop_claim_started", "timestamp": "${DateTime .now ().toIso8601String ()}"}' ,
@@ -615,8 +642,9 @@ class SwapWatcherService {
615642 fees: swap.fees? .copyWith (claimFee: swap.fees! .claimFee),
616643 );
617644 await _boltzRepo.updateSwap (swap: updatedSwap);
618- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
619645 } catch (e, st) {
646+ // Re-subscribe on error so watcher continues monitoring
647+ _boltzRepo.subscribeToSwaps ([swap.id]);
620648 log.severe (
621649 '{"swapId": "${swap .id }", "function": "_processChainBitcoinToLiquidClaim"}' ,
622650 error: e,
@@ -658,6 +686,10 @@ class SwapWatcherService {
658686 refundAddressForChainSwaps: refundAddress,
659687 );
660688 final absoluteFeeOptions = networkFee.toAbsolute (txSize);
689+
690+ // Unsubscribe BEFORE refunding to prevent race condition with WebSocket updates
691+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
692+
661693 String refundTxid;
662694 int actualFeesUsed;
663695 log.fine (
@@ -699,8 +731,9 @@ class SwapWatcherService {
699731 fees: swap.fees? .copyWith (claimFee: actualFeesUsed),
700732 );
701733 await _boltzRepo.updateSwap (swap: updatedSwap);
702- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
703734 } catch (e, st) {
735+ // Re-subscribe on error so watcher continues monitoring
736+ _boltzRepo.subscribeToSwaps ([swap.id]);
704737 log.severe (
705738 '{"swapId": "${swap .id }", "function": "_processChainLiquidToBitcoinRefund"}' ,
706739 error: e,
@@ -738,6 +771,10 @@ class SwapWatcherService {
738771 refundAddressForChainSwaps: refundAddress,
739772 );
740773 final absoluteFeeOptions = networkFee.toAbsolute (txSize);
774+
775+ // Unsubscribe BEFORE refunding to prevent race condition with WebSocket updates
776+ _boltzRepo.unsubscribeFromSwaps ([swap.id]);
777+
741778 String refundTxid;
742779 int actualFeesUsed;
743780 log.fine (
@@ -779,8 +816,9 @@ class SwapWatcherService {
779816 fees: swap.fees? .copyWith (claimFee: actualFeesUsed),
780817 );
781818 await _boltzRepo.updateSwap (swap: updatedSwap);
782- _boltzRepo.unsubscribeFromSwaps ([swap.id]);
783819 } catch (e, st) {
820+ // Re-subscribe on error so watcher continues monitoring
821+ _boltzRepo.subscribeToSwaps ([swap.id]);
784822 log.severe (
785823 '{"swapId": "${swap .id }", "function": "_processChainBitcoinToLiquidRefund"}' ,
786824 error: e,
@@ -810,19 +848,7 @@ class SwapWatcherService {
810848 return ;
811849 case SwapType .liquidToBitcoin:
812850 case SwapType .bitcoinToLiquid:
813- if (swap is ChainSwap &&
814- swap.receiveTxid == null &&
815- swap.refundTxid == null ) {
816- if (swap.status == SwapStatus .claimable) {
817- final updatedSwap = swap.copyWith (status: SwapStatus .claimable);
818- await _boltzRepo.updateSwap (swap: updatedSwap);
819- } else if (swap.status == SwapStatus .refundable) {
820- final updatedSwap = swap.copyWith (status: SwapStatus .refundable);
821- await _boltzRepo.updateSwap (swap: updatedSwap);
822- }
823- } else {
824- return ;
825- }
851+ return ;
826852 }
827853 } catch (e, st) {
828854 log.severe (
0 commit comments