@@ -25,9 +25,6 @@ class BoltzDatasource {
2525 final SwapStatusMapper _mapper = const SwapStatusMapper ();
2626 final Set <String > _subscribedSwapIds = {};
2727
28- /// Per-swap FIFO chains: every event for a swap is processed in arrival
29- /// order; events for different swaps run independently. Nothing is ever
30- /// dropped or delayed.
3128 final Map <String , Future <void >> _eventChains = {};
3229
3330 int _reconnectAttempt = 0 ;
@@ -991,11 +988,6 @@ class BoltzDatasource {
991988 return ;
992989 }
993990 log.fine ('[Boltz] event swap=${event .id } status=${event .status .name }' );
994- // SWAP_TESTER: temporary verbose logging — remove after live testing.
995- // log.info(
996- // 'SWAP_TESTER ws-event: ${event.id} ${event.status.name} '
997- // 'txid=${event.transaction?.id ?? "-"}',
998- // );
999991 _enqueueEvent (event.id, event.status, event.transaction? .id);
1000992 },
1001993 onError: (error) {
@@ -1005,9 +997,8 @@ class BoltzDatasource {
1005997 );
1006998 }
1007999
1008- /// Reconnect with capped exponential backoff (1s, 2s, ... 60s), then
1009- /// re-subscribe everything we were watching and reconcile each swap's
1010- /// status over REST — subscription replay is not a documented guarantee.
1000+ /// On reconnect, reconcile each swap's status over REST: Boltz does not
1001+ /// guarantee replay of events missed while disconnected.
10111002 void _scheduleReconnect () {
10121003 if (_reconnectTimer? .isActive ?? false ) return ;
10131004 final delaySeconds = min (60 , 1 << min (_reconnectAttempt, 6 ));
@@ -1030,8 +1021,6 @@ class BoltzDatasource {
10301021 });
10311022 }
10321023
1033- /// Appends the event to the swap's FIFO chain so events for one swap are
1034- /// processed strictly in arrival order, with nothing dropped.
10351024 Future <void > _enqueueEvent (
10361025 String swapId,
10371026 SwapStatus boltzStatus,
@@ -1051,32 +1040,24 @@ class BoltzDatasource {
10511040 return next;
10521041 }
10531042
1054- /// Fetches the swap's current status over REST and runs it through the
1055- /// same mapping pipeline as websocket events. Used after reconnects and on
1056- /// watcher restarts so recovery never depends on websocket replay .
1043+ /// Fetches each swap's current status over REST and runs it through the same
1044+ /// mapping pipeline as websocket events, so recovery never depends on Boltz
1045+ /// replaying events missed while disconnected .
10571046 Future <void > reconcileSwaps (List <String > swapIds) async {
10581047 for (final swapId in swapIds) {
10591048 try {
10601049 final response = await _http.get <Map <String , dynamic >>('/swap/$swapId ' );
10611050 final data = response.data;
10621051 if (data == null ) continue ;
10631052 final status = SwapStatusResponse .fromJson (json: jsonEncode (data));
1064- // SWAP_TESTER
1065- // log.info(
1066- // 'SWAP_TESTER reconcile: $swapId REST=${status.status.name} '
1067- // 'txid=${status.transaction?.id ?? "-"}',
1068- // );
10691053 await _enqueueEvent (swapId, status.status, status.transaction? .id);
10701054 } catch (e) {
10711055 log.warning ('[Boltz] reconcile failed for swap $swapId : $e ' );
10721056 }
10731057 }
10741058 }
10751059
1076- /// Maps one Boltz status event onto the stored swap via [SwapStatusMapper]
1077- /// and applies the outcome: persist + emit, delete stale rows, or
1078- /// unsubscribe settled swaps. Never throws — a failure here must not break
1079- /// the swap's event chain.
1060+ /// Never throws: a failure here must not break the swap's event chain.
10801061 Future <void > _processSwapEvent (
10811062 String swapId,
10821063 SwapStatus boltzStatus, {
@@ -1096,10 +1077,9 @@ class BoltzDatasource {
10961077 now: DateTime .now (),
10971078 );
10981079
1099- // The watcher writes concurrently with this event chain (e.g. a claim
1100- // completing while a reconcile event is being mapped). Re-fetch right
1101- // before acting and re-map if the row moved, so a store can never
1102- // write back a stale row and lose a txid or regress a terminal status.
1080+ // The watcher writes concurrently with this event chain; re-fetch and
1081+ // re-map if the row moved, so a store can't lose a txid or regress a
1082+ // terminal status by writing back a stale row.
11031083 if (mapping is ! SwapUnchanged ) {
11041084 final latest = await _boltzStore.fetch (swapId);
11051085 if (latest == null ) {
@@ -1119,8 +1099,6 @@ class BoltzDatasource {
11191099
11201100 switch (mapping) {
11211101 case SwapStale ():
1122- // SWAP_TESTER
1123- // log.info('SWAP_TESTER mapping: $swapId -> STALE (deleting)');
11241102 log.info (
11251103 '[Boltz] deleting stale pending swap $swapId '
11261104 '(no funds at risk, expired upstream)' ,
@@ -1130,39 +1108,21 @@ class BoltzDatasource {
11301108 await _boltzStore.deleteFromSecureStorage (swapId);
11311109
11321110 case SwapUnchanged ():
1133- // SWAP_TESTER
1134- // log.info(
1135- // 'SWAP_TESTER mapping: $swapId ${boltzStatus.name} -> UNCHANGED '
1136- // '(local=${swapModel.status} settled=${_isSettled(swapModel)} '
1137- // 'needsAction=${_swapNeedsProcessing(swapModel)})',
1138- // );
11391111 if (_isSettled (swapModel) && ! _swapNeedsProcessing (swapModel)) {
1140- // Re-emit so late listeners (e.g. a screen waiting on
1141- // completion) get the final state, then stop watching.
11421112 _swapUpdatesController.add (swapModel);
11431113 unsubscribeToSwaps ([swapId]);
11441114 } else if (_swapNeedsProcessing (swapModel)) {
1145- // The status didn't move but the swap still needs a claim,
1146- // refund or coop close — re-emit so the watcher retries (this is
1147- // how reconciliation un-sticks swaps after a missed action).
1115+ // Status unchanged but the swap still needs a claim, refund or coop
1116+ // close: re-emit so reconciliation un-sticks a missed action.
11481117 _swapUpdatesController.add (swapModel);
11491118 }
11501119
11511120 case SwapUpdated (: final swap):
1152- // SWAP_TESTER
1153- // log.info(
1154- // 'SWAP_TESTER mapping: $swapId ${boltzStatus.name}: '
1155- // '${swapModel.status} -> ${swap.status} (storing + emitting)',
1156- // );
11571121 await _boltzStore.store (swap);
11581122 log.info (
11591123 '[Boltz] swap $swapId : ${swapModel .status } -> ${swap .status } '
11601124 '(event ${boltzStatus .name })' ,
11611125 );
1162- // A SwapUpdated always carries a material change (status, txid,
1163- // completion time, ...) — emit unconditionally so the UI also sees
1164- // updates that don't change the status string, e.g. invoice.paid
1165- // stamping completionTime on an already-paid submarine swap.
11661126 _swapUpdatesController.add (swap);
11671127 if (_isSettled (swap) && ! _swapNeedsProcessing (swap)) {
11681128 unsubscribeToSwaps ([swapId]);
@@ -1238,8 +1198,6 @@ class BoltzDatasource {
12381198 if (newSwapIds.isEmpty) {
12391199 return ;
12401200 }
1241- // SWAP_TESTER
1242- // log.info('SWAP_TESTER ws-subscribe: $newSwapIds');
12431201 _boltzWebSocket.subscribe (newSwapIds);
12441202 _subscribedSwapIds.addAll (newSwapIds);
12451203 }
@@ -1252,8 +1210,6 @@ class BoltzDatasource {
12521210 if (swapIdsToUnsubscribe.isEmpty) {
12531211 return ;
12541212 }
1255- // SWAP_TESTER
1256- // log.info('SWAP_TESTER ws-unsubscribe: $swapIdsToUnsubscribe');
12571213 _boltzWebSocket.unsubscribe (swapIdsToUnsubscribe);
12581214 _subscribedSwapIds.removeAll (swapIdsToUnsubscribe);
12591215 }
@@ -1264,7 +1220,6 @@ class BoltzDatasource {
12641220 s: invoice,
12651221 boltzUrl: _httpsUrl,
12661222 );
1267- // convert decoded.msats to sats by dividing by 1000 and rounding down
12681223 final sats = (decoded.msats ~ / BigInt .from (1000 )).toInt ();
12691224 return (sats, decoded.isExpired, decoded.bip21);
12701225 } catch (e) {
0 commit comments