@atomiqlabs/sdk 8.9.1 → 8.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +1760 -1760
  3. package/api/index.d.ts +1 -1
  4. package/api/index.js +3 -3
  5. package/dist/ApiList.d.ts +37 -37
  6. package/dist/ApiList.js +30 -30
  7. package/dist/SmartChainAssets.d.ts +181 -181
  8. package/dist/SmartChainAssets.js +181 -181
  9. package/dist/api/ApiEndpoints.d.ts +393 -393
  10. package/dist/api/ApiEndpoints.js +2 -2
  11. package/dist/api/ApiParser.d.ts +10 -10
  12. package/dist/api/ApiParser.js +134 -134
  13. package/dist/api/ApiTypes.d.ts +157 -157
  14. package/dist/api/ApiTypes.js +75 -75
  15. package/dist/api/SerializedAction.d.ts +40 -40
  16. package/dist/api/SerializedAction.js +59 -59
  17. package/dist/api/SwapperApi.d.ts +50 -50
  18. package/dist/api/SwapperApi.js +431 -431
  19. package/dist/api/index.d.ts +5 -5
  20. package/dist/api/index.js +24 -24
  21. package/dist/bitcoin/coinselect2/accumulative.d.ts +7 -7
  22. package/dist/bitcoin/coinselect2/accumulative.js +52 -52
  23. package/dist/bitcoin/coinselect2/blackjack.d.ts +7 -7
  24. package/dist/bitcoin/coinselect2/blackjack.js +38 -38
  25. package/dist/bitcoin/coinselect2/index.d.ts +20 -20
  26. package/dist/bitcoin/coinselect2/index.js +69 -69
  27. package/dist/bitcoin/coinselect2/utils.d.ts +82 -82
  28. package/dist/bitcoin/coinselect2/utils.js +158 -158
  29. package/dist/bitcoin/wallet/BitcoinWallet.d.ts +113 -113
  30. package/dist/bitcoin/wallet/BitcoinWallet.js +335 -335
  31. package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +116 -116
  32. package/dist/bitcoin/wallet/IBitcoinWallet.js +21 -21
  33. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +106 -106
  34. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +196 -196
  35. package/dist/enums/FeeType.d.ts +15 -15
  36. package/dist/enums/FeeType.js +19 -19
  37. package/dist/enums/SwapAmountType.d.ts +15 -15
  38. package/dist/enums/SwapAmountType.js +19 -19
  39. package/dist/enums/SwapDirection.d.ts +15 -15
  40. package/dist/enums/SwapDirection.js +19 -19
  41. package/dist/enums/SwapSide.d.ts +15 -15
  42. package/dist/enums/SwapSide.js +19 -19
  43. package/dist/enums/SwapType.d.ts +75 -75
  44. package/dist/enums/SwapType.js +79 -79
  45. package/dist/errors/IntermediaryError.d.ts +13 -13
  46. package/dist/errors/IntermediaryError.js +27 -27
  47. package/dist/errors/RequestError.d.ts +32 -32
  48. package/dist/errors/RequestError.js +54 -54
  49. package/dist/errors/UserError.d.ts +8 -8
  50. package/dist/errors/UserError.js +16 -16
  51. package/dist/events/UnifiedSwapEventListener.d.ts +24 -24
  52. package/dist/events/UnifiedSwapEventListener.js +138 -138
  53. package/dist/http/HttpUtils.d.ts +29 -29
  54. package/dist/http/HttpUtils.js +97 -97
  55. package/dist/http/paramcoders/IParamReader.d.ts +8 -8
  56. package/dist/http/paramcoders/IParamReader.js +2 -2
  57. package/dist/http/paramcoders/ParamDecoder.d.ts +44 -44
  58. package/dist/http/paramcoders/ParamDecoder.js +137 -137
  59. package/dist/http/paramcoders/ParamEncoder.d.ts +20 -20
  60. package/dist/http/paramcoders/ParamEncoder.js +36 -36
  61. package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -26
  62. package/dist/http/paramcoders/SchemaVerifier.js +145 -145
  63. package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -11
  64. package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -57
  65. package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +13 -13
  66. package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -26
  67. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +17 -17
  68. package/dist/http/paramcoders/client/StreamingFetchPromise.js +175 -175
  69. package/dist/index.d.ts +86 -86
  70. package/dist/index.js +159 -159
  71. package/dist/intermediaries/Intermediary.d.ts +178 -178
  72. package/dist/intermediaries/Intermediary.js +166 -166
  73. package/dist/intermediaries/IntermediaryDiscovery.d.ts +216 -216
  74. package/dist/intermediaries/IntermediaryDiscovery.js +424 -424
  75. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +607 -607
  76. package/dist/intermediaries/apis/IntermediaryAPI.js +764 -764
  77. package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +155 -155
  78. package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +137 -137
  79. package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -14
  80. package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -68
  81. package/dist/lnurl/LNURL.d.ts +102 -102
  82. package/dist/lnurl/LNURL.js +321 -321
  83. package/dist/prices/RedundantSwapPrice.d.ts +110 -110
  84. package/dist/prices/RedundantSwapPrice.js +222 -222
  85. package/dist/prices/SingleSwapPrice.d.ts +34 -34
  86. package/dist/prices/SingleSwapPrice.js +44 -44
  87. package/dist/prices/SwapPriceWithChain.d.ts +107 -107
  88. package/dist/prices/SwapPriceWithChain.js +128 -128
  89. package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -28
  90. package/dist/prices/abstract/ICachedSwapPrice.js +62 -62
  91. package/dist/prices/abstract/IPriceProvider.d.ts +81 -81
  92. package/dist/prices/abstract/IPriceProvider.js +74 -74
  93. package/dist/prices/abstract/ISwapPrice.d.ts +168 -168
  94. package/dist/prices/abstract/ISwapPrice.js +279 -279
  95. package/dist/prices/providers/BinancePriceProvider.d.ts +23 -23
  96. package/dist/prices/providers/BinancePriceProvider.js +30 -30
  97. package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +23 -23
  98. package/dist/prices/providers/CoinGeckoPriceProvider.js +29 -29
  99. package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +25 -25
  100. package/dist/prices/providers/CoinPaprikaPriceProvider.js +29 -29
  101. package/dist/prices/providers/CustomPriceProvider.d.ts +24 -24
  102. package/dist/prices/providers/CustomPriceProvider.js +35 -35
  103. package/dist/prices/providers/KrakenPriceProvider.d.ts +38 -38
  104. package/dist/prices/providers/KrakenPriceProvider.js +45 -45
  105. package/dist/prices/providers/OKXPriceProvider.d.ts +34 -34
  106. package/dist/prices/providers/OKXPriceProvider.js +29 -29
  107. package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +17 -17
  108. package/dist/prices/providers/abstract/ExchangePriceProvider.js +21 -21
  109. package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -7
  110. package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -12
  111. package/dist/storage/IUnifiedStorage.d.ts +127 -127
  112. package/dist/storage/IUnifiedStorage.js +2 -2
  113. package/dist/storage/UnifiedSwapStorage.d.ts +120 -120
  114. package/dist/storage/UnifiedSwapStorage.js +154 -154
  115. package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +63 -63
  116. package/dist/storage-browser/IndexedDBUnifiedStorage.js +298 -298
  117. package/dist/storage-browser/LocalStorageManager.d.ts +49 -49
  118. package/dist/storage-browser/LocalStorageManager.js +93 -93
  119. package/dist/swapper/Swapper.d.ts +765 -770
  120. package/dist/swapper/Swapper.js +1749 -1758
  121. package/dist/swapper/SwapperFactory.d.ts +135 -135
  122. package/dist/swapper/SwapperFactory.js +162 -162
  123. package/dist/swapper/SwapperUtils.d.ts +222 -222
  124. package/dist/swapper/SwapperUtils.js +519 -519
  125. package/dist/swapper/SwapperWithChain.d.ts +404 -404
  126. package/dist/swapper/SwapperWithChain.js +469 -469
  127. package/dist/swapper/SwapperWithSigner.d.ts +322 -322
  128. package/dist/swapper/SwapperWithSigner.js +318 -318
  129. package/dist/swaps/IAddressSwap.d.ts +22 -22
  130. package/dist/swaps/IAddressSwap.js +14 -14
  131. package/dist/swaps/IBTCWalletSwap.d.ts +73 -73
  132. package/dist/swaps/IBTCWalletSwap.js +18 -18
  133. package/dist/swaps/IClaimableSwap.d.ts +49 -49
  134. package/dist/swaps/IClaimableSwap.js +15 -15
  135. package/dist/swaps/IClaimableSwapWrapper.d.ts +15 -15
  136. package/dist/swaps/IClaimableSwapWrapper.js +2 -2
  137. package/dist/swaps/IRefundableSwap.d.ts +43 -43
  138. package/dist/swaps/IRefundableSwap.js +14 -14
  139. package/dist/swaps/ISwap.d.ts +453 -453
  140. package/dist/swaps/ISwap.js +371 -371
  141. package/dist/swaps/ISwapWithGasDrop.d.ts +21 -21
  142. package/dist/swaps/ISwapWithGasDrop.js +12 -12
  143. package/dist/swaps/ISwapWrapper.d.ts +295 -295
  144. package/dist/swaps/ISwapWrapper.js +373 -373
  145. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +98 -98
  146. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +126 -126
  147. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +139 -139
  148. package/dist/swaps/escrow_swaps/IEscrowSwap.js +172 -172
  149. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +129 -129
  150. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +167 -167
  151. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +107 -107
  152. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +130 -130
  153. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +162 -162
  154. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +190 -190
  155. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +64 -64
  156. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +82 -82
  157. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +547 -547
  158. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +1419 -1419
  159. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +192 -192
  160. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +432 -432
  161. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +650 -650
  162. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +1577 -1577
  163. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +237 -237
  164. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +525 -525
  165. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +491 -491
  166. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +1463 -1463
  167. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +204 -204
  168. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +406 -406
  169. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +446 -446
  170. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +1097 -1097
  171. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +68 -68
  172. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +117 -117
  173. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +127 -127
  174. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +256 -256
  175. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +252 -252
  176. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +535 -535
  177. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +73 -73
  178. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +155 -155
  179. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +134 -134
  180. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +286 -286
  181. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +694 -694
  182. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1687 -1687
  183. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +259 -259
  184. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +947 -947
  185. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +302 -302
  186. package/dist/swaps/trusted/ln/LnForGasSwap.js +625 -625
  187. package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +40 -40
  188. package/dist/swaps/trusted/ln/LnForGasWrapper.js +82 -82
  189. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +343 -343
  190. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +698 -698
  191. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +71 -71
  192. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +93 -93
  193. package/dist/types/AmountData.d.ts +10 -10
  194. package/dist/types/AmountData.js +2 -2
  195. package/dist/types/CustomPriceFunction.d.ts +11 -11
  196. package/dist/types/CustomPriceFunction.js +2 -2
  197. package/dist/types/PriceInfoType.d.ts +28 -28
  198. package/dist/types/PriceInfoType.js +57 -57
  199. package/dist/types/SwapExecutionAction.d.ts +195 -195
  200. package/dist/types/SwapExecutionAction.js +106 -106
  201. package/dist/types/SwapExecutionStep.d.ts +144 -144
  202. package/dist/types/SwapExecutionStep.js +87 -87
  203. package/dist/types/SwapStateInfo.d.ts +5 -5
  204. package/dist/types/SwapStateInfo.js +2 -2
  205. package/dist/types/SwapWithSigner.d.ts +17 -17
  206. package/dist/types/SwapWithSigner.js +43 -43
  207. package/dist/types/Token.d.ts +99 -99
  208. package/dist/types/Token.js +76 -76
  209. package/dist/types/TokenAmount.d.ts +75 -75
  210. package/dist/types/TokenAmount.js +85 -85
  211. package/dist/types/fees/Fee.d.ts +50 -50
  212. package/dist/types/fees/Fee.js +2 -2
  213. package/dist/types/fees/FeeBreakdown.d.ts +11 -11
  214. package/dist/types/fees/FeeBreakdown.js +2 -2
  215. package/dist/types/fees/PercentagePPM.d.ts +17 -17
  216. package/dist/types/fees/PercentagePPM.js +18 -18
  217. package/dist/types/lnurl/LNURLPay.d.ts +61 -61
  218. package/dist/types/lnurl/LNURLPay.js +31 -31
  219. package/dist/types/lnurl/LNURLWithdraw.d.ts +48 -48
  220. package/dist/types/lnurl/LNURLWithdraw.js +27 -27
  221. package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -24
  222. package/dist/types/wallets/LightningInvoiceCreateService.js +15 -15
  223. package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +23 -23
  224. package/dist/types/wallets/MinimalBitcoinWalletInterface.js +2 -2
  225. package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +9 -9
  226. package/dist/types/wallets/MinimalLightningNetworkWalletInterface.js +2 -2
  227. package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -1
  228. package/dist/utils/AutomaticClockDriftCorrection.js +70 -70
  229. package/dist/utils/BitcoinUtils.d.ts +18 -18
  230. package/dist/utils/BitcoinUtils.js +174 -174
  231. package/dist/utils/BitcoinWalletUtils.d.ts +7 -7
  232. package/dist/utils/BitcoinWalletUtils.js +14 -14
  233. package/dist/utils/Logger.d.ts +7 -7
  234. package/dist/utils/Logger.js +12 -12
  235. package/dist/utils/RetryUtils.d.ts +22 -22
  236. package/dist/utils/RetryUtils.js +67 -67
  237. package/dist/utils/SwapUtils.d.ts +88 -88
  238. package/dist/utils/SwapUtils.js +72 -72
  239. package/dist/utils/TimeoutUtils.d.ts +17 -17
  240. package/dist/utils/TimeoutUtils.js +55 -55
  241. package/dist/utils/TokenUtils.d.ts +19 -19
  242. package/dist/utils/TokenUtils.js +37 -37
  243. package/dist/utils/TypeUtils.d.ts +7 -7
  244. package/dist/utils/TypeUtils.js +2 -2
  245. package/dist/utils/Utils.d.ts +69 -69
  246. package/dist/utils/Utils.js +214 -214
  247. package/package.json +46 -46
  248. package/src/SmartChainAssets.ts +186 -186
  249. package/src/api/ApiEndpoints.ts +427 -427
  250. package/src/api/ApiParser.ts +138 -138
  251. package/src/api/ApiTypes.ts +229 -229
  252. package/src/api/SerializedAction.ts +97 -97
  253. package/src/api/SwapperApi.ts +545 -545
  254. package/src/api/index.ts +5 -5
  255. package/src/bitcoin/coinselect2/accumulative.ts +69 -69
  256. package/src/bitcoin/coinselect2/blackjack.ts +50 -50
  257. package/src/bitcoin/coinselect2/index.ts +93 -93
  258. package/src/bitcoin/coinselect2/utils.ts +236 -236
  259. package/src/bitcoin/wallet/BitcoinWallet.ts +439 -439
  260. package/src/bitcoin/wallet/IBitcoinWallet.ts +140 -140
  261. package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +225 -225
  262. package/src/enums/FeeType.ts +15 -15
  263. package/src/enums/SwapAmountType.ts +16 -16
  264. package/src/enums/SwapDirection.ts +15 -15
  265. package/src/enums/SwapSide.ts +16 -16
  266. package/src/enums/SwapType.ts +75 -75
  267. package/src/errors/IntermediaryError.ts +28 -28
  268. package/src/errors/RequestError.ts +64 -64
  269. package/src/errors/UserError.ts +15 -15
  270. package/src/events/UnifiedSwapEventListener.ts +181 -181
  271. package/src/http/HttpUtils.ts +97 -97
  272. package/src/http/paramcoders/IParamReader.ts +9 -9
  273. package/src/http/paramcoders/ParamDecoder.ts +145 -145
  274. package/src/http/paramcoders/ParamEncoder.ts +40 -40
  275. package/src/http/paramcoders/SchemaVerifier.ts +153 -153
  276. package/src/http/paramcoders/client/ResponseParamDecoder.ts +57 -57
  277. package/src/http/paramcoders/client/StreamParamEncoder.ts +28 -28
  278. package/src/http/paramcoders/client/StreamingFetchPromise.ts +194 -194
  279. package/src/index.ts +141 -141
  280. package/src/intermediaries/Intermediary.ts +280 -280
  281. package/src/intermediaries/IntermediaryDiscovery.ts +548 -548
  282. package/src/intermediaries/apis/IntermediaryAPI.ts +1247 -1247
  283. package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -69
  284. package/src/lnurl/LNURL.ts +402 -402
  285. package/src/prices/RedundantSwapPrice.ts +264 -264
  286. package/src/prices/SingleSwapPrice.ts +50 -50
  287. package/src/prices/SwapPriceWithChain.ts +194 -194
  288. package/src/prices/abstract/ICachedSwapPrice.ts +85 -85
  289. package/src/prices/abstract/IPriceProvider.ts +127 -127
  290. package/src/prices/abstract/ISwapPrice.ts +390 -390
  291. package/src/prices/providers/BinancePriceProvider.ts +48 -48
  292. package/src/prices/providers/CoinGeckoPriceProvider.ts +46 -46
  293. package/src/prices/providers/CoinPaprikaPriceProvider.ts +49 -49
  294. package/src/prices/providers/CustomPriceProvider.ts +40 -40
  295. package/src/prices/providers/KrakenPriceProvider.ts +83 -83
  296. package/src/prices/providers/OKXPriceProvider.ts +59 -59
  297. package/src/prices/providers/abstract/ExchangePriceProvider.ts +31 -31
  298. package/src/prices/providers/abstract/HttpPriceProvider.ts +14 -14
  299. package/src/storage/IUnifiedStorage.ts +136 -136
  300. package/src/storage/UnifiedSwapStorage.ts +175 -175
  301. package/src/storage-browser/IndexedDBUnifiedStorage.ts +350 -350
  302. package/src/storage-browser/LocalStorageManager.ts +106 -106
  303. package/src/swapper/Swapper.ts +2557 -2570
  304. package/src/swapper/SwapperFactory.ts +307 -307
  305. package/src/swapper/SwapperUtils.ts +610 -610
  306. package/src/swapper/SwapperWithChain.ts +707 -707
  307. package/src/swapper/SwapperWithSigner.ts +511 -511
  308. package/src/swaps/IAddressSwap.ts +30 -30
  309. package/src/swaps/IBTCWalletSwap.ts +92 -92
  310. package/src/swaps/IClaimableSwap.ts +65 -65
  311. package/src/swaps/IClaimableSwapWrapper.ts +17 -17
  312. package/src/swaps/IRefundableSwap.ts +58 -58
  313. package/src/swaps/ISwap.ts +775 -775
  314. package/src/swaps/ISwapWithGasDrop.ts +25 -25
  315. package/src/swaps/ISwapWrapper.ts +564 -564
  316. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +217 -217
  317. package/src/swaps/escrow_swaps/IEscrowSwap.ts +271 -271
  318. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +284 -284
  319. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +172 -172
  320. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +300 -300
  321. package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +107 -107
  322. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +1670 -1671
  323. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +603 -603
  324. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +1883 -1883
  325. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +752 -752
  326. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +1753 -1753
  327. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +612 -612
  328. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +1327 -1327
  329. package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +138 -138
  330. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +304 -304
  331. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +787 -787
  332. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +206 -206
  333. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +403 -403
  334. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +2148 -2148
  335. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +1238 -1238
  336. package/src/swaps/trusted/ln/LnForGasSwap.ts +753 -753
  337. package/src/swaps/trusted/ln/LnForGasWrapper.ts +90 -90
  338. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +843 -843
  339. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +133 -133
  340. package/src/types/AmountData.ts +9 -9
  341. package/src/types/CustomPriceFunction.ts +11 -11
  342. package/src/types/PriceInfoType.ts +66 -66
  343. package/src/types/SwapExecutionAction.ts +323 -323
  344. package/src/types/SwapExecutionStep.ts +224 -224
  345. package/src/types/SwapStateInfo.ts +6 -6
  346. package/src/types/SwapWithSigner.ts +61 -61
  347. package/src/types/Token.ts +163 -163
  348. package/src/types/TokenAmount.ts +167 -167
  349. package/src/types/fees/Fee.ts +56 -56
  350. package/src/types/fees/FeeBreakdown.ts +11 -11
  351. package/src/types/fees/PercentagePPM.ts +26 -26
  352. package/src/types/lnurl/LNURLPay.ts +79 -79
  353. package/src/types/lnurl/LNURLWithdraw.ts +61 -61
  354. package/src/types/wallets/LightningInvoiceCreateService.ts +30 -30
  355. package/src/types/wallets/MinimalBitcoinWalletInterface.ts +21 -21
  356. package/src/types/wallets/MinimalLightningNetworkWalletInterface.ts +9 -9
  357. package/src/utils/AutomaticClockDriftCorrection.ts +71 -71
  358. package/src/utils/BitcoinUtils.ts +164 -164
  359. package/src/utils/BitcoinWalletUtils.ts +15 -15
  360. package/src/utils/Logger.ts +14 -14
  361. package/src/utils/RetryUtils.ts +78 -78
  362. package/src/utils/SwapUtils.ts +99 -99
  363. package/src/utils/TimeoutUtils.ts +49 -49
  364. package/src/utils/TokenUtils.ts +33 -33
  365. package/src/utils/TypeUtils.ts +8 -8
  366. package/src/utils/Utils.ts +221 -221
@@ -1,1097 +1,1097 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.IToBTCSwap = exports.ToBTCSwapState = exports.isIToBTCSwapInit = void 0;
4
- const base_1 = require("@atomiqlabs/base");
5
- const IntermediaryAPI_1 = require("../../../intermediaries/apis/IntermediaryAPI");
6
- const IntermediaryError_1 = require("../../../errors/IntermediaryError");
7
- const Utils_1 = require("../../../utils/Utils");
8
- const IEscrowSelfInitSwap_1 = require("../IEscrowSelfInitSwap");
9
- const FeeType_1 = require("../../../enums/FeeType");
10
- const PercentagePPM_1 = require("../../../types/fees/PercentagePPM");
11
- const TokenAmount_1 = require("../../../types/TokenAmount");
12
- const TimeoutUtils_1 = require("../../../utils/TimeoutUtils");
13
- function isIToBTCSwapInit(obj) {
14
- return typeof (obj.networkFee) === "bigint" &&
15
- typeof (obj.networkFeeBtc) === "bigint" &&
16
- (obj.signatureData == null || (typeof (obj.signatureData) === 'object' &&
17
- typeof (obj.signatureData.prefix) === "string" &&
18
- typeof (obj.signatureData.timeout) === "string" &&
19
- typeof (obj.signatureData.signature) === "string")) &&
20
- typeof (obj.data) === 'object' &&
21
- (0, IEscrowSelfInitSwap_1.isIEscrowSelfInitSwapInit)(obj);
22
- }
23
- exports.isIToBTCSwapInit = isIToBTCSwapInit;
24
- /**
25
- * State enum for escrow-based Smart chain -> Bitcoin (on-chain & lightning) swaps
26
- *
27
- * @category Swaps/Smart chain → Bitcoin
28
- */
29
- var ToBTCSwapState;
30
- (function (ToBTCSwapState) {
31
- /**
32
- * Intermediary (LP) was unable to process the swap and the funds were refunded on the
33
- * source chain
34
- */
35
- ToBTCSwapState[ToBTCSwapState["REFUNDED"] = -3] = "REFUNDED";
36
- /**
37
- * Swap has expired for good and there is no way how it can be executed anymore
38
- */
39
- ToBTCSwapState[ToBTCSwapState["QUOTE_EXPIRED"] = -2] = "QUOTE_EXPIRED";
40
- /**
41
- * A swap is almost expired, and it should be presented to the user as expired, though
42
- * there is still a chance that it will be processed
43
- */
44
- ToBTCSwapState[ToBTCSwapState["QUOTE_SOFT_EXPIRED"] = -1] = "QUOTE_SOFT_EXPIRED";
45
- /**
46
- * Swap was created, use the {@link IToBTCSwap.commit} or {@link IToBTCSwap.txsCommit} to
47
- * initiate it by creating the swap escrow on the source chain
48
- */
49
- ToBTCSwapState[ToBTCSwapState["CREATED"] = 0] = "CREATED";
50
- /**
51
- * Swap escrow was initiated (committed) on the source chain, the intermediary (LP) will
52
- * now process the swap. You can wait till that happens with the {@link IToBTCSwap.waitForPayment}
53
- * function.
54
- */
55
- ToBTCSwapState[ToBTCSwapState["COMMITED"] = 1] = "COMMITED";
56
- /**
57
- * The intermediary (LP) has processed the transaction and sent out the funds on the destination chain,
58
- * but hasn't yet settled the escrow on the source chain.
59
- */
60
- ToBTCSwapState[ToBTCSwapState["SOFT_CLAIMED"] = 2] = "SOFT_CLAIMED";
61
- /**
62
- * Swap was successfully settled by the intermediary (LP) on the source chain
63
- */
64
- ToBTCSwapState[ToBTCSwapState["CLAIMED"] = 3] = "CLAIMED";
65
- /**
66
- * Intermediary (LP) was unable to process the swap and the swap escrow on the source chain
67
- * is refundable, call {@link IToBTCSwap.refund} or {@link IToBTCSwap.txsRefund} to refund
68
- */
69
- ToBTCSwapState[ToBTCSwapState["REFUNDABLE"] = 4] = "REFUNDABLE";
70
- })(ToBTCSwapState = exports.ToBTCSwapState || (exports.ToBTCSwapState = {}));
71
- const ToBTCSwapStateDescription = {
72
- [ToBTCSwapState.REFUNDED]: "Intermediary (LP) was unable to process the swap and the funds were refunded on the source chain",
73
- [ToBTCSwapState.QUOTE_EXPIRED]: "Swap has expired for good and there is no way how it can be executed anymore",
74
- [ToBTCSwapState.QUOTE_SOFT_EXPIRED]: "A swap is expired, though there is still a chance that it will be processed",
75
- [ToBTCSwapState.CREATED]: "Swap was created, initiate it by creating the swap escrow on the source chain",
76
- [ToBTCSwapState.COMMITED]: "Swap escrow was initiated (committed) on the source chain, the intermediary (LP) will now process the swap.",
77
- [ToBTCSwapState.SOFT_CLAIMED]: "The intermediary (LP) has processed the transaction and sent out the funds on the destination chain, but hasn't yet settled the escrow on the source chain.",
78
- [ToBTCSwapState.CLAIMED]: "Swap was successfully settled by the intermediary (LP) on the source chain",
79
- [ToBTCSwapState.REFUNDABLE]: "Intermediary (LP) was unable to process the swap and the swap escrow on the source chain is refundable."
80
- };
81
- /**
82
- * Base class for escrow-based Smart chain -> Bitcoin (on-chain & lightning) swaps
83
- *
84
- * @category Swaps/Smart chain → Bitcoin
85
- */
86
- class IToBTCSwap extends IEscrowSelfInitSwap_1.IEscrowSelfInitSwap {
87
- constructor(wrapper, initOrObject) {
88
- super(wrapper, initOrObject);
89
- /**
90
- * @internal
91
- */
92
- this.swapStateDescription = ToBTCSwapStateDescription;
93
- /**
94
- * @internal
95
- */
96
- this.swapStateName = (state) => ToBTCSwapState[state];
97
- if (isIToBTCSwapInit(initOrObject)) {
98
- this._state = ToBTCSwapState.CREATED;
99
- this.networkFee = initOrObject.networkFee;
100
- this.networkFeeBtc = initOrObject.networkFeeBtc;
101
- this._data = initOrObject.data;
102
- this.signatureData = initOrObject.signatureData;
103
- }
104
- else {
105
- this.networkFee = (0, Utils_1.toBigInt)(initOrObject.networkFee);
106
- this.networkFeeBtc = (0, Utils_1.toBigInt)(initOrObject.networkFeeBtc);
107
- }
108
- }
109
- /**
110
- * @inheritDoc
111
- * @internal
112
- */
113
- getSwapData() {
114
- return this._data;
115
- }
116
- /**
117
- * @inheritDoc
118
- * @internal
119
- */
120
- upgradeVersion() {
121
- if (this.version == null) {
122
- switch (this._state) {
123
- case -2:
124
- this._state = ToBTCSwapState.REFUNDED;
125
- break;
126
- case -1:
127
- this._state = ToBTCSwapState.QUOTE_EXPIRED;
128
- break;
129
- case 0:
130
- this._state = ToBTCSwapState.CREATED;
131
- break;
132
- case 1:
133
- this._state = ToBTCSwapState.COMMITED;
134
- break;
135
- case 2:
136
- this._state = ToBTCSwapState.CLAIMED;
137
- break;
138
- case 3:
139
- this._state = ToBTCSwapState.REFUNDABLE;
140
- break;
141
- }
142
- this.version = 1;
143
- }
144
- }
145
- /**
146
- * @inheritDoc
147
- * @internal
148
- */
149
- tryRecomputeSwapPrice() {
150
- const output = this.getOutput();
151
- if (output.rawAmount != null) {
152
- if (this.swapFeeBtc == null) {
153
- this.swapFeeBtc = this.swapFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
154
- }
155
- if (this.networkFeeBtc == null) {
156
- this.networkFeeBtc = this.networkFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
157
- }
158
- }
159
- super.tryRecomputeSwapPrice();
160
- }
161
- /**
162
- * Returns the payment hash identifier to be sent to the LP for getStatus and getRefund
163
- * @internal
164
- */
165
- getLpIdentifier() {
166
- return this.getClaimHash();
167
- }
168
- //////////////////////////////
169
- //// Getters & utils
170
- /**
171
- * @inheritDoc
172
- */
173
- getInputAddress() {
174
- return this._getInitiator();
175
- }
176
- /**
177
- * @inheritDoc
178
- */
179
- getInputTxId() {
180
- return this._commitTxId ?? null;
181
- }
182
- /**
183
- * @inheritDoc
184
- */
185
- requiresAction() {
186
- return this.isRefundable();
187
- }
188
- /**
189
- * @inheritDoc
190
- */
191
- isFinished() {
192
- return this._state === ToBTCSwapState.CLAIMED || this._state === ToBTCSwapState.REFUNDED || this._state === ToBTCSwapState.QUOTE_EXPIRED;
193
- }
194
- /**
195
- * @inheritDoc
196
- */
197
- isRefundable() {
198
- return this._state === ToBTCSwapState.REFUNDABLE;
199
- }
200
- /**
201
- * @inheritDoc
202
- */
203
- isQuoteExpired() {
204
- return this._state === ToBTCSwapState.QUOTE_EXPIRED;
205
- }
206
- /**
207
- * @inheritDoc
208
- */
209
- isQuoteSoftExpired() {
210
- return this._state === ToBTCSwapState.QUOTE_EXPIRED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED;
211
- }
212
- /**
213
- * @inheritDoc
214
- */
215
- isSuccessful() {
216
- return this._state === ToBTCSwapState.CLAIMED;
217
- }
218
- /**
219
- * @inheritDoc
220
- */
221
- isFailed() {
222
- return this._state === ToBTCSwapState.REFUNDED;
223
- }
224
- /**
225
- * @inheritDoc
226
- */
227
- isInProgress() {
228
- return this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.SOFT_CLAIMED;
229
- }
230
- /**
231
- * Returns the time (in UNIX milliseconds) at which the swap expires and the user is able to unilaterally
232
- * refund it with the {@link refund} or {@link txsRefund} function.
233
- */
234
- getExpiry() {
235
- return Number(this._data.getExpiry()) * 1000;
236
- }
237
- /**
238
- * @inheritDoc
239
- * @internal
240
- */
241
- _getInitiator() {
242
- return this._data.getOfferer();
243
- }
244
- //////////////////////////////
245
- //// Amounts & fees
246
- /**
247
- * Returns the swap fee charged by the intermediary (LP) on this swap
248
- *
249
- * @internal
250
- */
251
- getSwapFee() {
252
- if (this.pricingInfo == null)
253
- throw new Error("No pricing info known, cannot estimate fee!");
254
- const feeWithoutBaseFee = this.swapFeeBtc - this.pricingInfo.satsBaseFee;
255
- const output = this.getOutput();
256
- const swapFeePPM = output.rawAmount == null ? 0n : feeWithoutBaseFee * 1000000n / output.rawAmount;
257
- const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.swapFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
258
- return {
259
- amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.swapFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
260
- amountInDstToken,
261
- currentUsdValue: amountInDstToken.currentUsdValue,
262
- usdValue: amountInDstToken.usdValue,
263
- pastUsdValue: amountInDstToken.pastUsdValue,
264
- composition: {
265
- base: (0, TokenAmount_1.toTokenAmount)(this.pricingInfo.satsBaseFee, this.outputToken, this.wrapper._prices, this.pricingInfo),
266
- percentage: (0, PercentagePPM_1.ppmToPercentage)(swapFeePPM)
267
- }
268
- };
269
- }
270
- /**
271
- * Returns network fee for on the destination chain for the swap
272
- *
273
- * @internal
274
- */
275
- getNetworkFee() {
276
- const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.networkFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
277
- return {
278
- amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.networkFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
279
- amountInDstToken,
280
- currentUsdValue: amountInDstToken.currentUsdValue,
281
- usdValue: amountInDstToken.usdValue,
282
- pastUsdValue: amountInDstToken.pastUsdValue
283
- };
284
- }
285
- /**
286
- * @inheritDoc
287
- */
288
- getFee() {
289
- const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.swapFeeBtc + this.networkFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
290
- return {
291
- amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.swapFee + this.networkFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
292
- amountInDstToken,
293
- currentUsdValue: amountInDstToken.currentUsdValue,
294
- usdValue: amountInDstToken.usdValue,
295
- pastUsdValue: amountInDstToken.pastUsdValue
296
- };
297
- }
298
- /**
299
- * @inheritDoc
300
- */
301
- getFeeBreakdown() {
302
- return [
303
- {
304
- type: FeeType_1.FeeType.SWAP,
305
- fee: this.getSwapFee()
306
- },
307
- {
308
- type: FeeType_1.FeeType.NETWORK_OUTPUT,
309
- fee: this.getNetworkFee()
310
- }
311
- ];
312
- }
313
- /**
314
- * @inheritDoc
315
- */
316
- getInputToken() {
317
- return this.wrapper._tokens[this._data.getToken()];
318
- }
319
- /**
320
- * @inheritDoc
321
- */
322
- getInput() {
323
- return (0, TokenAmount_1.toTokenAmount)(this._data.getAmount(), this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo);
324
- }
325
- /**
326
- * @inheritDoc
327
- */
328
- getInputWithoutFee() {
329
- return (0, TokenAmount_1.toTokenAmount)(this._data.getAmount() - (this.swapFee + this.networkFee), this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo);
330
- }
331
- /**
332
- * Checks if the initiator/sender on the source chain has enough balance to go through with the swap
333
- */
334
- async hasEnoughBalance() {
335
- const [balance, commitFee] = await Promise.all([
336
- this._contract.getBalance(this._getInitiator(), this._data.getToken(), false),
337
- this._data.getToken() === this.wrapper._chain.getNativeCurrencyAddress() ? this.getCommitFee() : Promise.resolve(null)
338
- ]);
339
- let required = this._data.getAmount();
340
- if (commitFee != null)
341
- required = required + commitFee;
342
- return {
343
- enoughBalance: balance >= required,
344
- balance: (0, TokenAmount_1.toTokenAmount)(balance, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
345
- required: (0, TokenAmount_1.toTokenAmount)(required, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo)
346
- };
347
- }
348
- /**
349
- * Checks if the initiator/sender on the source chain has enough native token balance
350
- * to cover the transaction fee of initiating the swap
351
- */
352
- async hasEnoughForTxFees() {
353
- const [balance, commitFee] = await Promise.all([
354
- this._contract.getBalance(this._getInitiator(), this.wrapper._chain.getNativeCurrencyAddress(), false),
355
- this.getCommitFee()
356
- ]);
357
- return {
358
- enoughBalance: balance >= commitFee,
359
- balance: (0, TokenAmount_1.toTokenAmount)(balance, this.wrapper._getNativeToken(), this.wrapper._prices),
360
- required: (0, TokenAmount_1.toTokenAmount)(commitFee, this.wrapper._getNativeToken(), this.wrapper._prices)
361
- };
362
- }
363
- //////////////////////////////
364
- //// Execution
365
- /**
366
- * Executes the swap with the provided smart chain wallet/signer
367
- *
368
- * @param signer Smart chain wallet/signer to use to sign the transaction on the source chain
369
- * @param callbacks Callbacks to track the progress of the swap
370
- * @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
371
- *
372
- * @returns {boolean} Whether the swap was successfully processed by the LP, in case `false` is returned
373
- * the user can refund their funds back on the source chain by calling {@link refund}
374
- */
375
- async execute(signer, callbacks, options) {
376
- if (this._state === ToBTCSwapState.QUOTE_EXPIRED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED)
377
- throw new Error("Quote expired");
378
- if (this._state === ToBTCSwapState.REFUNDED)
379
- throw new Error("Swap already refunded");
380
- if (this._state === ToBTCSwapState.REFUNDABLE)
381
- throw new Error("Swap refundable, refund with swap.refund()");
382
- if (this._state === ToBTCSwapState.SOFT_CLAIMED || this._state === ToBTCSwapState.CLAIMED)
383
- throw new Error("Swap already settled!");
384
- if (this._state === ToBTCSwapState.CREATED) {
385
- const txId = await this.commit(signer, options?.abortSignal, false, callbacks?.onSourceTransactionSent);
386
- if (callbacks?.onSourceTransactionConfirmed != null)
387
- callbacks.onSourceTransactionConfirmed(txId);
388
- }
389
- // @ts-ignore
390
- if (this._state === ToBTCSwapState.CLAIMED || this._state === ToBTCSwapState.SOFT_CLAIMED)
391
- return true;
392
- if (this._state === ToBTCSwapState.COMMITED) {
393
- const success = await this.waitForPayment(options?.maxWaitTillSwapProcessedSeconds ?? 120, options?.paymentCheckIntervalSeconds, options?.abortSignal);
394
- if (success) {
395
- if (callbacks?.onSwapSettled != null)
396
- callbacks.onSwapSettled(this.getOutputTxId());
397
- return true;
398
- }
399
- else {
400
- return false;
401
- }
402
- }
403
- throw new Error("Unexpected state reached!");
404
- }
405
- /**
406
- * @internal
407
- */
408
- async _getExecutionStatus() {
409
- const state = this._state;
410
- let sourcePaymentStatus = "inactive";
411
- let destinationPayoutStatus = "inactive";
412
- let refundStatus = "inactive";
413
- let buildCurrentAction = async () => undefined;
414
- switch (state) {
415
- case ToBTCSwapState.CREATED:
416
- const quoteValid = await this._verifyQuoteValid();
417
- sourcePaymentStatus = quoteValid ? "awaiting" : "soft_expired";
418
- if (this.signatureData != null && quoteValid) {
419
- buildCurrentAction = this._buildInitSmartChainTxAction.bind(this);
420
- }
421
- break;
422
- case ToBTCSwapState.QUOTE_SOFT_EXPIRED:
423
- sourcePaymentStatus = "soft_expired";
424
- break;
425
- case ToBTCSwapState.QUOTE_EXPIRED:
426
- sourcePaymentStatus = "expired";
427
- break;
428
- case ToBTCSwapState.COMMITED:
429
- sourcePaymentStatus = "confirmed";
430
- destinationPayoutStatus = "waiting_lp";
431
- buildCurrentAction = this._buildWaitLpAction.bind(this);
432
- break;
433
- case ToBTCSwapState.SOFT_CLAIMED:
434
- sourcePaymentStatus = "confirmed";
435
- destinationPayoutStatus = "soft_settled";
436
- break;
437
- case ToBTCSwapState.CLAIMED:
438
- sourcePaymentStatus = "confirmed";
439
- destinationPayoutStatus = "settled";
440
- break;
441
- case ToBTCSwapState.REFUNDABLE:
442
- sourcePaymentStatus = "confirmed";
443
- destinationPayoutStatus = "expired";
444
- refundStatus = "awaiting";
445
- buildCurrentAction = this._buildRefundSmartChainTxAction.bind(this);
446
- break;
447
- case ToBTCSwapState.REFUNDED:
448
- sourcePaymentStatus = "confirmed";
449
- destinationPayoutStatus = "expired";
450
- refundStatus = "refunded";
451
- break;
452
- }
453
- return {
454
- steps: [
455
- {
456
- type: "Payment",
457
- side: "source",
458
- chain: this.chainIdentifier,
459
- title: "Source payment",
460
- description: `Initiate the swap by funding the escrow on the ${this.chainIdentifier} side`,
461
- status: sourcePaymentStatus,
462
- initTxId: this._commitTxId,
463
- settleTxId: this._claimTxId
464
- },
465
- {
466
- type: "Settlement",
467
- side: "destination",
468
- chain: this.outputToken.chainId,
469
- title: "Destination payout",
470
- description: `Wait for the LP to process the swap and send the payout on the ${this.outputToken.chainId} side`,
471
- status: destinationPayoutStatus,
472
- initTxId: destinationPayoutStatus === "settled" || destinationPayoutStatus === "soft_settled" ? this.getOutputTxId() : undefined,
473
- settleTxId: destinationPayoutStatus === "settled" ? this.getOutputTxId() : undefined,
474
- },
475
- {
476
- type: "Refund",
477
- side: "source",
478
- chain: this.chainIdentifier,
479
- title: "Source refund",
480
- description: `Refund escrowed funds on the ${this.chainIdentifier} side, after LP failed to execute`,
481
- status: refundStatus,
482
- refundTxId: this._refundTxId
483
- }
484
- ],
485
- buildCurrentAction,
486
- state
487
- };
488
- }
489
- /**
490
- * @inheritDoc
491
- * @internal
492
- */
493
- async _submitExecutionTransactions(txs, abortSignal, requiredStates, idempotent) {
494
- const parsedTxs = [];
495
- for (let tx of txs) {
496
- parsedTxs.push(typeof (tx) === "string" ? await this.wrapper._chain.deserializeSignedTx(tx) : tx);
497
- }
498
- if (idempotent) {
499
- // Handle idempotent calls
500
- if (this.wrapper._chain.getTxId != null) {
501
- const txIds = await Promise.all(parsedTxs.map(tx => this.wrapper._chain.getTxId(tx)));
502
- const foundTxId = txIds.find(txId => this._commitTxId === txId || this._refundTxId === txId);
503
- if (foundTxId != null)
504
- return txIds;
505
- }
506
- }
507
- if (requiredStates != null && !requiredStates.includes(this._state))
508
- throw new Error("Swap state has changed before transactions were submitted!");
509
- if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED) {
510
- if (!await this._verifyQuoteValid())
511
- throw new Error("Quote is already expired!");
512
- const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
513
- await this.waitTillCommited(abortSignal);
514
- return txIds;
515
- }
516
- if (this._state === ToBTCSwapState.REFUNDABLE) {
517
- const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
518
- await this.waitTillRefunded(abortSignal);
519
- return txIds;
520
- }
521
- throw new Error("Invalid swap state for transaction submission!");
522
- }
523
- /**
524
- * @internal
525
- */
526
- async _buildInitSmartChainTxAction(actionOptions) {
527
- return {
528
- type: "SignSmartChainTransaction",
529
- name: "Initiate swap",
530
- description: `Initiates the swap by commiting the funds to the escrow on the ${this.chainIdentifier} side`,
531
- chain: this.chainIdentifier,
532
- txs: await this.prepareTransactions(this.txsCommit(actionOptions?.skipChecks)),
533
- submitTransactions: async (txs, abortSignal, idempotent) => {
534
- return this._submitExecutionTransactions(txs, abortSignal, [ToBTCSwapState.CREATED, ToBTCSwapState.QUOTE_SOFT_EXPIRED], idempotent);
535
- },
536
- requiredSigner: this._getInitiator()
537
- };
538
- }
539
- /**
540
- * @internal
541
- */
542
- async _buildWaitLpAction() {
543
- return {
544
- type: "Wait",
545
- name: "Awaiting LP payout",
546
- description: "Wait for the intermediary to process the swap and either send the payout or make the swap refundable",
547
- pollTimeSeconds: 5,
548
- expectedTimeSeconds: 10,
549
- wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
550
- await this.waitForPayment(maxWaitTimeSeconds, pollIntervalSeconds, abortSignal);
551
- }
552
- };
553
- }
554
- /**
555
- * @internal
556
- */
557
- async _buildRefundSmartChainTxAction(actionOptions) {
558
- const signerAddress = await this.wrapper._getSignerAddress(actionOptions?.refundSmartChainSigner);
559
- return {
560
- type: "SignSmartChainTransaction",
561
- name: "Refund",
562
- description: "Refund the swap after it failed to execute",
563
- chain: this.chainIdentifier,
564
- txs: await this.prepareTransactions(this.txsRefund(actionOptions?.refundSmartChainSigner)),
565
- submitTransactions: async (txs, abortSignal, idempotent) => {
566
- return this._submitExecutionTransactions(txs, abortSignal, [ToBTCSwapState.REFUNDABLE], idempotent);
567
- },
568
- requiredSigner: signerAddress ?? this._getInitiator()
569
- };
570
- }
571
- /**
572
- * @inheritDoc
573
- *
574
- * @param options.skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
575
- * (this is handled on swap creation, if you commit right after quoting, you can use `skipChecks=true`)
576
- * @param options.refundSmartChainSigner Optional smart chain signer to use when creating refunds transactions
577
- */
578
- async getExecutionAction(options) {
579
- const executionStatus = await this._getExecutionStatus();
580
- return executionStatus.buildCurrentAction(options);
581
- }
582
- /**
583
- * @inheritDoc
584
- */
585
- async getExecutionStatus(options) {
586
- const executionStatus = await this._getExecutionStatus();
587
- return {
588
- steps: executionStatus.steps,
589
- currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(options),
590
- stateInfo: this._getStateInfo(executionStatus.state)
591
- };
592
- }
593
- /**
594
- * @inheritDoc
595
- */
596
- async getExecutionSteps() {
597
- return (await this._getExecutionStatus()).steps;
598
- }
599
- //////////////////////////////
600
- //// Commit
601
- /**
602
- * @inheritDoc
603
- *
604
- * @throws {Error} When in invalid state (not {@link ToBTCSwapState.CREATED})
605
- */
606
- async txsCommit(skipChecks) {
607
- if (this._state !== ToBTCSwapState.CREATED && (!skipChecks || this._state !== ToBTCSwapState.QUOTE_SOFT_EXPIRED))
608
- throw new Error("Must be in CREATED state!");
609
- if (this.signatureData == null)
610
- throw new Error("Init signature data not known, cannot commit!");
611
- if (!this.initiated) {
612
- this.initiated = true;
613
- await this._saveAndEmit();
614
- }
615
- return await this._contract.txsInit(this._getInitiator(), this._data, this.signatureData, skipChecks, this.feeRate).catch(e => Promise.reject(e instanceof base_1.SignatureVerificationError ? new Error("Request timed out") : e));
616
- }
617
- /**
618
- * @inheritDoc
619
- *
620
- * @throws {Error} If invalid signer is provided that doesn't match the swap data
621
- */
622
- async commit(_signer, abortSignal, skipChecks, onBeforeTxSent) {
623
- const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
624
- this.checkSigner(signer);
625
- const txs = await this.txsCommit(skipChecks);
626
- let txCount = 0;
627
- const result = await this.wrapper._chain.sendAndConfirm(signer, txs, true, abortSignal, false, (txId, rawTx) => {
628
- txCount++;
629
- if (onBeforeTxSent != null && txCount === txs.length)
630
- onBeforeTxSent(txId);
631
- return Promise.resolve();
632
- });
633
- this._commitTxId = result[result.length - 1];
634
- if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.QUOTE_EXPIRED) {
635
- await this._saveAndEmit(ToBTCSwapState.COMMITED);
636
- }
637
- return this._commitTxId;
638
- }
639
- /**
640
- * @inheritDoc
641
- *
642
- * @throws {Error} If swap is not in the correct state (must be {@link ToBTCSwapState.CREATED})
643
- */
644
- async waitTillCommited(abortSignal) {
645
- if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.CLAIMED)
646
- return Promise.resolve();
647
- if (this._state !== ToBTCSwapState.CREATED && this._state !== ToBTCSwapState.QUOTE_SOFT_EXPIRED)
648
- throw new Error("Invalid state (not CREATED)");
649
- const abortController = (0, Utils_1.extendAbortController)(abortSignal);
650
- let result;
651
- try {
652
- result = await Promise.race([
653
- this.watchdogWaitTillCommited(undefined, abortController.signal),
654
- this.waitTillState(ToBTCSwapState.COMMITED, "gte", abortController.signal).then(() => 0)
655
- ]);
656
- abortController.abort();
657
- }
658
- catch (e) {
659
- abortController.abort();
660
- throw e;
661
- }
662
- if (result === 0) {
663
- this.logger.debug("waitTillCommited(): Resolved from state change");
664
- }
665
- else if (result != null) {
666
- this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
667
- }
668
- if (result === null) {
669
- this.logger.debug("waitTillCommited(): Resolved from watchdog - signature expiry");
670
- if (this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.CREATED) {
671
- await this._saveAndEmit(ToBTCSwapState.QUOTE_EXPIRED);
672
- }
673
- throw new Error("Quote expired while waiting for transaction confirmation!");
674
- }
675
- if (this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_EXPIRED) {
676
- if (typeof (result) === "object" && result.getInitTxId != null && this._commitTxId == null)
677
- this._commitTxId = await result.getInitTxId();
678
- await this._saveAndEmit(ToBTCSwapState.COMMITED);
679
- }
680
- }
681
- //////////////////////////////
682
- //// Payment
683
- /**
684
- * Waits till the swap is processed by the intermediary (LP)
685
- *
686
- * @param checkIntervalSeconds How often to poll the intermediary for status (5 seconds default)
687
- * @param abortSignal Abort signal
688
- * @internal
689
- */
690
- async waitTillIntermediarySwapProcessed(checkIntervalSeconds, abortSignal) {
691
- if (this.url == null)
692
- throw new Error("LP URL not specified!");
693
- checkIntervalSeconds ??= 5;
694
- let resp = { code: IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING, msg: "" };
695
- while (!abortSignal?.aborted && (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING || resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND)) {
696
- resp = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
697
- if (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID) {
698
- const validResponse = await this._setPaymentResult(resp.data, true);
699
- if (validResponse) {
700
- if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.REFUNDABLE) {
701
- await this._saveAndEmit(ToBTCSwapState.SOFT_CLAIMED);
702
- }
703
- }
704
- else {
705
- resp = { code: IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING, msg: "" };
706
- }
707
- }
708
- if (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING ||
709
- resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND)
710
- await (0, TimeoutUtils_1.timeoutPromise)(checkIntervalSeconds * 1000, abortSignal);
711
- }
712
- return resp;
713
- }
714
- /**
715
- * Checks whether the swap was already processed by the LP and is either successful (requires proof which is
716
- * either a HTLC pre-image for LN swaps or valid txId for on-chain swap) or failed and we can cooperatively
717
- * refund.
718
- *
719
- * @param save whether to save the data
720
- * @returns `true` if swap is processed, `false` if the swap is still ongoing
721
- *
722
- * @internal
723
- */
724
- async checkIntermediarySwapProcessed(save = true) {
725
- if (this._state === ToBTCSwapState.CREATED || this._state == ToBTCSwapState.QUOTE_EXPIRED || this.url == null)
726
- return false;
727
- if (this.isFinished() || this.isRefundable())
728
- return true;
729
- //Check if that maybe already concluded according to the LP
730
- const resp = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
731
- switch (resp.code) {
732
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID:
733
- const processed = await this._setPaymentResult(resp.data, true);
734
- if (processed) {
735
- this._state = ToBTCSwapState.SOFT_CLAIMED;
736
- if (save)
737
- await this._saveAndEmit();
738
- }
739
- return processed;
740
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA:
741
- await this._contract.isValidRefundAuthorization(this._data, resp.data);
742
- this._state = ToBTCSwapState.REFUNDABLE;
743
- if (save)
744
- await this._saveAndEmit();
745
- return true;
746
- default:
747
- return false;
748
- }
749
- }
750
- /**
751
- * A blocking promise resolving when swap was concluded by the intermediary (LP),
752
- * rejecting in case of failure
753
- *
754
- * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled, an error is thrown if the
755
- * swap is taking too long to claim
756
- * @param checkIntervalSeconds How often to poll the intermediary for answer
757
- * @param abortSignal Abort signal
758
- * @returns `true` if swap was successful, `false` if swap failed and we can refund
759
- *
760
- * @throws {IntermediaryError} If a swap is determined expired by the intermediary, but it is actually still valid
761
- * @throws {SignatureVerificationError} If the swap should be cooperatively refundable but the intermediary returned
762
- * invalid refund signature
763
- * @throws {Error} When swap expires or if the swap has invalid state (must be {@link ToBTCSwapState.COMMITED})
764
- */
765
- async waitForPayment(maxWaitTimeSeconds, checkIntervalSeconds, abortSignal) {
766
- if (this._state === ToBTCSwapState.CLAIMED)
767
- return Promise.resolve(true);
768
- if (this._state !== ToBTCSwapState.COMMITED && this._state !== ToBTCSwapState.SOFT_CLAIMED)
769
- throw new Error("Invalid state (not COMMITED)");
770
- const abortController = (0, Utils_1.extendAbortController)(abortSignal);
771
- let timedOut = false;
772
- if (maxWaitTimeSeconds != null) {
773
- const timeout = setTimeout(() => {
774
- timedOut = true;
775
- abortController.abort();
776
- }, maxWaitTimeSeconds * 1000);
777
- abortController.signal.addEventListener("abort", () => clearTimeout(timeout));
778
- }
779
- let result;
780
- try {
781
- result = await Promise.race([
782
- this.waitTillState(ToBTCSwapState.CLAIMED, "gte", abortController.signal),
783
- this.waitTillIntermediarySwapProcessed(checkIntervalSeconds, abortController.signal)
784
- ]);
785
- abortController.abort();
786
- }
787
- catch (e) {
788
- abortController.abort();
789
- if (timedOut) {
790
- throw new Error("Timed out while waiting for LP to process the swap, the LP might be unresponsive or offline!" +
791
- ` Please check later or wait till ${new Date(Number(this._data.getExpiry()) * 1000).toLocaleString()} to refund unilaterally!`);
792
- }
793
- throw e;
794
- }
795
- if (typeof result !== "object") {
796
- if (this._state === ToBTCSwapState.REFUNDABLE)
797
- throw new Error("Swap expired");
798
- this.logger.debug("waitTillRefunded(): Resolved from state change");
799
- return true;
800
- }
801
- this.logger.debug("waitTillRefunded(): Resolved from intermediary response");
802
- switch (result.code) {
803
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID:
804
- return true;
805
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA:
806
- const resultData = result.data;
807
- await this._contract.isValidRefundAuthorization(this._data, resultData);
808
- await this._saveAndEmit(ToBTCSwapState.REFUNDABLE);
809
- return false;
810
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.EXPIRED:
811
- if (await this._contract.isExpired(this._getInitiator(), this._data))
812
- throw new Error("Swap expired");
813
- throw new IntermediaryError_1.IntermediaryError("Swap expired");
814
- case IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND:
815
- if (this._state === ToBTCSwapState.CLAIMED)
816
- return true;
817
- throw new Error("LP swap not found");
818
- }
819
- throw new Error("Invalid response code returned by the LP");
820
- }
821
- //////////////////////////////
822
- //// Refund
823
- /**
824
- * Get the estimated smart chain transaction fee of the refund transaction
825
- */
826
- async getRefundNetworkFee() {
827
- const swapContract = this._contract;
828
- return (0, TokenAmount_1.toTokenAmount)(await swapContract.getRefundFee(this._getInitiator(), this._data), this.wrapper._getNativeToken(), this.wrapper._prices);
829
- }
830
- /**
831
- * @inheritDoc
832
- *
833
- * @throws {IntermediaryError} If intermediary returns invalid response in case cooperative refund should be used
834
- * @throws {SignatureVerificationError} If intermediary returned invalid cooperative refund signature
835
- * @throws {Error} When state is not refundable
836
- */
837
- async txsRefund(_signer) {
838
- if (!this.isRefundable())
839
- throw new Error("Must be in REFUNDABLE state or expired!");
840
- let signer;
841
- if (_signer != null) {
842
- if (typeof (_signer) === "string") {
843
- signer = _signer;
844
- }
845
- else if ((0, base_1.isAbstractSigner)(_signer)) {
846
- signer = _signer.getAddress();
847
- }
848
- else {
849
- signer = (await this.wrapper._chain.wrapSigner(_signer)).getAddress();
850
- }
851
- }
852
- else {
853
- signer = this._getInitiator();
854
- }
855
- if (await this._contract.isExpired(this._getInitiator(), this._data)) {
856
- return await this._contract.txsRefund(signer, this._data, true, true);
857
- }
858
- else {
859
- if (this.url == null)
860
- throw new Error("LP URL not known, cannot get cooperative refund message, wait till expiry to refund!");
861
- const res = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
862
- if (res.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA) {
863
- return await this._contract.txsRefundWithAuthorization(signer, this._data, res.data, true, true);
864
- }
865
- throw new IntermediaryError_1.IntermediaryError("Invalid intermediary cooperative message returned");
866
- }
867
- }
868
- /**
869
- * @inheritDoc
870
- *
871
- * @throws {Error} If invalid signer is provided that doesn't match the swap data
872
- */
873
- async refund(_signer, abortSignal) {
874
- const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
875
- const result = await this.wrapper._chain.sendAndConfirm(signer, await this.txsRefund(signer.getAddress()), true, abortSignal);
876
- this._refundTxId = result[0];
877
- if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.REFUNDABLE || this._state === ToBTCSwapState.SOFT_CLAIMED) {
878
- await this._saveAndEmit(ToBTCSwapState.REFUNDED);
879
- }
880
- return result[0];
881
- }
882
- /**
883
- * @inheritDoc
884
- *
885
- * @throws {Error} When swap is not in a valid state (must be {@link ToBTCSwapState.COMMITED} or
886
- * {@link ToBTCSwapState.REFUNDABLE})
887
- * @throws {Error} If we tried to refund but claimer was able to claim first
888
- */
889
- async waitTillRefunded(abortSignal) {
890
- if (this._state === ToBTCSwapState.REFUNDED)
891
- return Promise.resolve();
892
- if (this._state !== ToBTCSwapState.COMMITED &&
893
- this._state !== ToBTCSwapState.SOFT_CLAIMED &&
894
- this._state !== ToBTCSwapState.REFUNDABLE)
895
- throw new Error("Invalid state (not COMMITED)");
896
- const abortController = new AbortController();
897
- if (abortSignal != null)
898
- abortSignal.addEventListener("abort", () => abortController.abort(abortSignal.reason));
899
- const res = await Promise.race([
900
- this.watchdogWaitTillResult(undefined, abortController.signal),
901
- this.waitTillState(ToBTCSwapState.REFUNDED, "eq", abortController.signal).then(() => 0),
902
- this.waitTillState(ToBTCSwapState.CLAIMED, "eq", abortController.signal).then(() => 1),
903
- ]);
904
- abortController.abort();
905
- if (res === 0) {
906
- this.logger.debug("waitTillRefunded(): Resolved from state change (REFUNDED)");
907
- return;
908
- }
909
- if (res === 1) {
910
- this.logger.debug("waitTillRefunded(): Resolved from state change (CLAIMED)");
911
- throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
912
- }
913
- this.logger.debug("waitTillRefunded(): Resolved from watchdog");
914
- if (res?.type === base_1.SwapCommitStateType.PAID) {
915
- if (this._claimTxId == null)
916
- this._claimTxId = await res.getClaimTxId();
917
- await this._saveAndEmit(ToBTCSwapState.CLAIMED);
918
- throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
919
- }
920
- if (res?.type === base_1.SwapCommitStateType.NOT_COMMITED) {
921
- if (this._refundTxId == null && res.getRefundTxId != null)
922
- this._refundTxId = await res.getRefundTxId();
923
- await this._saveAndEmit(ToBTCSwapState.REFUNDED);
924
- }
925
- }
926
- //////////////////////////////
927
- //// Storage
928
- /**
929
- * @inheritDoc
930
- */
931
- serialize() {
932
- const obj = super.serialize();
933
- return {
934
- ...obj,
935
- networkFee: this.networkFee == null ? null : this.networkFee.toString(10),
936
- networkFeeBtc: this.networkFeeBtc == null ? null : this.networkFeeBtc.toString(10)
937
- };
938
- }
939
- //////////////////////////////
940
- //// Swap ticks & sync
941
- /**
942
- * Checks the swap's state on-chain and compares it to its internal state, updates/changes it according to on-chain
943
- * data
944
- *
945
- * @private
946
- */
947
- async syncStateFromChain(quoteDefinitelyExpired, commitStatus) {
948
- if (this._state === ToBTCSwapState.CREATED ||
949
- this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
950
- this._state === ToBTCSwapState.COMMITED ||
951
- this._state === ToBTCSwapState.SOFT_CLAIMED ||
952
- this._state === ToBTCSwapState.REFUNDABLE) {
953
- let quoteExpired = false;
954
- if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED) {
955
- //Check if quote is still valid
956
- quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired();
957
- }
958
- commitStatus ??= await this._contract.getCommitStatus(this._getInitiator(), this._data);
959
- if (commitStatus != null && await this._forciblySetOnchainState(commitStatus))
960
- return true;
961
- if ((this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED)) {
962
- if (quoteExpired) {
963
- this._state = ToBTCSwapState.QUOTE_EXPIRED;
964
- return true;
965
- }
966
- }
967
- }
968
- return false;
969
- }
970
- /**
971
- * @inheritDoc
972
- * @internal
973
- */
974
- _shouldFetchOnchainState() {
975
- return this._state === ToBTCSwapState.CREATED ||
976
- this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
977
- this._state === ToBTCSwapState.COMMITED ||
978
- this._state === ToBTCSwapState.SOFT_CLAIMED ||
979
- this._state === ToBTCSwapState.REFUNDABLE;
980
- }
981
- /**
982
- * @inheritDoc
983
- * @internal
984
- */
985
- _shouldFetchExpiryStatus() {
986
- return this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED;
987
- }
988
- /**
989
- * @inheritDoc
990
- * @internal
991
- */
992
- async _sync(save, quoteDefinitelyExpired, commitStatus) {
993
- let changed = await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus);
994
- if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.SOFT_CLAIMED) {
995
- //Check if that maybe already concluded
996
- try {
997
- if (await this.checkIntermediarySwapProcessed(false))
998
- changed = true;
999
- }
1000
- catch (e) {
1001
- this.logger.error("_sync(): Failed to synchronize swap, error: ", e);
1002
- }
1003
- }
1004
- if (save && changed)
1005
- await this._saveAndEmit();
1006
- return changed;
1007
- }
1008
- /**
1009
- * @inheritDoc
1010
- * @internal
1011
- */
1012
- async _forciblySetOnchainState(commitStatus) {
1013
- switch (commitStatus.type) {
1014
- case base_1.SwapCommitStateType.PAID:
1015
- if (this._commitTxId == null && commitStatus.getInitTxId != null)
1016
- this._commitTxId = await commitStatus.getInitTxId();
1017
- if (this._claimTxId == null && commitStatus.getClaimTxId)
1018
- this._claimTxId = await commitStatus.getClaimTxId();
1019
- const eventResult = await commitStatus.getClaimResult();
1020
- try {
1021
- await this._setPaymentResult({ secret: eventResult, txId: Buffer.from(eventResult, "hex").reverse().toString("hex") });
1022
- }
1023
- catch (e) {
1024
- this.logger.error(`Failed to set payment result ${eventResult} on the swap!`);
1025
- }
1026
- this._state = ToBTCSwapState.CLAIMED;
1027
- return true;
1028
- case base_1.SwapCommitStateType.REFUNDABLE:
1029
- if (this._commitTxId == null && commitStatus.getInitTxId != null)
1030
- this._commitTxId = await commitStatus.getInitTxId();
1031
- this._state = ToBTCSwapState.REFUNDABLE;
1032
- return true;
1033
- case base_1.SwapCommitStateType.EXPIRED:
1034
- if (this._commitTxId == null && commitStatus.getInitTxId != null)
1035
- this._commitTxId = await commitStatus.getInitTxId();
1036
- if (this._refundTxId == null && commitStatus.getRefundTxId)
1037
- this._refundTxId = await commitStatus.getRefundTxId();
1038
- this._state = this._refundTxId == null ? ToBTCSwapState.QUOTE_EXPIRED : ToBTCSwapState.REFUNDED;
1039
- return true;
1040
- case base_1.SwapCommitStateType.NOT_COMMITED:
1041
- let changed = false;
1042
- if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1043
- this._commitTxId = await commitStatus.getInitTxId();
1044
- changed = true;
1045
- }
1046
- if (this._refundTxId == null && commitStatus.getRefundTxId) {
1047
- this._refundTxId = await commitStatus.getRefundTxId();
1048
- changed = true;
1049
- }
1050
- if (this._refundTxId != null) {
1051
- this._state = ToBTCSwapState.REFUNDED;
1052
- changed = true;
1053
- }
1054
- return changed;
1055
- case base_1.SwapCommitStateType.COMMITED:
1056
- let save = false;
1057
- if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1058
- this._commitTxId = await commitStatus.getInitTxId();
1059
- save = true;
1060
- }
1061
- if (this._state !== ToBTCSwapState.COMMITED && this._state !== ToBTCSwapState.REFUNDABLE && this._state !== ToBTCSwapState.SOFT_CLAIMED) {
1062
- this._state = ToBTCSwapState.COMMITED;
1063
- save = true;
1064
- }
1065
- return save;
1066
- }
1067
- return false;
1068
- }
1069
- /**
1070
- * @inheritDoc
1071
- * @internal
1072
- */
1073
- async _tick(save) {
1074
- switch (this._state) {
1075
- case ToBTCSwapState.CREATED:
1076
- if (this.expiry < Date.now()) {
1077
- this._state = ToBTCSwapState.QUOTE_SOFT_EXPIRED;
1078
- if (save)
1079
- await this._saveAndEmit();
1080
- return true;
1081
- }
1082
- break;
1083
- case ToBTCSwapState.COMMITED:
1084
- case ToBTCSwapState.SOFT_CLAIMED:
1085
- const expired = await this._contract.isExpired(this._getInitiator(), this._data);
1086
- if (expired) {
1087
- this._state = ToBTCSwapState.REFUNDABLE;
1088
- if (save)
1089
- await this._saveAndEmit();
1090
- return true;
1091
- }
1092
- break;
1093
- }
1094
- return false;
1095
- }
1096
- }
1097
- exports.IToBTCSwap = IToBTCSwap;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IToBTCSwap = exports.ToBTCSwapState = exports.isIToBTCSwapInit = void 0;
4
+ const base_1 = require("@atomiqlabs/base");
5
+ const IntermediaryAPI_1 = require("../../../intermediaries/apis/IntermediaryAPI");
6
+ const IntermediaryError_1 = require("../../../errors/IntermediaryError");
7
+ const Utils_1 = require("../../../utils/Utils");
8
+ const IEscrowSelfInitSwap_1 = require("../IEscrowSelfInitSwap");
9
+ const FeeType_1 = require("../../../enums/FeeType");
10
+ const PercentagePPM_1 = require("../../../types/fees/PercentagePPM");
11
+ const TokenAmount_1 = require("../../../types/TokenAmount");
12
+ const TimeoutUtils_1 = require("../../../utils/TimeoutUtils");
13
+ function isIToBTCSwapInit(obj) {
14
+ return typeof (obj.networkFee) === "bigint" &&
15
+ typeof (obj.networkFeeBtc) === "bigint" &&
16
+ (obj.signatureData == null || (typeof (obj.signatureData) === 'object' &&
17
+ typeof (obj.signatureData.prefix) === "string" &&
18
+ typeof (obj.signatureData.timeout) === "string" &&
19
+ typeof (obj.signatureData.signature) === "string")) &&
20
+ typeof (obj.data) === 'object' &&
21
+ (0, IEscrowSelfInitSwap_1.isIEscrowSelfInitSwapInit)(obj);
22
+ }
23
+ exports.isIToBTCSwapInit = isIToBTCSwapInit;
24
+ /**
25
+ * State enum for escrow-based Smart chain -> Bitcoin (on-chain & lightning) swaps
26
+ *
27
+ * @category Swaps/Smart chain → Bitcoin
28
+ */
29
+ var ToBTCSwapState;
30
+ (function (ToBTCSwapState) {
31
+ /**
32
+ * Intermediary (LP) was unable to process the swap and the funds were refunded on the
33
+ * source chain
34
+ */
35
+ ToBTCSwapState[ToBTCSwapState["REFUNDED"] = -3] = "REFUNDED";
36
+ /**
37
+ * Swap has expired for good and there is no way how it can be executed anymore
38
+ */
39
+ ToBTCSwapState[ToBTCSwapState["QUOTE_EXPIRED"] = -2] = "QUOTE_EXPIRED";
40
+ /**
41
+ * A swap is almost expired, and it should be presented to the user as expired, though
42
+ * there is still a chance that it will be processed
43
+ */
44
+ ToBTCSwapState[ToBTCSwapState["QUOTE_SOFT_EXPIRED"] = -1] = "QUOTE_SOFT_EXPIRED";
45
+ /**
46
+ * Swap was created, use the {@link IToBTCSwap.commit} or {@link IToBTCSwap.txsCommit} to
47
+ * initiate it by creating the swap escrow on the source chain
48
+ */
49
+ ToBTCSwapState[ToBTCSwapState["CREATED"] = 0] = "CREATED";
50
+ /**
51
+ * Swap escrow was initiated (committed) on the source chain, the intermediary (LP) will
52
+ * now process the swap. You can wait till that happens with the {@link IToBTCSwap.waitForPayment}
53
+ * function.
54
+ */
55
+ ToBTCSwapState[ToBTCSwapState["COMMITED"] = 1] = "COMMITED";
56
+ /**
57
+ * The intermediary (LP) has processed the transaction and sent out the funds on the destination chain,
58
+ * but hasn't yet settled the escrow on the source chain.
59
+ */
60
+ ToBTCSwapState[ToBTCSwapState["SOFT_CLAIMED"] = 2] = "SOFT_CLAIMED";
61
+ /**
62
+ * Swap was successfully settled by the intermediary (LP) on the source chain
63
+ */
64
+ ToBTCSwapState[ToBTCSwapState["CLAIMED"] = 3] = "CLAIMED";
65
+ /**
66
+ * Intermediary (LP) was unable to process the swap and the swap escrow on the source chain
67
+ * is refundable, call {@link IToBTCSwap.refund} or {@link IToBTCSwap.txsRefund} to refund
68
+ */
69
+ ToBTCSwapState[ToBTCSwapState["REFUNDABLE"] = 4] = "REFUNDABLE";
70
+ })(ToBTCSwapState = exports.ToBTCSwapState || (exports.ToBTCSwapState = {}));
71
+ const ToBTCSwapStateDescription = {
72
+ [ToBTCSwapState.REFUNDED]: "Intermediary (LP) was unable to process the swap and the funds were refunded on the source chain",
73
+ [ToBTCSwapState.QUOTE_EXPIRED]: "Swap has expired for good and there is no way how it can be executed anymore",
74
+ [ToBTCSwapState.QUOTE_SOFT_EXPIRED]: "A swap is expired, though there is still a chance that it will be processed",
75
+ [ToBTCSwapState.CREATED]: "Swap was created, initiate it by creating the swap escrow on the source chain",
76
+ [ToBTCSwapState.COMMITED]: "Swap escrow was initiated (committed) on the source chain, the intermediary (LP) will now process the swap.",
77
+ [ToBTCSwapState.SOFT_CLAIMED]: "The intermediary (LP) has processed the transaction and sent out the funds on the destination chain, but hasn't yet settled the escrow on the source chain.",
78
+ [ToBTCSwapState.CLAIMED]: "Swap was successfully settled by the intermediary (LP) on the source chain",
79
+ [ToBTCSwapState.REFUNDABLE]: "Intermediary (LP) was unable to process the swap and the swap escrow on the source chain is refundable."
80
+ };
81
+ /**
82
+ * Base class for escrow-based Smart chain -> Bitcoin (on-chain & lightning) swaps
83
+ *
84
+ * @category Swaps/Smart chain → Bitcoin
85
+ */
86
+ class IToBTCSwap extends IEscrowSelfInitSwap_1.IEscrowSelfInitSwap {
87
+ constructor(wrapper, initOrObject) {
88
+ super(wrapper, initOrObject);
89
+ /**
90
+ * @internal
91
+ */
92
+ this.swapStateDescription = ToBTCSwapStateDescription;
93
+ /**
94
+ * @internal
95
+ */
96
+ this.swapStateName = (state) => ToBTCSwapState[state];
97
+ if (isIToBTCSwapInit(initOrObject)) {
98
+ this._state = ToBTCSwapState.CREATED;
99
+ this.networkFee = initOrObject.networkFee;
100
+ this.networkFeeBtc = initOrObject.networkFeeBtc;
101
+ this._data = initOrObject.data;
102
+ this.signatureData = initOrObject.signatureData;
103
+ }
104
+ else {
105
+ this.networkFee = (0, Utils_1.toBigInt)(initOrObject.networkFee);
106
+ this.networkFeeBtc = (0, Utils_1.toBigInt)(initOrObject.networkFeeBtc);
107
+ }
108
+ }
109
+ /**
110
+ * @inheritDoc
111
+ * @internal
112
+ */
113
+ getSwapData() {
114
+ return this._data;
115
+ }
116
+ /**
117
+ * @inheritDoc
118
+ * @internal
119
+ */
120
+ upgradeVersion() {
121
+ if (this.version == null) {
122
+ switch (this._state) {
123
+ case -2:
124
+ this._state = ToBTCSwapState.REFUNDED;
125
+ break;
126
+ case -1:
127
+ this._state = ToBTCSwapState.QUOTE_EXPIRED;
128
+ break;
129
+ case 0:
130
+ this._state = ToBTCSwapState.CREATED;
131
+ break;
132
+ case 1:
133
+ this._state = ToBTCSwapState.COMMITED;
134
+ break;
135
+ case 2:
136
+ this._state = ToBTCSwapState.CLAIMED;
137
+ break;
138
+ case 3:
139
+ this._state = ToBTCSwapState.REFUNDABLE;
140
+ break;
141
+ }
142
+ this.version = 1;
143
+ }
144
+ }
145
+ /**
146
+ * @inheritDoc
147
+ * @internal
148
+ */
149
+ tryRecomputeSwapPrice() {
150
+ const output = this.getOutput();
151
+ if (output.rawAmount != null) {
152
+ if (this.swapFeeBtc == null) {
153
+ this.swapFeeBtc = this.swapFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
154
+ }
155
+ if (this.networkFeeBtc == null) {
156
+ this.networkFeeBtc = this.networkFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
157
+ }
158
+ }
159
+ super.tryRecomputeSwapPrice();
160
+ }
161
+ /**
162
+ * Returns the payment hash identifier to be sent to the LP for getStatus and getRefund
163
+ * @internal
164
+ */
165
+ getLpIdentifier() {
166
+ return this.getClaimHash();
167
+ }
168
+ //////////////////////////////
169
+ //// Getters & utils
170
+ /**
171
+ * @inheritDoc
172
+ */
173
+ getInputAddress() {
174
+ return this._getInitiator();
175
+ }
176
+ /**
177
+ * @inheritDoc
178
+ */
179
+ getInputTxId() {
180
+ return this._commitTxId ?? null;
181
+ }
182
+ /**
183
+ * @inheritDoc
184
+ */
185
+ requiresAction() {
186
+ return this.isRefundable();
187
+ }
188
+ /**
189
+ * @inheritDoc
190
+ */
191
+ isFinished() {
192
+ return this._state === ToBTCSwapState.CLAIMED || this._state === ToBTCSwapState.REFUNDED || this._state === ToBTCSwapState.QUOTE_EXPIRED;
193
+ }
194
+ /**
195
+ * @inheritDoc
196
+ */
197
+ isRefundable() {
198
+ return this._state === ToBTCSwapState.REFUNDABLE;
199
+ }
200
+ /**
201
+ * @inheritDoc
202
+ */
203
+ isQuoteExpired() {
204
+ return this._state === ToBTCSwapState.QUOTE_EXPIRED;
205
+ }
206
+ /**
207
+ * @inheritDoc
208
+ */
209
+ isQuoteSoftExpired() {
210
+ return this._state === ToBTCSwapState.QUOTE_EXPIRED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED;
211
+ }
212
+ /**
213
+ * @inheritDoc
214
+ */
215
+ isSuccessful() {
216
+ return this._state === ToBTCSwapState.CLAIMED;
217
+ }
218
+ /**
219
+ * @inheritDoc
220
+ */
221
+ isFailed() {
222
+ return this._state === ToBTCSwapState.REFUNDED;
223
+ }
224
+ /**
225
+ * @inheritDoc
226
+ */
227
+ isInProgress() {
228
+ return this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.SOFT_CLAIMED;
229
+ }
230
+ /**
231
+ * Returns the time (in UNIX milliseconds) at which the swap expires and the user is able to unilaterally
232
+ * refund it with the {@link refund} or {@link txsRefund} function.
233
+ */
234
+ getExpiry() {
235
+ return Number(this._data.getExpiry()) * 1000;
236
+ }
237
+ /**
238
+ * @inheritDoc
239
+ * @internal
240
+ */
241
+ _getInitiator() {
242
+ return this._data.getOfferer();
243
+ }
244
+ //////////////////////////////
245
+ //// Amounts & fees
246
+ /**
247
+ * Returns the swap fee charged by the intermediary (LP) on this swap
248
+ *
249
+ * @internal
250
+ */
251
+ getSwapFee() {
252
+ if (this.pricingInfo == null)
253
+ throw new Error("No pricing info known, cannot estimate fee!");
254
+ const feeWithoutBaseFee = this.swapFeeBtc - this.pricingInfo.satsBaseFee;
255
+ const output = this.getOutput();
256
+ const swapFeePPM = output.rawAmount == null ? 0n : feeWithoutBaseFee * 1000000n / output.rawAmount;
257
+ const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.swapFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
258
+ return {
259
+ amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.swapFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
260
+ amountInDstToken,
261
+ currentUsdValue: amountInDstToken.currentUsdValue,
262
+ usdValue: amountInDstToken.usdValue,
263
+ pastUsdValue: amountInDstToken.pastUsdValue,
264
+ composition: {
265
+ base: (0, TokenAmount_1.toTokenAmount)(this.pricingInfo.satsBaseFee, this.outputToken, this.wrapper._prices, this.pricingInfo),
266
+ percentage: (0, PercentagePPM_1.ppmToPercentage)(swapFeePPM)
267
+ }
268
+ };
269
+ }
270
+ /**
271
+ * Returns network fee for on the destination chain for the swap
272
+ *
273
+ * @internal
274
+ */
275
+ getNetworkFee() {
276
+ const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.networkFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
277
+ return {
278
+ amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.networkFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
279
+ amountInDstToken,
280
+ currentUsdValue: amountInDstToken.currentUsdValue,
281
+ usdValue: amountInDstToken.usdValue,
282
+ pastUsdValue: amountInDstToken.pastUsdValue
283
+ };
284
+ }
285
+ /**
286
+ * @inheritDoc
287
+ */
288
+ getFee() {
289
+ const amountInDstToken = (0, TokenAmount_1.toTokenAmount)(this.swapFeeBtc + this.networkFeeBtc, this.outputToken, this.wrapper._prices, this.pricingInfo);
290
+ return {
291
+ amountInSrcToken: (0, TokenAmount_1.toTokenAmount)(this.swapFee + this.networkFee, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
292
+ amountInDstToken,
293
+ currentUsdValue: amountInDstToken.currentUsdValue,
294
+ usdValue: amountInDstToken.usdValue,
295
+ pastUsdValue: amountInDstToken.pastUsdValue
296
+ };
297
+ }
298
+ /**
299
+ * @inheritDoc
300
+ */
301
+ getFeeBreakdown() {
302
+ return [
303
+ {
304
+ type: FeeType_1.FeeType.SWAP,
305
+ fee: this.getSwapFee()
306
+ },
307
+ {
308
+ type: FeeType_1.FeeType.NETWORK_OUTPUT,
309
+ fee: this.getNetworkFee()
310
+ }
311
+ ];
312
+ }
313
+ /**
314
+ * @inheritDoc
315
+ */
316
+ getInputToken() {
317
+ return this.wrapper._tokens[this._data.getToken()];
318
+ }
319
+ /**
320
+ * @inheritDoc
321
+ */
322
+ getInput() {
323
+ return (0, TokenAmount_1.toTokenAmount)(this._data.getAmount(), this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo);
324
+ }
325
+ /**
326
+ * @inheritDoc
327
+ */
328
+ getInputWithoutFee() {
329
+ return (0, TokenAmount_1.toTokenAmount)(this._data.getAmount() - (this.swapFee + this.networkFee), this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo);
330
+ }
331
+ /**
332
+ * Checks if the initiator/sender on the source chain has enough balance to go through with the swap
333
+ */
334
+ async hasEnoughBalance() {
335
+ const [balance, commitFee] = await Promise.all([
336
+ this._contract.getBalance(this._getInitiator(), this._data.getToken(), false),
337
+ this._data.getToken() === this.wrapper._chain.getNativeCurrencyAddress() ? this.getCommitFee() : Promise.resolve(null)
338
+ ]);
339
+ let required = this._data.getAmount();
340
+ if (commitFee != null)
341
+ required = required + commitFee;
342
+ return {
343
+ enoughBalance: balance >= required,
344
+ balance: (0, TokenAmount_1.toTokenAmount)(balance, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo),
345
+ required: (0, TokenAmount_1.toTokenAmount)(required, this.wrapper._tokens[this._data.getToken()], this.wrapper._prices, this.pricingInfo)
346
+ };
347
+ }
348
+ /**
349
+ * Checks if the initiator/sender on the source chain has enough native token balance
350
+ * to cover the transaction fee of initiating the swap
351
+ */
352
+ async hasEnoughForTxFees() {
353
+ const [balance, commitFee] = await Promise.all([
354
+ this._contract.getBalance(this._getInitiator(), this.wrapper._chain.getNativeCurrencyAddress(), false),
355
+ this.getCommitFee()
356
+ ]);
357
+ return {
358
+ enoughBalance: balance >= commitFee,
359
+ balance: (0, TokenAmount_1.toTokenAmount)(balance, this.wrapper._getNativeToken(), this.wrapper._prices),
360
+ required: (0, TokenAmount_1.toTokenAmount)(commitFee, this.wrapper._getNativeToken(), this.wrapper._prices)
361
+ };
362
+ }
363
+ //////////////////////////////
364
+ //// Execution
365
+ /**
366
+ * Executes the swap with the provided smart chain wallet/signer
367
+ *
368
+ * @param signer Smart chain wallet/signer to use to sign the transaction on the source chain
369
+ * @param callbacks Callbacks to track the progress of the swap
370
+ * @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
371
+ *
372
+ * @returns {boolean} Whether the swap was successfully processed by the LP, in case `false` is returned
373
+ * the user can refund their funds back on the source chain by calling {@link refund}
374
+ */
375
+ async execute(signer, callbacks, options) {
376
+ if (this._state === ToBTCSwapState.QUOTE_EXPIRED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED)
377
+ throw new Error("Quote expired");
378
+ if (this._state === ToBTCSwapState.REFUNDED)
379
+ throw new Error("Swap already refunded");
380
+ if (this._state === ToBTCSwapState.REFUNDABLE)
381
+ throw new Error("Swap refundable, refund with swap.refund()");
382
+ if (this._state === ToBTCSwapState.SOFT_CLAIMED || this._state === ToBTCSwapState.CLAIMED)
383
+ throw new Error("Swap already settled!");
384
+ if (this._state === ToBTCSwapState.CREATED) {
385
+ const txId = await this.commit(signer, options?.abortSignal, false, callbacks?.onSourceTransactionSent);
386
+ if (callbacks?.onSourceTransactionConfirmed != null)
387
+ callbacks.onSourceTransactionConfirmed(txId);
388
+ }
389
+ // @ts-ignore
390
+ if (this._state === ToBTCSwapState.CLAIMED || this._state === ToBTCSwapState.SOFT_CLAIMED)
391
+ return true;
392
+ if (this._state === ToBTCSwapState.COMMITED) {
393
+ const success = await this.waitForPayment(options?.maxWaitTillSwapProcessedSeconds ?? 120, options?.paymentCheckIntervalSeconds, options?.abortSignal);
394
+ if (success) {
395
+ if (callbacks?.onSwapSettled != null)
396
+ callbacks.onSwapSettled(this.getOutputTxId());
397
+ return true;
398
+ }
399
+ else {
400
+ return false;
401
+ }
402
+ }
403
+ throw new Error("Unexpected state reached!");
404
+ }
405
+ /**
406
+ * @internal
407
+ */
408
+ async _getExecutionStatus() {
409
+ const state = this._state;
410
+ let sourcePaymentStatus = "inactive";
411
+ let destinationPayoutStatus = "inactive";
412
+ let refundStatus = "inactive";
413
+ let buildCurrentAction = async () => undefined;
414
+ switch (state) {
415
+ case ToBTCSwapState.CREATED:
416
+ const quoteValid = await this._verifyQuoteValid();
417
+ sourcePaymentStatus = quoteValid ? "awaiting" : "soft_expired";
418
+ if (this.signatureData != null && quoteValid) {
419
+ buildCurrentAction = this._buildInitSmartChainTxAction.bind(this);
420
+ }
421
+ break;
422
+ case ToBTCSwapState.QUOTE_SOFT_EXPIRED:
423
+ sourcePaymentStatus = "soft_expired";
424
+ break;
425
+ case ToBTCSwapState.QUOTE_EXPIRED:
426
+ sourcePaymentStatus = "expired";
427
+ break;
428
+ case ToBTCSwapState.COMMITED:
429
+ sourcePaymentStatus = "confirmed";
430
+ destinationPayoutStatus = "waiting_lp";
431
+ buildCurrentAction = this._buildWaitLpAction.bind(this);
432
+ break;
433
+ case ToBTCSwapState.SOFT_CLAIMED:
434
+ sourcePaymentStatus = "confirmed";
435
+ destinationPayoutStatus = "soft_settled";
436
+ break;
437
+ case ToBTCSwapState.CLAIMED:
438
+ sourcePaymentStatus = "confirmed";
439
+ destinationPayoutStatus = "settled";
440
+ break;
441
+ case ToBTCSwapState.REFUNDABLE:
442
+ sourcePaymentStatus = "confirmed";
443
+ destinationPayoutStatus = "expired";
444
+ refundStatus = "awaiting";
445
+ buildCurrentAction = this._buildRefundSmartChainTxAction.bind(this);
446
+ break;
447
+ case ToBTCSwapState.REFUNDED:
448
+ sourcePaymentStatus = "confirmed";
449
+ destinationPayoutStatus = "expired";
450
+ refundStatus = "refunded";
451
+ break;
452
+ }
453
+ return {
454
+ steps: [
455
+ {
456
+ type: "Payment",
457
+ side: "source",
458
+ chain: this.chainIdentifier,
459
+ title: "Source payment",
460
+ description: `Initiate the swap by funding the escrow on the ${this.chainIdentifier} side`,
461
+ status: sourcePaymentStatus,
462
+ initTxId: this._commitTxId,
463
+ settleTxId: this._claimTxId
464
+ },
465
+ {
466
+ type: "Settlement",
467
+ side: "destination",
468
+ chain: this.outputToken.chainId,
469
+ title: "Destination payout",
470
+ description: `Wait for the LP to process the swap and send the payout on the ${this.outputToken.chainId} side`,
471
+ status: destinationPayoutStatus,
472
+ initTxId: destinationPayoutStatus === "settled" || destinationPayoutStatus === "soft_settled" ? this.getOutputTxId() : undefined,
473
+ settleTxId: destinationPayoutStatus === "settled" ? this.getOutputTxId() : undefined,
474
+ },
475
+ {
476
+ type: "Refund",
477
+ side: "source",
478
+ chain: this.chainIdentifier,
479
+ title: "Source refund",
480
+ description: `Refund escrowed funds on the ${this.chainIdentifier} side, after LP failed to execute`,
481
+ status: refundStatus,
482
+ refundTxId: this._refundTxId
483
+ }
484
+ ],
485
+ buildCurrentAction,
486
+ state
487
+ };
488
+ }
489
+ /**
490
+ * @inheritDoc
491
+ * @internal
492
+ */
493
+ async _submitExecutionTransactions(txs, abortSignal, requiredStates, idempotent) {
494
+ const parsedTxs = [];
495
+ for (let tx of txs) {
496
+ parsedTxs.push(typeof (tx) === "string" ? await this.wrapper._chain.deserializeSignedTx(tx) : tx);
497
+ }
498
+ if (idempotent) {
499
+ // Handle idempotent calls
500
+ if (this.wrapper._chain.getTxId != null) {
501
+ const txIds = await Promise.all(parsedTxs.map(tx => this.wrapper._chain.getTxId(tx)));
502
+ const foundTxId = txIds.find(txId => this._commitTxId === txId || this._refundTxId === txId);
503
+ if (foundTxId != null)
504
+ return txIds;
505
+ }
506
+ }
507
+ if (requiredStates != null && !requiredStates.includes(this._state))
508
+ throw new Error("Swap state has changed before transactions were submitted!");
509
+ if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED) {
510
+ if (!await this._verifyQuoteValid())
511
+ throw new Error("Quote is already expired!");
512
+ const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
513
+ await this.waitTillCommited(abortSignal);
514
+ return txIds;
515
+ }
516
+ if (this._state === ToBTCSwapState.REFUNDABLE) {
517
+ const txIds = await this.wrapper._chain.sendSignedAndConfirm(parsedTxs, true, abortSignal, false);
518
+ await this.waitTillRefunded(abortSignal);
519
+ return txIds;
520
+ }
521
+ throw new Error("Invalid swap state for transaction submission!");
522
+ }
523
+ /**
524
+ * @internal
525
+ */
526
+ async _buildInitSmartChainTxAction(actionOptions) {
527
+ return {
528
+ type: "SignSmartChainTransaction",
529
+ name: "Initiate swap",
530
+ description: `Initiates the swap by commiting the funds to the escrow on the ${this.chainIdentifier} side`,
531
+ chain: this.chainIdentifier,
532
+ txs: await this.prepareTransactions(this.txsCommit(actionOptions?.skipChecks)),
533
+ submitTransactions: async (txs, abortSignal, idempotent) => {
534
+ return this._submitExecutionTransactions(txs, abortSignal, [ToBTCSwapState.CREATED, ToBTCSwapState.QUOTE_SOFT_EXPIRED], idempotent);
535
+ },
536
+ requiredSigner: this._getInitiator()
537
+ };
538
+ }
539
+ /**
540
+ * @internal
541
+ */
542
+ async _buildWaitLpAction() {
543
+ return {
544
+ type: "Wait",
545
+ name: "Awaiting LP payout",
546
+ description: "Wait for the intermediary to process the swap and either send the payout or make the swap refundable",
547
+ pollTimeSeconds: 5,
548
+ expectedTimeSeconds: 10,
549
+ wait: async (maxWaitTimeSeconds, pollIntervalSeconds, abortSignal) => {
550
+ await this.waitForPayment(maxWaitTimeSeconds, pollIntervalSeconds, abortSignal);
551
+ }
552
+ };
553
+ }
554
+ /**
555
+ * @internal
556
+ */
557
+ async _buildRefundSmartChainTxAction(actionOptions) {
558
+ const signerAddress = await this.wrapper._getSignerAddress(actionOptions?.refundSmartChainSigner);
559
+ return {
560
+ type: "SignSmartChainTransaction",
561
+ name: "Refund",
562
+ description: "Refund the swap after it failed to execute",
563
+ chain: this.chainIdentifier,
564
+ txs: await this.prepareTransactions(this.txsRefund(actionOptions?.refundSmartChainSigner)),
565
+ submitTransactions: async (txs, abortSignal, idempotent) => {
566
+ return this._submitExecutionTransactions(txs, abortSignal, [ToBTCSwapState.REFUNDABLE], idempotent);
567
+ },
568
+ requiredSigner: signerAddress ?? this._getInitiator()
569
+ };
570
+ }
571
+ /**
572
+ * @inheritDoc
573
+ *
574
+ * @param options.skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
575
+ * (this is handled on swap creation, if you commit right after quoting, you can use `skipChecks=true`)
576
+ * @param options.refundSmartChainSigner Optional smart chain signer to use when creating refunds transactions
577
+ */
578
+ async getExecutionAction(options) {
579
+ const executionStatus = await this._getExecutionStatus();
580
+ return executionStatus.buildCurrentAction(options);
581
+ }
582
+ /**
583
+ * @inheritDoc
584
+ */
585
+ async getExecutionStatus(options) {
586
+ const executionStatus = await this._getExecutionStatus();
587
+ return {
588
+ steps: executionStatus.steps,
589
+ currentAction: options?.skipBuildingAction ? undefined : await executionStatus.buildCurrentAction(options),
590
+ stateInfo: this._getStateInfo(executionStatus.state)
591
+ };
592
+ }
593
+ /**
594
+ * @inheritDoc
595
+ */
596
+ async getExecutionSteps() {
597
+ return (await this._getExecutionStatus()).steps;
598
+ }
599
+ //////////////////////////////
600
+ //// Commit
601
+ /**
602
+ * @inheritDoc
603
+ *
604
+ * @throws {Error} When in invalid state (not {@link ToBTCSwapState.CREATED})
605
+ */
606
+ async txsCommit(skipChecks) {
607
+ if (this._state !== ToBTCSwapState.CREATED && (!skipChecks || this._state !== ToBTCSwapState.QUOTE_SOFT_EXPIRED))
608
+ throw new Error("Must be in CREATED state!");
609
+ if (this.signatureData == null)
610
+ throw new Error("Init signature data not known, cannot commit!");
611
+ if (!this.initiated) {
612
+ this.initiated = true;
613
+ await this._saveAndEmit();
614
+ }
615
+ return await this._contract.txsInit(this._getInitiator(), this._data, this.signatureData, skipChecks, this.feeRate).catch(e => Promise.reject(e instanceof base_1.SignatureVerificationError ? new Error("Request timed out") : e));
616
+ }
617
+ /**
618
+ * @inheritDoc
619
+ *
620
+ * @throws {Error} If invalid signer is provided that doesn't match the swap data
621
+ */
622
+ async commit(_signer, abortSignal, skipChecks, onBeforeTxSent) {
623
+ const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
624
+ this.checkSigner(signer);
625
+ const txs = await this.txsCommit(skipChecks);
626
+ let txCount = 0;
627
+ const result = await this.wrapper._chain.sendAndConfirm(signer, txs, true, abortSignal, false, (txId, rawTx) => {
628
+ txCount++;
629
+ if (onBeforeTxSent != null && txCount === txs.length)
630
+ onBeforeTxSent(txId);
631
+ return Promise.resolve();
632
+ });
633
+ this._commitTxId = result[result.length - 1];
634
+ if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.QUOTE_EXPIRED) {
635
+ await this._saveAndEmit(ToBTCSwapState.COMMITED);
636
+ }
637
+ return this._commitTxId;
638
+ }
639
+ /**
640
+ * @inheritDoc
641
+ *
642
+ * @throws {Error} If swap is not in the correct state (must be {@link ToBTCSwapState.CREATED})
643
+ */
644
+ async waitTillCommited(abortSignal) {
645
+ if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.CLAIMED)
646
+ return Promise.resolve();
647
+ if (this._state !== ToBTCSwapState.CREATED && this._state !== ToBTCSwapState.QUOTE_SOFT_EXPIRED)
648
+ throw new Error("Invalid state (not CREATED)");
649
+ const abortController = (0, Utils_1.extendAbortController)(abortSignal);
650
+ let result;
651
+ try {
652
+ result = await Promise.race([
653
+ this.watchdogWaitTillCommited(undefined, abortController.signal),
654
+ this.waitTillState(ToBTCSwapState.COMMITED, "gte", abortController.signal).then(() => 0)
655
+ ]);
656
+ abortController.abort();
657
+ }
658
+ catch (e) {
659
+ abortController.abort();
660
+ throw e;
661
+ }
662
+ if (result === 0) {
663
+ this.logger.debug("waitTillCommited(): Resolved from state change");
664
+ }
665
+ else if (result != null) {
666
+ this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
667
+ }
668
+ if (result === null) {
669
+ this.logger.debug("waitTillCommited(): Resolved from watchdog - signature expiry");
670
+ if (this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.CREATED) {
671
+ await this._saveAndEmit(ToBTCSwapState.QUOTE_EXPIRED);
672
+ }
673
+ throw new Error("Quote expired while waiting for transaction confirmation!");
674
+ }
675
+ if (this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED || this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_EXPIRED) {
676
+ if (typeof (result) === "object" && result.getInitTxId != null && this._commitTxId == null)
677
+ this._commitTxId = await result.getInitTxId();
678
+ await this._saveAndEmit(ToBTCSwapState.COMMITED);
679
+ }
680
+ }
681
+ //////////////////////////////
682
+ //// Payment
683
+ /**
684
+ * Waits till the swap is processed by the intermediary (LP)
685
+ *
686
+ * @param checkIntervalSeconds How often to poll the intermediary for status (5 seconds default)
687
+ * @param abortSignal Abort signal
688
+ * @internal
689
+ */
690
+ async waitTillIntermediarySwapProcessed(checkIntervalSeconds, abortSignal) {
691
+ if (this.url == null)
692
+ throw new Error("LP URL not specified!");
693
+ checkIntervalSeconds ??= 5;
694
+ let resp = { code: IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING, msg: "" };
695
+ while (!abortSignal?.aborted && (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING || resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND)) {
696
+ resp = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
697
+ if (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID) {
698
+ const validResponse = await this._setPaymentResult(resp.data, true);
699
+ if (validResponse) {
700
+ if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.REFUNDABLE) {
701
+ await this._saveAndEmit(ToBTCSwapState.SOFT_CLAIMED);
702
+ }
703
+ }
704
+ else {
705
+ resp = { code: IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING, msg: "" };
706
+ }
707
+ }
708
+ if (resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.PENDING ||
709
+ resp.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND)
710
+ await (0, TimeoutUtils_1.timeoutPromise)(checkIntervalSeconds * 1000, abortSignal);
711
+ }
712
+ return resp;
713
+ }
714
+ /**
715
+ * Checks whether the swap was already processed by the LP and is either successful (requires proof which is
716
+ * either a HTLC pre-image for LN swaps or valid txId for on-chain swap) or failed and we can cooperatively
717
+ * refund.
718
+ *
719
+ * @param save whether to save the data
720
+ * @returns `true` if swap is processed, `false` if the swap is still ongoing
721
+ *
722
+ * @internal
723
+ */
724
+ async checkIntermediarySwapProcessed(save = true) {
725
+ if (this._state === ToBTCSwapState.CREATED || this._state == ToBTCSwapState.QUOTE_EXPIRED || this.url == null)
726
+ return false;
727
+ if (this.isFinished() || this.isRefundable())
728
+ return true;
729
+ //Check if that maybe already concluded according to the LP
730
+ const resp = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
731
+ switch (resp.code) {
732
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID:
733
+ const processed = await this._setPaymentResult(resp.data, true);
734
+ if (processed) {
735
+ this._state = ToBTCSwapState.SOFT_CLAIMED;
736
+ if (save)
737
+ await this._saveAndEmit();
738
+ }
739
+ return processed;
740
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA:
741
+ await this._contract.isValidRefundAuthorization(this._data, resp.data);
742
+ this._state = ToBTCSwapState.REFUNDABLE;
743
+ if (save)
744
+ await this._saveAndEmit();
745
+ return true;
746
+ default:
747
+ return false;
748
+ }
749
+ }
750
+ /**
751
+ * A blocking promise resolving when swap was concluded by the intermediary (LP),
752
+ * rejecting in case of failure
753
+ *
754
+ * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled, an error is thrown if the
755
+ * swap is taking too long to claim
756
+ * @param checkIntervalSeconds How often to poll the intermediary for answer
757
+ * @param abortSignal Abort signal
758
+ * @returns `true` if swap was successful, `false` if swap failed and we can refund
759
+ *
760
+ * @throws {IntermediaryError} If a swap is determined expired by the intermediary, but it is actually still valid
761
+ * @throws {SignatureVerificationError} If the swap should be cooperatively refundable but the intermediary returned
762
+ * invalid refund signature
763
+ * @throws {Error} When swap expires or if the swap has invalid state (must be {@link ToBTCSwapState.COMMITED})
764
+ */
765
+ async waitForPayment(maxWaitTimeSeconds, checkIntervalSeconds, abortSignal) {
766
+ if (this._state === ToBTCSwapState.CLAIMED)
767
+ return Promise.resolve(true);
768
+ if (this._state !== ToBTCSwapState.COMMITED && this._state !== ToBTCSwapState.SOFT_CLAIMED)
769
+ throw new Error("Invalid state (not COMMITED)");
770
+ const abortController = (0, Utils_1.extendAbortController)(abortSignal);
771
+ let timedOut = false;
772
+ if (maxWaitTimeSeconds != null) {
773
+ const timeout = setTimeout(() => {
774
+ timedOut = true;
775
+ abortController.abort();
776
+ }, maxWaitTimeSeconds * 1000);
777
+ abortController.signal.addEventListener("abort", () => clearTimeout(timeout));
778
+ }
779
+ let result;
780
+ try {
781
+ result = await Promise.race([
782
+ this.waitTillState(ToBTCSwapState.CLAIMED, "gte", abortController.signal),
783
+ this.waitTillIntermediarySwapProcessed(checkIntervalSeconds, abortController.signal)
784
+ ]);
785
+ abortController.abort();
786
+ }
787
+ catch (e) {
788
+ abortController.abort();
789
+ if (timedOut) {
790
+ throw new Error("Timed out while waiting for LP to process the swap, the LP might be unresponsive or offline!" +
791
+ ` Please check later or wait till ${new Date(Number(this._data.getExpiry()) * 1000).toLocaleString()} to refund unilaterally!`);
792
+ }
793
+ throw e;
794
+ }
795
+ if (typeof result !== "object") {
796
+ if (this._state === ToBTCSwapState.REFUNDABLE)
797
+ throw new Error("Swap expired");
798
+ this.logger.debug("waitTillRefunded(): Resolved from state change");
799
+ return true;
800
+ }
801
+ this.logger.debug("waitTillRefunded(): Resolved from intermediary response");
802
+ switch (result.code) {
803
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.PAID:
804
+ return true;
805
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA:
806
+ const resultData = result.data;
807
+ await this._contract.isValidRefundAuthorization(this._data, resultData);
808
+ await this._saveAndEmit(ToBTCSwapState.REFUNDABLE);
809
+ return false;
810
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.EXPIRED:
811
+ if (await this._contract.isExpired(this._getInitiator(), this._data))
812
+ throw new Error("Swap expired");
813
+ throw new IntermediaryError_1.IntermediaryError("Swap expired");
814
+ case IntermediaryAPI_1.RefundAuthorizationResponseCodes.NOT_FOUND:
815
+ if (this._state === ToBTCSwapState.CLAIMED)
816
+ return true;
817
+ throw new Error("LP swap not found");
818
+ }
819
+ throw new Error("Invalid response code returned by the LP");
820
+ }
821
+ //////////////////////////////
822
+ //// Refund
823
+ /**
824
+ * Get the estimated smart chain transaction fee of the refund transaction
825
+ */
826
+ async getRefundNetworkFee() {
827
+ const swapContract = this._contract;
828
+ return (0, TokenAmount_1.toTokenAmount)(await swapContract.getRefundFee(this._getInitiator(), this._data), this.wrapper._getNativeToken(), this.wrapper._prices);
829
+ }
830
+ /**
831
+ * @inheritDoc
832
+ *
833
+ * @throws {IntermediaryError} If intermediary returns invalid response in case cooperative refund should be used
834
+ * @throws {SignatureVerificationError} If intermediary returned invalid cooperative refund signature
835
+ * @throws {Error} When state is not refundable
836
+ */
837
+ async txsRefund(_signer) {
838
+ if (!this.isRefundable())
839
+ throw new Error("Must be in REFUNDABLE state or expired!");
840
+ let signer;
841
+ if (_signer != null) {
842
+ if (typeof (_signer) === "string") {
843
+ signer = _signer;
844
+ }
845
+ else if ((0, base_1.isAbstractSigner)(_signer)) {
846
+ signer = _signer.getAddress();
847
+ }
848
+ else {
849
+ signer = (await this.wrapper._chain.wrapSigner(_signer)).getAddress();
850
+ }
851
+ }
852
+ else {
853
+ signer = this._getInitiator();
854
+ }
855
+ if (await this._contract.isExpired(this._getInitiator(), this._data)) {
856
+ return await this._contract.txsRefund(signer, this._data, true, true);
857
+ }
858
+ else {
859
+ if (this.url == null)
860
+ throw new Error("LP URL not known, cannot get cooperative refund message, wait till expiry to refund!");
861
+ const res = await this.wrapper._lpApi.getRefundAuthorization(this.url, this.getLpIdentifier(), this._data.getSequence());
862
+ if (res.code === IntermediaryAPI_1.RefundAuthorizationResponseCodes.REFUND_DATA) {
863
+ return await this._contract.txsRefundWithAuthorization(signer, this._data, res.data, true, true);
864
+ }
865
+ throw new IntermediaryError_1.IntermediaryError("Invalid intermediary cooperative message returned");
866
+ }
867
+ }
868
+ /**
869
+ * @inheritDoc
870
+ *
871
+ * @throws {Error} If invalid signer is provided that doesn't match the swap data
872
+ */
873
+ async refund(_signer, abortSignal) {
874
+ const signer = (0, base_1.isAbstractSigner)(_signer) ? _signer : await this.wrapper._chain.wrapSigner(_signer);
875
+ const result = await this.wrapper._chain.sendAndConfirm(signer, await this.txsRefund(signer.getAddress()), true, abortSignal);
876
+ this._refundTxId = result[0];
877
+ if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.REFUNDABLE || this._state === ToBTCSwapState.SOFT_CLAIMED) {
878
+ await this._saveAndEmit(ToBTCSwapState.REFUNDED);
879
+ }
880
+ return result[0];
881
+ }
882
+ /**
883
+ * @inheritDoc
884
+ *
885
+ * @throws {Error} When swap is not in a valid state (must be {@link ToBTCSwapState.COMMITED} or
886
+ * {@link ToBTCSwapState.REFUNDABLE})
887
+ * @throws {Error} If we tried to refund but claimer was able to claim first
888
+ */
889
+ async waitTillRefunded(abortSignal) {
890
+ if (this._state === ToBTCSwapState.REFUNDED)
891
+ return Promise.resolve();
892
+ if (this._state !== ToBTCSwapState.COMMITED &&
893
+ this._state !== ToBTCSwapState.SOFT_CLAIMED &&
894
+ this._state !== ToBTCSwapState.REFUNDABLE)
895
+ throw new Error("Invalid state (not COMMITED)");
896
+ const abortController = new AbortController();
897
+ if (abortSignal != null)
898
+ abortSignal.addEventListener("abort", () => abortController.abort(abortSignal.reason));
899
+ const res = await Promise.race([
900
+ this.watchdogWaitTillResult(undefined, abortController.signal),
901
+ this.waitTillState(ToBTCSwapState.REFUNDED, "eq", abortController.signal).then(() => 0),
902
+ this.waitTillState(ToBTCSwapState.CLAIMED, "eq", abortController.signal).then(() => 1),
903
+ ]);
904
+ abortController.abort();
905
+ if (res === 0) {
906
+ this.logger.debug("waitTillRefunded(): Resolved from state change (REFUNDED)");
907
+ return;
908
+ }
909
+ if (res === 1) {
910
+ this.logger.debug("waitTillRefunded(): Resolved from state change (CLAIMED)");
911
+ throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
912
+ }
913
+ this.logger.debug("waitTillRefunded(): Resolved from watchdog");
914
+ if (res?.type === base_1.SwapCommitStateType.PAID) {
915
+ if (this._claimTxId == null)
916
+ this._claimTxId = await res.getClaimTxId();
917
+ await this._saveAndEmit(ToBTCSwapState.CLAIMED);
918
+ throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
919
+ }
920
+ if (res?.type === base_1.SwapCommitStateType.NOT_COMMITED) {
921
+ if (this._refundTxId == null && res.getRefundTxId != null)
922
+ this._refundTxId = await res.getRefundTxId();
923
+ await this._saveAndEmit(ToBTCSwapState.REFUNDED);
924
+ }
925
+ }
926
+ //////////////////////////////
927
+ //// Storage
928
+ /**
929
+ * @inheritDoc
930
+ */
931
+ serialize() {
932
+ const obj = super.serialize();
933
+ return {
934
+ ...obj,
935
+ networkFee: this.networkFee == null ? null : this.networkFee.toString(10),
936
+ networkFeeBtc: this.networkFeeBtc == null ? null : this.networkFeeBtc.toString(10)
937
+ };
938
+ }
939
+ //////////////////////////////
940
+ //// Swap ticks & sync
941
+ /**
942
+ * Checks the swap's state on-chain and compares it to its internal state, updates/changes it according to on-chain
943
+ * data
944
+ *
945
+ * @private
946
+ */
947
+ async syncStateFromChain(quoteDefinitelyExpired, commitStatus) {
948
+ if (this._state === ToBTCSwapState.CREATED ||
949
+ this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
950
+ this._state === ToBTCSwapState.COMMITED ||
951
+ this._state === ToBTCSwapState.SOFT_CLAIMED ||
952
+ this._state === ToBTCSwapState.REFUNDABLE) {
953
+ let quoteExpired = false;
954
+ if (this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED) {
955
+ //Check if quote is still valid
956
+ quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired();
957
+ }
958
+ commitStatus ??= await this._contract.getCommitStatus(this._getInitiator(), this._data);
959
+ if (commitStatus != null && await this._forciblySetOnchainState(commitStatus))
960
+ return true;
961
+ if ((this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED)) {
962
+ if (quoteExpired) {
963
+ this._state = ToBTCSwapState.QUOTE_EXPIRED;
964
+ return true;
965
+ }
966
+ }
967
+ }
968
+ return false;
969
+ }
970
+ /**
971
+ * @inheritDoc
972
+ * @internal
973
+ */
974
+ _shouldFetchOnchainState() {
975
+ return this._state === ToBTCSwapState.CREATED ||
976
+ this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
977
+ this._state === ToBTCSwapState.COMMITED ||
978
+ this._state === ToBTCSwapState.SOFT_CLAIMED ||
979
+ this._state === ToBTCSwapState.REFUNDABLE;
980
+ }
981
+ /**
982
+ * @inheritDoc
983
+ * @internal
984
+ */
985
+ _shouldFetchExpiryStatus() {
986
+ return this._state === ToBTCSwapState.CREATED || this._state === ToBTCSwapState.QUOTE_SOFT_EXPIRED;
987
+ }
988
+ /**
989
+ * @inheritDoc
990
+ * @internal
991
+ */
992
+ async _sync(save, quoteDefinitelyExpired, commitStatus) {
993
+ let changed = await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus);
994
+ if (this._state === ToBTCSwapState.COMMITED || this._state === ToBTCSwapState.SOFT_CLAIMED) {
995
+ //Check if that maybe already concluded
996
+ try {
997
+ if (await this.checkIntermediarySwapProcessed(false))
998
+ changed = true;
999
+ }
1000
+ catch (e) {
1001
+ this.logger.error("_sync(): Failed to synchronize swap, error: ", e);
1002
+ }
1003
+ }
1004
+ if (save && changed)
1005
+ await this._saveAndEmit();
1006
+ return changed;
1007
+ }
1008
+ /**
1009
+ * @inheritDoc
1010
+ * @internal
1011
+ */
1012
+ async _forciblySetOnchainState(commitStatus) {
1013
+ switch (commitStatus.type) {
1014
+ case base_1.SwapCommitStateType.PAID:
1015
+ if (this._commitTxId == null && commitStatus.getInitTxId != null)
1016
+ this._commitTxId = await commitStatus.getInitTxId();
1017
+ if (this._claimTxId == null && commitStatus.getClaimTxId)
1018
+ this._claimTxId = await commitStatus.getClaimTxId();
1019
+ const eventResult = await commitStatus.getClaimResult();
1020
+ try {
1021
+ await this._setPaymentResult({ secret: eventResult, txId: Buffer.from(eventResult, "hex").reverse().toString("hex") });
1022
+ }
1023
+ catch (e) {
1024
+ this.logger.error(`Failed to set payment result ${eventResult} on the swap!`);
1025
+ }
1026
+ this._state = ToBTCSwapState.CLAIMED;
1027
+ return true;
1028
+ case base_1.SwapCommitStateType.REFUNDABLE:
1029
+ if (this._commitTxId == null && commitStatus.getInitTxId != null)
1030
+ this._commitTxId = await commitStatus.getInitTxId();
1031
+ this._state = ToBTCSwapState.REFUNDABLE;
1032
+ return true;
1033
+ case base_1.SwapCommitStateType.EXPIRED:
1034
+ if (this._commitTxId == null && commitStatus.getInitTxId != null)
1035
+ this._commitTxId = await commitStatus.getInitTxId();
1036
+ if (this._refundTxId == null && commitStatus.getRefundTxId)
1037
+ this._refundTxId = await commitStatus.getRefundTxId();
1038
+ this._state = this._refundTxId == null ? ToBTCSwapState.QUOTE_EXPIRED : ToBTCSwapState.REFUNDED;
1039
+ return true;
1040
+ case base_1.SwapCommitStateType.NOT_COMMITED:
1041
+ let changed = false;
1042
+ if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1043
+ this._commitTxId = await commitStatus.getInitTxId();
1044
+ changed = true;
1045
+ }
1046
+ if (this._refundTxId == null && commitStatus.getRefundTxId) {
1047
+ this._refundTxId = await commitStatus.getRefundTxId();
1048
+ changed = true;
1049
+ }
1050
+ if (this._refundTxId != null) {
1051
+ this._state = ToBTCSwapState.REFUNDED;
1052
+ changed = true;
1053
+ }
1054
+ return changed;
1055
+ case base_1.SwapCommitStateType.COMMITED:
1056
+ let save = false;
1057
+ if (this._commitTxId == null && commitStatus.getInitTxId != null) {
1058
+ this._commitTxId = await commitStatus.getInitTxId();
1059
+ save = true;
1060
+ }
1061
+ if (this._state !== ToBTCSwapState.COMMITED && this._state !== ToBTCSwapState.REFUNDABLE && this._state !== ToBTCSwapState.SOFT_CLAIMED) {
1062
+ this._state = ToBTCSwapState.COMMITED;
1063
+ save = true;
1064
+ }
1065
+ return save;
1066
+ }
1067
+ return false;
1068
+ }
1069
+ /**
1070
+ * @inheritDoc
1071
+ * @internal
1072
+ */
1073
+ async _tick(save) {
1074
+ switch (this._state) {
1075
+ case ToBTCSwapState.CREATED:
1076
+ if (this.expiry < Date.now()) {
1077
+ this._state = ToBTCSwapState.QUOTE_SOFT_EXPIRED;
1078
+ if (save)
1079
+ await this._saveAndEmit();
1080
+ return true;
1081
+ }
1082
+ break;
1083
+ case ToBTCSwapState.COMMITED:
1084
+ case ToBTCSwapState.SOFT_CLAIMED:
1085
+ const expired = await this._contract.isExpired(this._getInitiator(), this._data);
1086
+ if (expired) {
1087
+ this._state = ToBTCSwapState.REFUNDABLE;
1088
+ if (save)
1089
+ await this._saveAndEmit();
1090
+ return true;
1091
+ }
1092
+ break;
1093
+ }
1094
+ return false;
1095
+ }
1096
+ }
1097
+ exports.IToBTCSwap = IToBTCSwap;