@@ -2,8 +2,11 @@ import 'dart:async';
22
33import 'package:bb_mobile/core/swaps/data/datasources/boltz_storage_datasource.dart' ;
44import 'package:bb_mobile/core/swaps/data/models/swap_model.dart' ;
5+ import 'package:bb_mobile/core/swaps/data/models/swap_tx_outspend_model.dart' ;
56import 'package:bb_mobile/core/swaps/domain/entity/swap.dart' as swap_entity;
7+ import 'package:bb_mobile/core/swaps/domain/entity/swap_tx_outspend.dart' ;
68import 'package:bb_mobile/core/utils/constants.dart' ;
9+ import 'package:bb_mobile/core/wallet/domain/entities/wallet.dart' ;
710import 'package:boltz/boltz.dart' ;
811
912class BoltzDatasource {
@@ -652,16 +655,15 @@ class BoltzDatasource {
652655 }) async {
653656 try {
654657 final chainSwap = await _boltzStore.fetchChainSwap (swapId);
655- final txId =
656- await (broadcastViaBoltz
657- ? chainSwap.broadcastBoltz (
658- signedHex: signedTxHex,
659- kind: SwapTxKind .refund,
660- )
661- : chainSwap.broadcastLocal (
662- signedHex: signedTxHex,
663- kind: SwapTxKind .refund,
664- ));
658+ final txId = await (broadcastViaBoltz
659+ ? chainSwap.broadcastBoltz (
660+ signedHex: signedTxHex,
661+ kind: SwapTxKind .refund,
662+ )
663+ : chainSwap.broadcastLocal (
664+ signedHex: signedTxHex,
665+ kind: SwapTxKind .refund,
666+ ));
665667 return txId;
666668 } catch (e) {
667669 if (e is BoltzError ) {
@@ -725,13 +727,13 @@ class BoltzDatasource {
725727 final chainSwap = await _boltzStore.fetchChainSwap (swapId);
726728 return await (broadcastViaBoltz
727729 ? chainSwap.broadcastBoltz (
728- signedHex: signedTxHex,
729- kind: SwapTxKind .claim,
730- )
730+ signedHex: signedTxHex,
731+ kind: SwapTxKind .claim,
732+ )
731733 : chainSwap.broadcastLocal (
732- signedHex: signedTxHex,
733- kind: SwapTxKind .claim,
734- ));
734+ signedHex: signedTxHex,
735+ kind: SwapTxKind .claim,
736+ ));
735737 } catch (e) {
736738 if (e is BoltzError ) {
737739 throw e.message;
@@ -1101,10 +1103,9 @@ class BoltzDatasource {
11011103 case SwapStatus .txnRefunded:
11021104 // Check if this swap needs to be refunded (no refundTxid)
11031105 if (swapModel is ChainSwapModel || swapModel is LnSendSwapModel ) {
1104- final refunded =
1105- swapModel is ChainSwapModel
1106- ? swapModel.refundTxid != null
1107- : (swapModel as LnSendSwapModel ).refundTxid != null ;
1106+ final refunded = swapModel is ChainSwapModel
1107+ ? swapModel.refundTxid != null
1108+ : (swapModel as LnSendSwapModel ).refundTxid != null ;
11081109
11091110 if (! refunded) {
11101111 updatedSwapModel = swapModel.copyWith (
@@ -1128,15 +1129,13 @@ class BoltzDatasource {
11281129 case SwapStatus .txnFailed:
11291130 // Transaction failed - check if refundable
11301131 if (swapModel is ChainSwapModel || swapModel is LnSendSwapModel ) {
1131- final hasSentFunds =
1132- swapModel is ChainSwapModel
1133- ? swapModel.sendTxid != null
1134- : (swapModel as LnSendSwapModel ).sendTxid != null ;
1132+ final hasSentFunds = swapModel is ChainSwapModel
1133+ ? swapModel.sendTxid != null
1134+ : (swapModel as LnSendSwapModel ).sendTxid != null ;
11351135
1136- final hasRefunded =
1137- swapModel is ChainSwapModel
1138- ? swapModel.refundTxid != null
1139- : (swapModel as LnSendSwapModel ).refundTxid != null ;
1136+ final hasRefunded = swapModel is ChainSwapModel
1137+ ? swapModel.refundTxid != null
1138+ : (swapModel as LnSendSwapModel ).refundTxid != null ;
11401139
11411140 if (hasSentFunds && ! hasRefunded) {
11421141 updatedSwapModel = swapModel.copyWith (
@@ -1153,15 +1152,13 @@ class BoltzDatasource {
11531152 case SwapStatus .invoiceExpired:
11541153 // Check if funds were sent but not refunded
11551154 if (swapModel is ChainSwapModel || swapModel is LnSendSwapModel ) {
1156- final hasSentFunds =
1157- swapModel is ChainSwapModel
1158- ? swapModel.sendTxid != null
1159- : (swapModel as LnSendSwapModel ).sendTxid != null ;
1155+ final hasSentFunds = swapModel is ChainSwapModel
1156+ ? swapModel.sendTxid != null
1157+ : (swapModel as LnSendSwapModel ).sendTxid != null ;
11601158
1161- final hasRefunded =
1162- swapModel is ChainSwapModel
1163- ? swapModel.refundTxid != null
1164- : (swapModel as LnSendSwapModel ).refundTxid != null ;
1159+ final hasRefunded = swapModel is ChainSwapModel
1160+ ? swapModel.refundTxid != null
1161+ : (swapModel as LnSendSwapModel ).refundTxid != null ;
11651162
11661163 if (hasSentFunds && ! hasRefunded) {
11671164 updatedSwapModel = swapModel.copyWith (
@@ -1180,10 +1177,9 @@ class BoltzDatasource {
11801177
11811178 case SwapStatus .swapRefunded:
11821179 if (swapModel is ChainSwapModel || swapModel is LnSendSwapModel ) {
1183- final hasRefunded =
1184- swapModel is ChainSwapModel
1185- ? swapModel.refundTxid != null
1186- : (swapModel as LnSendSwapModel ).refundTxid != null ;
1180+ final hasRefunded = swapModel is ChainSwapModel
1181+ ? swapModel.refundTxid != null
1182+ : (swapModel as LnSendSwapModel ).refundTxid != null ;
11871183
11881184 if (! hasRefunded) {
11891185 updatedSwapModel = swapModel.copyWith (
@@ -1200,15 +1196,13 @@ class BoltzDatasource {
12001196 case SwapStatus .swapError:
12011197 // Handle error states
12021198 if (swapModel is ChainSwapModel || swapModel is LnSendSwapModel ) {
1203- final hasSentFunds =
1204- swapModel is ChainSwapModel
1205- ? swapModel.sendTxid != null
1206- : (swapModel as LnSendSwapModel ).sendTxid != null ;
1199+ final hasSentFunds = swapModel is ChainSwapModel
1200+ ? swapModel.sendTxid != null
1201+ : (swapModel as LnSendSwapModel ).sendTxid != null ;
12071202
1208- final hasRefunded =
1209- swapModel is ChainSwapModel
1210- ? swapModel.refundTxid != null
1211- : (swapModel as LnSendSwapModel ).refundTxid != null ;
1203+ final hasRefunded = swapModel is ChainSwapModel
1204+ ? swapModel.refundTxid != null
1205+ : (swapModel as LnSendSwapModel ).refundTxid != null ;
12121206
12131207 if (hasSentFunds && ! hasRefunded) {
12141208 updatedSwapModel = swapModel.copyWith (
@@ -1271,8 +1265,9 @@ class BoltzDatasource {
12711265
12721266 void subscribeToSwaps (List <String > swapIds) {
12731267 final uniqueSwapIds = swapIds.toSet ().toList ();
1274- final newSwapIds =
1275- uniqueSwapIds.where ((id) => ! _subscribedSwapIds.contains (id)).toList ();
1268+ final newSwapIds = uniqueSwapIds
1269+ .where ((id) => ! _subscribedSwapIds.contains (id))
1270+ .toList ();
12761271
12771272 if (newSwapIds.isEmpty) {
12781273 return ;
@@ -1283,8 +1278,9 @@ class BoltzDatasource {
12831278
12841279 void unsubscribeToSwaps (List <String > swapIds) {
12851280 final uniqueSwapIds = swapIds.toSet ().toList ();
1286- final swapIdsToUnsubscribe =
1287- uniqueSwapIds.where ((id) => _subscribedSwapIds.contains (id)).toList ();
1281+ final swapIdsToUnsubscribe = uniqueSwapIds
1282+ .where ((id) => _subscribedSwapIds.contains (id))
1283+ .toList ();
12881284 if (swapIdsToUnsubscribe.isEmpty) {
12891285 return ;
12901286 }
@@ -1320,10 +1316,9 @@ class BoltzDatasource {
13201316 final fees = Fees (boltzUrl: _httpsUrl);
13211317 final reverseFees = await fees.reverse ();
13221318 final submarineFees = await fees.submarine ();
1323- final swapType =
1324- swap.kind == SwapType .reverse
1325- ? swap_entity.SwapType .lightningToBitcoin
1326- : swap_entity.SwapType .bitcoinToLightning;
1319+ final swapType = swap.kind == SwapType .reverse
1320+ ? swap_entity.SwapType .lightningToBitcoin
1321+ : swap_entity.SwapType .bitcoinToLightning;
13271322 if (swapType == swap_entity.SwapType .lightningToBitcoin) {
13281323 if (receiveWalletId == null ) {
13291324 throw 'Receive wallet ID is required for lightning to bitcoin swaps' ;
@@ -1384,10 +1379,9 @@ class BoltzDatasource {
13841379 final fees = Fees (boltzUrl: _httpsUrl);
13851380 final reverseFees = await fees.reverse ();
13861381 final submarineFees = await fees.submarine ();
1387- final swapType =
1388- swap.kind == SwapType .reverse
1389- ? swap_entity.SwapType .lightningToLiquid
1390- : swap_entity.SwapType .liquidToLightning;
1382+ final swapType = swap.kind == SwapType .reverse
1383+ ? swap_entity.SwapType .lightningToLiquid
1384+ : swap_entity.SwapType .liquidToLightning;
13911385 if (swapType == swap_entity.SwapType .lightningToLiquid) {
13921386 if (receiveWalletId == null ) {
13931387 throw 'Receive wallet ID is required for lightning to liquid swaps' ;
@@ -1447,10 +1441,9 @@ class BoltzDatasource {
14471441 ) async {
14481442 final fees = Fees (boltzUrl: _httpsUrl);
14491443 final chainFees = await fees.chain ();
1450- final swapType =
1451- swap.direction == ChainSwapDirection .lbtcToBtc
1452- ? swap_entity.SwapType .liquidToBitcoin
1453- : swap_entity.SwapType .bitcoinToLiquid;
1444+ final swapType = swap.direction == ChainSwapDirection .lbtcToBtc
1445+ ? swap_entity.SwapType .liquidToBitcoin
1446+ : swap_entity.SwapType .bitcoinToLiquid;
14541447 switch (swapType) {
14551448 case swap_entity.SwapType .liquidToBitcoin:
14561449 final swapModel = SwapModel .chain (
@@ -1463,10 +1456,12 @@ class BoltzDatasource {
14631456 paymentAddress: swap.scriptAddress,
14641457 paymentAmount: swap.outAmount.toInt (),
14651458 sendTxid: lockupTxid,
1466- receiveWalletId:
1467- isReceiveWalletExternal == false ? receiveWalletId : null ,
1468- receiveAddress:
1469- isReceiveWalletExternal == true ? receiveWalletId : null ,
1459+ receiveWalletId: isReceiveWalletExternal == false
1460+ ? receiveWalletId
1461+ : null ,
1462+ receiveAddress: isReceiveWalletExternal == true
1463+ ? receiveWalletId
1464+ : null ,
14701465 boltzFees:
14711466 (chainFees.btcFees.percentage * swap.outAmount.toInt () / 100 )
14721467 .ceil ()
@@ -1488,10 +1483,12 @@ class BoltzDatasource {
14881483 paymentAddress: swap.scriptAddress,
14891484 paymentAmount: swap.outAmount.toInt (),
14901485 sendTxid: lockupTxid,
1491- receiveWalletId:
1492- isReceiveWalletExternal == false ? receiveWalletId : null ,
1493- receiveAddress:
1494- isReceiveWalletExternal == true ? receiveWalletId : null ,
1486+ receiveWalletId: isReceiveWalletExternal == false
1487+ ? receiveWalletId
1488+ : null ,
1489+ receiveAddress: isReceiveWalletExternal == true
1490+ ? receiveWalletId
1491+ : null ,
14951492 boltzFees:
14961493 (chainFees.lbtcFees.percentage * swap.outAmount.toInt () / 100 )
14971494 .ceil ()
@@ -1506,4 +1503,53 @@ class BoltzDatasource {
15061503 throw Exception ('Invalid swap type' );
15071504 }
15081505 }
1506+
1507+ /// Checks the outspend status of a swap's lockup transaction
1508+ Future <SwapTxOutspendModel > checkSwapLockupOutspend ({
1509+ required String swapId,
1510+ required swap_entity.SwapType swapType,
1511+ required Network network,
1512+ SwapDirection ? swapDirection,
1513+ }) async {
1514+ final boltzSwapType = switch (swapType) {
1515+ swap_entity.SwapType .lightningToBitcoin ||
1516+ swap_entity.SwapType .lightningToLiquid => SwapType .reverse,
1517+ swap_entity.SwapType .bitcoinToLightning ||
1518+ swap_entity.SwapType .liquidToLightning => SwapType .submarine,
1519+ swap_entity.SwapType .bitcoinToLiquid ||
1520+ swap_entity.SwapType .liquidToBitcoin => SwapType .chain,
1521+ };
1522+
1523+ final boltzChain = switch (network) {
1524+ Network .bitcoinMainnet => Chain .bitcoin,
1525+ Network .bitcoinTestnet => Chain .bitcoinTestnet,
1526+ Network .liquidMainnet => Chain .liquid,
1527+ Network .liquidTestnet => Chain .liquidTestnet,
1528+ };
1529+
1530+ final chainSwapDirection = swapDirection != null
1531+ ? switch (swapDirection) {
1532+ SwapDirection .bitcoinToLiquid => ChainSwapDirection .btcToLbtc,
1533+ SwapDirection .liquidToBitcoin => ChainSwapDirection .lbtcToBtc,
1534+ }
1535+ : null ;
1536+
1537+ final outspendStatus = await checkVout0Outspend (
1538+ swapId: swapId,
1539+ swapType: boltzSwapType,
1540+ txKind: SwapTxKind .claim,
1541+ network: boltzChain,
1542+ boltzUrl: _httpsUrl,
1543+ chainSwapDirection: chainSwapDirection,
1544+ );
1545+
1546+ return SwapTxOutspendModel (
1547+ txid: outspendStatus.txid,
1548+ timestamp: outspendStatus.timestamp != null
1549+ ? DateTime .fromMillisecondsSinceEpoch (
1550+ outspendStatus.timestamp! .toInt () * 1000 ,
1551+ )
1552+ : null ,
1553+ );
1554+ }
15091555}
0 commit comments