11import 'dart:async' ;
22
33import 'package:bb_mobile/core/entities/signer_entity.dart' show SignerEntity;
4+ import 'package:bb_mobile/core/exchange/domain/entity/order.dart' ;
45import 'package:bb_mobile/core/exchange/domain/usecases/get_order_usercase.dart' ;
56import 'package:bb_mobile/core/swaps/domain/usecases/get_swap_usecase.dart' ;
67import 'package:bb_mobile/core/swaps/domain/usecases/watch_swap_usecase.dart' ;
@@ -145,6 +146,7 @@ void main() {
145146 late _MockBroadcastOriginalTransactionUsecase broadcastOriginalTransaction;
146147 late _MockGetTransactionOrderSwapUsecase getTransactionOrderSwap;
147148 late _MockWatchTransactionOrderSwapUsecase watchTransactionOrderSwap;
149+ late _MockGetOrderUsecase getOrder;
148150
149151 TransactionDetailsCubit buildCubit () => TransactionDetailsCubit (
150152 getWalletUsecase: getWallet,
@@ -155,7 +157,7 @@ void main() {
155157 getSwapUsecase: _MockGetSwapUsecase (),
156158 getPayjoinByIdUsecase: getPayjoinById,
157159 getPayjoinByTxIdUsecase: getPayjoinByTxId,
158- getOrderUsecase: _MockGetOrderUsecase () ,
160+ getOrderUsecase: getOrder ,
159161 watchSwapUsecase: _MockWatchSwapUsecase (),
160162 watchPayjoinUsecase: watchPayjoin,
161163 watchTransactionOrderSwapUsecase: watchTransactionOrderSwap,
@@ -178,6 +180,7 @@ void main() {
178180 broadcastOriginalTransaction = _MockBroadcastOriginalTransactionUsecase ();
179181 getTransactionOrderSwap = _MockGetTransactionOrderSwapUsecase ();
180182 watchTransactionOrderSwap = _MockWatchTransactionOrderSwapUsecase ();
183+ getOrder = _MockGetOrderUsecase ();
181184
182185 when (() => broadcastOriginalTransaction.canExecute (any ())).thenAnswer ((
183186 invocation,
@@ -1313,8 +1316,86 @@ void main() {
13131316 },
13141317 );
13151318 });
1319+
1320+ group ('TransactionDetailsCubit.initByOrderId transaction resolution' , () {
1321+ test ('resolves the payjoin txid when the order has no txid yet' , () async {
1322+ // The exchange can know the payjoin it broadcast before it reports its
1323+ // own payout txid. Without the fallback the screen stays on order-only
1324+ // details, with no payjoin shown and no watcher armed.
1325+ final order = _buyOrder (payjoinTxId: 'payjoin-txid' );
1326+ when (
1327+ () => getOrder.execute (orderId: 'order-1' ),
1328+ ).thenAnswer ((_) async => order);
1329+ when (() => getTransactionsByTxId.execute (any ())).thenAnswer (
1330+ (_) async => [Transaction (payjoin: _receiver (), order: order)],
1331+ );
1332+
1333+ final cubit = buildCubit ();
1334+ addTearDown (cubit.close);
1335+ await cubit.initByOrderId ('order-1' );
1336+
1337+ verify (() => getTransactionsByTxId.execute ('payjoin-txid' )).called (1 );
1338+ });
1339+
1340+ test ('prefers the order txid when both are known' , () async {
1341+ final order = _buyOrder (
1342+ bitcoinTransactionId: 'payout-txid' ,
1343+ payjoinTxId: 'payjoin-txid' ,
1344+ );
1345+ when (
1346+ () => getOrder.execute (orderId: 'order-1' ),
1347+ ).thenAnswer ((_) async => order);
1348+ when (() => getTransactionsByTxId.execute (any ())).thenAnswer (
1349+ (_) async => [Transaction (payjoin: _receiver (), order: order)],
1350+ );
1351+
1352+ final cubit = buildCubit ();
1353+ addTearDown (cubit.close);
1354+ await cubit.initByOrderId ('order-1' );
1355+
1356+ verify (() => getTransactionsByTxId.execute ('payout-txid' )).called (1 );
1357+ verifyNever (() => getTransactionsByTxId.execute ('payjoin-txid' ));
1358+ });
1359+
1360+ test ('falls back to order-only details when no txid is known' , () async {
1361+ final order = _buyOrder ();
1362+ when (
1363+ () => getOrder.execute (orderId: 'order-1' ),
1364+ ).thenAnswer ((_) async => order);
1365+
1366+ final cubit = buildCubit ();
1367+ addTearDown (cubit.close);
1368+ await cubit.initByOrderId ('order-1' );
1369+
1370+ verifyNever (() => getTransactionsByTxId.execute (any ()));
1371+ expect (cubit.state.transaction? .order, order);
1372+ });
1373+ });
13161374}
13171375
1376+ Order _buyOrder ({String ? bitcoinTransactionId, String ? payjoinTxId}) =>
1377+ Order .buy (
1378+ orderId: 'order-1' ,
1379+ orderType: OrderType .buy,
1380+ message: OrderMessage (code: '' , message: '' ),
1381+ orderNumber: 1 ,
1382+ payinAmount: 100 ,
1383+ payinCurrency: 'CAD' ,
1384+ payoutAmount: 0.001 ,
1385+ payoutCurrency: 'BTC' ,
1386+ payinMethod: OrderPaymentMethod .eTransfer,
1387+ payoutMethod: OrderPaymentMethod .bitcoin,
1388+ orderStatus: OrderStatus .inProgress,
1389+ payinStatus: OrderPayinStatus .completed,
1390+ payoutStatus: OrderPayoutStatus .completed,
1391+ createdAt: DateTime .utc (2026 , 8 , 19 ),
1392+ bitcoinTransactionId: bitcoinTransactionId,
1393+ payjoinDetails: payjoinTxId == null
1394+ ? null
1395+ : OrderPayjoinDetails (txid: payjoinTxId),
1396+ isTestnet: false ,
1397+ );
1398+
13181399OrderSwapRecord _receiveOrderSwap () {
13191400 final createdAt = DateTime .utc (2026 , 8 , 10 );
13201401 return OrderSwapRecord (
0 commit comments