@atomiqlabs/sdk 7.0.12 → 8.0.7

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 (364) hide show
  1. package/README.md +45 -29
  2. package/dist/SmartChainAssets.d.ts +11 -3
  3. package/dist/SmartChainAssets.js +7 -3
  4. package/dist/bitcoin/BitcoinRpcWithAddressIndex.d.ts +68 -0
  5. package/dist/bitcoin/BitcoinRpcWithAddressIndex.js +2 -0
  6. package/dist/bitcoin/LightningNetworkApi.d.ts +12 -0
  7. package/dist/bitcoin/LightningNetworkApi.js +2 -0
  8. package/dist/bitcoin/coinselect2/accumulative.d.ts +6 -0
  9. package/dist/bitcoin/coinselect2/accumulative.js +52 -0
  10. package/dist/bitcoin/coinselect2/blackjack.d.ts +6 -0
  11. package/dist/bitcoin/coinselect2/blackjack.js +38 -0
  12. package/dist/bitcoin/coinselect2/index.d.ts +19 -0
  13. package/dist/bitcoin/coinselect2/index.js +69 -0
  14. package/dist/bitcoin/coinselect2/utils.d.ts +71 -0
  15. package/dist/bitcoin/coinselect2/utils.js +123 -0
  16. package/dist/bitcoin/mempool/MempoolApi.d.ts +350 -0
  17. package/dist/bitcoin/mempool/MempoolApi.js +311 -0
  18. package/dist/bitcoin/mempool/MempoolBitcoinBlock.d.ts +44 -0
  19. package/dist/bitcoin/mempool/MempoolBitcoinBlock.js +48 -0
  20. package/dist/bitcoin/mempool/MempoolBitcoinRpc.d.ts +119 -0
  21. package/dist/bitcoin/mempool/MempoolBitcoinRpc.js +361 -0
  22. package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.d.ts +22 -0
  23. package/dist/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.js +105 -0
  24. package/dist/bitcoin/wallet/BitcoinWallet.d.ts +93 -0
  25. package/dist/bitcoin/wallet/BitcoinWallet.js +273 -0
  26. package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +28 -0
  27. package/dist/bitcoin/wallet/IBitcoinWallet.js +20 -0
  28. package/dist/bitcoin/wallet/MinimalBitcoinWalletInterface.d.ts +21 -0
  29. package/dist/bitcoin/wallet/MinimalBitcoinWalletInterface.js +2 -0
  30. package/dist/bitcoin/wallet/MinimalLightningNetworkWalletInterface.d.ts +7 -0
  31. package/dist/bitcoin/wallet/MinimalLightningNetworkWalletInterface.js +2 -0
  32. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +40 -0
  33. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +86 -0
  34. package/dist/enums/FeeType.d.ts +8 -0
  35. package/dist/enums/FeeType.js +12 -0
  36. package/dist/enums/SwapAmountType.d.ts +8 -0
  37. package/dist/enums/SwapAmountType.js +12 -0
  38. package/dist/enums/SwapDirection.d.ts +8 -0
  39. package/dist/enums/SwapDirection.js +12 -0
  40. package/dist/enums/SwapType.d.ts +14 -0
  41. package/dist/enums/SwapType.js +18 -0
  42. package/dist/errors/IntermediaryError.d.ts +9 -0
  43. package/dist/errors/IntermediaryError.js +26 -0
  44. package/dist/errors/PaymentAuthError.d.ts +11 -0
  45. package/dist/errors/PaymentAuthError.js +23 -0
  46. package/dist/errors/RequestError.d.ts +18 -0
  47. package/dist/errors/RequestError.js +46 -0
  48. package/dist/errors/UserError.d.ts +7 -0
  49. package/dist/errors/UserError.js +15 -0
  50. package/dist/events/UnifiedSwapEventListener.d.ts +23 -0
  51. package/dist/events/UnifiedSwapEventListener.js +130 -0
  52. package/dist/http/HttpUtils.d.ts +27 -0
  53. package/dist/http/HttpUtils.js +91 -0
  54. package/dist/http/paramcoders/IParamReader.d.ts +8 -0
  55. package/dist/http/paramcoders/IParamReader.js +2 -0
  56. package/dist/http/paramcoders/ParamDecoder.d.ts +44 -0
  57. package/dist/http/paramcoders/ParamDecoder.js +132 -0
  58. package/dist/http/paramcoders/ParamEncoder.d.ts +20 -0
  59. package/dist/http/paramcoders/ParamEncoder.js +31 -0
  60. package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -0
  61. package/dist/http/paramcoders/SchemaVerifier.js +145 -0
  62. package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -0
  63. package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -0
  64. package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +13 -0
  65. package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -0
  66. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +16 -0
  67. package/dist/http/paramcoders/client/StreamingFetchPromise.js +174 -0
  68. package/dist/index.d.ts +82 -4
  69. package/dist/index.js +128 -4
  70. package/dist/intermediaries/Intermediary.d.ts +111 -0
  71. package/dist/intermediaries/Intermediary.js +115 -0
  72. package/dist/intermediaries/IntermediaryDiscovery.d.ts +166 -0
  73. package/dist/intermediaries/IntermediaryDiscovery.js +390 -0
  74. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +436 -0
  75. package/dist/intermediaries/apis/IntermediaryAPI.js +600 -0
  76. package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +154 -0
  77. package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +136 -0
  78. package/dist/lnurl/LNURL.d.ts +102 -0
  79. package/dist/lnurl/LNURL.js +321 -0
  80. package/dist/prices/RedundantSwapPrice.d.ts +89 -0
  81. package/dist/prices/RedundantSwapPrice.js +202 -0
  82. package/dist/prices/SingleSwapPrice.d.ts +31 -0
  83. package/dist/prices/SingleSwapPrice.js +41 -0
  84. package/dist/prices/SwapPriceWithChain.d.ts +70 -0
  85. package/dist/prices/SwapPriceWithChain.js +91 -0
  86. package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -0
  87. package/dist/prices/abstract/ICachedSwapPrice.js +62 -0
  88. package/dist/prices/abstract/IPriceProvider.d.ts +81 -0
  89. package/dist/prices/abstract/IPriceProvider.js +74 -0
  90. package/dist/prices/abstract/ISwapPrice.d.ts +117 -0
  91. package/dist/prices/abstract/ISwapPrice.js +219 -0
  92. package/dist/prices/providers/BinancePriceProvider.d.ts +16 -0
  93. package/dist/prices/providers/BinancePriceProvider.js +23 -0
  94. package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +17 -0
  95. package/dist/prices/providers/CoinGeckoPriceProvider.js +23 -0
  96. package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +19 -0
  97. package/dist/prices/providers/CoinPaprikaPriceProvider.js +23 -0
  98. package/dist/prices/providers/CustomPriceProvider.d.ts +13 -0
  99. package/dist/prices/providers/CustomPriceProvider.js +24 -0
  100. package/dist/prices/providers/KrakenPriceProvider.d.ts +29 -0
  101. package/dist/prices/providers/KrakenPriceProvider.js +36 -0
  102. package/dist/prices/providers/OKXPriceProvider.d.ts +28 -0
  103. package/dist/prices/providers/OKXPriceProvider.js +23 -0
  104. package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +14 -0
  105. package/dist/prices/providers/abstract/ExchangePriceProvider.js +18 -0
  106. package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -0
  107. package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -0
  108. package/dist/storage/IUnifiedStorage.d.ts +73 -0
  109. package/dist/storage/IUnifiedStorage.js +2 -0
  110. package/dist/storage/UnifiedSwapStorage.d.ts +82 -0
  111. package/dist/storage/UnifiedSwapStorage.js +83 -0
  112. package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +39 -0
  113. package/dist/storage-browser/IndexedDBUnifiedStorage.js +275 -0
  114. package/dist/{storage → storage-browser}/LocalStorageManager.d.ts +1 -0
  115. package/dist/{storage → storage-browser}/LocalStorageManager.js +2 -1
  116. package/dist/swapper/Swapper.d.ts +533 -0
  117. package/dist/swapper/Swapper.js +1566 -0
  118. package/dist/swapper/SwapperFactory.d.ts +87 -0
  119. package/dist/{SwapperFactory.js → swapper/SwapperFactory.js} +37 -19
  120. package/dist/swapper/SwapperUtils.d.ts +153 -0
  121. package/dist/swapper/SwapperUtils.js +420 -0
  122. package/dist/swapper/SwapperWithChain.d.ts +214 -0
  123. package/dist/swapper/SwapperWithChain.js +315 -0
  124. package/dist/swapper/SwapperWithSigner.d.ts +178 -0
  125. package/dist/swapper/SwapperWithSigner.js +172 -0
  126. package/dist/swaps/IAddressSwap.d.ts +13 -0
  127. package/dist/swaps/IAddressSwap.js +13 -0
  128. package/dist/swaps/IBTCWalletSwap.d.ts +55 -0
  129. package/dist/swaps/IBTCWalletSwap.js +17 -0
  130. package/dist/swaps/IClaimableSwap.d.ts +17 -0
  131. package/dist/swaps/IClaimableSwap.js +14 -0
  132. package/dist/swaps/IClaimableSwapWrapper.d.ts +5 -0
  133. package/dist/swaps/IClaimableSwapWrapper.js +2 -0
  134. package/dist/swaps/IRefundableSwap.d.ts +17 -0
  135. package/dist/swaps/IRefundableSwap.js +13 -0
  136. package/dist/swaps/ISwap.d.ts +207 -0
  137. package/dist/swaps/ISwap.js +264 -0
  138. package/dist/swaps/ISwapWithGasDrop.d.ts +15 -0
  139. package/dist/swaps/ISwapWithGasDrop.js +11 -0
  140. package/dist/swaps/ISwapWrapper.d.ts +153 -0
  141. package/dist/swaps/ISwapWrapper.js +227 -0
  142. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +53 -0
  143. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +116 -0
  144. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +70 -0
  145. package/dist/swaps/escrow_swaps/IEscrowSwap.js +132 -0
  146. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +85 -0
  147. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +122 -0
  148. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +86 -0
  149. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +115 -0
  150. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +93 -0
  151. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +121 -0
  152. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +45 -0
  153. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +65 -0
  154. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +263 -0
  155. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +933 -0
  156. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +110 -0
  157. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +307 -0
  158. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +236 -0
  159. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +898 -0
  160. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +125 -0
  161. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +393 -0
  162. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +245 -0
  163. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +841 -0
  164. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +120 -0
  165. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +294 -0
  166. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +228 -0
  167. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +721 -0
  168. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +37 -0
  169. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +93 -0
  170. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +86 -0
  171. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +213 -0
  172. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +170 -0
  173. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +520 -0
  174. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +50 -0
  175. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +109 -0
  176. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +93 -0
  177. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +217 -0
  178. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +315 -0
  179. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1098 -0
  180. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +125 -0
  181. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +631 -0
  182. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +107 -0
  183. package/dist/swaps/trusted/ln/LnForGasSwap.js +343 -0
  184. package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +21 -0
  185. package/dist/swaps/trusted/ln/LnForGasWrapper.js +62 -0
  186. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +164 -0
  187. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +520 -0
  188. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +48 -0
  189. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +74 -0
  190. package/dist/types/AmountData.d.ts +9 -0
  191. package/dist/types/AmountData.js +2 -0
  192. package/dist/types/CustomPriceFunction.d.ts +5 -0
  193. package/dist/types/CustomPriceFunction.js +2 -0
  194. package/dist/types/PriceInfoType.d.ts +28 -0
  195. package/dist/types/PriceInfoType.js +57 -0
  196. package/dist/types/SwapExecutionAction.d.ts +7 -0
  197. package/dist/types/SwapExecutionAction.js +2 -0
  198. package/dist/types/SwapWithSigner.d.ts +14 -0
  199. package/dist/types/SwapWithSigner.js +40 -0
  200. package/dist/types/Token.d.ts +53 -0
  201. package/dist/types/Token.js +58 -0
  202. package/dist/types/TokenAmount.d.ts +57 -0
  203. package/dist/types/TokenAmount.js +47 -0
  204. package/dist/types/fees/Fee.d.ts +49 -0
  205. package/dist/types/fees/Fee.js +2 -0
  206. package/dist/types/fees/FeeBreakdown.d.ts +10 -0
  207. package/dist/types/fees/FeeBreakdown.js +2 -0
  208. package/dist/types/fees/PercentagePPM.d.ts +15 -0
  209. package/dist/types/fees/PercentagePPM.js +17 -0
  210. package/dist/types/lnurl/LNURLPay.d.ts +54 -0
  211. package/dist/types/lnurl/LNURLPay.js +28 -0
  212. package/dist/types/lnurl/LNURLWithdraw.d.ts +42 -0
  213. package/dist/types/lnurl/LNURLWithdraw.js +24 -0
  214. package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -0
  215. package/dist/utils/AutomaticClockDriftCorrection.js +70 -0
  216. package/dist/utils/BitcoinUtils.d.ts +13 -0
  217. package/dist/utils/BitcoinUtils.js +98 -0
  218. package/dist/utils/BitcoinWalletUtils.d.ts +7 -0
  219. package/dist/utils/BitcoinWalletUtils.js +14 -0
  220. package/dist/utils/Logger.d.ts +7 -0
  221. package/dist/utils/Logger.js +12 -0
  222. package/dist/utils/RetryUtils.d.ts +21 -0
  223. package/dist/utils/RetryUtils.js +66 -0
  224. package/dist/utils/SwapUtils.d.ts +31 -0
  225. package/dist/utils/SwapUtils.js +18 -0
  226. package/dist/{Utils.d.ts → utils/TimeoutUtils.d.ts} +9 -3
  227. package/dist/utils/TimeoutUtils.js +55 -0
  228. package/dist/utils/TokenUtils.d.ts +11 -0
  229. package/dist/utils/TokenUtils.js +29 -0
  230. package/dist/utils/TypeUtils.d.ts +7 -0
  231. package/dist/utils/TypeUtils.js +2 -0
  232. package/dist/utils/Utils.d.ts +57 -0
  233. package/dist/utils/Utils.js +178 -0
  234. package/package.json +14 -6
  235. package/src/SmartChainAssets.ts +11 -3
  236. package/src/bitcoin/BitcoinRpcWithAddressIndex.ts +87 -0
  237. package/src/bitcoin/LightningNetworkApi.ts +16 -0
  238. package/src/bitcoin/coinselect2/accumulative.ts +68 -0
  239. package/src/bitcoin/coinselect2/blackjack.ts +49 -0
  240. package/src/bitcoin/coinselect2/index.ts +92 -0
  241. package/src/bitcoin/coinselect2/utils.ts +189 -0
  242. package/src/bitcoin/mempool/MempoolApi.ts +554 -0
  243. package/src/bitcoin/mempool/MempoolBitcoinBlock.ts +88 -0
  244. package/src/bitcoin/mempool/MempoolBitcoinRpc.ts +437 -0
  245. package/src/bitcoin/mempool/synchronizer/MempoolBtcRelaySynchronizer.ts +134 -0
  246. package/src/bitcoin/wallet/BitcoinWallet.ts +375 -0
  247. package/src/bitcoin/wallet/IBitcoinWallet.ts +44 -0
  248. package/src/bitcoin/wallet/MinimalBitcoinWalletInterface.ts +19 -0
  249. package/src/bitcoin/wallet/MinimalLightningNetworkWalletInterface.ts +7 -0
  250. package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +108 -0
  251. package/src/enums/FeeType.ts +9 -0
  252. package/src/enums/SwapAmountType.ts +9 -0
  253. package/src/enums/SwapDirection.ts +9 -0
  254. package/src/enums/SwapType.ts +15 -0
  255. package/src/errors/IntermediaryError.ts +24 -0
  256. package/src/errors/PaymentAuthError.ts +26 -0
  257. package/src/errors/RequestError.ts +51 -0
  258. package/src/errors/UserError.ts +14 -0
  259. package/src/events/UnifiedSwapEventListener.ts +171 -0
  260. package/src/http/HttpUtils.ts +92 -0
  261. package/src/http/paramcoders/IParamReader.ts +10 -0
  262. package/src/http/paramcoders/ParamDecoder.ts +142 -0
  263. package/src/http/paramcoders/ParamEncoder.ts +37 -0
  264. package/src/http/paramcoders/SchemaVerifier.ts +153 -0
  265. package/src/http/paramcoders/client/ResponseParamDecoder.ts +58 -0
  266. package/src/http/paramcoders/client/StreamParamEncoder.ts +29 -0
  267. package/src/http/paramcoders/client/StreamingFetchPromise.ts +193 -0
  268. package/src/index.ts +102 -4
  269. package/src/intermediaries/Intermediary.ts +204 -0
  270. package/src/intermediaries/IntermediaryDiscovery.ts +485 -0
  271. package/src/intermediaries/apis/IntermediaryAPI.ts +940 -0
  272. package/src/intermediaries/apis/TrustedIntermediaryAPI.ts +257 -0
  273. package/src/lnurl/LNURL.ts +403 -0
  274. package/src/prices/RedundantSwapPrice.ts +245 -0
  275. package/src/prices/SingleSwapPrice.ts +47 -0
  276. package/src/prices/SwapPriceWithChain.ts +157 -0
  277. package/src/prices/abstract/ICachedSwapPrice.ts +86 -0
  278. package/src/prices/abstract/IPriceProvider.ts +128 -0
  279. package/src/prices/abstract/ISwapPrice.ts +328 -0
  280. package/src/prices/providers/BinancePriceProvider.ts +41 -0
  281. package/src/prices/providers/CoinGeckoPriceProvider.ts +40 -0
  282. package/src/prices/providers/CoinPaprikaPriceProvider.ts +44 -0
  283. package/src/prices/providers/CustomPriceProvider.ts +29 -0
  284. package/src/prices/providers/KrakenPriceProvider.ts +74 -0
  285. package/src/prices/providers/OKXPriceProvider.ts +53 -0
  286. package/src/prices/providers/abstract/ExchangePriceProvider.ts +29 -0
  287. package/src/prices/providers/abstract/HttpPriceProvider.ts +15 -0
  288. package/src/storage/IUnifiedStorage.ts +83 -0
  289. package/src/storage/UnifiedSwapStorage.ts +104 -0
  290. package/src/storage-browser/IndexedDBUnifiedStorage.ts +328 -0
  291. package/src/{storage → storage-browser}/LocalStorageManager.ts +2 -1
  292. package/src/swapper/Swapper.ts +2107 -0
  293. package/src/{SwapperFactory.ts → swapper/SwapperFactory.ts} +113 -72
  294. package/src/swapper/SwapperUtils.ts +510 -0
  295. package/src/swapper/SwapperWithChain.ts +464 -0
  296. package/src/swapper/SwapperWithSigner.ts +300 -0
  297. package/src/swaps/IAddressSwap.ts +20 -0
  298. package/src/swaps/IBTCWalletSwap.ts +77 -0
  299. package/src/swaps/IClaimableSwap.ts +30 -0
  300. package/src/swaps/IClaimableSwapWrapper.ts +9 -0
  301. package/src/swaps/IRefundableSwap.ts +29 -0
  302. package/src/swaps/ISwap.ts +490 -0
  303. package/src/swaps/ISwapWithGasDrop.ts +19 -0
  304. package/src/swaps/ISwapWrapper.ts +344 -0
  305. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +168 -0
  306. package/src/swaps/escrow_swaps/IEscrowSwap.ts +197 -0
  307. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +210 -0
  308. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +150 -0
  309. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +219 -0
  310. package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +84 -0
  311. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +1082 -0
  312. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +429 -0
  313. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +1078 -0
  314. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +549 -0
  315. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +974 -0
  316. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +443 -0
  317. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +860 -0
  318. package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +104 -0
  319. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +256 -0
  320. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +716 -0
  321. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +151 -0
  322. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +299 -0
  323. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +1394 -0
  324. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +796 -0
  325. package/src/swaps/trusted/ln/LnForGasSwap.ts +402 -0
  326. package/src/swaps/trusted/ln/LnForGasWrapper.ts +70 -0
  327. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +633 -0
  328. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +110 -0
  329. package/src/types/AmountData.ts +9 -0
  330. package/src/types/CustomPriceFunction.ts +5 -0
  331. package/src/types/PriceInfoType.ts +67 -0
  332. package/src/types/SwapExecutionAction.ts +8 -0
  333. package/src/types/SwapWithSigner.ts +57 -0
  334. package/src/types/Token.ts +90 -0
  335. package/src/types/TokenAmount.ts +110 -0
  336. package/src/types/fees/Fee.ts +55 -0
  337. package/src/types/fees/FeeBreakdown.ts +11 -0
  338. package/src/types/fees/PercentagePPM.ts +24 -0
  339. package/src/types/lnurl/LNURLPay.ts +72 -0
  340. package/src/types/lnurl/LNURLWithdraw.ts +55 -0
  341. package/src/utils/AutomaticClockDriftCorrection.ts +71 -0
  342. package/src/utils/BitcoinUtils.ts +86 -0
  343. package/src/utils/BitcoinWalletUtils.ts +16 -0
  344. package/src/utils/Logger.ts +15 -0
  345. package/src/utils/RetryUtils.ts +71 -0
  346. package/src/utils/SwapUtils.ts +38 -0
  347. package/src/utils/TimeoutUtils.ts +50 -0
  348. package/src/utils/TokenUtils.ts +25 -0
  349. package/src/utils/TypeUtils.ts +9 -0
  350. package/src/utils/Utils.ts +182 -0
  351. package/dist/SwapperFactory.d.ts +0 -52
  352. package/dist/Utils.js +0 -37
  353. package/dist/fs-storage/FileSystemStorageManager.d.ts +0 -15
  354. package/dist/fs-storage/FileSystemStorageManager.js +0 -60
  355. package/dist/fs-storage/index.d.ts +0 -1
  356. package/dist/fs-storage/index.js +0 -17
  357. package/src/SmartChainAssets.js +0 -75
  358. package/src/SwapperFactory.js +0 -120
  359. package/src/Utils.js +0 -37
  360. package/src/Utils.ts +0 -31
  361. package/src/fs-storage/FileSystemStorageManager.ts +0 -71
  362. package/src/fs-storage/index.ts +0 -1
  363. package/src/index.js +0 -21
  364. package/src/storage/LocalStorageManager.js +0 -72
@@ -0,0 +1,974 @@
1
+ import {IFromBTCSelfInitSwap} from "../IFromBTCSelfInitSwap";
2
+ import {SwapType} from "../../../../enums/SwapType";
3
+ import {FromBTCDefinition, FromBTCWrapper} from "./FromBTCWrapper";
4
+ import {ChainType, isAbstractSigner, SwapCommitState, SwapCommitStateType, SwapData} from "@atomiqlabs/base";
5
+ import {Buffer} from "buffer";
6
+ import {
7
+ extendAbortController,
8
+ getTxoHash
9
+ } from "../../../../utils/Utils";
10
+ import {
11
+ parsePsbtTransaction,
12
+ toOutputScript,
13
+ } from "../../../../utils/BitcoinUtils";
14
+ import {IBitcoinWallet, isIBitcoinWallet} from "../../../../bitcoin/wallet/IBitcoinWallet";
15
+ import {IBTCWalletSwap} from "../../../IBTCWalletSwap";
16
+ import {Address, OutScript, Transaction} from "@scure/btc-signer";
17
+ import {SingleAddressBitcoinWallet} from "../../../../bitcoin/wallet/SingleAddressBitcoinWallet";
18
+ import {
19
+ MinimalBitcoinWalletInterface,
20
+ MinimalBitcoinWalletInterfaceWithSigner
21
+ } from "../../../../bitcoin/wallet/MinimalBitcoinWalletInterface";
22
+ import {IClaimableSwap} from "../../../IClaimableSwap";
23
+ import {IEscrowSelfInitSwapInit, isIEscrowSelfInitSwapInit} from "../../IEscrowSelfInitSwap";
24
+ import {IAddressSwap} from "../../../IAddressSwap";
25
+ import {BtcTxWithBlockheight} from "../../../../bitcoin/BitcoinRpcWithAddressIndex";
26
+ import {TokenAmount, toTokenAmount} from "../../../../types/TokenAmount";
27
+ import {BitcoinTokens, BtcToken, SCToken, Token} from "../../../../types/Token";
28
+ import {getLogger, LoggerType} from "../../../../utils/Logger";
29
+ import {toBitcoinWallet} from "../../../../utils/BitcoinWalletUtils";
30
+
31
+ /**
32
+ * State enum for FromBTC swaps
33
+ * @category Swaps
34
+ */
35
+ export enum FromBTCSwapState {
36
+ FAILED = -4,
37
+ EXPIRED = -3,
38
+ QUOTE_EXPIRED = -2,
39
+ QUOTE_SOFT_EXPIRED = -1,
40
+ PR_CREATED = 0,
41
+ CLAIM_COMMITED = 1,
42
+ BTC_TX_CONFIRMED = 2,
43
+ CLAIM_CLAIMED = 3
44
+ }
45
+
46
+ export type FromBTCSwapInit<T extends SwapData> = IEscrowSelfInitSwapInit<T> & {
47
+ data: T;
48
+ feeRate: string;
49
+ address: string;
50
+ amount: bigint;
51
+ requiredConfirmations: number;
52
+ };
53
+
54
+ export function isFromBTCSwapInit<T extends SwapData>(obj: any): obj is FromBTCSwapInit<T> {
55
+ return typeof(obj.address) === "string" &&
56
+ typeof(obj.amount) === "bigint" &&
57
+ typeof(obj.data) === "object" &&
58
+ typeof(obj.requiredConfirmations) === "number" &&
59
+ isIEscrowSelfInitSwapInit<T>(obj);
60
+ }
61
+
62
+ export class FromBTCSwap<T extends ChainType = ChainType>
63
+ extends IFromBTCSelfInitSwap<T, FromBTCDefinition<T>, FromBTCSwapState>
64
+ implements IBTCWalletSwap, IClaimableSwap<T, FromBTCDefinition<T>, FromBTCSwapState>, IAddressSwap {
65
+
66
+ protected readonly logger: LoggerType;
67
+ protected readonly inputToken: BtcToken<false> = BitcoinTokens.BTC;
68
+ protected readonly TYPE = SwapType.FROM_BTC;
69
+
70
+ readonly data!: T["Data"];
71
+ readonly feeRate!: string;
72
+
73
+ address: string;
74
+ amount: bigint;
75
+ readonly requiredConfirmations: number;
76
+
77
+ senderAddress?: string;
78
+ txId?: string;
79
+ vout?: number;
80
+
81
+ constructor(wrapper: FromBTCWrapper<T>, init: FromBTCSwapInit<T["Data"]>);
82
+ constructor(wrapper: FromBTCWrapper<T>, obj: any);
83
+ constructor(wrapper: FromBTCWrapper<T>, initOrObject: FromBTCSwapInit<T["Data"]> | any) {
84
+ if(isFromBTCSwapInit(initOrObject) && initOrObject.url!=null) initOrObject.url += "/frombtc";
85
+ super(wrapper, initOrObject);
86
+ if(isFromBTCSwapInit(initOrObject)) {
87
+ this.state = FromBTCSwapState.PR_CREATED;
88
+ this.data = initOrObject.data;
89
+ this.feeRate = initOrObject.feeRate;
90
+ this.address = initOrObject.address;
91
+ this.amount = initOrObject.amount;
92
+ this.requiredConfirmations = initOrObject.requiredConfirmations;
93
+ } else {
94
+ this.address = initOrObject.address;
95
+ this.amount = BigInt(initOrObject.amount);
96
+ this.senderAddress = initOrObject.senderAddress;
97
+ this.txId = initOrObject.txId;
98
+ this.vout = initOrObject.vout;
99
+ this.requiredConfirmations = initOrObject.requiredConfirmations ?? this.data.getConfirmationsHint();
100
+ }
101
+ this.tryRecomputeSwapPrice();
102
+ this.logger = getLogger("FromBTC("+this.getIdentifierHashString()+"): ");
103
+ }
104
+
105
+ protected getSwapData(): T["Data"] {
106
+ return this.data;
107
+ }
108
+
109
+ protected upgradeVersion() {
110
+ if(this.version == null) {
111
+ switch(this.state) {
112
+ case -2:
113
+ this.state = FromBTCSwapState.FAILED
114
+ break;
115
+ case -1:
116
+ this.state = FromBTCSwapState.QUOTE_EXPIRED
117
+ break;
118
+ case 0:
119
+ this.state = FromBTCSwapState.PR_CREATED
120
+ break;
121
+ case 1:
122
+ this.state = FromBTCSwapState.CLAIM_COMMITED
123
+ break;
124
+ case 2:
125
+ this.state = FromBTCSwapState.BTC_TX_CONFIRMED
126
+ break;
127
+ case 3:
128
+ this.state = FromBTCSwapState.CLAIM_CLAIMED
129
+ break;
130
+ }
131
+ this.version = 1;
132
+ }
133
+ }
134
+
135
+
136
+ //////////////////////////////
137
+ //// Getters & utils
138
+
139
+ /**
140
+ * Returns bitcoin address where the on-chain BTC should be sent to
141
+ */
142
+ getAddress(): string {
143
+ if(this.state===FromBTCSwapState.PR_CREATED) throw new Error("Cannot get bitcoin address of non-committed swap");
144
+ return this.address;
145
+ }
146
+
147
+ /**
148
+ * Unsafe bitcoin hyperlink getter, returns the address even before the swap is committed!
149
+ *
150
+ * @private
151
+ */
152
+ private _getHyperlink(): string {
153
+ return "bitcoin:"+this.address+"?amount="+encodeURIComponent((Number(this.amount) / 100000000).toString(10));
154
+ }
155
+
156
+ getHyperlink(): string {
157
+ if(this.state===FromBTCSwapState.PR_CREATED) throw new Error("Cannot get bitcoin address of non-committed swap");
158
+ return this._getHyperlink();
159
+ }
160
+
161
+ getInputAddress(): string | null {
162
+ return this.senderAddress ?? null;
163
+ }
164
+
165
+ getInputTxId(): string | null {
166
+ return this.txId ?? null;
167
+ }
168
+
169
+ /**
170
+ * Returns timeout time (in UNIX milliseconds) when the on-chain address will expire and no funds should be sent
171
+ * to that address anymore
172
+ */
173
+ getTimeoutTime(): number {
174
+ return Number(this.wrapper.getOnchainSendTimeout(this.data, this.requiredConfirmations)) * 1000;
175
+ }
176
+
177
+ requiresAction(): boolean {
178
+ return this.isClaimable() || (this.state===FromBTCSwapState.CLAIM_COMMITED && this.getTimeoutTime()>Date.now() && this.txId==null);
179
+ }
180
+
181
+ isFinished(): boolean {
182
+ return this.state===FromBTCSwapState.CLAIM_CLAIMED || this.state===FromBTCSwapState.QUOTE_EXPIRED || this.state===FromBTCSwapState.FAILED;
183
+ }
184
+
185
+ isClaimable(): boolean {
186
+ return this.state===FromBTCSwapState.BTC_TX_CONFIRMED;
187
+ }
188
+
189
+ isSuccessful(): boolean {
190
+ return this.state===FromBTCSwapState.CLAIM_CLAIMED;
191
+ }
192
+
193
+ isFailed(): boolean {
194
+ return this.state===FromBTCSwapState.FAILED || this.state===FromBTCSwapState.EXPIRED;
195
+ }
196
+
197
+ isQuoteExpired(): boolean {
198
+ return this.state===FromBTCSwapState.QUOTE_EXPIRED;
199
+ }
200
+
201
+ isQuoteSoftExpired(): boolean {
202
+ return this.state===FromBTCSwapState.QUOTE_EXPIRED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED;
203
+ }
204
+
205
+ protected canCommit(): boolean {
206
+ if(this.state!==FromBTCSwapState.PR_CREATED) return false;
207
+ const expiry = this.wrapper.getOnchainSendTimeout(this.data, this.requiredConfirmations);
208
+ const currentTimestamp = BigInt(Math.floor(Date.now()/1000));
209
+
210
+ return (expiry - currentTimestamp) >= this.wrapper.options.minSendWindow;
211
+ }
212
+
213
+
214
+ //////////////////////////////
215
+ //// Amounts & fees
216
+
217
+ getInputToken(): BtcToken<false> {
218
+ return BitcoinTokens.BTC;
219
+ }
220
+
221
+ getInput(): TokenAmount<T["ChainId"], BtcToken<false>> {
222
+ return toTokenAmount(this.amount, this.inputToken, this.wrapper.prices);
223
+ }
224
+
225
+ /**
226
+ * Returns claimer bounty, acting as a reward for watchtowers to claim the swap automatically
227
+ */
228
+ getClaimerBounty(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>> {
229
+ return toTokenAmount(this.data.getClaimerBounty(), this.wrapper.tokens[this.data.getDepositToken()], this.wrapper.prices);
230
+ }
231
+
232
+
233
+ //////////////////////////////
234
+ //// Bitcoin tx
235
+
236
+ getRequiredConfirmationsCount(): number {
237
+ return this.requiredConfirmations;
238
+ }
239
+
240
+ /**
241
+ * Checks whether a bitcoin payment was already made, returns the payment or null when no payment has been made.
242
+ */
243
+ protected async getBitcoinPayment(): Promise<{
244
+ txId: string,
245
+ vout: number,
246
+ confirmations: number,
247
+ targetConfirmations: number,
248
+ inputAddresses?: string[]
249
+ } | null> {
250
+ const txoHashHint = this.data.getTxoHashHint();
251
+ if(txoHashHint==null) throw new Error("Swap data don't include the txo hash hint! Cannot check btc transaction!");
252
+
253
+ const result = await this.wrapper.btcRpc.checkAddressTxos(this.address, Buffer.from(txoHashHint, "hex"));
254
+ if(result==null) return null;
255
+
256
+ return {
257
+ inputAddresses: result.tx.inputAddresses,
258
+ txId: result.tx.txid,
259
+ vout: result.vout,
260
+ confirmations: result.tx.confirmations ?? 0,
261
+ targetConfirmations: this.requiredConfirmations
262
+ }
263
+ }
264
+
265
+ /**
266
+ * For internal use! Used to set the txId of the bitcoin payment from the on-chain events listener
267
+ *
268
+ * @param txId
269
+ */
270
+ async _setBitcoinTxId(txId: string) {
271
+ if(this.txId!==txId || this.address==null || this.vout==null || this.senderAddress==null || this.amount==null) {
272
+ const btcTx = await this.wrapper.btcRpc.getTransaction(txId);
273
+ if(btcTx==null) return;
274
+
275
+ const txoHashHint = this.data.getTxoHashHint();
276
+ if(txoHashHint!=null) {
277
+ const expectedTxoHash = Buffer.from(txoHashHint, "hex");
278
+ const vout = btcTx.outs.findIndex(out => getTxoHash(out.scriptPubKey.hex, out.value).equals(expectedTxoHash));
279
+ if(vout!==-1) {
280
+ this.vout = vout;
281
+ //If amount or address are not known, parse them from the bitcoin tx
282
+ // this can happen if the swap is recovered from on-chain data and
283
+ // hence doesn't contain the address and amount data
284
+ if(this.amount==null) this.amount = BigInt(btcTx.outs[vout].value);
285
+ if(this.address==null) try {
286
+ const addressData = OutScript.decode(Buffer.from(btcTx.outs[vout].scriptPubKey.hex, "hex"));
287
+ this.address = Address(this.wrapper.options.bitcoinNetwork).encode(addressData);
288
+ } catch (e: any) {
289
+ this.logger.warn("_setBitcoinTxId(): Failed to parse address from output script: ", e);
290
+ }
291
+ }
292
+ }
293
+
294
+ if(btcTx.inputAddresses!=null) {
295
+ this.senderAddress = btcTx.inputAddresses[0];
296
+ }
297
+ }
298
+
299
+ this.txId = txId;
300
+ }
301
+
302
+ /**
303
+ * Waits till the bitcoin transaction confirms and swap becomes claimable
304
+ *
305
+ * @param updateCallback Callback called when txId is found, and also called with subsequent confirmations
306
+ * @param checkIntervalSeconds How often to check the bitcoin transaction
307
+ * @param abortSignal Abort signal
308
+ * @throws {Error} if in invalid state (must be CLAIM_COMMITED)
309
+ */
310
+ async waitForBitcoinTransaction(
311
+ updateCallback?: (txId?: string, confirmations?: number, targetConfirmations?: number, txEtaMs?: number) => void,
312
+ checkIntervalSeconds?: number,
313
+ abortSignal?: AbortSignal
314
+ ): Promise<string> {
315
+ if(this.state!==FromBTCSwapState.CLAIM_COMMITED && this.state!==FromBTCSwapState.EXPIRED) throw new Error("Must be in COMMITED state!");
316
+ const txoHashHint = this.data.getTxoHashHint();
317
+ if(txoHashHint==null) throw new Error("Swap data don't include the txo hash hint! Cannot check btc transaction!");
318
+
319
+ const result = await this.wrapper.btcRpc.waitForAddressTxo(
320
+ this.address,
321
+ Buffer.from(txoHashHint, "hex"),
322
+ this.requiredConfirmations,
323
+ (btcTx?: Omit<BtcTxWithBlockheight, "hex" | "raw">, vout?: number, txEtaMs?: number) => {
324
+ if(updateCallback!=null) updateCallback(btcTx?.txid, btcTx==null ? undefined : (btcTx?.confirmations ?? 0), this.requiredConfirmations, txEtaMs);
325
+ if(btcTx!=null && btcTx.txid!==this.txId) {
326
+ this.txId = btcTx.txid;
327
+ this.vout = vout;
328
+ if(btcTx.inputAddresses!=null) this.senderAddress = btcTx.inputAddresses[0];
329
+ this._saveAndEmit().catch(e => {
330
+ this.logger.error("waitForBitcoinTransaction(): Failed to save swap from within waitForAddressTxo callback:", e)
331
+ });
332
+ }
333
+ },
334
+ abortSignal,
335
+ checkIntervalSeconds
336
+ );
337
+
338
+ if(abortSignal!=null) abortSignal.throwIfAborted();
339
+
340
+ this.txId = result.tx.txid;
341
+ this.vout = result.vout;
342
+ if(result.tx.inputAddresses!=null) this.senderAddress = result.tx.inputAddresses[0];
343
+
344
+ if(
345
+ (this.state as FromBTCSwapState)!==FromBTCSwapState.CLAIM_CLAIMED &&
346
+ (this.state as FromBTCSwapState)!==FromBTCSwapState.FAILED
347
+ ) {
348
+ this.state = FromBTCSwapState.BTC_TX_CONFIRMED;
349
+ }
350
+
351
+ await this._saveAndEmit();
352
+
353
+ return result.tx.txid;
354
+ }
355
+
356
+ /**
357
+ * Returns the PSBT that is already funded with wallet's UTXOs (runs a coin-selection algorithm to choose UTXOs to use),
358
+ * also returns inputs indices that need to be signed by the wallet before submitting the PSBT back to the SDK with
359
+ * `swap.submitPsbt()`
360
+ *
361
+ * @param _bitcoinWallet Sender's bitcoin wallet
362
+ * @param feeRate Optional fee rate for the transaction, needs to be at least as big as {minimumBtcFeeRate} field
363
+ * @param additionalOutputs additional outputs to add to the PSBT - can be used to collect fees from users
364
+ */
365
+ getFundedPsbt(
366
+ _bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface,
367
+ feeRate?: number,
368
+ additionalOutputs?: ({amount: bigint, outputScript: Uint8Array} | {amount: bigint, address: string})[]
369
+ ) {
370
+ if(this.state!==FromBTCSwapState.CLAIM_COMMITED)
371
+ throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
372
+ return this._getFundedPsbt(_bitcoinWallet, feeRate, additionalOutputs);
373
+ }
374
+
375
+ private async _getFundedPsbt(
376
+ _bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface,
377
+ feeRate?: number,
378
+ additionalOutputs?: ({amount: bigint, outputScript: Uint8Array} | {amount: bigint, address: string})[]
379
+ ): Promise<{psbt: Transaction, psbtHex: string, psbtBase64: string, signInputs: number[]}> {
380
+ let bitcoinWallet: IBitcoinWallet;
381
+ if(isIBitcoinWallet(_bitcoinWallet)) {
382
+ bitcoinWallet = _bitcoinWallet;
383
+ } else {
384
+ bitcoinWallet = new SingleAddressBitcoinWallet(this.wrapper.btcRpc, this.wrapper.options.bitcoinNetwork, _bitcoinWallet);
385
+ }
386
+ //TODO: Maybe re-introduce fee rate check here if passed from the user
387
+ if(feeRate==null) {
388
+ feeRate = await bitcoinWallet.getFeeRate();
389
+ }
390
+
391
+ const basePsbt = new Transaction({
392
+ allowUnknownOutputs: true,
393
+ allowLegacyWitnessUtxo: true
394
+ });
395
+ basePsbt.addOutput({
396
+ amount: this.amount,
397
+ script: toOutputScript(this.wrapper.options.bitcoinNetwork, this.address)
398
+ });
399
+ if(additionalOutputs!=null) additionalOutputs.forEach(output => {
400
+ basePsbt.addOutput({
401
+ amount: output.amount,
402
+ script: (output as {outputScript: Uint8Array}).outputScript ?? toOutputScript(this.wrapper.options.bitcoinNetwork, (output as {address: string}).address)
403
+ });
404
+ });
405
+
406
+ const psbt = await bitcoinWallet.fundPsbt(basePsbt, feeRate);
407
+ //Sign every input
408
+ const signInputs: number[] = [];
409
+ for(let i=0;i<psbt.inputsLength;i++) {
410
+ signInputs.push(i);
411
+ }
412
+ const serializedPsbt = Buffer.from(psbt.toPSBT());
413
+ return {
414
+ psbt,
415
+ psbtHex: serializedPsbt.toString("hex"),
416
+ psbtBase64: serializedPsbt.toString("base64"),
417
+ signInputs
418
+ };
419
+ }
420
+
421
+ /**
422
+ * Submits a PSBT signed by the wallet back to the SDK
423
+ *
424
+ * @param _psbt A psbt - either a Transaction object or a hex or base64 encoded PSBT string
425
+ */
426
+ async submitPsbt(_psbt: Transaction | string): Promise<string> {
427
+ const psbt = parsePsbtTransaction(_psbt);
428
+ if(this.state!==FromBTCSwapState.CLAIM_COMMITED)
429
+ throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
430
+
431
+ //Ensure not expired
432
+ if(this.getTimeoutTime()<Date.now()) {
433
+ throw new Error("Swap address expired!");
434
+ }
435
+
436
+ const output0 = psbt.getOutput(0);
437
+ if(output0.amount!==this.amount)
438
+ throw new Error("PSBT output amount invalid, expected: "+this.amount+" got: "+output0.amount);
439
+ const expectedOutputScript = toOutputScript(this.wrapper.options.bitcoinNetwork, this.address);
440
+ if(output0.script==null || !expectedOutputScript.equals(output0.script))
441
+ throw new Error("PSBT output script invalid!");
442
+
443
+ if(!psbt.isFinal) psbt.finalize();
444
+
445
+ return await this.wrapper.btcRpc.sendRawTransaction(Buffer.from(psbt.toBytes(true, true)).toString("hex"));
446
+ }
447
+
448
+ async estimateBitcoinFee(_bitcoinWallet: IBitcoinWallet | MinimalBitcoinWalletInterface, feeRate?: number): Promise<TokenAmount<any, BtcToken<false>> | null> {
449
+ const bitcoinWallet: IBitcoinWallet = toBitcoinWallet(_bitcoinWallet, this.wrapper.btcRpc, this.wrapper.options.bitcoinNetwork);
450
+ const txFee = await bitcoinWallet.getTransactionFee(this.address, this.amount, feeRate);
451
+ if(txFee==null) return null;
452
+ return toTokenAmount(BigInt(txFee), BitcoinTokens.BTC, this.wrapper.prices);
453
+ }
454
+
455
+ async sendBitcoinTransaction(wallet: IBitcoinWallet | MinimalBitcoinWalletInterfaceWithSigner, feeRate?: number): Promise<string> {
456
+ if(this.state!==FromBTCSwapState.CLAIM_COMMITED)
457
+ throw new Error("Swap not committed yet, please initiate the swap first with commit() call!");
458
+
459
+ //Ensure not expired
460
+ if(this.getTimeoutTime()<Date.now()) {
461
+ throw new Error("Swap address expired!");
462
+ }
463
+
464
+ if(isIBitcoinWallet(wallet)) {
465
+ return await wallet.sendTransaction(this.address, this.amount, feeRate);
466
+ } else {
467
+ const {psbt, psbtHex, psbtBase64, signInputs} = await this.getFundedPsbt(wallet, feeRate);
468
+ const signedPsbt = await wallet.signPsbt({
469
+ psbt, psbtHex, psbtBase64
470
+ }, signInputs);
471
+ return await this.submitPsbt(signedPsbt);
472
+ }
473
+ }
474
+
475
+
476
+ //////////////////////////////
477
+ //// Execution
478
+
479
+ /**
480
+ * Executes the swap with the provided bitcoin wallet,
481
+ *
482
+ * @param dstSigner Signer on the destination network, needs to have the same address as the one specified when
483
+ * quote was created, this is required for legacy swaps because the destination wallet needs to actively open
484
+ * a bitcoin swap address to which the BTC is then sent, this means that the address also needs to have enough
485
+ * native tokens to pay for gas on the destination network
486
+ * @param wallet Bitcoin wallet to use to sign the bitcoin transaction, can also be null - then the execution waits
487
+ * till a transaction is received from an external wallet
488
+ * @param callbacks Callbacks to track the progress of the swap
489
+ * @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
490
+ *
491
+ * @returns {boolean} Whether a swap was settled automatically by swap watchtowers or requires manual claim by the
492
+ * user, in case `false` is returned the user should call `swap.claim()` to settle the swap on the destination manually
493
+ */
494
+ async execute(
495
+ dstSigner: T["Signer"] | T["NativeSigner"],
496
+ wallet?: IBitcoinWallet | MinimalBitcoinWalletInterfaceWithSigner | null | undefined,
497
+ callbacks?: {
498
+ onDestinationCommitSent?: (destinationCommitTxId: string) => void,
499
+ onSourceTransactionSent?: (sourceTxId: string) => void,
500
+ onSourceTransactionConfirmationStatus?: (sourceTxId?: string, confirmations?: number, targetConfirations?: number, etaMs?: number) => void,
501
+ onSourceTransactionConfirmed?: (sourceTxId: string) => void,
502
+ onSwapSettled?: (destinationTxId: string) => void
503
+ },
504
+ options?: {
505
+ feeRate?: number,
506
+ abortSignal?: AbortSignal,
507
+ btcTxCheckIntervalSeconds?: number,
508
+ maxWaitTillAutomaticSettlementSeconds?: number
509
+ }
510
+ ): Promise<boolean> {
511
+ if(this.state===FromBTCSwapState.FAILED) throw new Error("Swap failed!");
512
+ if(this.state===FromBTCSwapState.EXPIRED) throw new Error("Swap address expired!");
513
+ if(this.state===FromBTCSwapState.QUOTE_EXPIRED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED) throw new Error("Swap quote expired!");
514
+ if(this.state===FromBTCSwapState.CLAIM_CLAIMED) throw new Error("Swap already settled!");
515
+
516
+ if(this.state===FromBTCSwapState.PR_CREATED) {
517
+ await this.commit(dstSigner, options?.abortSignal, undefined, callbacks?.onDestinationCommitSent);
518
+ }
519
+ if(this.state===FromBTCSwapState.CLAIM_COMMITED) {
520
+ if(wallet!=null) {
521
+ const bitcoinPaymentSent = await this.getBitcoinPayment();
522
+
523
+ if(bitcoinPaymentSent==null) {
524
+ //Send btc tx
525
+ const txId = await this.sendBitcoinTransaction(wallet, options?.feeRate);
526
+ if(callbacks?.onSourceTransactionSent!=null) callbacks.onSourceTransactionSent(txId);
527
+ }
528
+ }
529
+
530
+ const txId = await this.waitForBitcoinTransaction(callbacks?.onSourceTransactionConfirmationStatus, options?.btcTxCheckIntervalSeconds, options?.abortSignal);
531
+ if (callbacks?.onSourceTransactionConfirmed != null) callbacks.onSourceTransactionConfirmed(txId);
532
+ }
533
+
534
+ // @ts-ignore
535
+ if(this.state===FromBTCSwapState.CLAIM_CLAIMED) return true;
536
+
537
+ if(this.state===FromBTCSwapState.BTC_TX_CONFIRMED) {
538
+ const success = await this.waitTillClaimed(options?.maxWaitTillAutomaticSettlementSeconds ?? 60, options?.abortSignal);
539
+ if(success && callbacks?.onSwapSettled!=null) callbacks.onSwapSettled(this.getOutputTxId()!);
540
+ return success;
541
+ }
542
+
543
+ throw new Error("Invalid state reached!");
544
+ }
545
+
546
+ async txsExecute(options?: {
547
+ bitcoinWallet?: MinimalBitcoinWalletInterface,
548
+ skipChecks?: boolean
549
+ }) {
550
+ if(this.state===FromBTCSwapState.PR_CREATED) {
551
+ if(!await this.verifyQuoteValid()) throw new Error("Quote already expired or close to expiry!");
552
+ if(this.getTimeoutTime()<Date.now()) throw new Error("Swap address already expired or close to expiry!");
553
+ return [
554
+ {
555
+ name: "Commit" as const,
556
+ description: `Opens up the bitcoin swap address on the ${this.chainIdentifier} side`,
557
+ chain: this.chainIdentifier,
558
+ txs: await this.txsCommit(options?.skipChecks)
559
+ },
560
+ {
561
+ name: "Payment" as const,
562
+ description: "Send funds to the bitcoin swap address",
563
+ chain: "BITCOIN",
564
+ txs: [
565
+ options?.bitcoinWallet==null ? {
566
+ address: this.address,
567
+ amount: Number(this.amount),
568
+ hyperlink: this._getHyperlink(),
569
+ type: "ADDRESS"
570
+ } : {
571
+ ...await this.getFundedPsbt(options.bitcoinWallet),
572
+ type: "FUNDED_PSBT"
573
+ }
574
+ ]
575
+ }
576
+ ];
577
+ }
578
+
579
+ if(this.state===FromBTCSwapState.CLAIM_COMMITED) {
580
+ if(this.getTimeoutTime()<Date.now()) throw new Error("Swap address already expired or close to expiry!");
581
+ return [
582
+ {
583
+ name: "Payment" as const,
584
+ description: "Send funds to the bitcoin swap address",
585
+ chain: "BITCOIN",
586
+ txs: [
587
+ options?.bitcoinWallet==null ? {
588
+ address: this.address,
589
+ amount: Number(this.amount),
590
+ hyperlink: this._getHyperlink(),
591
+ type: "ADDRESS"
592
+ } : {
593
+ ...await this.getFundedPsbt(options.bitcoinWallet),
594
+ type: "FUNDED_PSBT"
595
+ }
596
+ ]
597
+ }
598
+ ];
599
+ }
600
+
601
+ throw new Error("Invalid swap state to obtain execution txns, required PR_CREATED or CLAIM_COMMITED");
602
+ }
603
+
604
+
605
+ //////////////////////////////
606
+ //// Commit
607
+
608
+ /**
609
+ * Commits the swap on-chain, locking the tokens from the intermediary in a PTLC
610
+ *
611
+ * @param _signer Signer to sign the transactions with, must be the same as used in the initialization
612
+ * @param abortSignal Abort signal to stop waiting for the transaction confirmation and abort
613
+ * @param skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
614
+ * (this is handled when swap is created (quoted), if you commit right after quoting, you can use skipChecks=true)
615
+ * @param onBeforeTxSent
616
+ * @throws {Error} If invalid signer is provided that doesn't match the swap data
617
+ */
618
+ async commit(_signer: T["Signer"] | T["NativeSigner"], abortSignal?: AbortSignal, skipChecks?: boolean, onBeforeTxSent?: (txId: string) => void): Promise<string> {
619
+ const signer = isAbstractSigner(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer);
620
+ this.checkSigner(signer);
621
+ let txCount = 0;
622
+ const txs = await this.txsCommit(skipChecks);
623
+ const result = await this.wrapper.chain.sendAndConfirm(
624
+ signer, txs, true, abortSignal, undefined, (txId: string) => {
625
+ txCount++;
626
+ if(onBeforeTxSent!=null && txCount===txs.length) onBeforeTxSent(txId);
627
+ return Promise.resolve();
628
+ }
629
+ );
630
+
631
+ this.commitTxId = result[result.length - 1];
632
+ if(this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
633
+ await this._saveAndEmit(FromBTCSwapState.CLAIM_COMMITED);
634
+ }
635
+ return this.commitTxId;
636
+ }
637
+
638
+ async waitTillCommited(abortSignal?: AbortSignal): Promise<void> {
639
+ if(this.state===FromBTCSwapState.CLAIM_COMMITED || this.state===FromBTCSwapState.CLAIM_CLAIMED) return Promise.resolve();
640
+ if(this.state!==FromBTCSwapState.PR_CREATED && this.state!==FromBTCSwapState.QUOTE_SOFT_EXPIRED) throw new Error("Invalid state");
641
+
642
+ const abortController = extendAbortController(abortSignal);
643
+ const result = await Promise.race([
644
+ this.watchdogWaitTillCommited(undefined, abortController.signal),
645
+ this.waitTillState(FromBTCSwapState.CLAIM_COMMITED, "gte", abortController.signal).then(() => 0)
646
+ ]);
647
+ abortController.abort();
648
+
649
+ if(result===0) this.logger.debug("waitTillCommited(): Resolved from state changed");
650
+ if(result===true) this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
651
+ if(result===false) {
652
+ this.logger.debug("waitTillCommited(): Resolved from watchdog - signature expired");
653
+ if(this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
654
+ await this._saveAndEmit(FromBTCSwapState.QUOTE_EXPIRED);
655
+ }
656
+ return;
657
+ }
658
+
659
+ if(this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
660
+ await this._saveAndEmit(FromBTCSwapState.CLAIM_COMMITED);
661
+ }
662
+ }
663
+
664
+
665
+ //////////////////////////////
666
+ //// Claim
667
+
668
+ /**
669
+ * Returns transactions required to claim the swap on-chain (and possibly also sync the bitcoin light client)
670
+ * after a bitcoin transaction was sent and confirmed
671
+ *
672
+ * @throws {Error} If the swap is in invalid state (must be BTC_TX_CONFIRMED)
673
+ */
674
+ async txsClaim(_signer?: string | T["Signer"] | T["NativeSigner"]): Promise<T["TX"][]> {
675
+ let signer: string | T["Signer"] | undefined = undefined;
676
+ if(_signer!=null) {
677
+ if (typeof (_signer) === "string") {
678
+ signer = _signer;
679
+ } else if (isAbstractSigner(_signer)) {
680
+ signer = _signer;
681
+ } else {
682
+ signer = await this.wrapper.chain.wrapSigner(_signer);
683
+ }
684
+ }
685
+
686
+ if(this.state!==FromBTCSwapState.BTC_TX_CONFIRMED) throw new Error("Must be in BTC_TX_CONFIRMED state!");
687
+ if(this.txId==null || this.vout==null) throw new Error("Bitcoin transaction ID not known!");
688
+
689
+ const tx = await this.wrapper.btcRpc.getTransaction(this.txId);
690
+ if(tx==null) throw new Error("Bitcoin transaction not found on the network!");
691
+ if(tx.blockhash==null || tx.confirmations==null || tx.blockheight==null || tx.confirmations<this.requiredConfirmations)
692
+ throw new Error("Bitcoin transaction not confirmed yet!");
693
+
694
+ return await this.wrapper.contract.txsClaimWithTxData(signer ?? this._getInitiator(), this.data, {
695
+ blockhash: tx.blockhash,
696
+ confirmations: tx.confirmations,
697
+ txid: tx.txid,
698
+ hex: tx.hex,
699
+ height: tx.blockheight
700
+ }, this.requiredConfirmations, this.vout, undefined, this.wrapper.synchronizer, true);
701
+ }
702
+
703
+ /**
704
+ * Claims and finishes the swap
705
+ *
706
+ * @param _signer Signer to sign the transactions with, can also be different to the initializer
707
+ * @param abortSignal Abort signal to stop waiting for transaction confirmation
708
+ * @param onBeforeTxSent
709
+ */
710
+ async claim(_signer: T["Signer"] | T["NativeSigner"], abortSignal?: AbortSignal, onBeforeTxSent?: (txId: string) => void): Promise<string> {
711
+ const signer = isAbstractSigner(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer);
712
+ let txIds: string[];
713
+ try {
714
+ let txCount = 0;
715
+ const txs = await this.txsClaim(signer);
716
+ txIds = await this.wrapper.chain.sendAndConfirm(
717
+ signer, txs, true, abortSignal, undefined, (txId: string) => {
718
+ txCount++;
719
+ if(onBeforeTxSent!=null && txCount===txs.length) onBeforeTxSent(txId);
720
+ return Promise.resolve();
721
+ }
722
+ );
723
+ } catch (e) {
724
+ this.logger.info("claim(): Failed to claim ourselves, checking swap claim state...");
725
+ if(this.state===FromBTCSwapState.CLAIM_CLAIMED) {
726
+ this.logger.info("claim(): Transaction state is CLAIM_CLAIMED, swap was successfully claimed by the watchtower");
727
+ return this.claimTxId!;
728
+ }
729
+ const status = await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
730
+ if(status?.type===SwapCommitStateType.PAID) {
731
+ this.logger.info("claim(): Transaction commit status is PAID, swap was successfully claimed by the watchtower");
732
+ if(this.claimTxId==null) this.claimTxId = await status.getClaimTxId();
733
+ const txId = Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
734
+ await this._setBitcoinTxId(txId);
735
+ await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
736
+ return this.claimTxId;
737
+ }
738
+ throw e;
739
+ }
740
+
741
+ this.claimTxId = txIds[txIds.length - 1];
742
+ if(
743
+ this.state===FromBTCSwapState.CLAIM_COMMITED || this.state===FromBTCSwapState.BTC_TX_CONFIRMED ||
744
+ this.state===FromBTCSwapState.EXPIRED || this.state===FromBTCSwapState.FAILED
745
+ ) {
746
+ await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
747
+ }
748
+ return txIds[txIds.length - 1];
749
+ }
750
+
751
+ /**
752
+ * Waits till the swap is successfully claimed
753
+ *
754
+ * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled
755
+ * @param abortSignal AbortSignal
756
+ * @throws {Error} If swap is in invalid state (must be BTC_TX_CONFIRMED)
757
+ * @throws {Error} If the LP refunded sooner than we were able to claim
758
+ * @returns {boolean} whether the swap was claimed in time or not
759
+ */
760
+ async waitTillClaimed(maxWaitTimeSeconds?: number, abortSignal?: AbortSignal): Promise<boolean> {
761
+ if(this.state===FromBTCSwapState.CLAIM_CLAIMED) return Promise.resolve(true);
762
+ if(this.state!==FromBTCSwapState.BTC_TX_CONFIRMED) throw new Error("Invalid state (not BTC_TX_CONFIRMED)");
763
+
764
+ const abortController = extendAbortController(abortSignal);
765
+
766
+ let timedOut: boolean = false;
767
+ if(maxWaitTimeSeconds!=null) {
768
+ const timeout = setTimeout(() => {
769
+ timedOut = true;
770
+ abortController.abort();
771
+ }, maxWaitTimeSeconds * 1000);
772
+ abortController.signal.addEventListener("abort", () => clearTimeout(timeout));
773
+ }
774
+
775
+ let res: 0 | 1 | SwapCommitState;
776
+ try {
777
+ res = await Promise.race([
778
+ this.watchdogWaitTillResult(undefined, abortController.signal),
779
+ this.waitTillState(FromBTCSwapState.CLAIM_CLAIMED, "eq", abortController.signal).then(() => 0 as const),
780
+ this.waitTillState(FromBTCSwapState.FAILED, "eq", abortController.signal).then(() => 1 as const),
781
+ ]);
782
+ abortController.abort();
783
+ } catch (e) {
784
+ abortController.abort();
785
+ if(timedOut) return false;
786
+ throw e;
787
+ }
788
+
789
+ if(res===0) {
790
+ this.logger.debug("waitTillClaimed(): Resolved from state change (CLAIM_CLAIMED)");
791
+ return true;
792
+ }
793
+ if(res===1) {
794
+ this.logger.debug("waitTillClaimed(): Resolved from state change (FAILED)");
795
+ throw new Error("Offerer refunded during claiming");
796
+ }
797
+ this.logger.debug("waitTillClaimed(): Resolved from watchdog");
798
+
799
+ if(res?.type===SwapCommitStateType.PAID) {
800
+ if((this.state as FromBTCSwapState)!==FromBTCSwapState.CLAIM_CLAIMED) {
801
+ if(this.claimTxId==null) this.claimTxId = await res.getClaimTxId();
802
+ const txId = Buffer.from(await res.getClaimResult(), "hex").reverse().toString("hex");
803
+ await this._setBitcoinTxId(txId);
804
+ await this._saveAndEmit(FromBTCSwapState.CLAIM_CLAIMED);
805
+ }
806
+ }
807
+ if(res?.type===SwapCommitStateType.NOT_COMMITED || res?.type===SwapCommitStateType.EXPIRED) {
808
+ if(
809
+ (this.state as FromBTCSwapState)!==FromBTCSwapState.CLAIM_CLAIMED &&
810
+ (this.state as FromBTCSwapState)!==FromBTCSwapState.FAILED
811
+ ) {
812
+ if(res.getRefundTxId!=null) this.refundTxId = await res.getRefundTxId();
813
+ await this._saveAndEmit(FromBTCSwapState.FAILED);
814
+ }
815
+ throw new Error("Swap expired while waiting for claim!");
816
+ }
817
+
818
+ return true;
819
+ }
820
+
821
+
822
+ //////////////////////////////
823
+ //// Storage
824
+
825
+ serialize(): any {
826
+ return {
827
+ ...super.serialize(),
828
+ address: this.address,
829
+ amount: this.amount.toString(10),
830
+ requiredConfirmations: this.requiredConfirmations,
831
+ senderAddress: this.senderAddress,
832
+ txId: this.txId,
833
+ vout: this.vout
834
+ };
835
+ }
836
+
837
+
838
+ //////////////////////////////
839
+ //// Swap ticks & sync
840
+
841
+ /**
842
+ * Checks the swap's state on-chain and compares it to its internal state, updates/changes it according to on-chain
843
+ * data
844
+ *
845
+ * @private
846
+ */
847
+ private async syncStateFromChain(quoteDefinitelyExpired?: boolean, commitStatus?: SwapCommitState): Promise<boolean> {
848
+ if(this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED) {
849
+ const quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired(); //Make sure we check for expiry here, to prevent race conditions
850
+ const status = commitStatus ?? await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
851
+ switch(status?.type) {
852
+ case SwapCommitStateType.COMMITED:
853
+ this.state = FromBTCSwapState.CLAIM_COMMITED;
854
+ return true;
855
+ case SwapCommitStateType.EXPIRED:
856
+ if(this.refundTxId==null && status.getRefundTxId) this.refundTxId = await status.getRefundTxId();
857
+ this.state = FromBTCSwapState.QUOTE_EXPIRED;
858
+ return true;
859
+ case SwapCommitStateType.PAID:
860
+ if(this.claimTxId==null) this.claimTxId = await status.getClaimTxId();
861
+ const txId = Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
862
+ await this._setBitcoinTxId(txId);
863
+ this.state = FromBTCSwapState.CLAIM_CLAIMED;
864
+ return true;
865
+ }
866
+
867
+ if(quoteExpired) {
868
+ this.state = FromBTCSwapState.QUOTE_EXPIRED;
869
+ return true;
870
+ }
871
+
872
+ return false;
873
+ }
874
+
875
+ if(this.state===FromBTCSwapState.CLAIM_COMMITED || this.state===FromBTCSwapState.BTC_TX_CONFIRMED || this.state===FromBTCSwapState.EXPIRED) {
876
+ const status = commitStatus ?? await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
877
+ switch(status?.type) {
878
+ case SwapCommitStateType.PAID:
879
+ if(this.claimTxId==null) this.claimTxId = await status.getClaimTxId();
880
+ const txId = Buffer.from(await status.getClaimResult(), "hex").reverse().toString("hex");
881
+ await this._setBitcoinTxId(txId);
882
+ this.state = FromBTCSwapState.CLAIM_CLAIMED;
883
+ return true;
884
+ case SwapCommitStateType.NOT_COMMITED:
885
+ case SwapCommitStateType.EXPIRED:
886
+ if(this.refundTxId==null && status.getRefundTxId) this.refundTxId = await status.getRefundTxId();
887
+ this.state = FromBTCSwapState.FAILED;
888
+ return true;
889
+ case SwapCommitStateType.COMMITED:
890
+ const res = await this.getBitcoinPayment();
891
+ if(res!=null) {
892
+ let save: boolean = false;
893
+ if(this.txId!==res.txId) {
894
+ if(res.inputAddresses!=null) this.senderAddress = res.inputAddresses[0];
895
+ this.txId = res.txId;
896
+ this.vout = res.vout;
897
+ save = true;
898
+ }
899
+ if(res.confirmations>=this.requiredConfirmations) {
900
+ this.state = FromBTCSwapState.BTC_TX_CONFIRMED;
901
+ save = true;
902
+ }
903
+ return save;
904
+ }
905
+ break;
906
+ }
907
+ }
908
+
909
+ return false;
910
+ }
911
+
912
+ _shouldFetchCommitStatus(): boolean {
913
+ return this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED ||
914
+ this.state===FromBTCSwapState.CLAIM_COMMITED || this.state===FromBTCSwapState.BTC_TX_CONFIRMED ||
915
+ this.state===FromBTCSwapState.EXPIRED;
916
+ }
917
+
918
+ _shouldFetchExpiryStatus(): boolean {
919
+ return this.state===FromBTCSwapState.PR_CREATED || this.state===FromBTCSwapState.QUOTE_SOFT_EXPIRED;
920
+ }
921
+
922
+ async _sync(save?: boolean, quoteDefinitelyExpired?: boolean, commitStatus?: SwapCommitState): Promise<boolean> {
923
+ const changed = await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus);
924
+ if(changed && save) await this._saveAndEmit();
925
+ return changed;
926
+ }
927
+
928
+ async _tick(save?: boolean): Promise<boolean> {
929
+ switch(this.state) {
930
+ case FromBTCSwapState.PR_CREATED:
931
+ if(this.expiry<Date.now()) {
932
+ this.state = FromBTCSwapState.QUOTE_SOFT_EXPIRED;
933
+ if(save) await this._saveAndEmit();
934
+ return true;
935
+ }
936
+ break;
937
+ case FromBTCSwapState.CLAIM_COMMITED:
938
+ if(this.getTimeoutTime()<Date.now()) {
939
+ this.state = FromBTCSwapState.EXPIRED;
940
+ if(save) await this._saveAndEmit();
941
+ return true;
942
+ }
943
+ case FromBTCSwapState.EXPIRED:
944
+ //Check if bitcoin payment was received every 2 minutes
945
+ if(Math.floor(Date.now()/1000)%120===0) {
946
+ try {
947
+ const res = await this.getBitcoinPayment();
948
+ if(res!=null) {
949
+ let shouldSave: boolean = false;
950
+ if(this.txId!==res.txId) {
951
+ this.txId = res.txId;
952
+ this.vout = res.vout;
953
+ if(res.inputAddresses!=null) this.senderAddress = res.inputAddresses[0];
954
+ shouldSave = true;
955
+ }
956
+ if(res.confirmations>=this.requiredConfirmations) {
957
+ this.state = FromBTCSwapState.BTC_TX_CONFIRMED;
958
+ if(save) await this._saveAndEmit();
959
+ shouldSave = true;
960
+ }
961
+ if(shouldSave && save) await this._saveAndEmit();
962
+ return shouldSave;
963
+ }
964
+ } catch (e) {
965
+ this.logger.warn("tickSwap("+this.getIdentifierHashString()+"): ", e);
966
+ }
967
+ }
968
+ break;
969
+ }
970
+
971
+ return false;
972
+ }
973
+
974
+ }