@@ -76,6 +76,9 @@ class TransactionDetailsCubit extends Cubit<TransactionDetailsState> {
7676 StreamSubscription ? _payjoinTxSubscription;
7777 StreamSubscription ? _payjoinOriginalTxSubscription;
7878 StreamSubscription ? _orderSwapSubscription;
79+ String ? _watchedOrderSwapTransactionId;
80+ WalletTransaction ? _pendingOrderSwapWalletTransaction;
81+ int _orderSwapTransactionWatchGeneration = 0 ;
7982
8083 // The payjoin id _payjoinSubscription is currently listening to on the
8184 // by-wallet-tx path, so reloads triggered by its own events don't
@@ -149,25 +152,7 @@ class TransactionDetailsCubit extends Cubit<TransactionDetailsState> {
149152 .execute (localId)
150153 .listen (
151154 (orderSwap) {
152- if (isClosed) return ;
153- final transaction = state.transaction;
154- if (transaction? .orderSwap? .localId != orderSwap.localId) return ;
155- final walletTransaction = transaction? .walletTransaction;
156- final canonicalTransactionChanged =
157- walletTransaction != null &&
158- walletTransaction.txId !=
159- orderSwap.canonicalWalletTransactionId;
160- emit (
161- state.copyWith (
162- transaction: transaction! .copyWith (
163- walletTransaction: canonicalTransactionChanged
164- ? null
165- : walletTransaction,
166- orderSwap: orderSwap,
167- ),
168- swapCounterpartTxId: orderSwap.counterpartTransactionId,
169- ),
170- );
155+ unawaited (_handleOrderSwapUpdate (orderSwap));
171156 },
172157 onError: (Object error) {
173158 if (isClosed) return ;
@@ -176,10 +161,88 @@ class TransactionDetailsCubit extends Cubit<TransactionDetailsState> {
176161 );
177162 }
178163
164+ Future <void > _handleOrderSwapUpdate (OrderSwapRecord orderSwap) async {
165+ if (isClosed) return ;
166+ final transaction = state.transaction;
167+ if (transaction? .orderSwap? .localId != orderSwap.localId) {
168+ await _loadDetailsByOrderSwapLocalId (orderSwap.localId);
169+ await _watchOrderSwapWalletTransaction (state.transaction? .orderSwap);
170+ return ;
171+ }
172+ final walletTransaction = transaction? .walletTransaction;
173+ final canonicalTransactionChanged =
174+ walletTransaction != null &&
175+ walletTransaction.txId != orderSwap.canonicalWalletTransactionId;
176+ emit (
177+ state.copyWith (
178+ transaction: transaction! .copyWith (
179+ walletTransaction: canonicalTransactionChanged
180+ ? null
181+ : walletTransaction,
182+ orderSwap: orderSwap,
183+ ),
184+ swapCounterpartTxId: orderSwap.counterpartTransactionId,
185+ ),
186+ );
187+ await _watchOrderSwapWalletTransaction (orderSwap);
188+ }
189+
190+ Future <void > _watchOrderSwapWalletTransaction (
191+ OrderSwapRecord ? orderSwap,
192+ ) async {
193+ final transactionId = orderSwap? .canonicalWalletTransactionId;
194+ final walletId = orderSwap? .canonicalWalletId;
195+ if (transactionId == null || walletId == null ) return ;
196+ if (_watchedOrderSwapTransactionId == transactionId) return ;
197+ final generation = ++ _orderSwapTransactionWatchGeneration;
198+ _pendingOrderSwapWalletTransaction = null ;
199+ await _walletTransactionSubscription? .cancel ();
200+ if (isClosed || generation != _orderSwapTransactionWatchGeneration) return ;
201+ try {
202+ _walletTransactionSubscription = _watchWalletTransactionByTxIdUsecase
203+ .execute (txId: transactionId, walletId: walletId)
204+ .listen (
205+ (walletTransaction) {
206+ if (isClosed) return ;
207+ final latestOrderSwap = state.transaction? .orderSwap;
208+ if (latestOrderSwap == null ) {
209+ _pendingOrderSwapWalletTransaction = walletTransaction;
210+ return ;
211+ }
212+ if (latestOrderSwap.canonicalWalletTransactionId !=
213+ transactionId) {
214+ return ;
215+ }
216+ emit (
217+ state.copyWith (
218+ transaction: state.transaction? .copyWith (
219+ walletTransaction: walletTransaction,
220+ ),
221+ ),
222+ );
223+ },
224+ onError: (_) {
225+ if (_watchedOrderSwapTransactionId == transactionId) {
226+ _watchedOrderSwapTransactionId = null ;
227+ }
228+ log.warning ('Order swap wallet transaction watcher failed' );
229+ },
230+ );
231+ _watchedOrderSwapTransactionId = transactionId;
232+ } catch (_) {
233+ _watchedOrderSwapTransactionId = null ;
234+ log.warning ('Order swap wallet transaction watcher failed' );
235+ }
236+ }
237+
179238 Future <void > _loadDetailsByOrderSwapLocalId (String localId) async {
180239 try {
181240 final orderSwap = await _getTransactionOrderSwapUsecase.execute (localId);
241+ await _watchOrderSwapWalletTransaction (orderSwap);
182242 await _loadOrderSwapDetails (orderSwap);
243+ } on ParallelWaitError catch (error) {
244+ if (isClosed) return ;
245+ emit (state.copyWith (err: _firstParallelError (error)));
183246 } on TransactionNotFoundError catch (error) {
184247 if (isClosed) return ;
185248 emit (state.copyWith (notFoundError: error));
@@ -216,10 +279,22 @@ class TransactionDetailsCubit extends Cubit<TransactionDetailsState> {
216279 walletId: walletId,
217280 ),
218281 ).wait;
219- final walletTransaction = switch (walletTransactionResult) {
282+ final loadedWalletTransaction = switch (walletTransactionResult) {
220283 Ok (: final value) => value,
221- Err () => null ,
284+ Err () => () {
285+ log.warning ('Order swap wallet transaction lookup failed' );
286+ return null ;
287+ }(),
222288 };
289+ final pendingWalletTransaction = _pendingOrderSwapWalletTransaction;
290+ _pendingOrderSwapWalletTransaction = null ;
291+ final matchingPendingWalletTransaction =
292+ pendingWalletTransaction? .txId == transactionId &&
293+ pendingWalletTransaction? .walletId == walletId
294+ ? pendingWalletTransaction
295+ : null ;
296+ final walletTransaction =
297+ matchingPendingWalletTransaction ?? loadedWalletTransaction;
223298 if (isClosed) return ;
224299 emit (
225300 state.copyWith (
@@ -230,10 +305,17 @@ class TransactionDetailsCubit extends Cubit<TransactionDetailsState> {
230305 wallet: wallet,
231306 counterpartWallet: counterpartWallet,
232307 swapCounterpartTxId: orderSwap.counterpartTransactionId,
308+ err: null ,
309+ notFoundError: null ,
233310 ),
234311 );
235312 }
236313
314+ Object _firstParallelError (ParallelWaitError error) {
315+ final errors = error.errors as (AsyncError ? , AsyncError ? , AsyncError ? );
316+ return (errors.$1 ?? errors.$2 ?? errors.$3)? .error ?? error;
317+ }
318+
237319 Future <void > _loadDetailsByWalletTxId (
238320 String txId, {
239321 required String walletId,
0 commit comments