@atomiqlabs/sdk 7.0.11 → 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} +40 -22
  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} +116 -75
  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,860 @@
1
+ import {IToBTCDefinition, IToBTCWrapper} from "./IToBTCWrapper";
2
+ import {
3
+ ChainType,
4
+ isAbstractSigner,
5
+ SignatureData,
6
+ SignatureVerificationError,
7
+ SwapCommitState,
8
+ SwapCommitStateType,
9
+ SwapData
10
+ } from "@atomiqlabs/base";
11
+ import {
12
+ IntermediaryAPI,
13
+ RefundAuthorizationResponse,
14
+ RefundAuthorizationResponseCodes
15
+ } from "../../../intermediaries/apis/IntermediaryAPI";
16
+ import {IntermediaryError} from "../../../errors/IntermediaryError";
17
+ import {extendAbortController, toBigInt} from "../../../utils/Utils";
18
+ import {Fee} from "../../../types/fees/Fee";
19
+ import {IEscrowSelfInitSwap, IEscrowSelfInitSwapInit, isIEscrowSelfInitSwapInit} from "../IEscrowSelfInitSwap";
20
+ import {IRefundableSwap} from "../../IRefundableSwap";
21
+ import {FeeType} from "../../../enums/FeeType";
22
+ import {ppmToPercentage} from "../../../types/fees/PercentagePPM";
23
+ import {TokenAmount, toTokenAmount} from "../../../types/TokenAmount";
24
+ import {BtcToken, SCToken} from "../../../types/Token";
25
+ import {timeoutPromise} from "../../../utils/TimeoutUtils";
26
+
27
+ export type IToBTCSwapInit<T extends SwapData> = IEscrowSelfInitSwapInit<T> & {
28
+ signatureData?: SignatureData,
29
+ data: T,
30
+ networkFee: bigint,
31
+ networkFeeBtc: bigint
32
+ };
33
+
34
+ export function isIToBTCSwapInit<T extends SwapData>(obj: any): obj is IToBTCSwapInit<T> {
35
+ return typeof(obj.networkFee) === "bigint" &&
36
+ typeof(obj.networkFeeBtc) === "bigint" &&
37
+ (obj.signatureData==null || (
38
+ typeof(obj.signatureData) === 'object' &&
39
+ typeof(obj.signatureData.prefix)==="string" &&
40
+ typeof(obj.signatureData.timeout)==="string" &&
41
+ typeof(obj.signatureData.signature)==="string"
42
+ )) &&
43
+ typeof(obj.data) === 'object' &&
44
+ isIEscrowSelfInitSwapInit<T>(obj);
45
+ }
46
+
47
+ export abstract class IToBTCSwap<
48
+ T extends ChainType = ChainType,
49
+ D extends IToBTCDefinition<T, IToBTCWrapper<T, D>, IToBTCSwap<T, D>> = IToBTCDefinition<T, IToBTCWrapper<T, any>, IToBTCSwap<T, any>>,
50
+ > extends IEscrowSelfInitSwap<T, D, ToBTCSwapState> implements IRefundableSwap<T, D, ToBTCSwapState> {
51
+ protected readonly networkFee: bigint;
52
+ protected networkFeeBtc: bigint;
53
+ protected readonly abstract outputToken: BtcToken;
54
+
55
+ readonly data!: T["Data"];
56
+ readonly signatureData?: SignatureData;
57
+
58
+ protected constructor(wrapper: D["Wrapper"], serializedObject: any);
59
+ protected constructor(wrapper: D["Wrapper"], init: IToBTCSwapInit<T["Data"]>);
60
+ protected constructor(
61
+ wrapper: D["Wrapper"],
62
+ initOrObject: IToBTCSwapInit<T["Data"]> | any
63
+ ) {
64
+ super(wrapper, initOrObject);
65
+ if(isIToBTCSwapInit<T["Data"]>(initOrObject)) {
66
+ this.state = ToBTCSwapState.CREATED;
67
+ this.networkFee = initOrObject.networkFee;
68
+ this.networkFeeBtc = initOrObject.networkFeeBtc;
69
+ this.data = initOrObject.data;
70
+ this.signatureData = initOrObject.signatureData;
71
+ } else {
72
+ this.networkFee = toBigInt(initOrObject.networkFee);
73
+ this.networkFeeBtc = toBigInt(initOrObject.networkFeeBtc);
74
+ }
75
+ }
76
+
77
+ protected getSwapData(): T["Data"] {
78
+ return this.data;
79
+ }
80
+
81
+ protected upgradeVersion() {
82
+ if(this.version == null) {
83
+ switch(this.state) {
84
+ case -2:
85
+ this.state = ToBTCSwapState.REFUNDED
86
+ break;
87
+ case -1:
88
+ this.state = ToBTCSwapState.QUOTE_EXPIRED
89
+ break;
90
+ case 0:
91
+ this.state = ToBTCSwapState.CREATED
92
+ break;
93
+ case 1:
94
+ this.state = ToBTCSwapState.COMMITED
95
+ break;
96
+ case 2:
97
+ this.state = ToBTCSwapState.CLAIMED
98
+ break;
99
+ case 3:
100
+ this.state = ToBTCSwapState.REFUNDABLE
101
+ break;
102
+ }
103
+ this.version = 1;
104
+ }
105
+ }
106
+
107
+ /**
108
+ * In case swapFee in BTC is not supplied it recalculates it based on swap price
109
+ * @protected
110
+ */
111
+ protected tryRecomputeSwapPrice() {
112
+ const output = this.getOutput();
113
+ if(output!=null) {
114
+ if(this.swapFeeBtc==null) {
115
+ this.swapFeeBtc = this.swapFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
116
+ }
117
+ if(this.networkFeeBtc==null) {
118
+ this.networkFeeBtc = this.networkFee * output.rawAmount / this.getInputWithoutFee().rawAmount;
119
+ }
120
+ }
121
+ super.tryRecomputeSwapPrice();
122
+ }
123
+
124
+ /**
125
+ * Returns the payment hash identifier to be sent to the LP for getStatus and getRefund
126
+ * @protected
127
+ */
128
+ protected getLpIdentifier(): string {
129
+ return this.getClaimHash();
130
+ }
131
+
132
+ /**
133
+ * Sets the payment result for the swap, optionally also checking it (checking that tx exist or swap secret is valid)
134
+ *
135
+ * @param result Result returned by the LP
136
+ * @param check Whether to check the passed result
137
+ * @returns true if check passed, false if check failed with a soft error (e.g. tx not yet found in the mempool)
138
+ * @throws {IntermediaryError} When the data returned by the intermediary isn't valid
139
+ */
140
+ abstract _setPaymentResult(result: {secret?: string, txId?: string}, check?: boolean): Promise<boolean>;
141
+
142
+
143
+ //////////////////////////////
144
+ //// Getters & utils
145
+
146
+ getInputAddress(): string | null {
147
+ return this._getInitiator();
148
+ }
149
+
150
+ getInputTxId(): string | null {
151
+ return this.commitTxId ?? null;
152
+ }
153
+
154
+ requiresAction(): boolean {
155
+ return this.isRefundable();
156
+ }
157
+
158
+ /**
159
+ * Returns whether the swap is finished and in its terminal state (this can mean successful, refunded or failed)
160
+ */
161
+ isFinished(): boolean {
162
+ return this.state===ToBTCSwapState.CLAIMED || this.state===ToBTCSwapState.REFUNDED || this.state===ToBTCSwapState.QUOTE_EXPIRED;
163
+ }
164
+
165
+ isRefundable(): boolean {
166
+ return this.state===ToBTCSwapState.REFUNDABLE;
167
+ }
168
+
169
+ isQuoteExpired(): boolean {
170
+ return this.state===ToBTCSwapState.QUOTE_EXPIRED;
171
+ }
172
+
173
+ isQuoteSoftExpired(): boolean {
174
+ return this.state===ToBTCSwapState.QUOTE_EXPIRED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED;
175
+ }
176
+
177
+ isSuccessful(): boolean {
178
+ return this.state===ToBTCSwapState.CLAIMED;
179
+ }
180
+
181
+ isFailed(): boolean {
182
+ return this.state===ToBTCSwapState.REFUNDED;
183
+ }
184
+
185
+ _getInitiator(): string {
186
+ return this.data.getOfferer();
187
+ }
188
+
189
+
190
+ //////////////////////////////
191
+ //// Amounts & fees
192
+
193
+ protected getSwapFee(): Fee<T["ChainId"], SCToken<T["ChainId"]>, BtcToken> {
194
+ if(this.pricingInfo==null) throw new Error("No pricing info known, cannot estimate fee!");
195
+
196
+ const feeWithoutBaseFee = this.swapFeeBtc - this.pricingInfo.satsBaseFee;
197
+ const output = this.getOutput();
198
+ const swapFeePPM = output?.rawAmount==null ? 0n : feeWithoutBaseFee * 1000000n / output.rawAmount;
199
+
200
+ const amountInDstToken = toTokenAmount(
201
+ this.swapFeeBtc, this.outputToken, this.wrapper.prices, this.pricingInfo
202
+ );
203
+ return {
204
+ amountInSrcToken: toTokenAmount(this.swapFee, this.wrapper.tokens[this.data.getToken()], this.wrapper.prices, this.pricingInfo),
205
+ amountInDstToken,
206
+ currentUsdValue: amountInDstToken.currentUsdValue,
207
+ usdValue: amountInDstToken.usdValue,
208
+ pastUsdValue: amountInDstToken.pastUsdValue,
209
+ composition: {
210
+ base: toTokenAmount(this.pricingInfo.satsBaseFee, this.outputToken, this.wrapper.prices, this.pricingInfo),
211
+ percentage: ppmToPercentage(swapFeePPM)
212
+ }
213
+ };
214
+ }
215
+
216
+ /**
217
+ * Returns network fee for the swap, the fee is represented in source currency & destination currency, but is
218
+ * paid only once
219
+ */
220
+ protected getNetworkFee(): Fee<T["ChainId"], SCToken<T["ChainId"]>, BtcToken> {
221
+ const amountInDstToken = toTokenAmount(
222
+ this.networkFeeBtc, this.outputToken, this.wrapper.prices, this.pricingInfo
223
+ );
224
+ return {
225
+ amountInSrcToken: toTokenAmount(
226
+ this.networkFee, this.wrapper.tokens[this.data.getToken()], this.wrapper.prices, this.pricingInfo
227
+ ),
228
+ amountInDstToken,
229
+ currentUsdValue: amountInDstToken.currentUsdValue,
230
+ usdValue: amountInDstToken.usdValue,
231
+ pastUsdValue: amountInDstToken.pastUsdValue
232
+ };
233
+ }
234
+
235
+ getFee(): Fee<T["ChainId"], SCToken<T["ChainId"]>, BtcToken> {
236
+ const amountInDstToken = toTokenAmount(
237
+ this.swapFeeBtc + this.networkFeeBtc, this.outputToken, this.wrapper.prices, this.pricingInfo
238
+ );
239
+ return {
240
+ amountInSrcToken: toTokenAmount(
241
+ this.swapFee + this.networkFee, this.wrapper.tokens[this.data.getToken()],
242
+ this.wrapper.prices, this.pricingInfo
243
+ ),
244
+ amountInDstToken,
245
+ currentUsdValue: amountInDstToken.currentUsdValue,
246
+ usdValue: amountInDstToken.usdValue,
247
+ pastUsdValue: amountInDstToken.pastUsdValue
248
+ }
249
+ }
250
+
251
+ getFeeBreakdown(): [
252
+ {type: FeeType.SWAP, fee: Fee<T["ChainId"], SCToken<T["ChainId"]>, BtcToken>},
253
+ {type: FeeType.NETWORK_OUTPUT, fee: Fee<T["ChainId"], SCToken<T["ChainId"]>, BtcToken>},
254
+ ] {
255
+ return [
256
+ {
257
+ type: FeeType.SWAP,
258
+ fee: this.getSwapFee()
259
+ },
260
+ {
261
+ type: FeeType.NETWORK_OUTPUT,
262
+ fee: this.getNetworkFee()
263
+ }
264
+ ];
265
+ }
266
+
267
+ getInputToken(): SCToken<T["ChainId"]> {
268
+ return this.wrapper.tokens[this.data.getToken()];
269
+ }
270
+
271
+ getInput(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>> {
272
+ return toTokenAmount(
273
+ this.data.getAmount(), this.wrapper.tokens[this.data.getToken()],
274
+ this.wrapper.prices, this.pricingInfo
275
+ );
276
+ }
277
+
278
+ getInputWithoutFee(): TokenAmount<T["ChainId"], SCToken<T["ChainId"]>> {
279
+ return toTokenAmount(
280
+ this.data.getAmount() - (this.swapFee + this.networkFee),
281
+ this.wrapper.tokens[this.data.getToken()], this.wrapper.prices, this.pricingInfo
282
+ );
283
+ }
284
+
285
+ /**
286
+ * Checks if the intiator/sender has enough balance to go through with the swap
287
+ */
288
+ async hasEnoughBalance(): Promise<{enoughBalance: boolean, balance: TokenAmount, required: TokenAmount}> {
289
+ const [balance, commitFee] = await Promise.all([
290
+ this.wrapper.contract.getBalance(this._getInitiator(), this.data.getToken(), false),
291
+ this.data.getToken()===this.wrapper.chain.getNativeCurrencyAddress() ? this.getCommitFee() : Promise.resolve(null)
292
+ ]);
293
+ let required = this.data.getAmount();
294
+ if(commitFee!=null) required = required + commitFee;
295
+ return {
296
+ enoughBalance: balance >= required,
297
+ balance: toTokenAmount(balance, this.wrapper.tokens[this.data.getToken()], this.wrapper.prices, this.pricingInfo),
298
+ required: toTokenAmount(required, this.wrapper.tokens[this.data.getToken()], this.wrapper.prices, this.pricingInfo)
299
+ };
300
+ }
301
+
302
+ /**
303
+ * Check if the initiator/sender has enough balance to cover the transaction fee for processing the swap
304
+ */
305
+ async hasEnoughForTxFees(): Promise<{enoughBalance: boolean, balance: TokenAmount, required: TokenAmount}> {
306
+ const [balance, commitFee] = await Promise.all([
307
+ this.wrapper.contract.getBalance(this._getInitiator(), this.wrapper.chain.getNativeCurrencyAddress(), false),
308
+ this.getCommitFee()
309
+ ]);
310
+ return {
311
+ enoughBalance: balance >= commitFee,
312
+ balance: toTokenAmount(balance, this.wrapper.getNativeToken(), this.wrapper.prices),
313
+ required: toTokenAmount(commitFee, this.wrapper.getNativeToken(), this.wrapper.prices)
314
+ };
315
+ }
316
+
317
+
318
+ //////////////////////////////
319
+ //// Execution
320
+
321
+ /**
322
+ * Executes the swap with the provided smart chain wallet/signer
323
+ *
324
+ * @param signer Smart chain wallet/signer to use to sign the transaction on the source chain
325
+ * @param callbacks Callbacks to track the progress of the swap
326
+ * @param options Optional options for the swap like feeRate, AbortSignal, and timeouts/intervals
327
+ *
328
+ * @returns {boolean} Whether the swap was successfully processed by the LP, in case `false` is returned
329
+ * the user can refund their funds back on the source chain by calling `swap.refund()`
330
+ */
331
+ async execute(
332
+ signer: T["Signer"] | T["NativeSigner"],
333
+ callbacks?: {
334
+ onSourceTransactionSent?: (sourceTxId: string) => void,
335
+ onSourceTransactionConfirmed?: (sourceTxId: string) => void,
336
+ onSwapSettled?: (destinationTxId: string) => void
337
+ },
338
+ options?: {
339
+ abortSignal?: AbortSignal,
340
+ paymentCheckIntervalSeconds?: number,
341
+ maxWaitTillSwapProcessedSeconds?: number
342
+ }
343
+ ): Promise<boolean> {
344
+ if(this.state===ToBTCSwapState.QUOTE_EXPIRED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED) throw new Error("Quote expired");
345
+ if(this.state===ToBTCSwapState.REFUNDED) throw new Error("Swap already refunded");
346
+ if(this.state===ToBTCSwapState.REFUNDABLE) throw new Error("Swap refundable, refund with swap.refund()");
347
+ if(this.state===ToBTCSwapState.SOFT_CLAIMED || this.state===ToBTCSwapState.CLAIMED) throw new Error("Swap already settled!");
348
+
349
+ if(this.state===ToBTCSwapState.CREATED) {
350
+ const txId = await this.commit(signer, options?.abortSignal, false, callbacks?.onSourceTransactionSent);
351
+ if(callbacks?.onSourceTransactionConfirmed!=null) callbacks.onSourceTransactionConfirmed(txId);
352
+ }
353
+
354
+ // @ts-ignore
355
+ if(this.state===ToBTCSwapState.CLAIMED || this.state===ToBTCSwapState.SOFT_CLAIMED) return true;
356
+
357
+ if(this.state===ToBTCSwapState.COMMITED) {
358
+ const success = await this.waitForPayment(options?.maxWaitTillSwapProcessedSeconds ?? 120, options?.paymentCheckIntervalSeconds, options?.abortSignal);
359
+ if(success) {
360
+ if(callbacks?.onSwapSettled!=null) callbacks.onSwapSettled(this.getOutputTxId()!);
361
+ return true;
362
+ } else {
363
+ return false;
364
+ }
365
+ }
366
+
367
+ throw new Error("Unexpected state reached!");
368
+ }
369
+
370
+ async txsExecute(options?: {
371
+ skipChecks?: boolean
372
+ }) {
373
+ if(this.state!==ToBTCSwapState.CREATED) throw new Error("Invalid swap state, needs to be CREATED!");
374
+ const txsCommit = await this.txsCommit(options?.skipChecks);
375
+ return [
376
+ {
377
+ name: "Commit" as const,
378
+ description: `Initiates the swap by commiting the funds to the escrow on the ${this.chainIdentifier} side`,
379
+ chain: this.chainIdentifier,
380
+ txs: txsCommit
381
+ }
382
+ ];
383
+ }
384
+
385
+
386
+ //////////////////////////////
387
+ //// Commit
388
+
389
+ /**
390
+ * Returns transactions for committing the swap on-chain, initiating the swap
391
+ *
392
+ * @param skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
393
+ * (this is handled on swap creation, if you commit right after quoting, you can use skipChecks=true)
394
+ *
395
+ * @throws {Error} When in invalid state (not PR_CREATED)
396
+ */
397
+ async txsCommit(skipChecks?: boolean): Promise<T["TX"][]> {
398
+ if(this.state!==ToBTCSwapState.CREATED) throw new Error("Must be in CREATED state!");
399
+ if(this.signatureData==null) throw new Error("Init signature data not known, cannot commit!");
400
+
401
+ if(!this.initiated) {
402
+ this.initiated = true;
403
+ await this._saveAndEmit();
404
+ }
405
+
406
+ return await this.wrapper.contract.txsInit(
407
+ this._getInitiator(), this.data, this.signatureData, skipChecks, this.feeRate
408
+ ).catch(e => Promise.reject(e instanceof SignatureVerificationError ? new Error("Request timed out") : e));
409
+ }
410
+
411
+ /**
412
+ * Commits the swap on-chain, initiating the swap
413
+ *
414
+ * @param _signer Signer to sign the transactions with, must be the same as used in the initialization
415
+ * @param abortSignal Abort signal
416
+ * @param skipChecks Skip checks like making sure init signature is still valid and swap wasn't commited yet
417
+ * (this is handled on swap creation, if you commit right after quoting, you can skipChecks)`
418
+ * @param onBeforeTxSent
419
+ * @throws {Error} If invalid signer is provided that doesn't match the swap data
420
+ */
421
+ async commit(_signer: T["Signer"] | T["NativeSigner"], abortSignal?: AbortSignal, skipChecks?: boolean, onBeforeTxSent?: (txId: string) => void): Promise<string> {
422
+ const signer = isAbstractSigner(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer);
423
+ this.checkSigner(signer);
424
+ const txs = await this.txsCommit(skipChecks);
425
+ let txCount = 0;
426
+ const result = await this.wrapper.chain.sendAndConfirm(
427
+ signer, txs, true, abortSignal, false, (txId, rawTx) => {
428
+ txCount++;
429
+ if(onBeforeTxSent!=null && txCount===txs.length) onBeforeTxSent(txId);
430
+ return Promise.resolve();
431
+ }
432
+ );
433
+
434
+ this.commitTxId = result[result.length-1];
435
+ if(this.state===ToBTCSwapState.CREATED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED || this.state===ToBTCSwapState.QUOTE_EXPIRED) {
436
+ await this._saveAndEmit(ToBTCSwapState.COMMITED);
437
+ }
438
+ return this.commitTxId;
439
+ }
440
+
441
+ /**
442
+ * Waits till a swap is committed, should be called after sending the commit transactions manually
443
+ *
444
+ * @param abortSignal AbortSignal
445
+ * @throws {Error} If swap is not in the correct state (must be CREATED)
446
+ */
447
+ async waitTillCommited(abortSignal?: AbortSignal): Promise<void> {
448
+ if(this.state===ToBTCSwapState.COMMITED || this.state===ToBTCSwapState.CLAIMED) return Promise.resolve();
449
+ if(this.state!==ToBTCSwapState.CREATED && this.state!==ToBTCSwapState.QUOTE_SOFT_EXPIRED) throw new Error("Invalid state (not CREATED)");
450
+
451
+ const abortController = extendAbortController(abortSignal);
452
+ let result: number | boolean;
453
+ try {
454
+ result = await Promise.race([
455
+ this.watchdogWaitTillCommited(undefined, abortController.signal),
456
+ this.waitTillState(ToBTCSwapState.COMMITED, "gte", abortController.signal).then(() => 0)
457
+ ]);
458
+ abortController.abort();
459
+ } catch (e) {
460
+ abortController.abort();
461
+ throw e;
462
+ }
463
+
464
+ if(result===0) this.logger.debug("waitTillCommited(): Resolved from state change");
465
+ if(result===true) this.logger.debug("waitTillCommited(): Resolved from watchdog - commited");
466
+ if(result===false) {
467
+ this.logger.debug("waitTillCommited(): Resolved from watchdog - signature expiry");
468
+ if(this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED || this.state===ToBTCSwapState.CREATED) {
469
+ await this._saveAndEmit(ToBTCSwapState.QUOTE_EXPIRED);
470
+ }
471
+ throw new Error("Quote expired while waiting for transaction confirmation!");
472
+ }
473
+
474
+ if(this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED || this.state===ToBTCSwapState.CREATED || this.state===ToBTCSwapState.QUOTE_EXPIRED) {
475
+ await this._saveAndEmit(ToBTCSwapState.COMMITED);
476
+ }
477
+ }
478
+
479
+
480
+ //////////////////////////////
481
+ //// Payment
482
+
483
+ protected async waitTillIntermediarySwapProcessed(
484
+ checkIntervalSeconds?: number,
485
+ abortSignal?: AbortSignal
486
+ ): Promise<RefundAuthorizationResponse> {
487
+ if(this.url==null) throw new Error("LP URL not specified!");
488
+ checkIntervalSeconds ??= 5;
489
+ let resp: RefundAuthorizationResponse = {code: RefundAuthorizationResponseCodes.PENDING, msg: ""};
490
+ while(!abortSignal?.aborted && (
491
+ resp.code===RefundAuthorizationResponseCodes.PENDING || resp.code===RefundAuthorizationResponseCodes.NOT_FOUND
492
+ )) {
493
+ resp = await IntermediaryAPI.getRefundAuthorization(this.url, this.getLpIdentifier(), this.data.getSequence());
494
+ if(resp.code===RefundAuthorizationResponseCodes.PAID) {
495
+ const validResponse = await this._setPaymentResult(resp.data, true);
496
+ if(validResponse) {
497
+ if(this.state===ToBTCSwapState.COMMITED || this.state===ToBTCSwapState.REFUNDABLE) {
498
+ await this._saveAndEmit(ToBTCSwapState.SOFT_CLAIMED);
499
+ }
500
+ } else {
501
+ resp = {code: RefundAuthorizationResponseCodes.PENDING, msg: ""};
502
+ }
503
+ }
504
+ if(
505
+ resp.code===RefundAuthorizationResponseCodes.PENDING ||
506
+ resp.code===RefundAuthorizationResponseCodes.NOT_FOUND
507
+ ) await timeoutPromise(checkIntervalSeconds*1000, abortSignal);
508
+ }
509
+ return resp;
510
+ }
511
+
512
+ /**
513
+ * Checks whether the swap was already processed by the LP and is either successful (requires proof which is
514
+ * either a HTLC pre-image for LN swaps or valid txId for on-chain swap) or failed and we can cooperatively
515
+ * refund.
516
+ *
517
+ * @param save whether to save the data
518
+ * @returns true if swap is processed, false if the swap is still ongoing
519
+ * @private
520
+ */
521
+ protected async checkIntermediarySwapProcessed(save: boolean = true): Promise<boolean> {
522
+ if(this.state===ToBTCSwapState.CREATED || this.state==ToBTCSwapState.QUOTE_EXPIRED || this.url==null) return false;
523
+ if(this.isFinished() || this.isRefundable()) return true;
524
+ //Check if that maybe already concluded according to the LP
525
+ const resp = await IntermediaryAPI.getRefundAuthorization(this.url, this.getLpIdentifier(), this.data.getSequence());
526
+ switch(resp.code) {
527
+ case RefundAuthorizationResponseCodes.PAID:
528
+ const processed = await this._setPaymentResult(resp.data, true);
529
+ if(processed) {
530
+ this.state = ToBTCSwapState.SOFT_CLAIMED;
531
+ if(save) await this._saveAndEmit();
532
+ }
533
+ return processed;
534
+ case RefundAuthorizationResponseCodes.REFUND_DATA:
535
+ await this.wrapper.contract.isValidRefundAuthorization(this.data, resp.data);
536
+ this.state = ToBTCSwapState.REFUNDABLE;
537
+ if(save) await this._saveAndEmit();
538
+ return true;
539
+ default:
540
+ return false;
541
+ }
542
+ }
543
+
544
+ /**
545
+ * A blocking promise resolving when swap was concluded by the intermediary,
546
+ * rejecting in case of failure
547
+ *
548
+ * @param maxWaitTimeSeconds Maximum time in seconds to wait for the swap to be settled, an error is thrown if the
549
+ * swap is taking too long to claim
550
+ * @param checkIntervalSeconds How often to poll the intermediary for answer
551
+ * @param abortSignal Abort signal
552
+ * @returns {Promise<boolean>} Was the payment successful? If not we can refund.
553
+ * @throws {IntermediaryError} If a swap is determined expired by the intermediary, but it is actually still valid
554
+ * @throws {SignatureVerificationError} If the swap should be cooperatively refundable but the intermediary returned
555
+ * invalid refund signature
556
+ * @throws {Error} When swap expires or if the swap has invalid state (must be COMMITED)
557
+ */
558
+ async waitForPayment(maxWaitTimeSeconds?: number, checkIntervalSeconds?: number, abortSignal?: AbortSignal): Promise<boolean> {
559
+ if(this.state===ToBTCSwapState.CLAIMED) return Promise.resolve(true);
560
+ if(this.state!==ToBTCSwapState.COMMITED && this.state!==ToBTCSwapState.SOFT_CLAIMED) throw new Error("Invalid state (not COMMITED)");
561
+
562
+ const abortController = extendAbortController(abortSignal);
563
+
564
+ let timedOut: boolean = false;
565
+ if(maxWaitTimeSeconds!=null) {
566
+ const timeout = setTimeout(() => {
567
+ timedOut = true;
568
+ abortController.abort();
569
+ }, maxWaitTimeSeconds * 1000);
570
+ abortController.signal.addEventListener("abort", () => clearTimeout(timeout));
571
+ }
572
+
573
+ let result: void | RefundAuthorizationResponse;
574
+ try {
575
+ result = await Promise.race([
576
+ this.waitTillState(ToBTCSwapState.CLAIMED, "gte", abortController.signal),
577
+ this.waitTillIntermediarySwapProcessed(checkIntervalSeconds, abortController.signal)
578
+ ]);
579
+ abortController.abort();
580
+ } catch (e) {
581
+ abortController.abort();
582
+ if(timedOut) {
583
+ throw new Error("Timed out while waiting for LP to process the swap, the LP might be unresponsive or offline!" +
584
+ ` Please check later or wait till ${new Date(Number(this.data.getExpiry())*1000).toLocaleString()} to refund unilaterally!`);
585
+ }
586
+ throw e;
587
+ }
588
+
589
+ if(typeof result !== "object") {
590
+ if((this.state as ToBTCSwapState)===ToBTCSwapState.REFUNDABLE) throw new Error("Swap expired");
591
+ this.logger.debug("waitTillRefunded(): Resolved from state change");
592
+ return true;
593
+ }
594
+ this.logger.debug("waitTillRefunded(): Resolved from intermediary response");
595
+
596
+ switch(result.code) {
597
+ case RefundAuthorizationResponseCodes.PAID:
598
+ return true;
599
+ case RefundAuthorizationResponseCodes.REFUND_DATA:
600
+ const resultData = result.data;
601
+ await this.wrapper.contract.isValidRefundAuthorization(
602
+ this.data,
603
+ resultData
604
+ );
605
+ await this._saveAndEmit(ToBTCSwapState.REFUNDABLE);
606
+ return false;
607
+ case RefundAuthorizationResponseCodes.EXPIRED:
608
+ if(await this.wrapper.contract.isExpired(this._getInitiator(), this.data)) throw new Error("Swap expired");
609
+ throw new IntermediaryError("Swap expired");
610
+ case RefundAuthorizationResponseCodes.NOT_FOUND:
611
+ if((this.state as ToBTCSwapState)===ToBTCSwapState.CLAIMED) return true;
612
+ throw new Error("LP swap not found");
613
+ }
614
+
615
+ throw new Error("Invalid response code returned by the LP");
616
+ }
617
+
618
+
619
+ //////////////////////////////
620
+ //// Refund
621
+
622
+ /**
623
+ * Get the estimated smart chain transaction fee of the refund transaction
624
+ */
625
+ getRefundFee(): Promise<bigint> {
626
+ return this.wrapper.contract.getRefundFee(this._getInitiator(), this.data);
627
+ }
628
+
629
+ /**
630
+ * Returns transactions for refunding the swap if the swap is in refundable state, you can check so with isRefundable()
631
+ *
632
+ * @throws {IntermediaryError} If intermediary returns invalid response in case cooperative refund should be used
633
+ * @throws {SignatureVerificationError} If intermediary returned invalid cooperative refund signature
634
+ * @throws {Error} When state is not refundable
635
+ */
636
+ async txsRefund(signer?: string): Promise<T["TX"][]> {
637
+ if(!this.isRefundable()) throw new Error("Must be in REFUNDABLE state or expired!");
638
+
639
+ signer ??= this._getInitiator();
640
+
641
+ if(await this.wrapper.contract.isExpired(this._getInitiator(), this.data)) {
642
+ return await this.wrapper.contract.txsRefund(signer, this.data, true, true);
643
+ } else {
644
+ if(this.url==null) throw new Error("LP URL not known, cannot get cooperative refund message, wait till expiry to refund!");
645
+ const res = await IntermediaryAPI.getRefundAuthorization(this.url, this.getLpIdentifier(), this.data.getSequence());
646
+ if(res.code===RefundAuthorizationResponseCodes.REFUND_DATA) {
647
+ return await this.wrapper.contract.txsRefundWithAuthorization(
648
+ signer,
649
+ this.data,
650
+ res.data,
651
+ true,
652
+ true
653
+ );
654
+ }
655
+ throw new IntermediaryError("Invalid intermediary cooperative message returned");
656
+ }
657
+ }
658
+
659
+ /**
660
+ * Refunds the swap if the swap is in refundable state, you can check so with isRefundable()
661
+ *
662
+ * @param _signer Signer to sign the transactions with, must be the same as used in the initialization
663
+ * @param abortSignal Abort signal
664
+ * @throws {Error} If invalid signer is provided that doesn't match the swap data
665
+ */
666
+ async refund(_signer: T["Signer"] | T["NativeSigner"], abortSignal?: AbortSignal): Promise<string> {
667
+ const signer = isAbstractSigner(_signer) ? _signer : await this.wrapper.chain.wrapSigner(_signer);
668
+ const result = await this.wrapper.chain.sendAndConfirm(signer, await this.txsRefund(signer.getAddress()), true, abortSignal)
669
+
670
+ this.refundTxId = result[0];
671
+ if(this.state===ToBTCSwapState.COMMITED || this.state===ToBTCSwapState.REFUNDABLE || this.state===ToBTCSwapState.SOFT_CLAIMED) {
672
+ await this._saveAndEmit(ToBTCSwapState.REFUNDED);
673
+ }
674
+ return result[0];
675
+ }
676
+
677
+ /**
678
+ * Waits till a swap is refunded, should be called after sending the refund transactions manually
679
+ *
680
+ * @param abortSignal AbortSignal
681
+ * @throws {Error} When swap is not in a valid state (must be COMMITED)
682
+ * @throws {Error} If we tried to refund but claimer was able to claim first
683
+ */
684
+ async waitTillRefunded(abortSignal?: AbortSignal): Promise<void> {
685
+ if(this.state===ToBTCSwapState.REFUNDED) return Promise.resolve();
686
+ if(this.state!==ToBTCSwapState.COMMITED && this.state!==ToBTCSwapState.SOFT_CLAIMED) throw new Error("Invalid state (not COMMITED)");
687
+
688
+ const abortController = new AbortController();
689
+ if(abortSignal!=null) abortSignal.addEventListener("abort", () => abortController.abort(abortSignal.reason));
690
+ const res = await Promise.race([
691
+ this.watchdogWaitTillResult(undefined, abortController.signal),
692
+ this.waitTillState(ToBTCSwapState.REFUNDED, "eq", abortController.signal).then(() => 0 as const),
693
+ this.waitTillState(ToBTCSwapState.CLAIMED, "eq", abortController.signal).then(() => 1 as const),
694
+ ]);
695
+ abortController.abort();
696
+
697
+ if(res===0) {
698
+ this.logger.debug("waitTillRefunded(): Resolved from state change (REFUNDED)");
699
+ return;
700
+ }
701
+ if(res===1) {
702
+ this.logger.debug("waitTillRefunded(): Resolved from state change (CLAIMED)");
703
+ throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
704
+ }
705
+ this.logger.debug("waitTillRefunded(): Resolved from watchdog");
706
+
707
+ if(res?.type===SwapCommitStateType.PAID) {
708
+ if(this.claimTxId==null) this.claimTxId = await res.getClaimTxId();
709
+ await this._saveAndEmit(ToBTCSwapState.CLAIMED);
710
+ throw new Error("Tried to refund swap, but claimer claimed it in the meantime!");
711
+ }
712
+ if(res?.type===SwapCommitStateType.NOT_COMMITED) {
713
+ if(this.refundTxId==null && res.getRefundTxId!=null) this.refundTxId = await res.getRefundTxId();
714
+ await this._saveAndEmit(ToBTCSwapState.REFUNDED);
715
+ }
716
+ }
717
+
718
+
719
+ //////////////////////////////
720
+ //// Storage
721
+
722
+ serialize(): any {
723
+ const obj = super.serialize();
724
+ return {
725
+ ...obj,
726
+ networkFee: this.networkFee==null ? null : this.networkFee.toString(10),
727
+ networkFeeBtc: this.networkFeeBtc==null ? null : this.networkFeeBtc.toString(10)
728
+ };
729
+ }
730
+
731
+
732
+ //////////////////////////////
733
+ //// Swap ticks & sync
734
+
735
+ /**
736
+ * Checks the swap's state on-chain and compares it to its internal state, updates/changes it according to on-chain
737
+ * data
738
+ *
739
+ * @private
740
+ */
741
+ private async syncStateFromChain(quoteDefinitelyExpired?: boolean, commitStatus?: SwapCommitState): Promise<boolean> {
742
+ if(
743
+ this.state===ToBTCSwapState.CREATED ||
744
+ this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
745
+ this.state===ToBTCSwapState.COMMITED ||
746
+ this.state===ToBTCSwapState.SOFT_CLAIMED ||
747
+ this.state===ToBTCSwapState.REFUNDABLE
748
+ ) {
749
+ let quoteExpired = false;
750
+ if(this.state===ToBTCSwapState.CREATED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED) {
751
+ //Check if quote is still valid
752
+ quoteExpired = quoteDefinitelyExpired ?? await this._verifyQuoteDefinitelyExpired();
753
+ }
754
+
755
+ commitStatus ??= await this.wrapper.contract.getCommitStatus(this._getInitiator(), this.data);
756
+ switch(commitStatus?.type) {
757
+ case SwapCommitStateType.PAID:
758
+ if(this.claimTxId==null && commitStatus.getClaimTxId) this.claimTxId = await commitStatus.getClaimTxId();
759
+ const eventResult = await commitStatus.getClaimResult();
760
+ try {
761
+ await this._setPaymentResult({secret: eventResult, txId: Buffer.from(eventResult, "hex").reverse().toString("hex")});
762
+ } catch (e) {
763
+ this.logger.error(`Failed to set payment result ${eventResult} on the swap!`);
764
+ }
765
+ this.state = ToBTCSwapState.CLAIMED;
766
+ return true;
767
+ case SwapCommitStateType.REFUNDABLE:
768
+ this.state = ToBTCSwapState.REFUNDABLE;
769
+ return true;
770
+ case SwapCommitStateType.EXPIRED:
771
+ if(this.refundTxId==null && commitStatus.getRefundTxId) this.refundTxId = await commitStatus.getRefundTxId();
772
+ this.state = ToBTCSwapState.QUOTE_EXPIRED;
773
+ return true;
774
+ case SwapCommitStateType.NOT_COMMITED:
775
+ if(this.refundTxId==null && commitStatus.getRefundTxId) this.refundTxId = await commitStatus.getRefundTxId();
776
+ if(this.state===ToBTCSwapState.COMMITED || this.state===ToBTCSwapState.REFUNDABLE) {
777
+ this.state = ToBTCSwapState.REFUNDED;
778
+ return true;
779
+ }
780
+ break;
781
+ case SwapCommitStateType.COMMITED:
782
+ if(this.state!==ToBTCSwapState.COMMITED && this.state!==ToBTCSwapState.REFUNDABLE) {
783
+ this.state = ToBTCSwapState.COMMITED;
784
+ return true;
785
+ }
786
+ break;
787
+ }
788
+
789
+ if((this.state===ToBTCSwapState.CREATED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED)) {
790
+ if(quoteExpired) {
791
+ this.state = ToBTCSwapState.QUOTE_EXPIRED;
792
+ return true;
793
+ }
794
+ }
795
+ }
796
+ return false;
797
+ }
798
+
799
+ _shouldFetchCommitStatus(): boolean {
800
+ return this.state===ToBTCSwapState.CREATED ||
801
+ this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED ||
802
+ this.state===ToBTCSwapState.COMMITED ||
803
+ this.state===ToBTCSwapState.SOFT_CLAIMED ||
804
+ this.state===ToBTCSwapState.REFUNDABLE;
805
+ }
806
+
807
+ _shouldFetchExpiryStatus(): boolean {
808
+ return this.state===ToBTCSwapState.CREATED || this.state===ToBTCSwapState.QUOTE_SOFT_EXPIRED;
809
+ }
810
+
811
+ async _sync(save?: boolean, quoteDefinitelyExpired?: boolean, commitStatus?: SwapCommitState): Promise<boolean> {
812
+ let changed = await this.syncStateFromChain(quoteDefinitelyExpired, commitStatus);
813
+
814
+ if(this.state===ToBTCSwapState.COMMITED || this.state===ToBTCSwapState.SOFT_CLAIMED) {
815
+ //Check if that maybe already concluded
816
+ try {
817
+ if(await this.checkIntermediarySwapProcessed(false)) changed = true;
818
+ } catch (e) {
819
+ this.logger.error("_sync(): Failed to synchronize swap, error: ", e);
820
+ }
821
+ }
822
+
823
+ if(save && changed) await this._saveAndEmit();
824
+
825
+ return changed;
826
+ }
827
+
828
+ async _tick(save?: boolean): Promise<boolean> {
829
+ switch(this.state) {
830
+ case ToBTCSwapState.CREATED:
831
+ if(this.expiry<Date.now()) {
832
+ this.state = ToBTCSwapState.QUOTE_SOFT_EXPIRED;
833
+ if(save) await this._saveAndEmit();
834
+ return true;
835
+ }
836
+ break;
837
+ case ToBTCSwapState.COMMITED:
838
+ case ToBTCSwapState.SOFT_CLAIMED:
839
+ const expired = await this.wrapper.contract.isExpired(this._getInitiator(), this.data);
840
+ if(expired) {
841
+ this.state = ToBTCSwapState.REFUNDABLE;
842
+ if(save) await this._saveAndEmit();
843
+ return true;
844
+ }
845
+ break;
846
+ }
847
+ return false;
848
+ }
849
+ }
850
+
851
+ export enum ToBTCSwapState {
852
+ REFUNDED = -3,
853
+ QUOTE_EXPIRED = -2,
854
+ QUOTE_SOFT_EXPIRED = -1,
855
+ CREATED = 0,
856
+ COMMITED = 1,
857
+ SOFT_CLAIMED = 2,
858
+ CLAIMED = 3,
859
+ REFUNDABLE = 4
860
+ }