@atomiqlabs/sdk 8.9.1 → 8.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (366) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +1760 -1760
  3. package/api/index.d.ts +1 -1
  4. package/api/index.js +3 -3
  5. package/dist/ApiList.d.ts +37 -37
  6. package/dist/ApiList.js +30 -30
  7. package/dist/SmartChainAssets.d.ts +181 -181
  8. package/dist/SmartChainAssets.js +181 -181
  9. package/dist/api/ApiEndpoints.d.ts +393 -393
  10. package/dist/api/ApiEndpoints.js +2 -2
  11. package/dist/api/ApiParser.d.ts +10 -10
  12. package/dist/api/ApiParser.js +134 -134
  13. package/dist/api/ApiTypes.d.ts +157 -157
  14. package/dist/api/ApiTypes.js +75 -75
  15. package/dist/api/SerializedAction.d.ts +40 -40
  16. package/dist/api/SerializedAction.js +59 -59
  17. package/dist/api/SwapperApi.d.ts +50 -50
  18. package/dist/api/SwapperApi.js +431 -431
  19. package/dist/api/index.d.ts +5 -5
  20. package/dist/api/index.js +24 -24
  21. package/dist/bitcoin/coinselect2/accumulative.d.ts +7 -7
  22. package/dist/bitcoin/coinselect2/accumulative.js +52 -52
  23. package/dist/bitcoin/coinselect2/blackjack.d.ts +7 -7
  24. package/dist/bitcoin/coinselect2/blackjack.js +38 -38
  25. package/dist/bitcoin/coinselect2/index.d.ts +20 -20
  26. package/dist/bitcoin/coinselect2/index.js +69 -69
  27. package/dist/bitcoin/coinselect2/utils.d.ts +82 -82
  28. package/dist/bitcoin/coinselect2/utils.js +158 -158
  29. package/dist/bitcoin/wallet/BitcoinWallet.d.ts +113 -113
  30. package/dist/bitcoin/wallet/BitcoinWallet.js +335 -335
  31. package/dist/bitcoin/wallet/IBitcoinWallet.d.ts +116 -116
  32. package/dist/bitcoin/wallet/IBitcoinWallet.js +21 -21
  33. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.d.ts +106 -106
  34. package/dist/bitcoin/wallet/SingleAddressBitcoinWallet.js +196 -196
  35. package/dist/enums/FeeType.d.ts +15 -15
  36. package/dist/enums/FeeType.js +19 -19
  37. package/dist/enums/SwapAmountType.d.ts +15 -15
  38. package/dist/enums/SwapAmountType.js +19 -19
  39. package/dist/enums/SwapDirection.d.ts +15 -15
  40. package/dist/enums/SwapDirection.js +19 -19
  41. package/dist/enums/SwapSide.d.ts +15 -15
  42. package/dist/enums/SwapSide.js +19 -19
  43. package/dist/enums/SwapType.d.ts +75 -75
  44. package/dist/enums/SwapType.js +79 -79
  45. package/dist/errors/IntermediaryError.d.ts +13 -13
  46. package/dist/errors/IntermediaryError.js +27 -27
  47. package/dist/errors/RequestError.d.ts +32 -32
  48. package/dist/errors/RequestError.js +54 -54
  49. package/dist/errors/UserError.d.ts +8 -8
  50. package/dist/errors/UserError.js +16 -16
  51. package/dist/events/UnifiedSwapEventListener.d.ts +24 -24
  52. package/dist/events/UnifiedSwapEventListener.js +138 -138
  53. package/dist/http/HttpUtils.d.ts +29 -29
  54. package/dist/http/HttpUtils.js +97 -97
  55. package/dist/http/paramcoders/IParamReader.d.ts +8 -8
  56. package/dist/http/paramcoders/IParamReader.js +2 -2
  57. package/dist/http/paramcoders/ParamDecoder.d.ts +44 -44
  58. package/dist/http/paramcoders/ParamDecoder.js +137 -137
  59. package/dist/http/paramcoders/ParamEncoder.d.ts +20 -20
  60. package/dist/http/paramcoders/ParamEncoder.js +36 -36
  61. package/dist/http/paramcoders/SchemaVerifier.d.ts +26 -26
  62. package/dist/http/paramcoders/SchemaVerifier.js +145 -145
  63. package/dist/http/paramcoders/client/ResponseParamDecoder.d.ts +11 -11
  64. package/dist/http/paramcoders/client/ResponseParamDecoder.js +57 -57
  65. package/dist/http/paramcoders/client/StreamParamEncoder.d.ts +13 -13
  66. package/dist/http/paramcoders/client/StreamParamEncoder.js +26 -26
  67. package/dist/http/paramcoders/client/StreamingFetchPromise.d.ts +17 -17
  68. package/dist/http/paramcoders/client/StreamingFetchPromise.js +175 -175
  69. package/dist/index.d.ts +86 -86
  70. package/dist/index.js +159 -159
  71. package/dist/intermediaries/Intermediary.d.ts +178 -178
  72. package/dist/intermediaries/Intermediary.js +166 -166
  73. package/dist/intermediaries/IntermediaryDiscovery.d.ts +216 -216
  74. package/dist/intermediaries/IntermediaryDiscovery.js +424 -424
  75. package/dist/intermediaries/apis/IntermediaryAPI.d.ts +607 -607
  76. package/dist/intermediaries/apis/IntermediaryAPI.js +764 -764
  77. package/dist/intermediaries/apis/TrustedIntermediaryAPI.d.ts +155 -155
  78. package/dist/intermediaries/apis/TrustedIntermediaryAPI.js +137 -137
  79. package/dist/intermediaries/auth/SignedKeyBasedAuth.d.ts +14 -14
  80. package/dist/intermediaries/auth/SignedKeyBasedAuth.js +68 -68
  81. package/dist/lnurl/LNURL.d.ts +102 -102
  82. package/dist/lnurl/LNURL.js +321 -321
  83. package/dist/prices/RedundantSwapPrice.d.ts +110 -110
  84. package/dist/prices/RedundantSwapPrice.js +222 -222
  85. package/dist/prices/SingleSwapPrice.d.ts +34 -34
  86. package/dist/prices/SingleSwapPrice.js +44 -44
  87. package/dist/prices/SwapPriceWithChain.d.ts +107 -107
  88. package/dist/prices/SwapPriceWithChain.js +128 -128
  89. package/dist/prices/abstract/ICachedSwapPrice.d.ts +28 -28
  90. package/dist/prices/abstract/ICachedSwapPrice.js +62 -62
  91. package/dist/prices/abstract/IPriceProvider.d.ts +81 -81
  92. package/dist/prices/abstract/IPriceProvider.js +74 -74
  93. package/dist/prices/abstract/ISwapPrice.d.ts +168 -168
  94. package/dist/prices/abstract/ISwapPrice.js +279 -279
  95. package/dist/prices/providers/BinancePriceProvider.d.ts +23 -23
  96. package/dist/prices/providers/BinancePriceProvider.js +30 -30
  97. package/dist/prices/providers/CoinGeckoPriceProvider.d.ts +23 -23
  98. package/dist/prices/providers/CoinGeckoPriceProvider.js +29 -29
  99. package/dist/prices/providers/CoinPaprikaPriceProvider.d.ts +25 -25
  100. package/dist/prices/providers/CoinPaprikaPriceProvider.js +29 -29
  101. package/dist/prices/providers/CustomPriceProvider.d.ts +24 -24
  102. package/dist/prices/providers/CustomPriceProvider.js +35 -35
  103. package/dist/prices/providers/KrakenPriceProvider.d.ts +38 -38
  104. package/dist/prices/providers/KrakenPriceProvider.js +45 -45
  105. package/dist/prices/providers/OKXPriceProvider.d.ts +34 -34
  106. package/dist/prices/providers/OKXPriceProvider.js +29 -29
  107. package/dist/prices/providers/abstract/ExchangePriceProvider.d.ts +17 -17
  108. package/dist/prices/providers/abstract/ExchangePriceProvider.js +21 -21
  109. package/dist/prices/providers/abstract/HttpPriceProvider.d.ts +7 -7
  110. package/dist/prices/providers/abstract/HttpPriceProvider.js +12 -12
  111. package/dist/storage/IUnifiedStorage.d.ts +127 -127
  112. package/dist/storage/IUnifiedStorage.js +2 -2
  113. package/dist/storage/UnifiedSwapStorage.d.ts +120 -120
  114. package/dist/storage/UnifiedSwapStorage.js +154 -154
  115. package/dist/storage-browser/IndexedDBUnifiedStorage.d.ts +63 -63
  116. package/dist/storage-browser/IndexedDBUnifiedStorage.js +298 -298
  117. package/dist/storage-browser/LocalStorageManager.d.ts +49 -49
  118. package/dist/storage-browser/LocalStorageManager.js +93 -93
  119. package/dist/swapper/Swapper.d.ts +770 -770
  120. package/dist/swapper/Swapper.js +1758 -1758
  121. package/dist/swapper/SwapperFactory.d.ts +135 -135
  122. package/dist/swapper/SwapperFactory.js +162 -162
  123. package/dist/swapper/SwapperUtils.d.ts +222 -222
  124. package/dist/swapper/SwapperUtils.js +519 -519
  125. package/dist/swapper/SwapperWithChain.d.ts +404 -404
  126. package/dist/swapper/SwapperWithChain.js +469 -469
  127. package/dist/swapper/SwapperWithSigner.d.ts +322 -322
  128. package/dist/swapper/SwapperWithSigner.js +318 -318
  129. package/dist/swaps/IAddressSwap.d.ts +22 -22
  130. package/dist/swaps/IAddressSwap.js +14 -14
  131. package/dist/swaps/IBTCWalletSwap.d.ts +73 -73
  132. package/dist/swaps/IBTCWalletSwap.js +18 -18
  133. package/dist/swaps/IClaimableSwap.d.ts +49 -49
  134. package/dist/swaps/IClaimableSwap.js +15 -15
  135. package/dist/swaps/IClaimableSwapWrapper.d.ts +15 -15
  136. package/dist/swaps/IClaimableSwapWrapper.js +2 -2
  137. package/dist/swaps/IRefundableSwap.d.ts +43 -43
  138. package/dist/swaps/IRefundableSwap.js +14 -14
  139. package/dist/swaps/ISwap.d.ts +453 -453
  140. package/dist/swaps/ISwap.js +371 -371
  141. package/dist/swaps/ISwapWithGasDrop.d.ts +21 -21
  142. package/dist/swaps/ISwapWithGasDrop.js +12 -12
  143. package/dist/swaps/ISwapWrapper.d.ts +295 -295
  144. package/dist/swaps/ISwapWrapper.js +373 -373
  145. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.d.ts +98 -98
  146. package/dist/swaps/escrow_swaps/IEscrowSelfInitSwap.js +126 -126
  147. package/dist/swaps/escrow_swaps/IEscrowSwap.d.ts +139 -139
  148. package/dist/swaps/escrow_swaps/IEscrowSwap.js +172 -172
  149. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.d.ts +129 -129
  150. package/dist/swaps/escrow_swaps/IEscrowSwapWrapper.js +167 -167
  151. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.d.ts +107 -107
  152. package/dist/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.js +130 -130
  153. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.d.ts +162 -162
  154. package/dist/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.js +190 -190
  155. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.d.ts +64 -64
  156. package/dist/swaps/escrow_swaps/frombtc/IFromBTCWrapper.js +82 -82
  157. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.d.ts +547 -547
  158. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.js +1419 -1419
  159. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.d.ts +192 -192
  160. package/dist/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.js +432 -432
  161. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.d.ts +650 -650
  162. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.js +1577 -1577
  163. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.d.ts +237 -237
  164. package/dist/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.js +525 -525
  165. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.d.ts +491 -491
  166. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.js +1463 -1463
  167. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.d.ts +204 -204
  168. package/dist/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.js +406 -406
  169. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.d.ts +446 -446
  170. package/dist/swaps/escrow_swaps/tobtc/IToBTCSwap.js +1097 -1097
  171. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.d.ts +68 -68
  172. package/dist/swaps/escrow_swaps/tobtc/IToBTCWrapper.js +117 -117
  173. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.d.ts +127 -127
  174. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.js +256 -256
  175. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.d.ts +252 -252
  176. package/dist/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.js +535 -535
  177. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.d.ts +73 -73
  178. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.js +155 -155
  179. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.d.ts +134 -134
  180. package/dist/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.js +286 -286
  181. package/dist/swaps/spv_swaps/SpvFromBTCSwap.d.ts +694 -694
  182. package/dist/swaps/spv_swaps/SpvFromBTCSwap.js +1687 -1687
  183. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.d.ts +259 -259
  184. package/dist/swaps/spv_swaps/SpvFromBTCWrapper.js +947 -947
  185. package/dist/swaps/trusted/ln/LnForGasSwap.d.ts +302 -302
  186. package/dist/swaps/trusted/ln/LnForGasSwap.js +625 -625
  187. package/dist/swaps/trusted/ln/LnForGasWrapper.d.ts +40 -40
  188. package/dist/swaps/trusted/ln/LnForGasWrapper.js +82 -82
  189. package/dist/swaps/trusted/onchain/OnchainForGasSwap.d.ts +343 -343
  190. package/dist/swaps/trusted/onchain/OnchainForGasSwap.js +698 -698
  191. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.d.ts +71 -71
  192. package/dist/swaps/trusted/onchain/OnchainForGasWrapper.js +93 -93
  193. package/dist/types/AmountData.d.ts +10 -10
  194. package/dist/types/AmountData.js +2 -2
  195. package/dist/types/CustomPriceFunction.d.ts +11 -11
  196. package/dist/types/CustomPriceFunction.js +2 -2
  197. package/dist/types/PriceInfoType.d.ts +28 -28
  198. package/dist/types/PriceInfoType.js +57 -57
  199. package/dist/types/SwapExecutionAction.d.ts +195 -195
  200. package/dist/types/SwapExecutionAction.js +106 -106
  201. package/dist/types/SwapExecutionStep.d.ts +144 -144
  202. package/dist/types/SwapExecutionStep.js +87 -87
  203. package/dist/types/SwapStateInfo.d.ts +5 -5
  204. package/dist/types/SwapStateInfo.js +2 -2
  205. package/dist/types/SwapWithSigner.d.ts +17 -17
  206. package/dist/types/SwapWithSigner.js +43 -43
  207. package/dist/types/Token.d.ts +99 -99
  208. package/dist/types/Token.js +76 -76
  209. package/dist/types/TokenAmount.d.ts +75 -75
  210. package/dist/types/TokenAmount.js +85 -85
  211. package/dist/types/fees/Fee.d.ts +50 -50
  212. package/dist/types/fees/Fee.js +2 -2
  213. package/dist/types/fees/FeeBreakdown.d.ts +11 -11
  214. package/dist/types/fees/FeeBreakdown.js +2 -2
  215. package/dist/types/fees/PercentagePPM.d.ts +17 -17
  216. package/dist/types/fees/PercentagePPM.js +18 -18
  217. package/dist/types/lnurl/LNURLPay.d.ts +61 -61
  218. package/dist/types/lnurl/LNURLPay.js +31 -31
  219. package/dist/types/lnurl/LNURLWithdraw.d.ts +48 -48
  220. package/dist/types/lnurl/LNURLWithdraw.js +27 -27
  221. package/dist/types/wallets/LightningInvoiceCreateService.d.ts +24 -24
  222. package/dist/types/wallets/LightningInvoiceCreateService.js +15 -15
  223. package/dist/types/wallets/MinimalBitcoinWalletInterface.d.ts +23 -23
  224. package/dist/types/wallets/MinimalBitcoinWalletInterface.js +2 -2
  225. package/dist/types/wallets/MinimalLightningNetworkWalletInterface.d.ts +9 -9
  226. package/dist/types/wallets/MinimalLightningNetworkWalletInterface.js +2 -2
  227. package/dist/utils/AutomaticClockDriftCorrection.d.ts +1 -1
  228. package/dist/utils/AutomaticClockDriftCorrection.js +70 -70
  229. package/dist/utils/BitcoinUtils.d.ts +18 -18
  230. package/dist/utils/BitcoinUtils.js +174 -174
  231. package/dist/utils/BitcoinWalletUtils.d.ts +7 -7
  232. package/dist/utils/BitcoinWalletUtils.js +14 -14
  233. package/dist/utils/Logger.d.ts +7 -7
  234. package/dist/utils/Logger.js +12 -12
  235. package/dist/utils/RetryUtils.d.ts +22 -22
  236. package/dist/utils/RetryUtils.js +67 -67
  237. package/dist/utils/SwapUtils.d.ts +88 -88
  238. package/dist/utils/SwapUtils.js +72 -72
  239. package/dist/utils/TimeoutUtils.d.ts +17 -17
  240. package/dist/utils/TimeoutUtils.js +55 -55
  241. package/dist/utils/TokenUtils.d.ts +19 -19
  242. package/dist/utils/TokenUtils.js +37 -37
  243. package/dist/utils/TypeUtils.d.ts +7 -7
  244. package/dist/utils/TypeUtils.js +2 -2
  245. package/dist/utils/Utils.d.ts +69 -69
  246. package/dist/utils/Utils.js +214 -214
  247. package/package.json +46 -46
  248. package/src/SmartChainAssets.ts +186 -186
  249. package/src/api/ApiEndpoints.ts +427 -427
  250. package/src/api/ApiParser.ts +138 -138
  251. package/src/api/ApiTypes.ts +229 -229
  252. package/src/api/SerializedAction.ts +97 -97
  253. package/src/api/SwapperApi.ts +545 -545
  254. package/src/api/index.ts +5 -5
  255. package/src/bitcoin/coinselect2/accumulative.ts +69 -69
  256. package/src/bitcoin/coinselect2/blackjack.ts +50 -50
  257. package/src/bitcoin/coinselect2/index.ts +93 -93
  258. package/src/bitcoin/coinselect2/utils.ts +236 -236
  259. package/src/bitcoin/wallet/BitcoinWallet.ts +439 -439
  260. package/src/bitcoin/wallet/IBitcoinWallet.ts +140 -140
  261. package/src/bitcoin/wallet/SingleAddressBitcoinWallet.ts +225 -225
  262. package/src/enums/FeeType.ts +15 -15
  263. package/src/enums/SwapAmountType.ts +16 -16
  264. package/src/enums/SwapDirection.ts +15 -15
  265. package/src/enums/SwapSide.ts +16 -16
  266. package/src/enums/SwapType.ts +75 -75
  267. package/src/errors/IntermediaryError.ts +28 -28
  268. package/src/errors/RequestError.ts +64 -64
  269. package/src/errors/UserError.ts +15 -15
  270. package/src/events/UnifiedSwapEventListener.ts +181 -181
  271. package/src/http/HttpUtils.ts +97 -97
  272. package/src/http/paramcoders/IParamReader.ts +9 -9
  273. package/src/http/paramcoders/ParamDecoder.ts +145 -145
  274. package/src/http/paramcoders/ParamEncoder.ts +40 -40
  275. package/src/http/paramcoders/SchemaVerifier.ts +153 -153
  276. package/src/http/paramcoders/client/ResponseParamDecoder.ts +57 -57
  277. package/src/http/paramcoders/client/StreamParamEncoder.ts +28 -28
  278. package/src/http/paramcoders/client/StreamingFetchPromise.ts +194 -194
  279. package/src/index.ts +141 -141
  280. package/src/intermediaries/Intermediary.ts +280 -280
  281. package/src/intermediaries/IntermediaryDiscovery.ts +548 -548
  282. package/src/intermediaries/apis/IntermediaryAPI.ts +1247 -1247
  283. package/src/intermediaries/auth/SignedKeyBasedAuth.ts +69 -69
  284. package/src/lnurl/LNURL.ts +402 -402
  285. package/src/prices/RedundantSwapPrice.ts +264 -264
  286. package/src/prices/SingleSwapPrice.ts +50 -50
  287. package/src/prices/SwapPriceWithChain.ts +194 -194
  288. package/src/prices/abstract/ICachedSwapPrice.ts +85 -85
  289. package/src/prices/abstract/IPriceProvider.ts +127 -127
  290. package/src/prices/abstract/ISwapPrice.ts +390 -390
  291. package/src/prices/providers/BinancePriceProvider.ts +48 -48
  292. package/src/prices/providers/CoinGeckoPriceProvider.ts +46 -46
  293. package/src/prices/providers/CoinPaprikaPriceProvider.ts +49 -49
  294. package/src/prices/providers/CustomPriceProvider.ts +40 -40
  295. package/src/prices/providers/KrakenPriceProvider.ts +83 -83
  296. package/src/prices/providers/OKXPriceProvider.ts +59 -59
  297. package/src/prices/providers/abstract/ExchangePriceProvider.ts +31 -31
  298. package/src/prices/providers/abstract/HttpPriceProvider.ts +14 -14
  299. package/src/storage/IUnifiedStorage.ts +136 -136
  300. package/src/storage/UnifiedSwapStorage.ts +175 -175
  301. package/src/storage-browser/IndexedDBUnifiedStorage.ts +350 -350
  302. package/src/storage-browser/LocalStorageManager.ts +106 -106
  303. package/src/swapper/Swapper.ts +2570 -2570
  304. package/src/swapper/SwapperFactory.ts +307 -307
  305. package/src/swapper/SwapperUtils.ts +610 -610
  306. package/src/swapper/SwapperWithChain.ts +707 -707
  307. package/src/swapper/SwapperWithSigner.ts +511 -511
  308. package/src/swaps/IAddressSwap.ts +30 -30
  309. package/src/swaps/IBTCWalletSwap.ts +92 -92
  310. package/src/swaps/IClaimableSwap.ts +65 -65
  311. package/src/swaps/IClaimableSwapWrapper.ts +17 -17
  312. package/src/swaps/IRefundableSwap.ts +58 -58
  313. package/src/swaps/ISwap.ts +775 -775
  314. package/src/swaps/ISwapWithGasDrop.ts +25 -25
  315. package/src/swaps/ISwapWrapper.ts +564 -564
  316. package/src/swaps/escrow_swaps/IEscrowSelfInitSwap.ts +217 -217
  317. package/src/swaps/escrow_swaps/IEscrowSwap.ts +271 -271
  318. package/src/swaps/escrow_swaps/IEscrowSwapWrapper.ts +284 -284
  319. package/src/swaps/escrow_swaps/frombtc/IFromBTCLNWrapper.ts +172 -172
  320. package/src/swaps/escrow_swaps/frombtc/IFromBTCSelfInitSwap.ts +300 -300
  321. package/src/swaps/escrow_swaps/frombtc/IFromBTCWrapper.ts +107 -107
  322. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNSwap.ts +1670 -1671
  323. package/src/swaps/escrow_swaps/frombtc/ln/FromBTCLNWrapper.ts +603 -603
  324. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoSwap.ts +1883 -1883
  325. package/src/swaps/escrow_swaps/frombtc/ln_auto/FromBTCLNAutoWrapper.ts +752 -752
  326. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCSwap.ts +1753 -1753
  327. package/src/swaps/escrow_swaps/frombtc/onchain/FromBTCWrapper.ts +612 -612
  328. package/src/swaps/escrow_swaps/tobtc/IToBTCSwap.ts +1327 -1327
  329. package/src/swaps/escrow_swaps/tobtc/IToBTCWrapper.ts +138 -138
  330. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNSwap.ts +304 -304
  331. package/src/swaps/escrow_swaps/tobtc/ln/ToBTCLNWrapper.ts +787 -787
  332. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCSwap.ts +206 -206
  333. package/src/swaps/escrow_swaps/tobtc/onchain/ToBTCWrapper.ts +403 -403
  334. package/src/swaps/spv_swaps/SpvFromBTCSwap.ts +2148 -2148
  335. package/src/swaps/spv_swaps/SpvFromBTCWrapper.ts +1238 -1238
  336. package/src/swaps/trusted/ln/LnForGasSwap.ts +753 -753
  337. package/src/swaps/trusted/ln/LnForGasWrapper.ts +90 -90
  338. package/src/swaps/trusted/onchain/OnchainForGasSwap.ts +843 -843
  339. package/src/swaps/trusted/onchain/OnchainForGasWrapper.ts +133 -133
  340. package/src/types/AmountData.ts +9 -9
  341. package/src/types/CustomPriceFunction.ts +11 -11
  342. package/src/types/PriceInfoType.ts +66 -66
  343. package/src/types/SwapExecutionAction.ts +323 -323
  344. package/src/types/SwapExecutionStep.ts +224 -224
  345. package/src/types/SwapStateInfo.ts +6 -6
  346. package/src/types/SwapWithSigner.ts +61 -61
  347. package/src/types/Token.ts +163 -163
  348. package/src/types/TokenAmount.ts +167 -167
  349. package/src/types/fees/Fee.ts +56 -56
  350. package/src/types/fees/FeeBreakdown.ts +11 -11
  351. package/src/types/fees/PercentagePPM.ts +26 -26
  352. package/src/types/lnurl/LNURLPay.ts +79 -79
  353. package/src/types/lnurl/LNURLWithdraw.ts +61 -61
  354. package/src/types/wallets/LightningInvoiceCreateService.ts +30 -30
  355. package/src/types/wallets/MinimalBitcoinWalletInterface.ts +21 -21
  356. package/src/types/wallets/MinimalLightningNetworkWalletInterface.ts +9 -9
  357. package/src/utils/AutomaticClockDriftCorrection.ts +71 -71
  358. package/src/utils/BitcoinUtils.ts +164 -164
  359. package/src/utils/BitcoinWalletUtils.ts +15 -15
  360. package/src/utils/Logger.ts +14 -14
  361. package/src/utils/RetryUtils.ts +78 -78
  362. package/src/utils/SwapUtils.ts +99 -99
  363. package/src/utils/TimeoutUtils.ts +49 -49
  364. package/src/utils/TokenUtils.ts +33 -33
  365. package/src/utils/TypeUtils.ts +8 -8
  366. package/src/utils/Utils.ts +221 -221
package/README.md CHANGED
@@ -1,1760 +1,1760 @@
1
- # atomiqlabs SDK
2
-
3
- A typescript multichain client for atomiqlabs trustlesss cross-chain swaps. Enables trustless swaps between smart chains (Solana, EVM, Starknet, etc.) and bitcoin (on-chain - L1 and lightning network - L2).
4
-
5
- Example SDK integration in NodeJS available [here](https://github.com/atomiqlabs/atomiq-sdk-demo)
6
-
7
- ## Installation
8
- ```
9
- npm install @atomiqlabs/sdk@latest
10
- ```
11
-
12
- ## Installing chain-specific connectors
13
-
14
- You can install only the chain-specific connectors that your project requires
15
-
16
- ```
17
- npm install @atomiqlabs/chain-solana@latest
18
- npm install @atomiqlabs/chain-starknet@latest
19
- npm install @atomiqlabs/chain-evm@latest
20
- ```
21
-
22
- ## How to use?
23
-
24
- - [Preparations](#preparations)
25
- - [Setting up signers](#signer)
26
- - [Initialization](#initialization)
27
- - Swaps:
28
- - [Smart Chain -> BTC L1](#swap-smart-chain---bitcoin-on-chain)
29
- - [BTC L1 -> Solana (Old swap protocol)](#swap-bitcoin-on-chain---solana)
30
- - [BTC L1 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-on-chain---starknetevm)
31
- - [Smart Chain -> BTC Lightning network L2](#swap-smart-chain---bitcoin-lightning-network)
32
- - [Smart Chain -> BTC Lightning network L2 (LNURL-pay)](#swap-smart-chain---bitcoin-lightning-network-1)
33
- - [BTC Lightning network L2 -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana)
34
- - [BTC Lightning network L2 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm)
35
- - [BTC Lightning network L2 (LNURL-withdraw) -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana-1)
36
- - [BTC Lightning network L2 (LNURL-withdraw) -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm-1)
37
- - [Swap states](#getting-state-of-the-swap)
38
- - [Swap size limits](#swap-size-limits)
39
- - [Stored swaps](#stored-swaps)
40
- - [Get existing swaps](#get-swap-by-id)
41
- - [Refundable swaps](#get-refundable-swaps)
42
- - [Claimable swaps](#get-claimable-swaps)
43
- - [Helpers](#helpers)
44
- - [Wallet spendable balance](#getting-wallet-balances)
45
- - [Unified address parsers](#unified-address-parser)
46
- - [Customize swapper instance](#additional-swapper-options)
47
-
48
- ### Preparations
49
-
50
- Set Solana & Starknet RPC URL to use
51
-
52
- ```typescript
53
- const solanaRpc = "https://api.mainnet-beta.solana.com";
54
- const starknetRpc = "https://rpc.starknet.lava.build/"; //Alternatively: https://starknet.api.onfinality.io/public or https://api.zan.top/public/starknet-mainnet
55
- const citreaRpc = "https://rpc.mainnet.citrea.xyz";
56
- ```
57
-
58
- Create swapper factory, here we can pick and choose which chains we want to have supported in the SDK, ensure the "as const" keyword is used such that the typescript compiler can properly infer the types.
59
-
60
- ```typescript
61
- import {SolanaInitializer, SolanaInitializerType} from "@atomiqlabs/chain-solana";
62
- import {StarknetInitializer, StarknetInitializerType} from "@atomiqlabs/chain-starknet";
63
- import {CitreaInitializer, CitreaInitializerType} from "@atomiqlabs/chain-evm";
64
- import {SwapperFactory, TypedTokens} from "@atomiqlabs/sdk";
65
-
66
- //Define chains that you want to support here
67
- const chains = [SolanaInitializer, StarknetInitializer, CitreaInitializer] as const;
68
- type SupportedChains = typeof chains; //It's helpful that we also get the type of the chains array
69
-
70
- const Factory = new SwapperFactory<SupportedChains>(chains); //Create swapper factory
71
- const Tokens: TypedTokens<SupportedChains> = Factory.Tokens; //Get the supported tokens for all the specified chains.
72
- ```
73
-
74
- #### Browser
75
-
76
- This uses browser's Indexed DB by default
77
-
78
- ```typescript
79
- import {BitcoinNetwork, TypedSwapper} from "@atomiqlabs/sdk";
80
-
81
- const swapper: TypedSwapper<SupportedChains> = Factory.newSwapper({
82
- chains: {
83
- SOLANA: {
84
- rpcUrl: solanaRpc //You can also pass Connection object here
85
- },
86
- STARKNET: {
87
- rpcUrl: starknetRpc //You can also pass Provider object here
88
- },
89
- CITREA: {
90
- rpcUrl: citreaRpc, //You can also pass JsonRpcApiProvider object here
91
- }
92
- },
93
- bitcoinNetwork: BitcoinNetwork.MAINNET //or BitcoinNetwork.TESTNET3, BitcoinNetwork.TESTNET4 - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
94
- });
95
- ```
96
-
97
- if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
98
-
99
- #### NodeJS
100
-
101
- For NodeJS we need to use sqlite storage, for that we first need to install the sqlite storage adaptor
102
-
103
- ```
104
- npm install @atomiqlabs/storage-sqlite@latest
105
- ```
106
-
107
- Then use pass it in the newSwapper function
108
-
109
- ```typescript
110
- import {SqliteStorageManager, SqliteUnifiedStorage} from "@atomiqlabs/storage-sqlite";
111
- import {BitcoinNetwork, TypedSwapper} from "@atomiqlabs/sdk";
112
-
113
- const swapper: TypedSwapper<SupportedChains> = Factory.newSwapper({
114
- chains: {
115
- SOLANA: {
116
- rpcUrl: solanaRpc //You can also pass Connection object here
117
- },
118
- STARKNET: {
119
- rpcUrl: starknetRpc //You can also pass Provider object here
120
- },
121
- CITREA: {
122
- rpcUrl: citreaRpc, //You can also pass JsonApiProvider object here
123
- }
124
- },
125
- bitcoinNetwork: BitcoinNetwork.MAINNET //or BitcoinNetwork.TESTNET3, BitcoinNetwork.TESTNET4 - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
126
- //The following lines are important for running on backend node.js,
127
- // because the SDK by default uses browser's Indexed DB
128
- swapStorage: chainId => new SqliteUnifiedStorage("CHAIN_"+chainId+".sqlite3"),
129
- chainStorageCtor: name => new SqliteStorageManager("STORE_"+name+".sqlite3"),
130
- });
131
- ```
132
-
133
- if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
134
-
135
- ### Signer
136
-
137
- ```typescript
138
- import {SolanaSigner} from "@atomiqlabs/chain-solana";
139
- //Browser - react, using solana wallet adapter
140
- const anchorWallet = useAnchorWallet();
141
- const wallet = new SolanaSigner(anchorWallet);
142
- ```
143
-
144
- ```typescript
145
- import {WalletAccount} from "starknet";
146
- import {StarknetBrowserSigner} from "@atomiqlabs/chain-starknet";
147
- //Browser, using get-starknet
148
- const swo = await connect();
149
- const wallet = new StarknetBrowserSigner(new WalletAccount(starknetRpc, swo.wallet));
150
- ```
151
-
152
- or
153
-
154
- ```typescript
155
- import {Keypair} from "@solana/web3.js";
156
- import {SolanaKeypairWallet, SolanaSigner} from "@atomiqlabs/chain-solana";
157
- //Creating Solana signer from private key
158
- const solanaSigner = new SolanaSigner(new SolanaKeypairWallet(Keypair.fromSecretKey(solanaKey)), Keypair.fromSecretKey(solanaKey));
159
- ```
160
-
161
- ```typescript
162
- import {StarknetSigner, StarknetKeypairWallet} from "@atomiqlabs/chain-starknet";
163
- //Creating Starknet signer from private key
164
- const starknetSigner = new StarknetSigner(new StarknetKeypairWallet(starknetRpc, starknetKey));
165
- ```
166
-
167
- ```typescript
168
- import {BaseWallet, SigningKey} from "ethers";
169
- import {EVMSigner} from "@atomiqlabs/chain-evm";
170
- //Creating EVM signer from private key
171
- const wallet = new BaseWallet(new SigningKey(evmKey));
172
- const evmWallet = new EVMSigner(wallet, wallet.address);
173
- ```
174
-
175
- ### Initialization
176
-
177
- Initialize the swapper, this should be done once when your app starts. Checks existing in-progress swaps and does initial LP discovery
178
-
179
- ```typescript
180
- await swapper.init();
181
- ```
182
-
183
- Now we have the multichain swapper initialized
184
-
185
- ### Extract chain-specific swapper with signer
186
-
187
- To make it easier to do swaps between bitcoin and a specific chain we can extract a chain-specific swapper, and also set a signer. e.g.:
188
-
189
- ```typescript
190
- const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA");
191
- ```
192
-
193
- ### Bitcoin on-chain swaps
194
-
195
- #### Swap Smart chain -> Bitcoin on-chain
196
-
197
- Getting swap quote
198
-
199
- ```typescript
200
- //Create the swap: swapping SOL to Bitcoin on-chain, receiving _amount of satoshis (smallest unit of bitcoin) to _address
201
- const swap: ToBTCSwap<SolanaChainType> = await swapper.swap(
202
- Tokens.SOLANA.SOL, //From specified source token
203
- Tokens.BITCOIN.BTC, //Swap to BTC
204
- "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
205
- SwapAmountType.EXACT_OUT, //EXACT_OUT, so we specify the output amount
206
- solanaSigner.getAddress(), //Source address and smart chain signer
207
- "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt" //BTC address of the recipient
208
- );
209
-
210
- //Get the amount required to pay and fee
211
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
212
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
213
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
214
-
215
- const output: string = swap.getOutput().toString(); //Total output amount
216
-
217
- //Get swap expiration time
218
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
219
-
220
- //Get pricing info
221
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
222
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
223
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
224
- ```
225
-
226
- Executing the swap (simple)
227
-
228
- ```typescript
229
- const swapSuccessful = await swap.execute(
230
- solanaSigner,
231
- { //Callbacks
232
- onSourceTransactionSent: (txId: string) => {
233
- //Transaction on the source chain was sent
234
- },
235
- onSourceTransactionConfirmed: (txId: string) => {
236
- //Transaction on the source chain was confirmed
237
- },
238
- onSwapSettled: (destinationTxId: string) => {
239
- //Bitcoin transaction on the destination chain was sent and swap settled
240
- }
241
- }
242
- );
243
-
244
- //Refund in case of failure
245
- if(!swapSuccessful) {
246
- //Swap failed, money can be refunded
247
- await swap.refund(solanaSigner);
248
- } else {
249
- //Swap successful!
250
- }
251
- ```
252
-
253
- <details>
254
- <summary>Manual swap execution (advanced)</summary>
255
-
256
- - __1.__ Initiate the swap on the smart-chain side
257
-
258
- - __a.__ Commit with a signer
259
- ```typescript
260
- await swap.commit(solanaSigner);
261
- ```
262
-
263
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
264
- ```typescript
265
- const txsCommit = await swap.txsCommit();
266
- //Sign and send these...
267
- ...
268
- //Important to wait till SDK processes the swap initialization
269
- await swap.waitTillCommited();
270
- ```
271
-
272
- - __2.__ Wait for the swap to execute and for the payment to be sent
273
- ```typescript
274
- const swapSuccessful = await swap.waitForPayment();
275
- ```
276
-
277
- - __3.__ In case the swap fails we can refund our funds on the source chain
278
-
279
- - __a.__ Refund with a signer
280
- ```typescript
281
- if(!swapSuccessful) {
282
- await swap.refund(solanaSigner);
283
- return;
284
- }
285
- ```
286
-
287
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
288
- ```typescript
289
- if(!swapSuccessful) {
290
- const txsRefund = await swap.txsRefund();
291
- //Sign and send these...
292
- ...
293
- }
294
- ```
295
-
296
- </details>
297
-
298
- <details>
299
- <summary>Swap states</summary>
300
-
301
- - ToBTCSwapState.REFUNDED = -3
302
- - Swap failed and was successfully refunded
303
- - ToBTCSwapState.QUOTE_EXPIRED = -2
304
- - Swap quote expired and cannot be executed anymore
305
- - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
306
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
307
- - ToBTCSwapState.CREATED = 0
308
- - Swap quote is created, waiting to be executed
309
- - ToBTCSwapState.COMMITED = 1,
310
- - Swap was initiated (init transaction sent)
311
- - ToBTCSwapState.SOFT_CLAIMED = 2,
312
- - Swap was processed by the counterparty but not yet claimed on-chain (bitcoin transaction was sent, but unconfirmed yet)
313
- - ToBTCSwapState.CLAIMED = 3
314
- - Swap was finished and funds were successfully claimed by the counterparty
315
- - ToBTCSwapState.REFUNDABLE = 4
316
- - Swap was initiated but counterparty failed to process it, the user can now refund his funds
317
-
318
- </details>
319
-
320
- #### Swap Bitcoin on-chain -> Solana
321
-
322
- NOTE: Solana uses an old swap protocol for Bitcoin on-chain -> Solana swaps, the flow here is different from the one for Starknet and other chains.
323
-
324
- Getting swap quote
325
-
326
- ```typescript
327
- //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
328
- const swap: FromBTCSwap<SolanaChainType> = await swapper.swap(
329
- Tokens.BITCOIN.BTC, //Swap from BTC
330
- Tokens.SOLANA.SOL, //Into specified destination token
331
- "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
332
- SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
333
- undefined, //Source address for the swap, not used for swaps from BTC
334
- solanaSigner.getAddress() //Destination address
335
- );
336
-
337
- //Get the amount required to pay and fee
338
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
339
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
340
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
341
-
342
- const output: string = swap.getOutput().toString(); //Total output amount
343
-
344
- //Get swap expiration time
345
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
346
-
347
- //Get security deposit amount (Human readable amount of SOL that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
348
- const securityDeposit: string = swap.getSecurityDeposit().toString();
349
- //Get claimer bounty (Human readable amount of SOL reserved as a reward for watchtowers to claim the swap on your behalf)
350
- const claimerBounty: string = swap.getClaimerBounty().toString();
351
-
352
- //Get pricing info
353
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
354
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
355
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
356
- ```
357
-
358
- Executing the swap (simple)
359
-
360
- ```typescript
361
- const automaticSettlementSuccess = await swap.execute(
362
- solanaSigner,
363
- { //Bitcoin wallet, you can also pass null/undefined and send the bitcoin transaction from an external wallet
364
- address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
365
- publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
366
- signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
367
- //Sign the PSBT with the bitcoin wallet
368
- ...
369
- //Return the signed PSBT in the hex or base64 format!
370
- return "<signed PSBT>";
371
- }
372
- },
373
- { //Callbacks
374
- onDestinationCommitSent: (swapAddressOpeningTxId: string) => {
375
- //Swap address opening transaction sent on the destination chain
376
- },
377
- onSourceTransactionSent: (txId: string) => {
378
- //Bitcoin transaction sent on the source
379
- },
380
- onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
381
- //Bitcoin transaction confirmation status updates
382
- },
383
- onSourceTransactionConfirmed: (txId: string) => {
384
- //Bitcoin transaction confirmed
385
- },
386
- onSwapSettled: (destinationTxId: string) => {
387
- //Swap settled on the destination
388
- }
389
- }
390
- );
391
-
392
- //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
393
- if(!automaticSettlementSuccess) {
394
- await swap.claim(solanaSigner);
395
- }
396
- ```
397
-
398
- <details>
399
- <summary>Manual swap execution (advanced)</summary>
400
-
401
- - __1.__ Initiate the swap on the destination chain (Solana) by opening up the bitcoin swap address
402
-
403
- - __a.__ Commit using signer
404
- ```typescript
405
- await swap.commit(solanaWallet);
406
- ```
407
-
408
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
409
- ```typescript
410
- const txsCommit = await swap.txsCommit();
411
- //Sign and send these...
412
- ...
413
- //Important to wait till SDK processes the swap initialization
414
- await swap.waitTillCommited();
415
- ```
416
-
417
- - __2.__ Send bitcoin transaction
418
-
419
- - __a.__ Get funded PSBT and sign it
420
- ```typescript
421
- const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({
422
- address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
423
- publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba"
424
- });
425
- //Sign the psbt
426
- const signedPsbt = ...; //Can be hex or base64 encoded
427
- const bitcoinTxId = await swap.submitPsbt(signedPsbt);
428
- ```
429
-
430
- - __b.__ Get the bitcoin address or deeplink and send from external wallet
431
- ```typescript
432
- //It is imporant to send the EXACT amount, sending different amount will lead to loss of funds!
433
- const btcSwapAddress = swap.getAddress();
434
- const btcDeepLink = swap.getHyperlink();
435
- ```
436
-
437
- - __3.__ Wait for the bitcoin on-chain transaction to confirm
438
- ```typescript
439
- await swap.waitForBitcoinTransaction(
440
- (txId, confirmations, targetConfirmations, txEtaMs) => {
441
- //Bitcoin transaction confirmation status callback
442
- }
443
- );
444
- ```
445
-
446
- - __4.__ Wait for the automatic settlement of the swap
447
- ```typescript
448
- const automaticSettlementSuccess = await swap.waitTillClaimed(30);
449
- ```
450
-
451
- - __5.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
452
-
453
- - __a.__ Claim with a signer
454
- ```typescript
455
- if(!automaticSettlementSuccess) {
456
- await swap.claim(solanaSigner);
457
- }
458
- ```
459
-
460
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
461
- ```typescript
462
- if(!automaticSettlementSuccess) {}
463
- const txsClaim = await swap.txsClaim();
464
- //Sign and send these...
465
- ...
466
- //Important to wait till SDK processes the swap initialization
467
- await swap.waitTillCommited();
468
- }
469
- ```
470
-
471
- </details>
472
-
473
- <details>
474
- <summary>Swap states</summary>
475
-
476
- - FromBTCSwapState.EXPIRED = -3
477
- - Bitcoin swap address expired
478
- - FromBTCSwapState.QUOTE_EXPIRED = -2
479
- - Swap quote expired and cannot be executed anymore
480
- - FromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
481
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
482
- - FromBTCSwapState.PR_CREATED = 0
483
- - Swap quote is created, waiting for the user to open a bitcoin swap address
484
- - FromBTCSwapState.CLAIM_COMMITED = 1
485
- - Bitcoin swap address is opened
486
- - FromBTCSwapState.BTC_TX_CONFIRMED = 2
487
- - Bitcoin transaction sending funds to the swap address is confirmed
488
- - FromBTCSwapState.CLAIM_CLAIMED = 3
489
- - Swap funds are claimed to the user's wallet
490
-
491
- </details>
492
-
493
- #### Swap Bitcoin on-chain -> Starknet/EVM
494
-
495
- NOTE: Starknet & EVM uses a new swap protocol for Bitcoin on-chain -> Smart chain swaps, the flow here is different from the one for Solana!
496
-
497
- Getting swap quote
498
-
499
- ```typescript
500
- //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
501
- const swap: SpvFromBTCSwap<StarknetChainType> = await swapper.swap(
502
- Tokens.BITCOIN.BTC, //Swap from BTC
503
- Tokens.STARKNET.STRK, //Into specified destination token
504
- "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
505
- SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
506
- undefined, //Source address for the swap, not used for swaps from BTC
507
- starknetSigner.getAddress(), //Destination address
508
- {
509
- gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
510
- }
511
- );
512
-
513
- //Get the amount required to pay and fee
514
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
515
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
516
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
517
-
518
- const output: string = swap.getOutput().toString(); //Total output amount
519
-
520
- //Get swap expiration time
521
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
522
-
523
- //Get pricing info
524
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
525
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
526
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
527
- ```
528
-
529
- Executing the swap (simple)
530
-
531
- ```typescript
532
- const automaticSettlementSuccess = await swap.execute(
533
- { //Bitcoin wallet
534
- address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
535
- publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
536
- signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
537
- //Sign the PSBT with the bitcoin wallet
538
- ...
539
- //Return the signed PSBT in the hex or base64 format!
540
- return "<signed PSBT>";
541
- }
542
- },
543
- { //Callbacks
544
- onSourceTransactionSent: (txId: string) => {
545
- //Bitcoin transaction sent on the source
546
- },
547
- onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
548
- //Bitcoin transaction confirmation status updates
549
- },
550
- onSourceTransactionConfirmed: (txId: string) => {
551
- //Bitcoin transaction confirmed
552
- },
553
- onSwapSettled: (destinationTxId: string) => {
554
- //Swap settled on the destination
555
- }
556
- }
557
- );
558
-
559
- //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
560
- if(!automaticSettlementSuccess) {
561
- await swap.claim(starknetWallet);
562
- }
563
- ```
564
-
565
-
566
- <details>
567
- <summary>Manual swap execution (advanced)</summary>
568
-
569
- - __1.__ Send bitcoin transaction
570
-
571
- - __a.__ Get funded PSBT and sign it using external wallet (e.g. browser-based like Xverse, Unisat, Phantom, etc.)
572
- ```typescript
573
- //Obtain the funded PSBT (input already added) - ready for signing
574
- const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({address: "", publicKey: ""});
575
- //Pass `psbtBase64` or `psbtHex` (and also `signInputs`) to an external signer like Xverse, Unisat, etc.
576
- const signedPsbtHexOrBase64 = await <signPsbt function of the external wallet>; //Call the signPsbt function of the external signer with psbtBase64 or psbtHex and signInputs
577
- //The SDK automatically recognizes hex & base64 encoded PSBTs
578
- const bitcoinTxId = await swap.submitPsbt(signedPsbtHexOrBase64);
579
- ```
580
-
581
- - __b.__ Or obtain raw PSBT to which inputs still need to be added
582
- ```typescript
583
- const {psbt, psbtHex, psbtBase64, in1sequence} = await swap.getPsbt();
584
- psbt.addInput(...);
585
- //Make sure the second input's sequence (index 1) is as specified in the in1sequence variable
586
- psbt.updateInput(1, {sequence: in1sequence});
587
- //Sign the PSBT, sign every input except the first one
588
- for(let i=1;i<psbt.inputsLength; i++) psbt.signIdx(..., i); //Or pass it to external signer
589
- //Submit the signed PSBT, can be the Transaction object, or hex/base64 serialized
590
- const bitcoinTxId = await swap.submitPsbt(psbt);
591
- ```
592
-
593
- - __2.__ Wait for the bitcoin on-chain transaction to confirm
594
- ```typescript
595
- await swap.waitForBitcoinTransaction(
596
- (txId, confirmations, targetConfirmations, txEtaMs) => {
597
- //Bitcoin transaction confirmation status callback
598
- }
599
- );
600
- ```
601
-
602
- - __3.__ Wait for the automatic settlement of the swap
603
- ```typescript
604
- const automaticSettlementSuccess = await swap.waitTillClaimed(60);
605
- ```
606
-
607
- - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
608
-
609
- - __a.__ Claim with a signer
610
- ```typescript
611
- if(!automaticSettlementSuccess) {
612
- await swap.claim(starknetSigner);
613
- }
614
- ```
615
-
616
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
617
- ```typescript
618
- if(!automaticSettlementSuccess) {}
619
- const txsClaim = await swap.txsClaim();
620
- //Sign and send these...
621
- ...
622
- //Important to wait till SDK processes the swap initialization
623
- await swap.waitTillCommited();
624
- }
625
- ```
626
-
627
- </details>
628
-
629
- <details>
630
- <summary>Swap states</summary>
631
-
632
- - SpvFromBTCSwapState.CLOSED = -5
633
- - Catastrophic failure during swap, shall never happen
634
- - SpvFromBTCSwapState.FAILED = -4
635
- - Bitcoin transaction was sent, but was double-spent later, therefore the swap was failed (no BTC was sent)
636
- - SpvFromBTCSwapState.DECLINED = -3
637
- - LP declined to process the swap transaction, no BTC was sent
638
- - SpvFromBTCSwapState.QUOTE_EXPIRED = -2
639
- - Swap quote expired and cannot be executed anymore
640
- - SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
641
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is a bitcoin transaction being submitted it might still succeed)
642
- - SpvFromBTCSwapState.CREATED = 0
643
- - Swap quote is created, waiting on user to sign the bitcoin swap transaction
644
- - SpvFromBTCSwapState.SIGNED = 1
645
- - Bitcoin swap transaction was signed by the client
646
- - SpvFromBTCSwapState.POSTED = 2
647
- - Bitcoin swap transaction was posted to the LP
648
- - SpvFromBTCSwapState.BROADCASTED = 3
649
- - LP broadcasted the bitcoin swap transaction
650
- - SpvFromBTCSwapState.FRONTED = 4
651
- - Swap funds have been deposited to the user's wallet in front of the time
652
- - SpvFromBTCSwapState.BTC_TX_CONFIRMED = 5
653
- - Bitcoin swap transaction is confirmed
654
- - SpvFromBTCSwapState.CLAIM_CLAIMED = 6
655
- - Swap funds are claimed to the user's wallet
656
- -
657
- </details>
658
-
659
- ### Bitcoin lightning network swaps
660
-
661
- #### Swap Smart chain -> Bitcoin lightning network
662
-
663
- Getting swap quote
664
-
665
- ```typescript
666
- //Create the swap: swapping SOL to Bitcoin lightning
667
- const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
668
- Tokens.SOLANA.SOL, //From specified source token
669
- Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
670
- undefined, //Amount is specified in the lightning network invoice!
671
- SwapAmountType.EXACT_OUT, //Make sure we use EXACT_OUT for swaps to BTC-LN, if you want to use EXACT_IN and set an amount, use LNURL-pay!
672
- solanaSigner.getAddress(), //Source address and smart chain signer
673
- //Destination lightning network invoice, amount needs to be part of the invoice!
674
- "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya"
675
- );
676
-
677
- //Get the amount required to pay and fee
678
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
679
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
680
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
681
-
682
- const output: string = swap.getOutput().toString(); //Total output amount
683
-
684
- //Get swap expiration time
685
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
686
-
687
- //Get pricing info
688
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
689
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
690
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
691
- ```
692
-
693
- Executing the swap (simple)
694
-
695
- ```typescript
696
- const swapSuccessful = await swap.execute(
697
- solanaSigner,
698
- { //Callbacks
699
- onSourceTransactionSent: (txId: string) => {
700
- //Transaction on the source chain was sent
701
- },
702
- onSourceTransactionConfirmed: (txId: string) => {
703
- //Transaction on the source chain was confirmed
704
- },
705
- onSwapSettled: (destinationTxId: string) => {
706
- //Lightning payment on the destination chain was sent and swap settled
707
- }
708
- }
709
- );
710
-
711
- //Refund in case of failure
712
- if(!swapSuccessful) {
713
- //Swap failed, money can be refunded
714
- await swap.refund(solanaSigner);
715
- } else {
716
- //Swap successful!
717
- }
718
- ```
719
-
720
- <details>
721
- <summary>Manual swap execution (advanced)</summary>
722
-
723
- - __1.__ Initiate the swap on the smart-chain side
724
-
725
- - __a.__ Commit with a signer
726
- ```typescript
727
- await swap.commit(solanaSigner);
728
- ```
729
-
730
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
731
- ```typescript
732
- const txsCommit = await swap.txsCommit();
733
- //Sign and send these...
734
- ...
735
- //Important to wait till SDK processes the swap initialization
736
- await swap.waitTillCommited();
737
- ```
738
-
739
- - __2.__ Wait for the swap to execute and for the payment to be sent
740
- ```typescript
741
- const swapSuccessful = await swap.waitForPayment();
742
- ```
743
-
744
- - __3.__ In case the swap fails we can refund our funds on the source chain
745
-
746
- - __a.__ Refund with a signer
747
- ```typescript
748
- if(!swapSuccessful) {
749
- await swap.refund(solanaSigner);
750
- return;
751
- }
752
- ```
753
-
754
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
755
- ```typescript
756
- if(!swapSuccessful) {
757
- const txsRefund = await swap.txsRefund();
758
- //Sign and send these...
759
- ...
760
- }
761
- ```
762
-
763
- </details>
764
-
765
- <details>
766
- <summary>Swap states</summary>
767
-
768
- - ToBTCSwapState.REFUNDED = -3
769
- - Swap failed and was successfully refunded
770
- - ToBTCSwapState.QUOTE_EXPIRED = -2
771
- - Swap quote expired and cannot be executed anymore
772
- - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
773
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
774
- - ToBTCSwapState.CREATED = 0
775
- - Swap quote is created, waiting to be executed
776
- - ToBTCSwapState.COMMITED = 1,
777
- - Swap was initiated (init transaction sent)
778
- - ToBTCSwapState.SOFT_CLAIMED = 2,
779
- - Swap was processed by the counterparty but not yet claimed on-chain (lightning network payment secret was revealed)
780
- - ToBTCSwapState.CLAIMED = 3
781
- - Swap was finished and funds were successfully claimed by the counterparty
782
- - ToBTCSwapState.REFUNDABLE = 4
783
- - Swap was initiated but counterparty failed to process it, the user can now refund his funds
784
-
785
- </details>
786
-
787
- #### Swap Bitcoin lightning network -> Solana
788
-
789
- NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
790
-
791
- Getting swap quote
792
-
793
- ```typescript
794
- const swap: FromBTCLNSwap<SolanaChainType> = await swapper.swap(
795
- Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
796
- Tokens.SOLANA.SOL, //Into specified destination token
797
- 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
798
- SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
799
- undefined, //Source address for the swap, not used for swaps from BTC-LN
800
- signer.getAddress() //Destination address
801
- );
802
-
803
- //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
804
- const receivingLightningInvoice: string = swap.getAddress();
805
- //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
806
- const qrCodeData: string = swap.getHyperlink();
807
-
808
- //Get the amount required to pay and fee
809
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
810
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
811
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
812
-
813
- const output: string = swap.getOutput().toString(); //Total output amount
814
-
815
- //Get swap expiration time
816
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
817
-
818
- //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
819
- const securityDeposit: string = swap.getSecurityDeposit().toString();
820
-
821
- //Get pricing info
822
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
823
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
824
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
825
- ```
826
-
827
- Executing the swap (simple)
828
-
829
- ```typescript
830
- await swap.execute(
831
- solanaSigner,
832
- { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
833
- payInvoice: (bolt11PaymentRequest: string) => {
834
- //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
835
- // promise here would block till the payment is settled
836
- return Promise.resolve("");
837
- }
838
- },
839
- { //Callbacks
840
- onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
841
- //Lightning network payment received by the LP
842
- },
843
- onDestinationCommitSent: (destinationCommitTxId: string) => {
844
- //HTLC initialization transaction sent on the destination chain
845
- },
846
- onDestinationClaimSent: (destinationClaimTxId: string) => {
847
- //HTLC claim transaction sent on the destination chain
848
- },
849
- onSwapSettled: (destinationClaimTxId: string) => {
850
- //Swap settled and funds received on destination
851
- }
852
- }
853
- );
854
- ```
855
-
856
- <details>
857
- <summary>Manual swap execution (advanced)</summary>
858
-
859
- - __1.__ Pay the LN invoice from a lightning network wallet
860
- ```typescript
861
- const lightningInvoice = swap.getAddress();
862
- ```
863
-
864
- - __2.__ Start listening to incoming lightning network payment
865
- ```typescript
866
- const success = await swap.waitForPayment();
867
- if(!success) {
868
- //Lightning network payment not received in time and quote expired
869
- return;
870
- }
871
- ```
872
-
873
- - __3.__ Claim the swap at the destination
874
-
875
- - __a.__ Commit & claim with signer
876
- ```typescript
877
- await swap.commitAndClaim(solanaSigner);
878
- ```
879
-
880
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
881
- ```typescript
882
- const txsCommitAndClaim = await swap.txsCommitAndClaim();
883
- //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
884
- // for prior transaction confirmation before sending the next one
885
- //Sign and send these...
886
- ...
887
- ```
888
-
889
- </details>
890
-
891
- <details>
892
- <summary>Swap states</summary>
893
-
894
- - FromBTCLNSwapState.FAILED = -4
895
- - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
896
- - FromBTCLNSwapState.QUOTE_EXPIRED = -3
897
- - Swap quote expired and cannot be executed anymore
898
- - FromBTCLNSwapState.QUOTE_SOFT_EXPIRED = -2
899
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
900
- - FromBTCLNSwapState.EXPIRED = -1
901
- - Lightning network invoice expired, meaning the swap is expired
902
- - FromBTCLNSwapState.PR_CREATED = 0
903
- - Swap is created, the user should now pay the provided lightning network invoice
904
- - FromBTCLNSwapState.PR_PAID = 1
905
- - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
906
- - FromBTCLNSwapState.CLAIM_COMMITED = 2
907
- - Claiming of the funds was initiated
908
- - FromBTCLNSwapState.CLAIM_CLAIMED = 3
909
- - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
910
-
911
- </details>
912
-
913
- #### Swap Bitcoin lightning network -> Starknet/EVM
914
-
915
- Getting swap quote
916
-
917
- ```typescript
918
- const swap: FromBTCLNAutoSwap<StarknetChainType> = await swapper.swap(
919
- Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
920
- Tokens.STARKNET.STRK, //Into specified destination token
921
- 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
922
- SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
923
- undefined, //Source address for the swap, not used for swaps from BTC-LN
924
- signer.getAddress(), //Destination address
925
- {
926
- gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
927
- }
928
- );
929
-
930
- //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
931
- const receivingLightningInvoice: string = swap.getAddress();
932
- //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
933
- const qrCodeData: string = swap.getHyperlink();
934
-
935
- //Get the amount required to pay and fee
936
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
937
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
938
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
939
-
940
- const output: string = swap.getOutput().toString(); //Total output amount
941
-
942
- //Get swap expiration time
943
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
944
-
945
- //Get pricing info
946
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
947
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
948
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
949
- ```
950
-
951
- Executing the swap (simple)
952
-
953
- ```typescript
954
- const automaticSettlementSuccess = await swap.execute(
955
- { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
956
- payInvoice: (bolt11PaymentRequest: string) => {
957
- //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
958
- // promise here would block till the payment is settled
959
- return Promise.resolve("");
960
- }
961
- },
962
- { //Callbacks
963
- onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
964
- //Lightning network payment received by the LP
965
- },
966
- onSwapSettled: (destinationClaimTxId: string) => {
967
- //Swap settled and funds received on destination
968
- }
969
- }
970
- );
971
-
972
- //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
973
- if(!automaticSettlementSuccess) {
974
- await swap.claim(starknetSigner);
975
- }
976
- ```
977
-
978
-
979
- <details>
980
- <summary>Manual swap execution (advanced)</summary>
981
-
982
- - __1.__ Pay the LN invoice from a lightning network wallet
983
- ```typescript
984
- const lightningInvoice = swap.getAddress();
985
- ```
986
-
987
- - __2.__ Start listening to incoming lightning network payment
988
- ```typescript
989
- const success = await swap.waitForPayment();
990
- if(!success) {
991
- //Lightning network payment not received in time and quote expired
992
- return;
993
- }
994
- ```
995
-
996
- - __3.__ Wait for the swap to be automatically settled
997
- ```typescript
998
- const automaticSettlementSuccess = await swap.waitTillClaimed(60);
999
- ```
1000
-
1001
- - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1002
-
1003
- - __a.__ Claim with signer
1004
- ```typescript
1005
- if(!automaticSettlementSuccess) {
1006
- await swap.claim(starknetSigner);
1007
- }
1008
- ```
1009
-
1010
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1011
- ```typescript
1012
- if(!automaticSettlementSuccess) {
1013
- const txsClaim = await swap.txsClaim();
1014
- //Sign and send these...
1015
- ...
1016
- }
1017
- ```
1018
-
1019
- </details>
1020
-
1021
- <details>
1022
- <summary>Swap states</summary>
1023
-
1024
- - FromBTCLNAutoSwapState.FAILED = -4
1025
- - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
1026
- - FromBTCLNAutoSwapState.QUOTE_EXPIRED = -3
1027
- - Swap quote expired and cannot be executed anymore
1028
- - FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED = -2
1029
- - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
1030
- - FromBTCLNAutoSwapState.EXPIRED = -1
1031
- - Lightning network invoice expired, meaning the swap is expired
1032
- - FromBTCLNAutoSwapState.PR_CREATED = 0
1033
- - Swap is created, the user should now pay the provided lightning network invoice
1034
- - FromBTCLNAutoSwapState.PR_PAID = 1
1035
- - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
1036
- - FromBTCLNAutoSwapState.CLAIM_COMMITED = 2
1037
- - A swap HTLC was offered by the LP to the user
1038
- - FromBTCLNAutoSwapState.CLAIM_CLAIMED = 3
1039
- - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
1040
-
1041
- </details>
1042
-
1043
- ### LNURLs & readable lightning identifiers
1044
-
1045
- LNURLs extend the lightning network functionality by creating static lightning addreses (LNURL-pay & static internet identifiers) and QR codes which allow you to pull funds from them (LNURL-withdraw)
1046
-
1047
- This SDK supports:
1048
- * LNURL-pay ([LUD-6](https://github.com/lnurl/luds/blob/luds/06.md), [LUD-9](https://github.com/lnurl/luds/blob/luds/09.md), [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md), [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md))
1049
- * LNURL-withdraw ([LUD-3](https://github.com/lnurl/luds/blob/luds/03.md))
1050
- * Static internet identifiers ([LUD-16](https://github.com/lnurl/luds/blob/luds/16.md))
1051
-
1052
- You can parse LNURLs and lightning invoices automatically using the [Unified address parser](#unified-address-parser)
1053
-
1054
- #### Differences
1055
-
1056
- Lightning invoices:
1057
- * One time use only
1058
- * Need to have a fixed amount, therefore recipient has to set the amount
1059
- * Static and bounded expiration
1060
- * You can only pay to a lightning invoice, not withdraw funds from it
1061
-
1062
- LNURLs & lightning identifiers:
1063
- * Reusable
1064
- * Programmable expiry
1065
- * Allows payer to set an amount
1066
- * Supports both, paying (LNURL-pay) and withdrawing (LNURL-withdraw)
1067
- * Possibility to attach a message/comment to a payment
1068
- * Receive a message/url as a result of the payment
1069
-
1070
- #### Swap Smart chain -> Bitcoin lightning network
1071
-
1072
- Getting swap quote
1073
-
1074
- ```typescript
1075
- //Create the swap: swapping SOL to Bitcoin lightning
1076
- const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
1077
- Tokens.SOLANA.SOL, //From specified source token
1078
- Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
1079
- 10000n, //Now we can specify an amount for a lightning network payment!
1080
- SwapAmountType.EXACT_OUT, //We can also use exactIn=true here and set an amount in input token
1081
- solanaSigner.getAddress(), //Source address and smart chain signer
1082
- //Destination LNURL-pay or readable identifier
1083
- "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1084
- {
1085
- comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
1086
- }
1087
- );
1088
-
1089
- //Get the amount required to pay and fee
1090
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1091
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1092
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1093
-
1094
- const output: string = swap.getOutput().toString(); //Total output amount
1095
-
1096
- //Get swap expiration time
1097
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1098
-
1099
- //Get pricing info
1100
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1101
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1102
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1103
- ```
1104
-
1105
-
1106
- Executing the swap (simple)
1107
-
1108
- ```typescript
1109
- const swapSuccessful = await swap.execute(
1110
- solanaSigner,
1111
- { //Callbacks
1112
- onSourceTransactionSent: (txId: string) => {
1113
- //Transaction on the source chain was sent
1114
- },
1115
- onSourceTransactionConfirmed: (txId: string) => {
1116
- //Transaction on the source chain was confirmed
1117
- },
1118
- onSwapSettled: (destinationTxId: string) => {
1119
- //Lightning payment on the destination chain was sent and swap settled
1120
- }
1121
- }
1122
- );
1123
-
1124
- //Refund in case of failure
1125
- if(!swapSuccessful) {
1126
- //Swap failed, money can be refunded
1127
- await swap.refund(solanaSigner);
1128
- return;
1129
- }
1130
-
1131
- //Swap successful!
1132
- const lightningSecret = swap.getSecret();
1133
- //In case the LNURL contained a success action, we can read it now and display it to user
1134
- if(swap.hasSuccessAction()) {
1135
- //Contains a success action that should displayed to the user
1136
- const successMessage = swap.getSuccessAction();
1137
- const description: string = successMessage.description; //Description of the message
1138
- const text: (string | null) = successMessage.text; //Main text of the message
1139
- const url: (string | null) = successMessage.url; //URL link which should be displayed
1140
- }
1141
- ```
1142
-
1143
- <details>
1144
- <summary>Manual swap execution (advanced)</summary>
1145
-
1146
- - __1.__ Initiate the swap on the smart-chain side
1147
-
1148
- - __a.__ Commit with a signer
1149
- ```typescript
1150
- await swap.commit(solanaSigner);
1151
- ```
1152
-
1153
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1154
- ```typescript
1155
- const txsCommit = await swap.txsCommit();
1156
- //Sign and send these...
1157
- ...
1158
- //Important to wait till SDK processes the swap initialization
1159
- await swap.waitTillCommited();
1160
- ```
1161
-
1162
- - __2.__ Wait for the swap to execute and for the payment to be sent
1163
-
1164
- ```typescript
1165
- const swapSuccessful = await swap.waitForPayment();
1166
- ```
1167
-
1168
- - __3.__ In case the swap fails we can refund our funds on the source chain
1169
-
1170
- - __a.__ Refund with a signer
1171
- ```typescript
1172
- if(!swapSuccessful) {
1173
- await swap.refund(solanaSigner);
1174
- return;
1175
- }
1176
- ```
1177
-
1178
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1179
- ```typescript
1180
- if(!swapSuccessful) {
1181
- const txsRefund = await swap.txsRefund();
1182
- //Sign and send these...
1183
- ...
1184
- }
1185
- ```
1186
-
1187
- </details>
1188
-
1189
- #### Swap Bitcoin lightning network -> Solana
1190
-
1191
- NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
1192
-
1193
- Getting swap quote
1194
-
1195
- ```typescript
1196
- const swap: FromBTCLNSwap<SolanaChainType> = await swapper.swap(
1197
- Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
1198
- Tokens.SOLANA.SOL, //Into specified destination token
1199
- 10000n,
1200
- SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1201
- //Source LNURL-withdraw link
1202
- "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1203
- signer.getAddress(), //Destination address
1204
- );
1205
-
1206
- //Get the amount required to pay and fee
1207
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1208
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1209
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1210
-
1211
- const output: string = swap.getOutput().toString(); //Total output amount
1212
-
1213
- //Get swap expiration time
1214
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1215
-
1216
- //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
1217
- const securityDeposit: string = swap.getSecurityDeposit().toString();
1218
-
1219
- //Get pricing info
1220
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1221
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1222
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1223
- ```
1224
-
1225
- Executing the swap (simple)
1226
-
1227
- ```typescript
1228
- await swap.execute(
1229
- solanaSigner,
1230
- undefined, //No need to specify a wallet, we are sourcing the fund from LNURL-withdraw link
1231
- { //Callbacks
1232
- onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1233
- //Lightning network payment received by the LP
1234
- },
1235
- onDestinationCommitSent: (destinationCommitTxId: string) => {
1236
- //HTLC initialization transaction sent on the destination chain
1237
- },
1238
- onDestinationClaimSent: (destinationClaimTxId: string) => {
1239
- //HTLC claim transaction sent on the destination chain
1240
- },
1241
- onSwapSettled: (destinationClaimTxId: string) => {
1242
- //Swap settled and funds received on destination
1243
- }
1244
- }
1245
- );
1246
- ```
1247
-
1248
- <details>
1249
- <summary>Manual swap execution (advanced)</summary>
1250
-
1251
- - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1252
- ```typescript
1253
- const success = await swap.waitForPayment();
1254
- if(!success) {
1255
- //Lightning network payment not received in time and quote expired
1256
- return;
1257
- }
1258
- ```
1259
-
1260
- - __2.__ Claim the swap at the destination
1261
-
1262
- - __a.__ Commit & claim with signer
1263
- ```typescript
1264
- await swap.commitAndClaim(solanaSigner);
1265
- ```
1266
-
1267
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1268
- ```typescript
1269
- const txsCommitAndClaim = await swap.txsCommitAndClaim();
1270
- //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
1271
- // for prior transaction confirmation before sending the next one
1272
- //Sign and send these...
1273
- ...
1274
- ```
1275
-
1276
- </details>
1277
-
1278
- #### Swap Bitcoin lightning network -> Starknet/EVM
1279
-
1280
- Getting swap quote
1281
-
1282
- ```typescript
1283
- const swap: FromBTCLNAutoSwap<StarknetChainType> = await swapper.swap(
1284
- Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
1285
- Tokens.STARKNET.STRK, //Into specified destination token
1286
- 10000n,
1287
- SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1288
- //Source LNURL-withdraw link
1289
- "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1290
- signer.getAddress(), //Destination address
1291
- {
1292
- gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
1293
- }
1294
- );
1295
-
1296
- //Get the amount required to pay and fee
1297
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1298
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1299
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1300
-
1301
- const output: string = swap.getOutput().toString(); //Total output amount
1302
-
1303
- //Get swap expiration time
1304
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1305
-
1306
- //Get pricing info
1307
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1308
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1309
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1310
- ```
1311
-
1312
-
1313
- Executing the swap (simple)
1314
-
1315
- ```typescript
1316
- const automaticSettlementSuccess = await swap.execute(
1317
- undefined, //No need to specify a wallet, we are sourcing the funds from LNURL-withdraw link
1318
- { //Callbacks
1319
- onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1320
- //Lightning network payment received by the LP
1321
- },
1322
- onSwapSettled: (destinationClaimTxId: string) => {
1323
- //Swap settled and funds received on destination
1324
- }
1325
- }
1326
- );
1327
-
1328
- //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1329
- if(!automaticSettlementSuccess) {
1330
- await swap.claim(starknetSigner);
1331
- }
1332
- ```
1333
-
1334
-
1335
- <details>
1336
- <summary>Manual swap execution (advanced)</summary>
1337
-
1338
- - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1339
- ```typescript
1340
- const success = await swap.waitForPayment();
1341
- if(!success) {
1342
- //Lightning network payment not received in time and quote expired
1343
- return;
1344
- }
1345
- ```
1346
-
1347
- - __2.__ Wait for the swap to be automatically settled
1348
- ```typescript
1349
- const automaticSettlementSuccess = await swap.waitTillClaimed(60);
1350
- ```
1351
-
1352
- - __3.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1353
-
1354
- - __a.__ Claim with signer
1355
- ```typescript
1356
- if(!automaticSettlementSuccess) {
1357
- await swap.claim(starknetSigner);
1358
- }
1359
- ```
1360
-
1361
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1362
- ```typescript
1363
- if(!automaticSettlementSuccess) {
1364
- const txsClaim = await swap.txsClaim();
1365
- //Sign and send these...
1366
- ...
1367
- }
1368
- ```
1369
-
1370
- </details>
1371
-
1372
- ### Exact-In Smart Chain - Lightning swaps
1373
-
1374
- The main limitation of regular lightning network swaps (Smart chains -> Lightning), is the fact that exactIn swaps are not possible (as invoices need to have a fixed amount). LNURL-pay links solve this issue, but are not supported by all the wallets. Therefore, the SDK exposes a hook/callback that can be implemented by lightning wallets directly, which request fixed amount invoices on-demand. This then makes exact input amount swaps possible. The way it works:
1375
-
1376
- 1. SDK sends a request to the LP saying it wants to swap `x` USDC to BTC, with a dummy invoice (either 1 sat or as specified in the `minMsats` parameter - this is requested from the `getInvoice()` function) - this dummy invoice is used to estimate the routing fees by the LP (extra care must be taken for both invoices, dummy and the real one to have the same destination node public key & routing hints).
1377
- 2. LP responds with the output amount of `y` BTC
1378
- 3. SDK calls the provided `getInvoice()` callback to request the real invoice for the `y` amount of BTC (in satoshis)
1379
- 4. SDK forwards the returned fixed amount (`y` BTC) lightning network invoice back to the LP to finish creating the quote
1380
-
1381
- Getting swap quote
1382
-
1383
- ```typescript
1384
- //Create the swap: swapping SOL to Bitcoin lightning
1385
- const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
1386
- Tokens.SOLANA.SOL, //From specified source token
1387
- Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
1388
- 1_000_000_000n, //We can specify an amount for a lightning network payment!
1389
- SwapAmountType.EXACT_IN, //We can use exactIn=true here and set an amount in input token
1390
- solanaSigner.getAddress(), //Source address and smart chain signer
1391
- //Instead of the destination we pass a handler object
1392
- {
1393
- getInvoice: async (amountSats: number, abortSignal?: AbortSignal) => {
1394
- //Generate invoice with fixed amountSats here!
1395
- ...
1396
- return invoice;
1397
- },
1398
- //Optionally you can also specify minimum and maximum in msats (millisatoshis, 1 sat = 1000 msats)
1399
- minMsats: 1_000_000n,
1400
- maxMsats: 1_000_000_000n
1401
- },
1402
- {
1403
- comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
1404
- }
1405
- );
1406
-
1407
- //Get the amount required to pay and fee
1408
- const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1409
- const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1410
- const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1411
-
1412
- const output: string = swap.getOutput().toString(); //Total output amount
1413
-
1414
- //Get swap expiration time
1415
- const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1416
-
1417
- //Get pricing info
1418
- const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1419
- const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1420
- const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1421
- ```
1422
-
1423
-
1424
- Executing the swap (simple)
1425
-
1426
- ```typescript
1427
- const swapSuccessful = await swap.execute(
1428
- solanaSigner,
1429
- { //Callbacks
1430
- onSourceTransactionSent: (txId: string) => {
1431
- //Transaction on the source chain was sent
1432
- },
1433
- onSourceTransactionConfirmed: (txId: string) => {
1434
- //Transaction on the source chain was confirmed
1435
- },
1436
- onSwapSettled: (destinationTxId: string) => {
1437
- //Lightning payment on the destination chain was sent and swap settled
1438
- }
1439
- }
1440
- );
1441
-
1442
- //Refund in case of failure
1443
- if(!swapSuccessful) {
1444
- //Swap failed, money can be refunded
1445
- await swap.refund(solanaSigner);
1446
- return;
1447
- }
1448
-
1449
- //Swap successful!
1450
- const lightningSecret = swap.getSecret();
1451
- ```
1452
-
1453
- <details>
1454
- <summary>Manual swap execution (advanced)</summary>
1455
-
1456
- - __1.__ Initiate the swap on the smart-chain side
1457
-
1458
- - __a.__ Commit with a signer
1459
- ```typescript
1460
- await swap.commit(solanaSigner);
1461
- ```
1462
-
1463
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1464
- ```typescript
1465
- const txsCommit = await swap.txsCommit();
1466
- //Sign and send these...
1467
- ...
1468
- //Important to wait till SDK processes the swap initialization
1469
- await swap.waitTillCommited();
1470
- ```
1471
-
1472
- - __2.__ Wait for the swap to execute and for the payment to be sent
1473
-
1474
- ```typescript
1475
- const swapSuccessful = await swap.waitForPayment();
1476
- ```
1477
-
1478
- - __3.__ In case the swap fails we can refund our funds on the source chain
1479
-
1480
- - __a.__ Refund with a signer
1481
- ```typescript
1482
- if(!swapSuccessful) {
1483
- await swap.refund(solanaSigner);
1484
- return;
1485
- }
1486
- ```
1487
-
1488
- - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1489
- ```typescript
1490
- if(!swapSuccessful) {
1491
- const txsRefund = await swap.txsRefund();
1492
- //Sign and send these...
1493
- ...
1494
- }
1495
- ```
1496
-
1497
- </details>
1498
-
1499
- ### Getting state of the swap
1500
-
1501
- You can get the current state of the swap with:
1502
-
1503
- ```typescript
1504
- const state = swap.getState();
1505
- ```
1506
-
1507
- You can also set a listener to listen for swap state changes:
1508
-
1509
- ```typescript
1510
- swap.events.on("swapState", swap => {
1511
- const newState = swap.getState();
1512
- });
1513
- ```
1514
-
1515
- For the meaning of the states please refer to the "Swap state" section under each swap type.
1516
-
1517
- ### Swap size limits
1518
-
1519
- Swap sizes are limited by the LPs you are connected to, they are advertised in BTC terms by LPs during handshake
1520
-
1521
- ```typescript
1522
- const swapLimits = swapper.getSwapLimits(srcToken, dstToken);
1523
- const inputMin = swapLimits.input.min;
1524
- const inputMax = swapLimits.input.max;
1525
- const outputMin = swapLimits.output.min;
1526
- const outputMax = swapLimits.output.max;
1527
- ```
1528
-
1529
- NOTE: swap limits denominated in BTC are retrieved from the LPs during initial handshake, however limits in other tokens are only returned when getting a quote fails due to amount being too low or too high. For example if you want to get swap limits for the BTC -> SOL swap, the input limits will be immediately available, while the output limits will only get populated once a quote request fails due to amount being too low or high.
1530
-
1531
- ```typescript
1532
- let swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
1533
- let inputMin = swapLimits.input.min; //Immediately available
1534
- let inputMax = swapLimits.input.max; //Immediately available
1535
- let outputMin = swapLimits.output.min; //Not available from the get-go
1536
- let outputMax = swapLimits.output.max; //Not available from the get-go
1537
-
1538
- //You can also listen to swap limit changes (optional)
1539
- swapper.on("swapLimitsChanged", () => {
1540
- //New limits available with swapper.getSwapLimits(srcToken, dstToken)
1541
- //Useful in e.g. a react application where you want to dynamically set min/max swappable amount
1542
- })
1543
-
1544
- //Try to swap really small amount of SOL with exactOut swap
1545
- try {
1546
- const swap = await swapper.swap(
1547
- Tokens.BITCOIN.BTC, //Swap from BTC
1548
- Tokens.SOLANA.SOL, //Into specified destination token
1549
- 1n, //1 lamport = 0.000000001 SOL
1550
- false, //Whether we define an input or output amount
1551
- undefined, //Source address for the swap, not used for swaps from BTC
1552
- solanaSigner.getAddress() //Destination address
1553
- );
1554
- } catch (e) {
1555
- //Fails with OutOfBoundsError
1556
- }
1557
-
1558
- swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
1559
- inputMin = swapLimits.input.min; //Immediately available
1560
- inputMax = swapLimits.input.max; //Immediately available
1561
- outputMin = swapLimits.output.min; //Now available due to failed quote
1562
- outputMax = swapLimits.output.max; //Now available due to failed quote
1563
- ```
1564
-
1565
- ### Stored swaps
1566
-
1567
- #### Get swap by ID
1568
-
1569
- You can retrieve a swap by it's id, you can get an ID of the swap with
1570
-
1571
- ```typescript
1572
- const swapId = swap.getId();
1573
- ```
1574
-
1575
- And then later retrieve it from the storage
1576
-
1577
- ```typescript
1578
- import {isSwapType} from "@atomiqlabs/sdk";
1579
-
1580
- //Use this to obtain a correctly typed swap, returns `undefined` if the type of the
1581
- // underlying swap is not as requested, `swapType` uses the SwapType enum
1582
- const typedSwap = await swapper.getTypedSwapById(swapId, chainId, swapType);
1583
-
1584
- //This returns just a base type `ISwap`, so you have to do typecasting yourself, useful
1585
- // if you don't know which type of the swap to expect
1586
- const swap = await swapper.getSwapById(swapId);
1587
- //You can later narrow this down with the `isSwapType()` typeguard
1588
- if(isSwapType(swap, swapType)) {
1589
- //You now have a properly narrowed down type of the swap here
1590
- }
1591
- ```
1592
-
1593
- #### Get refundable swaps
1594
- You can refund the swaps in one of two cases:
1595
- * In case intermediary is non-cooperative and goes offline, you can claim the funds from the swap contract back after some time.
1596
- * In case intermediary tried to pay but was unsuccessful, so he sent you signed message with which you can refund now without waiting.
1597
-
1598
- This call can be checked on every startup and periodically every few minutes.
1599
- ```typescript
1600
- //Get refundable swaps and refund them
1601
- const refundableSolanaSwaps = await swapper.getRefundableSwaps("SOLANA", solanaSigner.getAddress());
1602
- for(let swap of refundableSolanaSwaps) await swap.refund(solanaSigner);
1603
- const refundableStarknetSwaps = await swapper.getRefundableSwaps("STARKNET", starknetSigner.getAddress());
1604
- for(let swap of refundableStarknetSwaps) await swap.refund(starknetSigner);
1605
- ```
1606
-
1607
- #### Get claimable swaps
1608
- Returns swaps that are ready to be claimed by the client, this can happen if client closes the application when a swap is in-progress and the swap is concluded while the client is offline.
1609
-
1610
- ```typescript
1611
- //Get the swaps
1612
- const claimableSolanaSwaps = await swapper.getClaimableSwaps("SOLANA", solanaSigner.getAddress());
1613
- //Claim all the claimable swaps
1614
- for(let swap of claimableSolanaSwaps) {
1615
- await swap.claim(solanaSigner);
1616
- }
1617
- //Get the swaps
1618
- const claimableStarknetSwaps = await swapper.getClaimableSwaps("STARKNET", starknetSigner.getAddress());
1619
- //Claim all the claimable swaps
1620
- for(let swap of claimableStarknetSwaps) {
1621
- await swap.claim(starknetSigner);
1622
- }
1623
- ```
1624
-
1625
- ### Helpers
1626
-
1627
- #### Getting wallet balances
1628
-
1629
- The SDK also contains helper functions for getting the maximum spendable balance of wallets
1630
-
1631
- ```typescript
1632
- //Spendable balance of the starknet wallet address (discounting transaction fees)
1633
- const strkBalance = await swapper.Utils.getSpendableBalance(starknetSigner, Tokens.STARKNET.STRK);
1634
- //Spendable balance of the solana wallet address (discounting transaction fees)
1635
- const solBalance = await swapper.Utils.getSpendableBalance(solanaSigner, Tokens.SOLANA.SOL);
1636
- //Spendable balance of the bitcoin wallet - here we also need to specify the destination chain (as there are different swap protocols available with different on-chain footprints)
1637
- const {balance: btcBalance, feeRate: btcFeeRate} = await swapper.Utils.getBitcoinSpendableBalance(bitcoinWalletAddress, "SOLANA");
1638
- ```
1639
-
1640
- #### Unified address parser
1641
-
1642
- A common way for parsing all address formats supported by the SDK, automatically recognizes:
1643
- - Bitcoin on-chain L1 address formats (p2pkh, p2wpkh, p2wsh, p2wsh, p2tr)
1644
- - [BIP-21](https://en.bitcoin.it/wiki/BIP_0021) bitcoin payment URI
1645
- - BOLT11 lightning network invoices
1646
- - [LUD-6](https://github.com/lnurl/luds/blob/luds/06.md) LNURL-pay links
1647
- - [LUD-3](https://github.com/lnurl/luds/blob/luds/03.md) LNURL-withdraw links
1648
- - [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) Lightning static internet identifiers
1649
- - Smart chain addresses (Solana, Starknet, etc.)
1650
-
1651
- ```typescript
1652
- const res = await swapper.Utils.parseAddress(address);
1653
- switch(res.type) {
1654
- case "BITCOIN":
1655
- //Bitcoin on-chain L1 address or BIP-21 URI scheme with amount
1656
- const btcAmount = res.amount;
1657
- break;
1658
- case "LIGHTNING":
1659
- //BOLT11 lightning network invoice with pre-set amount
1660
- const lnAmount = res.amount;
1661
- break;
1662
- case "LNURL":
1663
- //LNURL payment or withdrawal link
1664
- if(isLNURLWithdraw(res.lnurl)) {
1665
- //LNURL-withdraw allowing withdrawals over the lightning network
1666
- const lnurlWithdrawData: LNURLWithdraw = res.lnurl;
1667
- const minWithdrawable = res.min; //Minimum payment amount
1668
- const maxWithdrawable = res.max; //Maximum payment amount
1669
- const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
1670
- //Should show a UI allowing the user to choose an amount he wishes to withdraw
1671
- }
1672
- if(isLNURLPay(res.lnurl)) {
1673
- //LNURL-pay or static lightning internet identifier allowing repeated payments over the lightning network
1674
- const lnurlPayData: LNURLPay = res.lnurl;
1675
- const minPayable = res.min; //Minimum payment amount
1676
- const maxPayable = res.max; //Maximum payment amount
1677
- const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
1678
- const icon: (string | null) = res.lnurl.icon; //URL encoded icon that should be displayed on the UI
1679
- const shortDescription: (string | null) = res.lnurl.shortDescription; //Short description of the payment
1680
- const longDescription: (string | null) = res.lnurl.longDescription; //Long description of the payment
1681
- const maxCommentLength: (number | 0) = res.lnurl.commentMaxLength; //Maximum allowed length of the payment message/comment (0 means no comment allowed)
1682
- //Should show a UI displaying the icon, short description, long description, allowing the user to choose an amount he wishes to pay and possibly also a comment
1683
- }
1684
- break;
1685
- default:
1686
- //Addresses for smart chains
1687
- break;
1688
- }
1689
- ```
1690
-
1691
- ### Manually signing smart chain transactions
1692
-
1693
- You can also sign the transactions on smart chain side (Solana, Starknet, etc.) of the SDK externally by a separate wallet. Each function which executes any transaction has its txs(action) counterpart, e.g.:
1694
- - commit() -> txsCommit()
1695
- - claim() -> txsClaim()
1696
- - commitAndClaim -> txsCommitAndClaim()
1697
- - refund() -> txsRefund()
1698
-
1699
- After sending the transactions, you also need to make sure the SDK has enough time to receive an event notification of the transaction being executed, for this you have the waitTill(action) functions, e.g.:
1700
-
1701
- - commit() -> waitTillCommited()
1702
- - claim() -> waitTillClaimed()
1703
- - commitAndClaim -> waitTillClaimed()
1704
- - refund() -> waitTillRefunded()
1705
-
1706
- ```typescript
1707
- //Example for Solana
1708
- const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1709
- txns.forEach(val => if(val.signers.length>0) { val.tx.sign(...val.signers) });
1710
- const signedTransactions = await solanaSigner.wallet.signAllTransactions(txns.map(val => val.tx));
1711
- for(let tx of signedTransactions) {
1712
- const res = await solanaRpc.sendRawTransaction(tx.serialize());
1713
- await solanaRpc.confirmTransaction(res);
1714
- }
1715
- await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1716
-
1717
- //Example for Starknet
1718
- const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1719
- for(let tx of txns) {
1720
- if(tx.type==="INVOKE") await starknetSigner.account.execute(tx.tx, tx.details);
1721
- if(tx.type==="DEPLOY_ACCOUNT") await starknetSigner.account.deployAccount(tx.tx, tx.details);
1722
- }
1723
- await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1724
-
1725
- //Example for EVM
1726
- const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1727
- for(let tx of txns) {
1728
- await evmSigner.account.sendTransaction(tx);
1729
- }
1730
- await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1731
- ```
1732
-
1733
- ### Additional swapper options
1734
-
1735
- You can further customize the swapper instance with these options, you can:
1736
- - adjust the maximum accepted pricing difference from the LPs
1737
- - use custom mempool.space instance
1738
- - use custom pricing API
1739
- - use own LP node for swaps
1740
- - adjust HTTP request timeouts
1741
- - add parameters to be sent with each LP request
1742
-
1743
- ```typescript
1744
- const swapper = Factory.newSwapper({
1745
- ...
1746
- //Additional optional options
1747
- pricingFeeDifferencePPM: 20000n, //Maximum allowed pricing difference for quote (between swap & market price) in ppm (parts per million) (20000 == 2%)
1748
- mempoolApi: new MempoolApi("<url to custom mempool.space instance>"), //Set the SDK to use a custom mempool.space instance instead of the public one
1749
- getPriceFn: (tickers: string[], abortSignal?: AbortSignal) => customPricingApi.getUsdPriceForTickers(tickers) //Overrides the default pricing API engine with a custom price getter
1750
-
1751
- intermediaryUrl: "<url to custom LP node>",
1752
- registryUrl: "<url to custom LP node registry>",
1753
-
1754
- getRequestTimeout: 10000, //Timeout in milliseconds for GET requests
1755
- postRequestTimeout: 10000, //Timeout in milliseconds for POST requests
1756
- defaultAdditionalParameters: {lpData: "Pls give gud price"}, //Additional request data sent to LPs
1757
-
1758
- defaultTrustedIntermediaryUrl: "<url to custom LP node>" //LP node/intermediary to use for trusted gas swaps
1759
- });
1760
- ```
1
+ # atomiqlabs SDK
2
+
3
+ A typescript multichain client for atomiqlabs trustlesss cross-chain swaps. Enables trustless swaps between smart chains (Solana, EVM, Starknet, etc.) and bitcoin (on-chain - L1 and lightning network - L2).
4
+
5
+ Example SDK integration in NodeJS available [here](https://github.com/atomiqlabs/atomiq-sdk-demo)
6
+
7
+ ## Installation
8
+ ```
9
+ npm install @atomiqlabs/sdk@latest
10
+ ```
11
+
12
+ ## Installing chain-specific connectors
13
+
14
+ You can install only the chain-specific connectors that your project requires
15
+
16
+ ```
17
+ npm install @atomiqlabs/chain-solana@latest
18
+ npm install @atomiqlabs/chain-starknet@latest
19
+ npm install @atomiqlabs/chain-evm@latest
20
+ ```
21
+
22
+ ## How to use?
23
+
24
+ - [Preparations](#preparations)
25
+ - [Setting up signers](#signer)
26
+ - [Initialization](#initialization)
27
+ - Swaps:
28
+ - [Smart Chain -> BTC L1](#swap-smart-chain---bitcoin-on-chain)
29
+ - [BTC L1 -> Solana (Old swap protocol)](#swap-bitcoin-on-chain---solana)
30
+ - [BTC L1 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-on-chain---starknetevm)
31
+ - [Smart Chain -> BTC Lightning network L2](#swap-smart-chain---bitcoin-lightning-network)
32
+ - [Smart Chain -> BTC Lightning network L2 (LNURL-pay)](#swap-smart-chain---bitcoin-lightning-network-1)
33
+ - [BTC Lightning network L2 -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana)
34
+ - [BTC Lightning network L2 -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm)
35
+ - [BTC Lightning network L2 (LNURL-withdraw) -> Solana (Old swap protocol)](#swap-bitcoin-lightning-network---solana-1)
36
+ - [BTC Lightning network L2 (LNURL-withdraw) -> Starknet/EVM (New swap protocol)](#swap-bitcoin-lightning-network---starknetevm-1)
37
+ - [Swap states](#getting-state-of-the-swap)
38
+ - [Swap size limits](#swap-size-limits)
39
+ - [Stored swaps](#stored-swaps)
40
+ - [Get existing swaps](#get-swap-by-id)
41
+ - [Refundable swaps](#get-refundable-swaps)
42
+ - [Claimable swaps](#get-claimable-swaps)
43
+ - [Helpers](#helpers)
44
+ - [Wallet spendable balance](#getting-wallet-balances)
45
+ - [Unified address parsers](#unified-address-parser)
46
+ - [Customize swapper instance](#additional-swapper-options)
47
+
48
+ ### Preparations
49
+
50
+ Set Solana & Starknet RPC URL to use
51
+
52
+ ```typescript
53
+ const solanaRpc = "https://api.mainnet-beta.solana.com";
54
+ const starknetRpc = "https://rpc.starknet.lava.build/"; //Alternatively: https://starknet.api.onfinality.io/public or https://api.zan.top/public/starknet-mainnet
55
+ const citreaRpc = "https://rpc.mainnet.citrea.xyz";
56
+ ```
57
+
58
+ Create swapper factory, here we can pick and choose which chains we want to have supported in the SDK, ensure the "as const" keyword is used such that the typescript compiler can properly infer the types.
59
+
60
+ ```typescript
61
+ import {SolanaInitializer, SolanaInitializerType} from "@atomiqlabs/chain-solana";
62
+ import {StarknetInitializer, StarknetInitializerType} from "@atomiqlabs/chain-starknet";
63
+ import {CitreaInitializer, CitreaInitializerType} from "@atomiqlabs/chain-evm";
64
+ import {SwapperFactory, TypedTokens} from "@atomiqlabs/sdk";
65
+
66
+ //Define chains that you want to support here
67
+ const chains = [SolanaInitializer, StarknetInitializer, CitreaInitializer] as const;
68
+ type SupportedChains = typeof chains; //It's helpful that we also get the type of the chains array
69
+
70
+ const Factory = new SwapperFactory<SupportedChains>(chains); //Create swapper factory
71
+ const Tokens: TypedTokens<SupportedChains> = Factory.Tokens; //Get the supported tokens for all the specified chains.
72
+ ```
73
+
74
+ #### Browser
75
+
76
+ This uses browser's Indexed DB by default
77
+
78
+ ```typescript
79
+ import {BitcoinNetwork, TypedSwapper} from "@atomiqlabs/sdk";
80
+
81
+ const swapper: TypedSwapper<SupportedChains> = Factory.newSwapper({
82
+ chains: {
83
+ SOLANA: {
84
+ rpcUrl: solanaRpc //You can also pass Connection object here
85
+ },
86
+ STARKNET: {
87
+ rpcUrl: starknetRpc //You can also pass Provider object here
88
+ },
89
+ CITREA: {
90
+ rpcUrl: citreaRpc, //You can also pass JsonRpcApiProvider object here
91
+ }
92
+ },
93
+ bitcoinNetwork: BitcoinNetwork.MAINNET //or BitcoinNetwork.TESTNET3, BitcoinNetwork.TESTNET4 - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
94
+ });
95
+ ```
96
+
97
+ if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
98
+
99
+ #### NodeJS
100
+
101
+ For NodeJS we need to use sqlite storage, for that we first need to install the sqlite storage adaptor
102
+
103
+ ```
104
+ npm install @atomiqlabs/storage-sqlite@latest
105
+ ```
106
+
107
+ Then use pass it in the newSwapper function
108
+
109
+ ```typescript
110
+ import {SqliteStorageManager, SqliteUnifiedStorage} from "@atomiqlabs/storage-sqlite";
111
+ import {BitcoinNetwork, TypedSwapper} from "@atomiqlabs/sdk";
112
+
113
+ const swapper: TypedSwapper<SupportedChains> = Factory.newSwapper({
114
+ chains: {
115
+ SOLANA: {
116
+ rpcUrl: solanaRpc //You can also pass Connection object here
117
+ },
118
+ STARKNET: {
119
+ rpcUrl: starknetRpc //You can also pass Provider object here
120
+ },
121
+ CITREA: {
122
+ rpcUrl: citreaRpc, //You can also pass JsonApiProvider object here
123
+ }
124
+ },
125
+ bitcoinNetwork: BitcoinNetwork.MAINNET //or BitcoinNetwork.TESTNET3, BitcoinNetwork.TESTNET4 - this also sets the network to use for Solana (solana devnet for bitcoin testnet) & Starknet (sepolia for bitcoin testnet)
126
+ //The following lines are important for running on backend node.js,
127
+ // because the SDK by default uses browser's Indexed DB
128
+ swapStorage: chainId => new SqliteUnifiedStorage("CHAIN_"+chainId+".sqlite3"),
129
+ chainStorageCtor: name => new SqliteStorageManager("STORE_"+name+".sqlite3"),
130
+ });
131
+ ```
132
+
133
+ if you want to use custom pricing api, mempool.space RPC url, or tune HTTP request timeouts check out [additional options](#additional-swapper-options)
134
+
135
+ ### Signer
136
+
137
+ ```typescript
138
+ import {SolanaSigner} from "@atomiqlabs/chain-solana";
139
+ //Browser - react, using solana wallet adapter
140
+ const anchorWallet = useAnchorWallet();
141
+ const wallet = new SolanaSigner(anchorWallet);
142
+ ```
143
+
144
+ ```typescript
145
+ import {WalletAccount} from "starknet";
146
+ import {StarknetBrowserSigner} from "@atomiqlabs/chain-starknet";
147
+ //Browser, using get-starknet
148
+ const swo = await connect();
149
+ const wallet = new StarknetBrowserSigner(new WalletAccount(starknetRpc, swo.wallet));
150
+ ```
151
+
152
+ or
153
+
154
+ ```typescript
155
+ import {Keypair} from "@solana/web3.js";
156
+ import {SolanaKeypairWallet, SolanaSigner} from "@atomiqlabs/chain-solana";
157
+ //Creating Solana signer from private key
158
+ const solanaSigner = new SolanaSigner(new SolanaKeypairWallet(Keypair.fromSecretKey(solanaKey)), Keypair.fromSecretKey(solanaKey));
159
+ ```
160
+
161
+ ```typescript
162
+ import {StarknetSigner, StarknetKeypairWallet} from "@atomiqlabs/chain-starknet";
163
+ //Creating Starknet signer from private key
164
+ const starknetSigner = new StarknetSigner(new StarknetKeypairWallet(starknetRpc, starknetKey));
165
+ ```
166
+
167
+ ```typescript
168
+ import {BaseWallet, SigningKey} from "ethers";
169
+ import {EVMSigner} from "@atomiqlabs/chain-evm";
170
+ //Creating EVM signer from private key
171
+ const wallet = new BaseWallet(new SigningKey(evmKey));
172
+ const evmWallet = new EVMSigner(wallet, wallet.address);
173
+ ```
174
+
175
+ ### Initialization
176
+
177
+ Initialize the swapper, this should be done once when your app starts. Checks existing in-progress swaps and does initial LP discovery
178
+
179
+ ```typescript
180
+ await swapper.init();
181
+ ```
182
+
183
+ Now we have the multichain swapper initialized
184
+
185
+ ### Extract chain-specific swapper with signer
186
+
187
+ To make it easier to do swaps between bitcoin and a specific chain we can extract a chain-specific swapper, and also set a signer. e.g.:
188
+
189
+ ```typescript
190
+ const solanaSwapper = swapper.withChain<"SOLANA">("SOLANA");
191
+ ```
192
+
193
+ ### Bitcoin on-chain swaps
194
+
195
+ #### Swap Smart chain -> Bitcoin on-chain
196
+
197
+ Getting swap quote
198
+
199
+ ```typescript
200
+ //Create the swap: swapping SOL to Bitcoin on-chain, receiving _amount of satoshis (smallest unit of bitcoin) to _address
201
+ const swap: ToBTCSwap<SolanaChainType> = await swapper.swap(
202
+ Tokens.SOLANA.SOL, //From specified source token
203
+ Tokens.BITCOIN.BTC, //Swap to BTC
204
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
205
+ SwapAmountType.EXACT_OUT, //EXACT_OUT, so we specify the output amount
206
+ solanaSigner.getAddress(), //Source address and smart chain signer
207
+ "bc1qtw67hj77rt8zrkkg3jgngutu0yfgt9czjwusxt" //BTC address of the recipient
208
+ );
209
+
210
+ //Get the amount required to pay and fee
211
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
212
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
213
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
214
+
215
+ const output: string = swap.getOutput().toString(); //Total output amount
216
+
217
+ //Get swap expiration time
218
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
219
+
220
+ //Get pricing info
221
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
222
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
223
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
224
+ ```
225
+
226
+ Executing the swap (simple)
227
+
228
+ ```typescript
229
+ const swapSuccessful = await swap.execute(
230
+ solanaSigner,
231
+ { //Callbacks
232
+ onSourceTransactionSent: (txId: string) => {
233
+ //Transaction on the source chain was sent
234
+ },
235
+ onSourceTransactionConfirmed: (txId: string) => {
236
+ //Transaction on the source chain was confirmed
237
+ },
238
+ onSwapSettled: (destinationTxId: string) => {
239
+ //Bitcoin transaction on the destination chain was sent and swap settled
240
+ }
241
+ }
242
+ );
243
+
244
+ //Refund in case of failure
245
+ if(!swapSuccessful) {
246
+ //Swap failed, money can be refunded
247
+ await swap.refund(solanaSigner);
248
+ } else {
249
+ //Swap successful!
250
+ }
251
+ ```
252
+
253
+ <details>
254
+ <summary>Manual swap execution (advanced)</summary>
255
+
256
+ - __1.__ Initiate the swap on the smart-chain side
257
+
258
+ - __a.__ Commit with a signer
259
+ ```typescript
260
+ await swap.commit(solanaSigner);
261
+ ```
262
+
263
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
264
+ ```typescript
265
+ const txsCommit = await swap.txsCommit();
266
+ //Sign and send these...
267
+ ...
268
+ //Important to wait till SDK processes the swap initialization
269
+ await swap.waitTillCommited();
270
+ ```
271
+
272
+ - __2.__ Wait for the swap to execute and for the payment to be sent
273
+ ```typescript
274
+ const swapSuccessful = await swap.waitForPayment();
275
+ ```
276
+
277
+ - __3.__ In case the swap fails we can refund our funds on the source chain
278
+
279
+ - __a.__ Refund with a signer
280
+ ```typescript
281
+ if(!swapSuccessful) {
282
+ await swap.refund(solanaSigner);
283
+ return;
284
+ }
285
+ ```
286
+
287
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
288
+ ```typescript
289
+ if(!swapSuccessful) {
290
+ const txsRefund = await swap.txsRefund();
291
+ //Sign and send these...
292
+ ...
293
+ }
294
+ ```
295
+
296
+ </details>
297
+
298
+ <details>
299
+ <summary>Swap states</summary>
300
+
301
+ - ToBTCSwapState.REFUNDED = -3
302
+ - Swap failed and was successfully refunded
303
+ - ToBTCSwapState.QUOTE_EXPIRED = -2
304
+ - Swap quote expired and cannot be executed anymore
305
+ - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
306
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
307
+ - ToBTCSwapState.CREATED = 0
308
+ - Swap quote is created, waiting to be executed
309
+ - ToBTCSwapState.COMMITED = 1,
310
+ - Swap was initiated (init transaction sent)
311
+ - ToBTCSwapState.SOFT_CLAIMED = 2,
312
+ - Swap was processed by the counterparty but not yet claimed on-chain (bitcoin transaction was sent, but unconfirmed yet)
313
+ - ToBTCSwapState.CLAIMED = 3
314
+ - Swap was finished and funds were successfully claimed by the counterparty
315
+ - ToBTCSwapState.REFUNDABLE = 4
316
+ - Swap was initiated but counterparty failed to process it, the user can now refund his funds
317
+
318
+ </details>
319
+
320
+ #### Swap Bitcoin on-chain -> Solana
321
+
322
+ NOTE: Solana uses an old swap protocol for Bitcoin on-chain -> Solana swaps, the flow here is different from the one for Starknet and other chains.
323
+
324
+ Getting swap quote
325
+
326
+ ```typescript
327
+ //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
328
+ const swap: FromBTCSwap<SolanaChainType> = await swapper.swap(
329
+ Tokens.BITCOIN.BTC, //Swap from BTC
330
+ Tokens.SOLANA.SOL, //Into specified destination token
331
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
332
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
333
+ undefined, //Source address for the swap, not used for swaps from BTC
334
+ solanaSigner.getAddress() //Destination address
335
+ );
336
+
337
+ //Get the amount required to pay and fee
338
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
339
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
340
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
341
+
342
+ const output: string = swap.getOutput().toString(); //Total output amount
343
+
344
+ //Get swap expiration time
345
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
346
+
347
+ //Get security deposit amount (Human readable amount of SOL that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
348
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
349
+ //Get claimer bounty (Human readable amount of SOL reserved as a reward for watchtowers to claim the swap on your behalf)
350
+ const claimerBounty: string = swap.getClaimerBounty().toString();
351
+
352
+ //Get pricing info
353
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
354
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
355
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
356
+ ```
357
+
358
+ Executing the swap (simple)
359
+
360
+ ```typescript
361
+ const automaticSettlementSuccess = await swap.execute(
362
+ solanaSigner,
363
+ { //Bitcoin wallet, you can also pass null/undefined and send the bitcoin transaction from an external wallet
364
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
365
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
366
+ signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
367
+ //Sign the PSBT with the bitcoin wallet
368
+ ...
369
+ //Return the signed PSBT in the hex or base64 format!
370
+ return "<signed PSBT>";
371
+ }
372
+ },
373
+ { //Callbacks
374
+ onDestinationCommitSent: (swapAddressOpeningTxId: string) => {
375
+ //Swap address opening transaction sent on the destination chain
376
+ },
377
+ onSourceTransactionSent: (txId: string) => {
378
+ //Bitcoin transaction sent on the source
379
+ },
380
+ onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
381
+ //Bitcoin transaction confirmation status updates
382
+ },
383
+ onSourceTransactionConfirmed: (txId: string) => {
384
+ //Bitcoin transaction confirmed
385
+ },
386
+ onSwapSettled: (destinationTxId: string) => {
387
+ //Swap settled on the destination
388
+ }
389
+ }
390
+ );
391
+
392
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
393
+ if(!automaticSettlementSuccess) {
394
+ await swap.claim(solanaSigner);
395
+ }
396
+ ```
397
+
398
+ <details>
399
+ <summary>Manual swap execution (advanced)</summary>
400
+
401
+ - __1.__ Initiate the swap on the destination chain (Solana) by opening up the bitcoin swap address
402
+
403
+ - __a.__ Commit using signer
404
+ ```typescript
405
+ await swap.commit(solanaWallet);
406
+ ```
407
+
408
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
409
+ ```typescript
410
+ const txsCommit = await swap.txsCommit();
411
+ //Sign and send these...
412
+ ...
413
+ //Important to wait till SDK processes the swap initialization
414
+ await swap.waitTillCommited();
415
+ ```
416
+
417
+ - __2.__ Send bitcoin transaction
418
+
419
+ - __a.__ Get funded PSBT and sign it
420
+ ```typescript
421
+ const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({
422
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
423
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba"
424
+ });
425
+ //Sign the psbt
426
+ const signedPsbt = ...; //Can be hex or base64 encoded
427
+ const bitcoinTxId = await swap.submitPsbt(signedPsbt);
428
+ ```
429
+
430
+ - __b.__ Get the bitcoin address or deeplink and send from external wallet
431
+ ```typescript
432
+ //It is imporant to send the EXACT amount, sending different amount will lead to loss of funds!
433
+ const btcSwapAddress = swap.getAddress();
434
+ const btcDeepLink = swap.getHyperlink();
435
+ ```
436
+
437
+ - __3.__ Wait for the bitcoin on-chain transaction to confirm
438
+ ```typescript
439
+ await swap.waitForBitcoinTransaction(
440
+ (txId, confirmations, targetConfirmations, txEtaMs) => {
441
+ //Bitcoin transaction confirmation status callback
442
+ }
443
+ );
444
+ ```
445
+
446
+ - __4.__ Wait for the automatic settlement of the swap
447
+ ```typescript
448
+ const automaticSettlementSuccess = await swap.waitTillClaimed(30);
449
+ ```
450
+
451
+ - __5.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
452
+
453
+ - __a.__ Claim with a signer
454
+ ```typescript
455
+ if(!automaticSettlementSuccess) {
456
+ await swap.claim(solanaSigner);
457
+ }
458
+ ```
459
+
460
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
461
+ ```typescript
462
+ if(!automaticSettlementSuccess) {}
463
+ const txsClaim = await swap.txsClaim();
464
+ //Sign and send these...
465
+ ...
466
+ //Important to wait till SDK processes the swap initialization
467
+ await swap.waitTillCommited();
468
+ }
469
+ ```
470
+
471
+ </details>
472
+
473
+ <details>
474
+ <summary>Swap states</summary>
475
+
476
+ - FromBTCSwapState.EXPIRED = -3
477
+ - Bitcoin swap address expired
478
+ - FromBTCSwapState.QUOTE_EXPIRED = -2
479
+ - Swap quote expired and cannot be executed anymore
480
+ - FromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
481
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
482
+ - FromBTCSwapState.PR_CREATED = 0
483
+ - Swap quote is created, waiting for the user to open a bitcoin swap address
484
+ - FromBTCSwapState.CLAIM_COMMITED = 1
485
+ - Bitcoin swap address is opened
486
+ - FromBTCSwapState.BTC_TX_CONFIRMED = 2
487
+ - Bitcoin transaction sending funds to the swap address is confirmed
488
+ - FromBTCSwapState.CLAIM_CLAIMED = 3
489
+ - Swap funds are claimed to the user's wallet
490
+
491
+ </details>
492
+
493
+ #### Swap Bitcoin on-chain -> Starknet/EVM
494
+
495
+ NOTE: Starknet & EVM uses a new swap protocol for Bitcoin on-chain -> Smart chain swaps, the flow here is different from the one for Solana!
496
+
497
+ Getting swap quote
498
+
499
+ ```typescript
500
+ //Create the swap: swapping _amount of satoshis of Bitcoin on-chain to SOL
501
+ const swap: SpvFromBTCSwap<StarknetChainType> = await swapper.swap(
502
+ Tokens.BITCOIN.BTC, //Swap from BTC
503
+ Tokens.STARKNET.STRK, //Into specified destination token
504
+ "0.0001", //Amount can be either passed in base units as bigint or in decimal format as string
505
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
506
+ undefined, //Source address for the swap, not used for swaps from BTC
507
+ starknetSigner.getAddress(), //Destination address
508
+ {
509
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
510
+ }
511
+ );
512
+
513
+ //Get the amount required to pay and fee
514
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
515
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
516
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
517
+
518
+ const output: string = swap.getOutput().toString(); //Total output amount
519
+
520
+ //Get swap expiration time
521
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
522
+
523
+ //Get pricing info
524
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
525
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
526
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
527
+ ```
528
+
529
+ Executing the swap (simple)
530
+
531
+ ```typescript
532
+ const automaticSettlementSuccess = await swap.execute(
533
+ { //Bitcoin wallet
534
+ address: "bc1pscnrk588hdj79mwccucu06007mj5np2jurwfwp5mvhkjldzyphzqyk62m5",
535
+ publicKey: "03a2d8b728935f61d5bcba0cfb09c2c443c483b5c31ebd180e1833f37344bd34ba",
536
+ signPsbt: (psbt: {psbt, psbtHex: string, psbtBase64: string}, signInputs: number[]) => {
537
+ //Sign the PSBT with the bitcoin wallet
538
+ ...
539
+ //Return the signed PSBT in the hex or base64 format!
540
+ return "<signed PSBT>";
541
+ }
542
+ },
543
+ { //Callbacks
544
+ onSourceTransactionSent: (txId: string) => {
545
+ //Bitcoin transaction sent on the source
546
+ },
547
+ onSourceTransactionConfirmationStatus: (txId: string, confirmations: number, targetConfirmations: number, txEtaMs: number) => {
548
+ //Bitcoin transaction confirmation status updates
549
+ },
550
+ onSourceTransactionConfirmed: (txId: string) => {
551
+ //Bitcoin transaction confirmed
552
+ },
553
+ onSwapSettled: (destinationTxId: string) => {
554
+ //Swap settled on the destination
555
+ }
556
+ }
557
+ );
558
+
559
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
560
+ if(!automaticSettlementSuccess) {
561
+ await swap.claim(starknetWallet);
562
+ }
563
+ ```
564
+
565
+
566
+ <details>
567
+ <summary>Manual swap execution (advanced)</summary>
568
+
569
+ - __1.__ Send bitcoin transaction
570
+
571
+ - __a.__ Get funded PSBT and sign it using external wallet (e.g. browser-based like Xverse, Unisat, Phantom, etc.)
572
+ ```typescript
573
+ //Obtain the funded PSBT (input already added) - ready for signing
574
+ const {psbt, psbtHex, psbtBase64, signInputs} = await swap.getFundedPsbt({address: "", publicKey: ""});
575
+ //Pass `psbtBase64` or `psbtHex` (and also `signInputs`) to an external signer like Xverse, Unisat, etc.
576
+ const signedPsbtHexOrBase64 = await <signPsbt function of the external wallet>; //Call the signPsbt function of the external signer with psbtBase64 or psbtHex and signInputs
577
+ //The SDK automatically recognizes hex & base64 encoded PSBTs
578
+ const bitcoinTxId = await swap.submitPsbt(signedPsbtHexOrBase64);
579
+ ```
580
+
581
+ - __b.__ Or obtain raw PSBT to which inputs still need to be added
582
+ ```typescript
583
+ const {psbt, psbtHex, psbtBase64, in1sequence} = await swap.getPsbt();
584
+ psbt.addInput(...);
585
+ //Make sure the second input's sequence (index 1) is as specified in the in1sequence variable
586
+ psbt.updateInput(1, {sequence: in1sequence});
587
+ //Sign the PSBT, sign every input except the first one
588
+ for(let i=1;i<psbt.inputsLength; i++) psbt.signIdx(..., i); //Or pass it to external signer
589
+ //Submit the signed PSBT, can be the Transaction object, or hex/base64 serialized
590
+ const bitcoinTxId = await swap.submitPsbt(psbt);
591
+ ```
592
+
593
+ - __2.__ Wait for the bitcoin on-chain transaction to confirm
594
+ ```typescript
595
+ await swap.waitForBitcoinTransaction(
596
+ (txId, confirmations, targetConfirmations, txEtaMs) => {
597
+ //Bitcoin transaction confirmation status callback
598
+ }
599
+ );
600
+ ```
601
+
602
+ - __3.__ Wait for the automatic settlement of the swap
603
+ ```typescript
604
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
605
+ ```
606
+
607
+ - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
608
+
609
+ - __a.__ Claim with a signer
610
+ ```typescript
611
+ if(!automaticSettlementSuccess) {
612
+ await swap.claim(starknetSigner);
613
+ }
614
+ ```
615
+
616
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
617
+ ```typescript
618
+ if(!automaticSettlementSuccess) {}
619
+ const txsClaim = await swap.txsClaim();
620
+ //Sign and send these...
621
+ ...
622
+ //Important to wait till SDK processes the swap initialization
623
+ await swap.waitTillCommited();
624
+ }
625
+ ```
626
+
627
+ </details>
628
+
629
+ <details>
630
+ <summary>Swap states</summary>
631
+
632
+ - SpvFromBTCSwapState.CLOSED = -5
633
+ - Catastrophic failure during swap, shall never happen
634
+ - SpvFromBTCSwapState.FAILED = -4
635
+ - Bitcoin transaction was sent, but was double-spent later, therefore the swap was failed (no BTC was sent)
636
+ - SpvFromBTCSwapState.DECLINED = -3
637
+ - LP declined to process the swap transaction, no BTC was sent
638
+ - SpvFromBTCSwapState.QUOTE_EXPIRED = -2
639
+ - Swap quote expired and cannot be executed anymore
640
+ - SpvFromBTCSwapState.QUOTE_SOFT_EXPIRED = -1
641
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is a bitcoin transaction being submitted it might still succeed)
642
+ - SpvFromBTCSwapState.CREATED = 0
643
+ - Swap quote is created, waiting on user to sign the bitcoin swap transaction
644
+ - SpvFromBTCSwapState.SIGNED = 1
645
+ - Bitcoin swap transaction was signed by the client
646
+ - SpvFromBTCSwapState.POSTED = 2
647
+ - Bitcoin swap transaction was posted to the LP
648
+ - SpvFromBTCSwapState.BROADCASTED = 3
649
+ - LP broadcasted the bitcoin swap transaction
650
+ - SpvFromBTCSwapState.FRONTED = 4
651
+ - Swap funds have been deposited to the user's wallet in front of the time
652
+ - SpvFromBTCSwapState.BTC_TX_CONFIRMED = 5
653
+ - Bitcoin swap transaction is confirmed
654
+ - SpvFromBTCSwapState.CLAIM_CLAIMED = 6
655
+ - Swap funds are claimed to the user's wallet
656
+ -
657
+ </details>
658
+
659
+ ### Bitcoin lightning network swaps
660
+
661
+ #### Swap Smart chain -> Bitcoin lightning network
662
+
663
+ Getting swap quote
664
+
665
+ ```typescript
666
+ //Create the swap: swapping SOL to Bitcoin lightning
667
+ const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
668
+ Tokens.SOLANA.SOL, //From specified source token
669
+ Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
670
+ undefined, //Amount is specified in the lightning network invoice!
671
+ SwapAmountType.EXACT_OUT, //Make sure we use EXACT_OUT for swaps to BTC-LN, if you want to use EXACT_IN and set an amount, use LNURL-pay!
672
+ solanaSigner.getAddress(), //Source address and smart chain signer
673
+ //Destination lightning network invoice, amount needs to be part of the invoice!
674
+ "lnbc10u1pj2q0g9pp5ejs6m677m39cznpzum7muruvh50ys93ln82p4j9ks2luqm56xxlshp52r2anlhddfa9ex9vpw9gstxujff8a0p8s3pzvua930js0kwfea6scqzzsxqyz5vqsp5073zskc5qfgp7lre0t6s8uexxxey80ax564hsjklfwfjq2ew0ewq9qyyssqvzmgs6f8mvuwgfa9uqxhtza07qem4yfhn9wwlpskccmuwplsqmh8pdy6c42kqdu8p73kky9lsnl40qha5396d8lpgn90y27ltfc5rfqqq59cya"
675
+ );
676
+
677
+ //Get the amount required to pay and fee
678
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
679
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
680
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
681
+
682
+ const output: string = swap.getOutput().toString(); //Total output amount
683
+
684
+ //Get swap expiration time
685
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
686
+
687
+ //Get pricing info
688
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
689
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
690
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
691
+ ```
692
+
693
+ Executing the swap (simple)
694
+
695
+ ```typescript
696
+ const swapSuccessful = await swap.execute(
697
+ solanaSigner,
698
+ { //Callbacks
699
+ onSourceTransactionSent: (txId: string) => {
700
+ //Transaction on the source chain was sent
701
+ },
702
+ onSourceTransactionConfirmed: (txId: string) => {
703
+ //Transaction on the source chain was confirmed
704
+ },
705
+ onSwapSettled: (destinationTxId: string) => {
706
+ //Lightning payment on the destination chain was sent and swap settled
707
+ }
708
+ }
709
+ );
710
+
711
+ //Refund in case of failure
712
+ if(!swapSuccessful) {
713
+ //Swap failed, money can be refunded
714
+ await swap.refund(solanaSigner);
715
+ } else {
716
+ //Swap successful!
717
+ }
718
+ ```
719
+
720
+ <details>
721
+ <summary>Manual swap execution (advanced)</summary>
722
+
723
+ - __1.__ Initiate the swap on the smart-chain side
724
+
725
+ - __a.__ Commit with a signer
726
+ ```typescript
727
+ await swap.commit(solanaSigner);
728
+ ```
729
+
730
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
731
+ ```typescript
732
+ const txsCommit = await swap.txsCommit();
733
+ //Sign and send these...
734
+ ...
735
+ //Important to wait till SDK processes the swap initialization
736
+ await swap.waitTillCommited();
737
+ ```
738
+
739
+ - __2.__ Wait for the swap to execute and for the payment to be sent
740
+ ```typescript
741
+ const swapSuccessful = await swap.waitForPayment();
742
+ ```
743
+
744
+ - __3.__ In case the swap fails we can refund our funds on the source chain
745
+
746
+ - __a.__ Refund with a signer
747
+ ```typescript
748
+ if(!swapSuccessful) {
749
+ await swap.refund(solanaSigner);
750
+ return;
751
+ }
752
+ ```
753
+
754
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
755
+ ```typescript
756
+ if(!swapSuccessful) {
757
+ const txsRefund = await swap.txsRefund();
758
+ //Sign and send these...
759
+ ...
760
+ }
761
+ ```
762
+
763
+ </details>
764
+
765
+ <details>
766
+ <summary>Swap states</summary>
767
+
768
+ - ToBTCSwapState.REFUNDED = -3
769
+ - Swap failed and was successfully refunded
770
+ - ToBTCSwapState.QUOTE_EXPIRED = -2
771
+ - Swap quote expired and cannot be executed anymore
772
+ - ToBTCSwapState.QUOTE_SOFT_EXPIRED = -1
773
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
774
+ - ToBTCSwapState.CREATED = 0
775
+ - Swap quote is created, waiting to be executed
776
+ - ToBTCSwapState.COMMITED = 1,
777
+ - Swap was initiated (init transaction sent)
778
+ - ToBTCSwapState.SOFT_CLAIMED = 2,
779
+ - Swap was processed by the counterparty but not yet claimed on-chain (lightning network payment secret was revealed)
780
+ - ToBTCSwapState.CLAIMED = 3
781
+ - Swap was finished and funds were successfully claimed by the counterparty
782
+ - ToBTCSwapState.REFUNDABLE = 4
783
+ - Swap was initiated but counterparty failed to process it, the user can now refund his funds
784
+
785
+ </details>
786
+
787
+ #### Swap Bitcoin lightning network -> Solana
788
+
789
+ NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
790
+
791
+ Getting swap quote
792
+
793
+ ```typescript
794
+ const swap: FromBTCLNSwap<SolanaChainType> = await swapper.swap(
795
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
796
+ Tokens.SOLANA.SOL, //Into specified destination token
797
+ 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
798
+ SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
799
+ undefined, //Source address for the swap, not used for swaps from BTC-LN
800
+ signer.getAddress() //Destination address
801
+ );
802
+
803
+ //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
804
+ const receivingLightningInvoice: string = swap.getAddress();
805
+ //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
806
+ const qrCodeData: string = swap.getHyperlink();
807
+
808
+ //Get the amount required to pay and fee
809
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
810
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
811
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
812
+
813
+ const output: string = swap.getOutput().toString(); //Total output amount
814
+
815
+ //Get swap expiration time
816
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
817
+
818
+ //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
819
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
820
+
821
+ //Get pricing info
822
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
823
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
824
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
825
+ ```
826
+
827
+ Executing the swap (simple)
828
+
829
+ ```typescript
830
+ await swap.execute(
831
+ solanaSigner,
832
+ { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
833
+ payInvoice: (bolt11PaymentRequest: string) => {
834
+ //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
835
+ // promise here would block till the payment is settled
836
+ return Promise.resolve("");
837
+ }
838
+ },
839
+ { //Callbacks
840
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
841
+ //Lightning network payment received by the LP
842
+ },
843
+ onDestinationCommitSent: (destinationCommitTxId: string) => {
844
+ //HTLC initialization transaction sent on the destination chain
845
+ },
846
+ onDestinationClaimSent: (destinationClaimTxId: string) => {
847
+ //HTLC claim transaction sent on the destination chain
848
+ },
849
+ onSwapSettled: (destinationClaimTxId: string) => {
850
+ //Swap settled and funds received on destination
851
+ }
852
+ }
853
+ );
854
+ ```
855
+
856
+ <details>
857
+ <summary>Manual swap execution (advanced)</summary>
858
+
859
+ - __1.__ Pay the LN invoice from a lightning network wallet
860
+ ```typescript
861
+ const lightningInvoice = swap.getAddress();
862
+ ```
863
+
864
+ - __2.__ Start listening to incoming lightning network payment
865
+ ```typescript
866
+ const success = await swap.waitForPayment();
867
+ if(!success) {
868
+ //Lightning network payment not received in time and quote expired
869
+ return;
870
+ }
871
+ ```
872
+
873
+ - __3.__ Claim the swap at the destination
874
+
875
+ - __a.__ Commit & claim with signer
876
+ ```typescript
877
+ await swap.commitAndClaim(solanaSigner);
878
+ ```
879
+
880
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
881
+ ```typescript
882
+ const txsCommitAndClaim = await swap.txsCommitAndClaim();
883
+ //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
884
+ // for prior transaction confirmation before sending the next one
885
+ //Sign and send these...
886
+ ...
887
+ ```
888
+
889
+ </details>
890
+
891
+ <details>
892
+ <summary>Swap states</summary>
893
+
894
+ - FromBTCLNSwapState.FAILED = -4
895
+ - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
896
+ - FromBTCLNSwapState.QUOTE_EXPIRED = -3
897
+ - Swap quote expired and cannot be executed anymore
898
+ - FromBTCLNSwapState.QUOTE_SOFT_EXPIRED = -2
899
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
900
+ - FromBTCLNSwapState.EXPIRED = -1
901
+ - Lightning network invoice expired, meaning the swap is expired
902
+ - FromBTCLNSwapState.PR_CREATED = 0
903
+ - Swap is created, the user should now pay the provided lightning network invoice
904
+ - FromBTCLNSwapState.PR_PAID = 1
905
+ - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
906
+ - FromBTCLNSwapState.CLAIM_COMMITED = 2
907
+ - Claiming of the funds was initiated
908
+ - FromBTCLNSwapState.CLAIM_CLAIMED = 3
909
+ - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
910
+
911
+ </details>
912
+
913
+ #### Swap Bitcoin lightning network -> Starknet/EVM
914
+
915
+ Getting swap quote
916
+
917
+ ```typescript
918
+ const swap: FromBTCLNAutoSwap<StarknetChainType> = await swapper.swap(
919
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
920
+ Tokens.STARKNET.STRK, //Into specified destination token
921
+ 10000n, //Amount can be either passed in base units as bigint or in decimal format as string
922
+ SwapAmountType.EXACT_IN, //SwapAmountType.EXACT_IN, so we specify the input amount
923
+ undefined, //Source address for the swap, not used for swaps from BTC-LN
924
+ signer.getAddress(), //Destination address
925
+ {
926
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
927
+ }
928
+ );
929
+
930
+ //Get the bitcoin lightning network invoice (the invoice contains pre-entered amount)
931
+ const receivingLightningInvoice: string = swap.getAddress();
932
+ //Get the URI hyperlink (contains the lightning network invoice) which can be displayed also as QR code
933
+ const qrCodeData: string = swap.getHyperlink();
934
+
935
+ //Get the amount required to pay and fee
936
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
937
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
938
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
939
+
940
+ const output: string = swap.getOutput().toString(); //Total output amount
941
+
942
+ //Get swap expiration time
943
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
944
+
945
+ //Get pricing info
946
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
947
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
948
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
949
+ ```
950
+
951
+ Executing the swap (simple)
952
+
953
+ ```typescript
954
+ const automaticSettlementSuccess = await swap.execute(
955
+ { //Lightning network wallet, you can also pass null/undefined and pay the LN invoice from an external wallet
956
+ payInvoice: (bolt11PaymentRequest: string) => {
957
+ //Here you would usually call the WebLN or NWC to execute the payment, it's completely fine if the
958
+ // promise here would block till the payment is settled
959
+ return Promise.resolve("");
960
+ }
961
+ },
962
+ { //Callbacks
963
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
964
+ //Lightning network payment received by the LP
965
+ },
966
+ onSwapSettled: (destinationClaimTxId: string) => {
967
+ //Swap settled and funds received on destination
968
+ }
969
+ }
970
+ );
971
+
972
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
973
+ if(!automaticSettlementSuccess) {
974
+ await swap.claim(starknetSigner);
975
+ }
976
+ ```
977
+
978
+
979
+ <details>
980
+ <summary>Manual swap execution (advanced)</summary>
981
+
982
+ - __1.__ Pay the LN invoice from a lightning network wallet
983
+ ```typescript
984
+ const lightningInvoice = swap.getAddress();
985
+ ```
986
+
987
+ - __2.__ Start listening to incoming lightning network payment
988
+ ```typescript
989
+ const success = await swap.waitForPayment();
990
+ if(!success) {
991
+ //Lightning network payment not received in time and quote expired
992
+ return;
993
+ }
994
+ ```
995
+
996
+ - __3.__ Wait for the swap to be automatically settled
997
+ ```typescript
998
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
999
+ ```
1000
+
1001
+ - __4.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1002
+
1003
+ - __a.__ Claim with signer
1004
+ ```typescript
1005
+ if(!automaticSettlementSuccess) {
1006
+ await swap.claim(starknetSigner);
1007
+ }
1008
+ ```
1009
+
1010
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1011
+ ```typescript
1012
+ if(!automaticSettlementSuccess) {
1013
+ const txsClaim = await swap.txsClaim();
1014
+ //Sign and send these...
1015
+ ...
1016
+ }
1017
+ ```
1018
+
1019
+ </details>
1020
+
1021
+ <details>
1022
+ <summary>Swap states</summary>
1023
+
1024
+ - FromBTCLNAutoSwapState.FAILED = -4
1025
+ - If the claiming of the funds was initiated, but never concluded, the user will get his lightning network payment refunded
1026
+ - FromBTCLNAutoSwapState.QUOTE_EXPIRED = -3
1027
+ - Swap quote expired and cannot be executed anymore
1028
+ - FromBTCLNAutoSwapState.QUOTE_SOFT_EXPIRED = -2
1029
+ - Swap quote soft-expired (i.e. the quote probably expired, but if there is already an initialization transaction sent it might still succeed)
1030
+ - FromBTCLNAutoSwapState.EXPIRED = -1
1031
+ - Lightning network invoice expired, meaning the swap is expired
1032
+ - FromBTCLNAutoSwapState.PR_CREATED = 0
1033
+ - Swap is created, the user should now pay the provided lightning network invoice
1034
+ - FromBTCLNAutoSwapState.PR_PAID = 1
1035
+ - Lightning network invoice payment was received (but cannot be settled by the counterparty yet)
1036
+ - FromBTCLNAutoSwapState.CLAIM_COMMITED = 2
1037
+ - A swap HTLC was offered by the LP to the user
1038
+ - FromBTCLNAutoSwapState.CLAIM_CLAIMED = 3
1039
+ - Funds were successfully claimed & lightning network secret pre-image revealed, so the lightning network payment will settle now
1040
+
1041
+ </details>
1042
+
1043
+ ### LNURLs & readable lightning identifiers
1044
+
1045
+ LNURLs extend the lightning network functionality by creating static lightning addreses (LNURL-pay & static internet identifiers) and QR codes which allow you to pull funds from them (LNURL-withdraw)
1046
+
1047
+ This SDK supports:
1048
+ * LNURL-pay ([LUD-6](https://github.com/lnurl/luds/blob/luds/06.md), [LUD-9](https://github.com/lnurl/luds/blob/luds/09.md), [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md), [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md))
1049
+ * LNURL-withdraw ([LUD-3](https://github.com/lnurl/luds/blob/luds/03.md))
1050
+ * Static internet identifiers ([LUD-16](https://github.com/lnurl/luds/blob/luds/16.md))
1051
+
1052
+ You can parse LNURLs and lightning invoices automatically using the [Unified address parser](#unified-address-parser)
1053
+
1054
+ #### Differences
1055
+
1056
+ Lightning invoices:
1057
+ * One time use only
1058
+ * Need to have a fixed amount, therefore recipient has to set the amount
1059
+ * Static and bounded expiration
1060
+ * You can only pay to a lightning invoice, not withdraw funds from it
1061
+
1062
+ LNURLs & lightning identifiers:
1063
+ * Reusable
1064
+ * Programmable expiry
1065
+ * Allows payer to set an amount
1066
+ * Supports both, paying (LNURL-pay) and withdrawing (LNURL-withdraw)
1067
+ * Possibility to attach a message/comment to a payment
1068
+ * Receive a message/url as a result of the payment
1069
+
1070
+ #### Swap Smart chain -> Bitcoin lightning network
1071
+
1072
+ Getting swap quote
1073
+
1074
+ ```typescript
1075
+ //Create the swap: swapping SOL to Bitcoin lightning
1076
+ const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
1077
+ Tokens.SOLANA.SOL, //From specified source token
1078
+ Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
1079
+ 10000n, //Now we can specify an amount for a lightning network payment!
1080
+ SwapAmountType.EXACT_OUT, //We can also use exactIn=true here and set an amount in input token
1081
+ solanaSigner.getAddress(), //Source address and smart chain signer
1082
+ //Destination LNURL-pay or readable identifier
1083
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1084
+ {
1085
+ comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
1086
+ }
1087
+ );
1088
+
1089
+ //Get the amount required to pay and fee
1090
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1091
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1092
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1093
+
1094
+ const output: string = swap.getOutput().toString(); //Total output amount
1095
+
1096
+ //Get swap expiration time
1097
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1098
+
1099
+ //Get pricing info
1100
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1101
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1102
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1103
+ ```
1104
+
1105
+
1106
+ Executing the swap (simple)
1107
+
1108
+ ```typescript
1109
+ const swapSuccessful = await swap.execute(
1110
+ solanaSigner,
1111
+ { //Callbacks
1112
+ onSourceTransactionSent: (txId: string) => {
1113
+ //Transaction on the source chain was sent
1114
+ },
1115
+ onSourceTransactionConfirmed: (txId: string) => {
1116
+ //Transaction on the source chain was confirmed
1117
+ },
1118
+ onSwapSettled: (destinationTxId: string) => {
1119
+ //Lightning payment on the destination chain was sent and swap settled
1120
+ }
1121
+ }
1122
+ );
1123
+
1124
+ //Refund in case of failure
1125
+ if(!swapSuccessful) {
1126
+ //Swap failed, money can be refunded
1127
+ await swap.refund(solanaSigner);
1128
+ return;
1129
+ }
1130
+
1131
+ //Swap successful!
1132
+ const lightningSecret = swap.getSecret();
1133
+ //In case the LNURL contained a success action, we can read it now and display it to user
1134
+ if(swap.hasSuccessAction()) {
1135
+ //Contains a success action that should displayed to the user
1136
+ const successMessage = swap.getSuccessAction();
1137
+ const description: string = successMessage.description; //Description of the message
1138
+ const text: (string | null) = successMessage.text; //Main text of the message
1139
+ const url: (string | null) = successMessage.url; //URL link which should be displayed
1140
+ }
1141
+ ```
1142
+
1143
+ <details>
1144
+ <summary>Manual swap execution (advanced)</summary>
1145
+
1146
+ - __1.__ Initiate the swap on the smart-chain side
1147
+
1148
+ - __a.__ Commit with a signer
1149
+ ```typescript
1150
+ await swap.commit(solanaSigner);
1151
+ ```
1152
+
1153
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1154
+ ```typescript
1155
+ const txsCommit = await swap.txsCommit();
1156
+ //Sign and send these...
1157
+ ...
1158
+ //Important to wait till SDK processes the swap initialization
1159
+ await swap.waitTillCommited();
1160
+ ```
1161
+
1162
+ - __2.__ Wait for the swap to execute and for the payment to be sent
1163
+
1164
+ ```typescript
1165
+ const swapSuccessful = await swap.waitForPayment();
1166
+ ```
1167
+
1168
+ - __3.__ In case the swap fails we can refund our funds on the source chain
1169
+
1170
+ - __a.__ Refund with a signer
1171
+ ```typescript
1172
+ if(!swapSuccessful) {
1173
+ await swap.refund(solanaSigner);
1174
+ return;
1175
+ }
1176
+ ```
1177
+
1178
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1179
+ ```typescript
1180
+ if(!swapSuccessful) {
1181
+ const txsRefund = await swap.txsRefund();
1182
+ //Sign and send these...
1183
+ ...
1184
+ }
1185
+ ```
1186
+
1187
+ </details>
1188
+
1189
+ #### Swap Bitcoin lightning network -> Solana
1190
+
1191
+ NOTE: Solana uses an old swap protocol for Bitcoin lightning network -> Solana swaps, the flow here is different from the one for Starknet and other chains.
1192
+
1193
+ Getting swap quote
1194
+
1195
+ ```typescript
1196
+ const swap: FromBTCLNSwap<SolanaChainType> = await swapper.swap(
1197
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
1198
+ Tokens.SOLANA.SOL, //Into specified destination token
1199
+ 10000n,
1200
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1201
+ //Source LNURL-withdraw link
1202
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1203
+ signer.getAddress(), //Destination address
1204
+ );
1205
+
1206
+ //Get the amount required to pay and fee
1207
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1208
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1209
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1210
+
1211
+ const output: string = swap.getOutput().toString(); //Total output amount
1212
+
1213
+ //Get swap expiration time
1214
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1215
+
1216
+ //Get security deposit amount (Human readable amount of STRK that needs to be put down to rent the liquidity from swap intermediary), you will get this deposit back if the swap succeeds
1217
+ const securityDeposit: string = swap.getSecurityDeposit().toString();
1218
+
1219
+ //Get pricing info
1220
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1221
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1222
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1223
+ ```
1224
+
1225
+ Executing the swap (simple)
1226
+
1227
+ ```typescript
1228
+ await swap.execute(
1229
+ solanaSigner,
1230
+ undefined, //No need to specify a wallet, we are sourcing the fund from LNURL-withdraw link
1231
+ { //Callbacks
1232
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1233
+ //Lightning network payment received by the LP
1234
+ },
1235
+ onDestinationCommitSent: (destinationCommitTxId: string) => {
1236
+ //HTLC initialization transaction sent on the destination chain
1237
+ },
1238
+ onDestinationClaimSent: (destinationClaimTxId: string) => {
1239
+ //HTLC claim transaction sent on the destination chain
1240
+ },
1241
+ onSwapSettled: (destinationClaimTxId: string) => {
1242
+ //Swap settled and funds received on destination
1243
+ }
1244
+ }
1245
+ );
1246
+ ```
1247
+
1248
+ <details>
1249
+ <summary>Manual swap execution (advanced)</summary>
1250
+
1251
+ - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1252
+ ```typescript
1253
+ const success = await swap.waitForPayment();
1254
+ if(!success) {
1255
+ //Lightning network payment not received in time and quote expired
1256
+ return;
1257
+ }
1258
+ ```
1259
+
1260
+ - __2.__ Claim the swap at the destination
1261
+
1262
+ - __a.__ Commit & claim with signer
1263
+ ```typescript
1264
+ await swap.commitAndClaim(solanaSigner);
1265
+ ```
1266
+
1267
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1268
+ ```typescript
1269
+ const txsCommitAndClaim = await swap.txsCommitAndClaim();
1270
+ //Take EXTRA care to make sure transaction are sent sequentially and in order - always wait
1271
+ // for prior transaction confirmation before sending the next one
1272
+ //Sign and send these...
1273
+ ...
1274
+ ```
1275
+
1276
+ </details>
1277
+
1278
+ #### Swap Bitcoin lightning network -> Starknet/EVM
1279
+
1280
+ Getting swap quote
1281
+
1282
+ ```typescript
1283
+ const swap: FromBTCLNAutoSwap<StarknetChainType> = await swapper.swap(
1284
+ Tokens.BITCOIN.BTCLN, //Swap from BTC-LN
1285
+ Tokens.STARKNET.STRK, //Into specified destination token
1286
+ 10000n,
1287
+ SwapAmountType.EXACT_IN, //EXACT_IN, so we specify the input amount
1288
+ //Source LNURL-withdraw link
1289
+ "lnurl1dp68gurn8ghj7ampd3kx2ar0veekzar0wd5xjtnrdakj7tnhv4kxctttdehhwm30d3h82unvwqhkx6rfvdjx2ctvxyesuk0a27",
1290
+ signer.getAddress(), //Destination address
1291
+ {
1292
+ gasAmount: 1_000_000_000_000_000_000n //We can also request a gas drop on the destination chain (here requesting 1 STRK)
1293
+ }
1294
+ );
1295
+
1296
+ //Get the amount required to pay and fee
1297
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1298
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1299
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1300
+
1301
+ const output: string = swap.getOutput().toString(); //Total output amount
1302
+
1303
+ //Get swap expiration time
1304
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1305
+
1306
+ //Get pricing info
1307
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1308
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1309
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1310
+ ```
1311
+
1312
+
1313
+ Executing the swap (simple)
1314
+
1315
+ ```typescript
1316
+ const automaticSettlementSuccess = await swap.execute(
1317
+ undefined, //No need to specify a wallet, we are sourcing the funds from LNURL-withdraw link
1318
+ { //Callbacks
1319
+ onSourceTransactionReceived: (sourceLnPaymentHash: string) => {
1320
+ //Lightning network payment received by the LP
1321
+ },
1322
+ onSwapSettled: (destinationClaimTxId: string) => {
1323
+ //Swap settled and funds received on destination
1324
+ }
1325
+ }
1326
+ );
1327
+
1328
+ //In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1329
+ if(!automaticSettlementSuccess) {
1330
+ await swap.claim(starknetSigner);
1331
+ }
1332
+ ```
1333
+
1334
+
1335
+ <details>
1336
+ <summary>Manual swap execution (advanced)</summary>
1337
+
1338
+ - __1.__ Start listening to incoming lightning network payment (this also requests the payment from LNURL-withdraw service)
1339
+ ```typescript
1340
+ const success = await swap.waitForPayment();
1341
+ if(!success) {
1342
+ //Lightning network payment not received in time and quote expired
1343
+ return;
1344
+ }
1345
+ ```
1346
+
1347
+ - __2.__ Wait for the swap to be automatically settled
1348
+ ```typescript
1349
+ const automaticSettlementSuccess = await swap.waitTillClaimed(60);
1350
+ ```
1351
+
1352
+ - __3.__ In case the automatic swap settlement fails, we can settle it manually using the wallet of the destination chain
1353
+
1354
+ - __a.__ Claim with signer
1355
+ ```typescript
1356
+ if(!automaticSettlementSuccess) {
1357
+ await swap.claim(starknetSigner);
1358
+ }
1359
+ ```
1360
+
1361
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1362
+ ```typescript
1363
+ if(!automaticSettlementSuccess) {
1364
+ const txsClaim = await swap.txsClaim();
1365
+ //Sign and send these...
1366
+ ...
1367
+ }
1368
+ ```
1369
+
1370
+ </details>
1371
+
1372
+ ### Exact-In Smart Chain - Lightning swaps
1373
+
1374
+ The main limitation of regular lightning network swaps (Smart chains -> Lightning), is the fact that exactIn swaps are not possible (as invoices need to have a fixed amount). LNURL-pay links solve this issue, but are not supported by all the wallets. Therefore, the SDK exposes a hook/callback that can be implemented by lightning wallets directly, which request fixed amount invoices on-demand. This then makes exact input amount swaps possible. The way it works:
1375
+
1376
+ 1. SDK sends a request to the LP saying it wants to swap `x` USDC to BTC, with a dummy invoice (either 1 sat or as specified in the `minMsats` parameter - this is requested from the `getInvoice()` function) - this dummy invoice is used to estimate the routing fees by the LP (extra care must be taken for both invoices, dummy and the real one to have the same destination node public key & routing hints).
1377
+ 2. LP responds with the output amount of `y` BTC
1378
+ 3. SDK calls the provided `getInvoice()` callback to request the real invoice for the `y` amount of BTC (in satoshis)
1379
+ 4. SDK forwards the returned fixed amount (`y` BTC) lightning network invoice back to the LP to finish creating the quote
1380
+
1381
+ Getting swap quote
1382
+
1383
+ ```typescript
1384
+ //Create the swap: swapping SOL to Bitcoin lightning
1385
+ const swap: ToBTCLNSwap<SolanaChainType> = await swapper.swap(
1386
+ Tokens.SOLANA.SOL, //From specified source token
1387
+ Tokens.BITCOIN.BTCLN, //Swap to BTC-LN
1388
+ 1_000_000_000n, //We can specify an amount for a lightning network payment!
1389
+ SwapAmountType.EXACT_IN, //We can use exactIn=true here and set an amount in input token
1390
+ solanaSigner.getAddress(), //Source address and smart chain signer
1391
+ //Instead of the destination we pass a handler object
1392
+ {
1393
+ getInvoice: async (amountSats: number, abortSignal?: AbortSignal) => {
1394
+ //Generate invoice with fixed amountSats here!
1395
+ ...
1396
+ return invoice;
1397
+ },
1398
+ //Optionally you can also specify minimum and maximum in msats (millisatoshis, 1 sat = 1000 msats)
1399
+ minMsats: 1_000_000n,
1400
+ maxMsats: 1_000_000_000n
1401
+ },
1402
+ {
1403
+ comment: "Hello world" //For LNURL-pay we can also pass a comment to the recipient
1404
+ }
1405
+ );
1406
+
1407
+ //Get the amount required to pay and fee
1408
+ const input: string = swap.getInputWithoutFee().toString(); //Input amount excluding fees
1409
+ const fee: string = swap.getFee().amountInSrcToken.toString(); //Fees paid on the output
1410
+ const inputWithFees: string = swap.getInput().toString(); //Total amount paid including fees
1411
+
1412
+ const output: string = swap.getOutput().toString(); //Total output amount
1413
+
1414
+ //Get swap expiration time
1415
+ const expiry: number = swap.getQuoteExpiry(); //Expiration time of the swap quote in UNIX milliseconds, swap needs to be initiated before this time
1416
+
1417
+ //Get pricing info
1418
+ const swapPrice = swap.getPriceInfo().swapPrice; //Price of the current swap (excluding fees)
1419
+ const marketPrice = swap.getPriceInfo().marketPrice; //Current market price
1420
+ const difference = swap.getPriceInfo().difference; //Difference between the swap price & current market price
1421
+ ```
1422
+
1423
+
1424
+ Executing the swap (simple)
1425
+
1426
+ ```typescript
1427
+ const swapSuccessful = await swap.execute(
1428
+ solanaSigner,
1429
+ { //Callbacks
1430
+ onSourceTransactionSent: (txId: string) => {
1431
+ //Transaction on the source chain was sent
1432
+ },
1433
+ onSourceTransactionConfirmed: (txId: string) => {
1434
+ //Transaction on the source chain was confirmed
1435
+ },
1436
+ onSwapSettled: (destinationTxId: string) => {
1437
+ //Lightning payment on the destination chain was sent and swap settled
1438
+ }
1439
+ }
1440
+ );
1441
+
1442
+ //Refund in case of failure
1443
+ if(!swapSuccessful) {
1444
+ //Swap failed, money can be refunded
1445
+ await swap.refund(solanaSigner);
1446
+ return;
1447
+ }
1448
+
1449
+ //Swap successful!
1450
+ const lightningSecret = swap.getSecret();
1451
+ ```
1452
+
1453
+ <details>
1454
+ <summary>Manual swap execution (advanced)</summary>
1455
+
1456
+ - __1.__ Initiate the swap on the smart-chain side
1457
+
1458
+ - __a.__ Commit with a signer
1459
+ ```typescript
1460
+ await swap.commit(solanaSigner);
1461
+ ```
1462
+
1463
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1464
+ ```typescript
1465
+ const txsCommit = await swap.txsCommit();
1466
+ //Sign and send these...
1467
+ ...
1468
+ //Important to wait till SDK processes the swap initialization
1469
+ await swap.waitTillCommited();
1470
+ ```
1471
+
1472
+ - __2.__ Wait for the swap to execute and for the payment to be sent
1473
+
1474
+ ```typescript
1475
+ const swapSuccessful = await swap.waitForPayment();
1476
+ ```
1477
+
1478
+ - __3.__ In case the swap fails we can refund our funds on the source chain
1479
+
1480
+ - __a.__ Refund with a signer
1481
+ ```typescript
1482
+ if(!swapSuccessful) {
1483
+ await swap.refund(solanaSigner);
1484
+ return;
1485
+ }
1486
+ ```
1487
+
1488
+ - __b.__ Or get the transactions & [sign and send transaction manually](#manually-signing-smart-chain-transactions)
1489
+ ```typescript
1490
+ if(!swapSuccessful) {
1491
+ const txsRefund = await swap.txsRefund();
1492
+ //Sign and send these...
1493
+ ...
1494
+ }
1495
+ ```
1496
+
1497
+ </details>
1498
+
1499
+ ### Getting state of the swap
1500
+
1501
+ You can get the current state of the swap with:
1502
+
1503
+ ```typescript
1504
+ const state = swap.getState();
1505
+ ```
1506
+
1507
+ You can also set a listener to listen for swap state changes:
1508
+
1509
+ ```typescript
1510
+ swap.events.on("swapState", swap => {
1511
+ const newState = swap.getState();
1512
+ });
1513
+ ```
1514
+
1515
+ For the meaning of the states please refer to the "Swap state" section under each swap type.
1516
+
1517
+ ### Swap size limits
1518
+
1519
+ Swap sizes are limited by the LPs you are connected to, they are advertised in BTC terms by LPs during handshake
1520
+
1521
+ ```typescript
1522
+ const swapLimits = swapper.getSwapLimits(srcToken, dstToken);
1523
+ const inputMin = swapLimits.input.min;
1524
+ const inputMax = swapLimits.input.max;
1525
+ const outputMin = swapLimits.output.min;
1526
+ const outputMax = swapLimits.output.max;
1527
+ ```
1528
+
1529
+ NOTE: swap limits denominated in BTC are retrieved from the LPs during initial handshake, however limits in other tokens are only returned when getting a quote fails due to amount being too low or too high. For example if you want to get swap limits for the BTC -> SOL swap, the input limits will be immediately available, while the output limits will only get populated once a quote request fails due to amount being too low or high.
1530
+
1531
+ ```typescript
1532
+ let swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
1533
+ let inputMin = swapLimits.input.min; //Immediately available
1534
+ let inputMax = swapLimits.input.max; //Immediately available
1535
+ let outputMin = swapLimits.output.min; //Not available from the get-go
1536
+ let outputMax = swapLimits.output.max; //Not available from the get-go
1537
+
1538
+ //You can also listen to swap limit changes (optional)
1539
+ swapper.on("swapLimitsChanged", () => {
1540
+ //New limits available with swapper.getSwapLimits(srcToken, dstToken)
1541
+ //Useful in e.g. a react application where you want to dynamically set min/max swappable amount
1542
+ })
1543
+
1544
+ //Try to swap really small amount of SOL with exactOut swap
1545
+ try {
1546
+ const swap = await swapper.swap(
1547
+ Tokens.BITCOIN.BTC, //Swap from BTC
1548
+ Tokens.SOLANA.SOL, //Into specified destination token
1549
+ 1n, //1 lamport = 0.000000001 SOL
1550
+ false, //Whether we define an input or output amount
1551
+ undefined, //Source address for the swap, not used for swaps from BTC
1552
+ solanaSigner.getAddress() //Destination address
1553
+ );
1554
+ } catch (e) {
1555
+ //Fails with OutOfBoundsError
1556
+ }
1557
+
1558
+ swapLimits = swapper.getSwapLimits(Tokens.BITCOIN.BTC, Tokens.SOLANA.SOL);
1559
+ inputMin = swapLimits.input.min; //Immediately available
1560
+ inputMax = swapLimits.input.max; //Immediately available
1561
+ outputMin = swapLimits.output.min; //Now available due to failed quote
1562
+ outputMax = swapLimits.output.max; //Now available due to failed quote
1563
+ ```
1564
+
1565
+ ### Stored swaps
1566
+
1567
+ #### Get swap by ID
1568
+
1569
+ You can retrieve a swap by it's id, you can get an ID of the swap with
1570
+
1571
+ ```typescript
1572
+ const swapId = swap.getId();
1573
+ ```
1574
+
1575
+ And then later retrieve it from the storage
1576
+
1577
+ ```typescript
1578
+ import {isSwapType} from "@atomiqlabs/sdk";
1579
+
1580
+ //Use this to obtain a correctly typed swap, returns `undefined` if the type of the
1581
+ // underlying swap is not as requested, `swapType` uses the SwapType enum
1582
+ const typedSwap = await swapper.getTypedSwapById(swapId, chainId, swapType);
1583
+
1584
+ //This returns just a base type `ISwap`, so you have to do typecasting yourself, useful
1585
+ // if you don't know which type of the swap to expect
1586
+ const swap = await swapper.getSwapById(swapId);
1587
+ //You can later narrow this down with the `isSwapType()` typeguard
1588
+ if(isSwapType(swap, swapType)) {
1589
+ //You now have a properly narrowed down type of the swap here
1590
+ }
1591
+ ```
1592
+
1593
+ #### Get refundable swaps
1594
+ You can refund the swaps in one of two cases:
1595
+ * In case intermediary is non-cooperative and goes offline, you can claim the funds from the swap contract back after some time.
1596
+ * In case intermediary tried to pay but was unsuccessful, so he sent you signed message with which you can refund now without waiting.
1597
+
1598
+ This call can be checked on every startup and periodically every few minutes.
1599
+ ```typescript
1600
+ //Get refundable swaps and refund them
1601
+ const refundableSolanaSwaps = await swapper.getRefundableSwaps("SOLANA", solanaSigner.getAddress());
1602
+ for(let swap of refundableSolanaSwaps) await swap.refund(solanaSigner);
1603
+ const refundableStarknetSwaps = await swapper.getRefundableSwaps("STARKNET", starknetSigner.getAddress());
1604
+ for(let swap of refundableStarknetSwaps) await swap.refund(starknetSigner);
1605
+ ```
1606
+
1607
+ #### Get claimable swaps
1608
+ Returns swaps that are ready to be claimed by the client, this can happen if client closes the application when a swap is in-progress and the swap is concluded while the client is offline.
1609
+
1610
+ ```typescript
1611
+ //Get the swaps
1612
+ const claimableSolanaSwaps = await swapper.getClaimableSwaps("SOLANA", solanaSigner.getAddress());
1613
+ //Claim all the claimable swaps
1614
+ for(let swap of claimableSolanaSwaps) {
1615
+ await swap.claim(solanaSigner);
1616
+ }
1617
+ //Get the swaps
1618
+ const claimableStarknetSwaps = await swapper.getClaimableSwaps("STARKNET", starknetSigner.getAddress());
1619
+ //Claim all the claimable swaps
1620
+ for(let swap of claimableStarknetSwaps) {
1621
+ await swap.claim(starknetSigner);
1622
+ }
1623
+ ```
1624
+
1625
+ ### Helpers
1626
+
1627
+ #### Getting wallet balances
1628
+
1629
+ The SDK also contains helper functions for getting the maximum spendable balance of wallets
1630
+
1631
+ ```typescript
1632
+ //Spendable balance of the starknet wallet address (discounting transaction fees)
1633
+ const strkBalance = await swapper.Utils.getSpendableBalance(starknetSigner, Tokens.STARKNET.STRK);
1634
+ //Spendable balance of the solana wallet address (discounting transaction fees)
1635
+ const solBalance = await swapper.Utils.getSpendableBalance(solanaSigner, Tokens.SOLANA.SOL);
1636
+ //Spendable balance of the bitcoin wallet - here we also need to specify the destination chain (as there are different swap protocols available with different on-chain footprints)
1637
+ const {balance: btcBalance, feeRate: btcFeeRate} = await swapper.Utils.getBitcoinSpendableBalance(bitcoinWalletAddress, "SOLANA");
1638
+ ```
1639
+
1640
+ #### Unified address parser
1641
+
1642
+ A common way for parsing all address formats supported by the SDK, automatically recognizes:
1643
+ - Bitcoin on-chain L1 address formats (p2pkh, p2wpkh, p2wsh, p2wsh, p2tr)
1644
+ - [BIP-21](https://en.bitcoin.it/wiki/BIP_0021) bitcoin payment URI
1645
+ - BOLT11 lightning network invoices
1646
+ - [LUD-6](https://github.com/lnurl/luds/blob/luds/06.md) LNURL-pay links
1647
+ - [LUD-3](https://github.com/lnurl/luds/blob/luds/03.md) LNURL-withdraw links
1648
+ - [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md) Lightning static internet identifiers
1649
+ - Smart chain addresses (Solana, Starknet, etc.)
1650
+
1651
+ ```typescript
1652
+ const res = await swapper.Utils.parseAddress(address);
1653
+ switch(res.type) {
1654
+ case "BITCOIN":
1655
+ //Bitcoin on-chain L1 address or BIP-21 URI scheme with amount
1656
+ const btcAmount = res.amount;
1657
+ break;
1658
+ case "LIGHTNING":
1659
+ //BOLT11 lightning network invoice with pre-set amount
1660
+ const lnAmount = res.amount;
1661
+ break;
1662
+ case "LNURL":
1663
+ //LNURL payment or withdrawal link
1664
+ if(isLNURLWithdraw(res.lnurl)) {
1665
+ //LNURL-withdraw allowing withdrawals over the lightning network
1666
+ const lnurlWithdrawData: LNURLWithdraw = res.lnurl;
1667
+ const minWithdrawable = res.min; //Minimum payment amount
1668
+ const maxWithdrawable = res.max; //Maximum payment amount
1669
+ const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
1670
+ //Should show a UI allowing the user to choose an amount he wishes to withdraw
1671
+ }
1672
+ if(isLNURLPay(res.lnurl)) {
1673
+ //LNURL-pay or static lightning internet identifier allowing repeated payments over the lightning network
1674
+ const lnurlPayData: LNURLPay = res.lnurl;
1675
+ const minPayable = res.min; //Minimum payment amount
1676
+ const maxPayable = res.max; //Maximum payment amount
1677
+ const fixedAmount = res.amount; //If res.min===res.max, an fixed amount is returned instead
1678
+ const icon: (string | null) = res.lnurl.icon; //URL encoded icon that should be displayed on the UI
1679
+ const shortDescription: (string | null) = res.lnurl.shortDescription; //Short description of the payment
1680
+ const longDescription: (string | null) = res.lnurl.longDescription; //Long description of the payment
1681
+ const maxCommentLength: (number | 0) = res.lnurl.commentMaxLength; //Maximum allowed length of the payment message/comment (0 means no comment allowed)
1682
+ //Should show a UI displaying the icon, short description, long description, allowing the user to choose an amount he wishes to pay and possibly also a comment
1683
+ }
1684
+ break;
1685
+ default:
1686
+ //Addresses for smart chains
1687
+ break;
1688
+ }
1689
+ ```
1690
+
1691
+ ### Manually signing smart chain transactions
1692
+
1693
+ You can also sign the transactions on smart chain side (Solana, Starknet, etc.) of the SDK externally by a separate wallet. Each function which executes any transaction has its txs(action) counterpart, e.g.:
1694
+ - commit() -> txsCommit()
1695
+ - claim() -> txsClaim()
1696
+ - commitAndClaim -> txsCommitAndClaim()
1697
+ - refund() -> txsRefund()
1698
+
1699
+ After sending the transactions, you also need to make sure the SDK has enough time to receive an event notification of the transaction being executed, for this you have the waitTill(action) functions, e.g.:
1700
+
1701
+ - commit() -> waitTillCommited()
1702
+ - claim() -> waitTillClaimed()
1703
+ - commitAndClaim -> waitTillClaimed()
1704
+ - refund() -> waitTillRefunded()
1705
+
1706
+ ```typescript
1707
+ //Example for Solana
1708
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1709
+ txns.forEach(val => if(val.signers.length>0) { val.tx.sign(...val.signers) });
1710
+ const signedTransactions = await solanaSigner.wallet.signAllTransactions(txns.map(val => val.tx));
1711
+ for(let tx of signedTransactions) {
1712
+ const res = await solanaRpc.sendRawTransaction(tx.serialize());
1713
+ await solanaRpc.confirmTransaction(res);
1714
+ }
1715
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1716
+
1717
+ //Example for Starknet
1718
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1719
+ for(let tx of txns) {
1720
+ if(tx.type==="INVOKE") await starknetSigner.account.execute(tx.tx, tx.details);
1721
+ if(tx.type==="DEPLOY_ACCOUNT") await starknetSigner.account.deployAccount(tx.tx, tx.details);
1722
+ }
1723
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1724
+
1725
+ //Example for EVM
1726
+ const txns = await swap.txsCommit(); //Also works with txsClaim, txsRefund, txCommitAndClaim
1727
+ for(let tx of txns) {
1728
+ await evmSigner.account.sendTransaction(tx);
1729
+ }
1730
+ await swap.waitTillCommited(); //Or other relevant waitTillClaimed, waitTillRefunded
1731
+ ```
1732
+
1733
+ ### Additional swapper options
1734
+
1735
+ You can further customize the swapper instance with these options, you can:
1736
+ - adjust the maximum accepted pricing difference from the LPs
1737
+ - use custom mempool.space instance
1738
+ - use custom pricing API
1739
+ - use own LP node for swaps
1740
+ - adjust HTTP request timeouts
1741
+ - add parameters to be sent with each LP request
1742
+
1743
+ ```typescript
1744
+ const swapper = Factory.newSwapper({
1745
+ ...
1746
+ //Additional optional options
1747
+ pricingFeeDifferencePPM: 20000n, //Maximum allowed pricing difference for quote (between swap & market price) in ppm (parts per million) (20000 == 2%)
1748
+ mempoolApi: new MempoolApi("<url to custom mempool.space instance>"), //Set the SDK to use a custom mempool.space instance instead of the public one
1749
+ getPriceFn: (tickers: string[], abortSignal?: AbortSignal) => customPricingApi.getUsdPriceForTickers(tickers) //Overrides the default pricing API engine with a custom price getter
1750
+
1751
+ intermediaryUrl: "<url to custom LP node>",
1752
+ registryUrl: "<url to custom LP node registry>",
1753
+
1754
+ getRequestTimeout: 10000, //Timeout in milliseconds for GET requests
1755
+ postRequestTimeout: 10000, //Timeout in milliseconds for POST requests
1756
+ defaultAdditionalParameters: {lpData: "Pls give gud price"}, //Additional request data sent to LPs
1757
+
1758
+ defaultTrustedIntermediaryUrl: "<url to custom LP node>" //LP node/intermediary to use for trusted gas swaps
1759
+ });
1760
+ ```