@atomiqlabs/lp-lib 17.5.1 → 17.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/LICENSE +201 -201
  2. package/dist/fees/IBtcFeeEstimator.d.ts +3 -3
  3. package/dist/fees/IBtcFeeEstimator.js +2 -2
  4. package/dist/index.d.ts +43 -43
  5. package/dist/index.js +59 -59
  6. package/dist/info/InfoHandler.d.ts +17 -17
  7. package/dist/info/InfoHandler.js +61 -61
  8. package/dist/plugins/IPlugin.d.ts +158 -158
  9. package/dist/plugins/IPlugin.js +35 -35
  10. package/dist/plugins/PluginManager.d.ts +115 -115
  11. package/dist/plugins/PluginManager.js +304 -304
  12. package/dist/prices/BinanceSwapPrice.d.ts +29 -29
  13. package/dist/prices/BinanceSwapPrice.js +79 -79
  14. package/dist/prices/CoinGeckoSwapPrice.d.ts +33 -33
  15. package/dist/prices/CoinGeckoSwapPrice.js +51 -51
  16. package/dist/prices/ISwapPrice.d.ts +43 -43
  17. package/dist/prices/ISwapPrice.js +55 -55
  18. package/dist/prices/OKXSwapPrice.d.ts +29 -29
  19. package/dist/prices/OKXSwapPrice.js +79 -79
  20. package/dist/storage/IIntermediaryStorage.d.ts +18 -18
  21. package/dist/storage/IIntermediaryStorage.js +2 -2
  22. package/dist/storagemanager/IntermediaryStorageManager.d.ts +19 -19
  23. package/dist/storagemanager/IntermediaryStorageManager.js +111 -111
  24. package/dist/storagemanager/StorageManager.d.ts +13 -13
  25. package/dist/storagemanager/StorageManager.js +64 -64
  26. package/dist/swaps/SwapHandler.d.ts +178 -178
  27. package/dist/swaps/SwapHandler.js +225 -225
  28. package/dist/swaps/SwapHandlerSwap.d.ts +80 -80
  29. package/dist/swaps/SwapHandlerSwap.js +78 -78
  30. package/dist/swaps/assertions/AmountAssertions.d.ts +37 -37
  31. package/dist/swaps/assertions/AmountAssertions.js +83 -83
  32. package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -76
  33. package/dist/swaps/assertions/FromBtcAmountAssertions.js +189 -189
  34. package/dist/swaps/assertions/LightningAssertions.d.ts +44 -44
  35. package/dist/swaps/assertions/LightningAssertions.js +86 -86
  36. package/dist/swaps/assertions/ToBtcAmountAssertions.d.ts +53 -53
  37. package/dist/swaps/assertions/ToBtcAmountAssertions.js +154 -154
  38. package/dist/swaps/escrow/EscrowHandler.d.ts +50 -50
  39. package/dist/swaps/escrow/EscrowHandler.js +151 -151
  40. package/dist/swaps/escrow/EscrowHandlerSwap.d.ts +35 -35
  41. package/dist/swaps/escrow/EscrowHandlerSwap.js +69 -69
  42. package/dist/swaps/escrow/FromBtcBaseSwap.d.ts +14 -14
  43. package/dist/swaps/escrow/FromBtcBaseSwap.js +32 -32
  44. package/dist/swaps/escrow/FromBtcBaseSwapHandler.d.ts +102 -102
  45. package/dist/swaps/escrow/FromBtcBaseSwapHandler.js +210 -210
  46. package/dist/swaps/escrow/ToBtcBaseSwap.d.ts +36 -36
  47. package/dist/swaps/escrow/ToBtcBaseSwap.js +67 -67
  48. package/dist/swaps/escrow/ToBtcBaseSwapHandler.d.ts +53 -53
  49. package/dist/swaps/escrow/ToBtcBaseSwapHandler.js +81 -81
  50. package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.d.ts +84 -84
  51. package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +329 -329
  52. package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.d.ts +22 -22
  53. package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.js +53 -53
  54. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.d.ts +115 -115
  55. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +719 -719
  56. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +34 -34
  57. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.js +94 -94
  58. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.d.ts +119 -119
  59. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +730 -730
  60. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +56 -56
  61. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +123 -123
  62. package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.d.ts +170 -170
  63. package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +769 -769
  64. package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.d.ts +29 -29
  65. package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.js +67 -67
  66. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.d.ts +178 -178
  67. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +912 -912
  68. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +25 -25
  69. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.js +61 -61
  70. package/dist/swaps/spv_vault_swap/SpvVault.d.ts +45 -45
  71. package/dist/swaps/spv_vault_swap/SpvVault.js +148 -148
  72. package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +71 -71
  73. package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +165 -165
  74. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +72 -72
  75. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +710 -710
  76. package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +70 -70
  77. package/dist/swaps/spv_vault_swap/SpvVaults.js +554 -554
  78. package/dist/swaps/spv_vault_swap/StickyAddress.d.ts +6 -6
  79. package/dist/swaps/spv_vault_swap/StickyAddress.js +19 -19
  80. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.d.ts +52 -52
  81. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +677 -677
  82. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.d.ts +53 -53
  83. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.js +121 -121
  84. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.d.ts +77 -77
  85. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +518 -518
  86. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +35 -35
  87. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.js +84 -84
  88. package/dist/utils/BitcoinUtils.d.ts +4 -4
  89. package/dist/utils/BitcoinUtils.js +61 -61
  90. package/dist/utils/Utils.d.ts +32 -32
  91. package/dist/utils/Utils.js +130 -130
  92. package/dist/utils/paramcoders/IParamReader.d.ts +5 -5
  93. package/dist/utils/paramcoders/IParamReader.js +2 -2
  94. package/dist/utils/paramcoders/IParamWriter.d.ts +4 -4
  95. package/dist/utils/paramcoders/IParamWriter.js +2 -2
  96. package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -10
  97. package/dist/utils/paramcoders/LegacyParamEncoder.js +22 -22
  98. package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -25
  99. package/dist/utils/paramcoders/ParamDecoder.js +222 -222
  100. package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -9
  101. package/dist/utils/paramcoders/ParamEncoder.js +22 -22
  102. package/dist/utils/paramcoders/SchemaVerifier.d.ts +21 -21
  103. package/dist/utils/paramcoders/SchemaVerifier.js +84 -84
  104. package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -8
  105. package/dist/utils/paramcoders/server/ServerParamDecoder.js +107 -107
  106. package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -11
  107. package/dist/utils/paramcoders/server/ServerParamEncoder.js +65 -65
  108. package/dist/wallets/IBitcoinWallet.d.ts +155 -155
  109. package/dist/wallets/IBitcoinWallet.js +100 -100
  110. package/dist/wallets/ILightningWallet.d.ts +137 -137
  111. package/dist/wallets/ILightningWallet.js +37 -37
  112. package/dist/wallets/ISpvVaultSigner.d.ts +7 -7
  113. package/dist/wallets/ISpvVaultSigner.js +2 -2
  114. package/package.json +37 -37
  115. package/src/fees/IBtcFeeEstimator.ts +6 -6
  116. package/src/index.ts +54 -54
  117. package/src/info/InfoHandler.ts +106 -106
  118. package/src/plugins/IPlugin.ts +196 -196
  119. package/src/plugins/PluginManager.ts +389 -389
  120. package/src/prices/BinanceSwapPrice.ts +101 -101
  121. package/src/prices/CoinGeckoSwapPrice.ts +75 -75
  122. package/src/prices/ISwapPrice.ts +88 -88
  123. package/src/prices/OKXSwapPrice.ts +101 -101
  124. package/src/storage/IIntermediaryStorage.ts +19 -19
  125. package/src/storagemanager/IntermediaryStorageManager.ts +118 -118
  126. package/src/storagemanager/StorageManager.ts +78 -78
  127. package/src/swaps/SwapHandler.ts +337 -337
  128. package/src/swaps/SwapHandlerSwap.ts +143 -143
  129. package/src/swaps/assertions/AmountAssertions.ts +97 -97
  130. package/src/swaps/assertions/FromBtcAmountAssertions.ts +257 -257
  131. package/src/swaps/assertions/LightningAssertions.ts +103 -103
  132. package/src/swaps/assertions/ToBtcAmountAssertions.ts +209 -209
  133. package/src/swaps/escrow/EscrowHandler.ts +172 -172
  134. package/src/swaps/escrow/EscrowHandlerSwap.ts +86 -86
  135. package/src/swaps/escrow/FromBtcBaseSwap.ts +38 -38
  136. package/src/swaps/escrow/FromBtcBaseSwapHandler.ts +286 -286
  137. package/src/swaps/escrow/ToBtcBaseSwap.ts +85 -85
  138. package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +129 -129
  139. package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +468 -468
  140. package/src/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.ts +65 -65
  141. package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +900 -900
  142. package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +145 -145
  143. package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +892 -892
  144. package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +200 -200
  145. package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +947 -947
  146. package/src/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.ts +112 -112
  147. package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +1167 -1167
  148. package/src/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.ts +84 -84
  149. package/src/swaps/spv_vault_swap/SpvVault.ts +182 -182
  150. package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +239 -239
  151. package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +897 -897
  152. package/src/swaps/spv_vault_swap/SpvVaults.ts +640 -640
  153. package/src/swaps/spv_vault_swap/StickyAddress.ts +20 -20
  154. package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +782 -782
  155. package/src/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.ts +189 -189
  156. package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +622 -622
  157. package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.ts +125 -125
  158. package/src/utils/BitcoinUtils.ts +59 -59
  159. package/src/utils/Utils.ts +152 -152
  160. package/src/utils/paramcoders/IParamReader.ts +7 -7
  161. package/src/utils/paramcoders/IParamWriter.ts +8 -8
  162. package/src/utils/paramcoders/LegacyParamEncoder.ts +27 -27
  163. package/src/utils/paramcoders/ParamDecoder.ts +218 -218
  164. package/src/utils/paramcoders/ParamEncoder.ts +29 -29
  165. package/src/utils/paramcoders/SchemaVerifier.ts +96 -96
  166. package/src/utils/paramcoders/server/ServerParamDecoder.ts +118 -118
  167. package/src/utils/paramcoders/server/ServerParamEncoder.ts +75 -75
  168. package/src/wallets/IBitcoinWallet.ts +246 -246
  169. package/src/wallets/ILightningWallet.ts +201 -201
  170. package/src/wallets/ISpvVaultSigner.ts +10 -10
@@ -1,518 +1,518 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.FromBtcLnTrusted = void 0;
4
- const crypto_1 = require("crypto");
5
- const FromBtcLnTrustedSwap_1 = require("./FromBtcLnTrustedSwap");
6
- const SwapHandler_1 = require("../../SwapHandler");
7
- const Utils_1 = require("../../../utils/Utils");
8
- const SchemaVerifier_1 = require("../../../utils/paramcoders/SchemaVerifier");
9
- const PluginManager_1 = require("../../../plugins/PluginManager");
10
- const FromBtcAmountAssertions_1 = require("../../assertions/FromBtcAmountAssertions");
11
- const LightningAssertions_1 = require("../../assertions/LightningAssertions");
12
- const IPlugin_1 = require("../../../plugins/IPlugin");
13
- /**
14
- * Swap handler handling from BTCLN swaps using submarine swaps
15
- */
16
- class FromBtcLnTrusted extends SwapHandler_1.SwapHandler {
17
- constructor(storageDirectory, path, chains, lightning, swapPricing, config) {
18
- super(storageDirectory, path, chains, swapPricing);
19
- this.type = SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED;
20
- this.inflightSwapStates = new Set([FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED, FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT, FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED]);
21
- this.activeSubscriptions = new Map();
22
- this.processedTxIds = new Map();
23
- this.lightning = lightning;
24
- this.LightningAssertions = new LightningAssertions_1.LightningAssertions(this.logger, lightning);
25
- this.AmountAssertions = new FromBtcAmountAssertions_1.FromBtcAmountAssertions(config, swapPricing);
26
- this.config = config;
27
- this.config.invoiceTimeoutSeconds = this.config.invoiceTimeoutSeconds || 90;
28
- }
29
- /**
30
- * Unsubscribe from the pending lightning network invoice
31
- *
32
- * @param paymentHash
33
- * @private
34
- */
35
- unsubscribeInvoice(paymentHash) {
36
- const controller = this.activeSubscriptions.get(paymentHash);
37
- if (controller == null)
38
- return false;
39
- controller.abort("Unsubscribed");
40
- this.activeSubscriptions.delete(paymentHash);
41
- return true;
42
- }
43
- /**
44
- * Subscribe to a pending lightning network invoice
45
- *
46
- * @param invoiceData
47
- */
48
- subscribeToInvoice(invoiceData) {
49
- const hash = invoiceData.getIdentifierHash();
50
- //Already subscribed
51
- if (this.activeSubscriptions.has(hash))
52
- return;
53
- const abortController = new AbortController();
54
- this.lightning.waitForInvoice(hash, abortController.signal).then(invoice => {
55
- this.swapLogger.debug(invoiceData, "subscribeToInvoice(): invoice_updated: ", invoice);
56
- if (invoice.status !== "held")
57
- return;
58
- this.htlcReceived(invoiceData, invoice).catch(e => this.swapLogger.error(invoiceData, "subscribeToInvoice(): Error calling htlcReceived(): ", e));
59
- this.activeSubscriptions.delete(hash);
60
- });
61
- this.swapLogger.debug(invoiceData, "subscribeToInvoice(): Subscribed to invoice payment");
62
- this.activeSubscriptions.set(hash, abortController);
63
- }
64
- /**
65
- *
66
- * @param swap
67
- * @protected
68
- * @returns {Promise<boolean>} Whether the invoice should be cancelled
69
- */
70
- async processPastSwap(swap) {
71
- if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED)
72
- return true;
73
- if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
74
- return true;
75
- const parsedPR = await this.lightning.parsePaymentRequest(swap.pr);
76
- const invoice = await this.lightning.getInvoice(parsedPR.id);
77
- switch (invoice.status) {
78
- case "held":
79
- try {
80
- await this.htlcReceived(swap, invoice);
81
- //Result is either FromBtcLnTrustedSwapState.RECEIVED or FromBtcLnTrustedSwapState.CANCELED
82
- }
83
- catch (e) {
84
- this.swapLogger.error(swap, "processPastSwap(): Error calling htlcReceived(): ", e);
85
- }
86
- return false;
87
- case "confirmed":
88
- return false;
89
- default:
90
- const isInvoiceExpired = parsedPR.expiryEpochMillis < Date.now();
91
- if (isInvoiceExpired) {
92
- await swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
93
- return true;
94
- }
95
- this.subscribeToInvoice(swap);
96
- return false;
97
- }
98
- }
99
- async cancelInvoices(swaps) {
100
- for (let swap of swaps) {
101
- //Cancel invoices
102
- try {
103
- const paymentHash = swap.getIdentifierHash();
104
- await this.lightning.cancelHodlInvoice(paymentHash);
105
- this.unsubscribeInvoice(paymentHash);
106
- this.swapLogger.info(swap, "cancelInvoices(): invoice cancelled!");
107
- await this.removeSwapData(swap);
108
- }
109
- catch (e) {
110
- this.swapLogger.error(swap, "cancelInvoices(): cannot cancel hodl invoice id", e);
111
- }
112
- }
113
- }
114
- /**
115
- * Checks past swaps, refunds and deletes ones that are already expired.
116
- */
117
- async processPastSwaps() {
118
- const cancelInvoices = [];
119
- const queriedData = await this.storageManager.query([
120
- {
121
- key: "state",
122
- value: [
123
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED,
124
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED,
125
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT,
126
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED,
127
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED,
128
- FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED,
129
- ]
130
- }
131
- ]);
132
- for (let { obj: swap } of queriedData) {
133
- if (await this.processPastSwap(swap))
134
- cancelInvoices.push(swap);
135
- }
136
- await this.cancelInvoices(cancelInvoices);
137
- }
138
- async cancelSwapAndInvoice(swap) {
139
- if (swap.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
140
- return;
141
- await swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
142
- const paymentHash = swap.getIdentifierHash();
143
- await this.lightning.cancelHodlInvoice(paymentHash);
144
- this.unsubscribeInvoice(paymentHash);
145
- await this.removeSwapData(swap);
146
- this.swapLogger.info(swap, "cancelSwapAndInvoice(): swap removed & invoice cancelled, invoice: ", swap.pr);
147
- }
148
- /**
149
- * Saves the state of received HTLC of the lightning payment
150
- *
151
- * @param invoiceData
152
- * @param invoice
153
- */
154
- async htlcReceived(invoiceData, invoice) {
155
- const { signer, chainInterface } = this.getChain(invoiceData.chainIdentifier);
156
- //Important to prevent race condition and issuing 2 signed init messages at the same time
157
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED) {
158
- try {
159
- this.checkTooManyInflightSwaps();
160
- }
161
- catch (e) {
162
- await this.cancelSwapAndInvoice(invoiceData);
163
- throw e;
164
- }
165
- if (invoiceData.metadata != null)
166
- invoiceData.metadata.times.htlcReceived = Date.now();
167
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
168
- await this.storageManager.saveData(invoice.id, null, invoiceData);
169
- }
170
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
171
- const balance = chainInterface.getBalance(signer.getAddress(), invoiceData.token);
172
- try {
173
- await this.checkBalance(invoiceData.output, balance, null);
174
- if (invoiceData.metadata != null)
175
- invoiceData.metadata.times.htlcBalanceChecked = Date.now();
176
- }
177
- catch (e) {
178
- await this.cancelSwapAndInvoice(invoiceData);
179
- throw e;
180
- }
181
- if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
182
- return;
183
- const txns = await chainInterface.txsTransfer(signer.getAddress(), invoiceData.token, invoiceData.output, invoiceData.dstAddress);
184
- let unlock = invoiceData.lock(Infinity);
185
- if (unlock == null)
186
- return;
187
- const pluginCheckResult = await PluginManager_1.PluginManager.onHandlePreFromBtcExecute(SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED, invoiceData);
188
- if ((0, IPlugin_1.isQuoteThrow)(pluginCheckResult)) {
189
- await this.cancelSwapAndInvoice(invoiceData);
190
- unlock();
191
- throw {
192
- code: 29999,
193
- msg: pluginCheckResult.message
194
- };
195
- }
196
- if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
197
- unlock();
198
- return;
199
- }
200
- const result = await chainInterface.sendAndConfirm(signer, txns, true, null, false, async (txId, rawTx) => {
201
- invoiceData.txIds = { init: txId };
202
- invoiceData.scRawTx = rawTx;
203
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
204
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT);
205
- await this.storageManager.saveData(invoice.id, null, invoiceData);
206
- }
207
- }).catch(e => this.swapLogger.error(invoiceData, "htlcReceived(): Error sending transfer txns", e));
208
- if (result == null) {
209
- //Cancel invoice
210
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
211
- await this.storageManager.saveData(invoice.id, null, invoiceData);
212
- await this.lightning.cancelHodlInvoice(invoice.id);
213
- this.unsubscribeInvoice(invoice.id);
214
- await this.removeSwapData(invoiceData);
215
- this.swapLogger.info(invoiceData, "htlcReceived(): transaction sending failed, refunding lightning: ", invoiceData.pr);
216
- throw {
217
- code: 20002,
218
- msg: "Transaction sending failed"
219
- };
220
- }
221
- else {
222
- //Successfully paid
223
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
224
- await this.storageManager.saveData(invoice.id, null, invoiceData);
225
- }
226
- unlock();
227
- unlock = null;
228
- }
229
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT) {
230
- if (invoiceData.isLocked())
231
- return;
232
- const txStatus = await chainInterface.getTxStatus(invoiceData.scRawTx);
233
- if (txStatus === "not_found") {
234
- //Retry
235
- invoiceData.txIds = { init: null };
236
- invoiceData.scRawTx = null;
237
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
238
- await this.storageManager.saveData(invoice.id, null, invoiceData);
239
- }
240
- if (txStatus === "reverted") {
241
- //Cancel invoice
242
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
243
- await this.storageManager.saveData(invoice.id, null, invoiceData);
244
- await this.lightning.cancelHodlInvoice(invoice.id);
245
- this.unsubscribeInvoice(invoice.id);
246
- await this.removeSwapData(invoiceData);
247
- this.swapLogger.info(invoiceData, "htlcReceived(): transaction reverted, refunding lightning: ", invoiceData.pr);
248
- throw {
249
- code: 20002,
250
- msg: "Transaction reverted"
251
- };
252
- }
253
- if (txStatus === "success") {
254
- //Successfully paid
255
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
256
- await this.storageManager.saveData(invoice.id, null, invoiceData);
257
- }
258
- }
259
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED) {
260
- await this.lightning.settleHodlInvoice(invoiceData.secret);
261
- if (invoiceData.metadata != null)
262
- invoiceData.metadata.times.htlcSettled = Date.now();
263
- const paymentHash = invoiceData.getIdentifierHash();
264
- this.processedTxIds.set(paymentHash, invoiceData.txIds.init);
265
- await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED);
266
- this.unsubscribeInvoice(paymentHash);
267
- this.swapLogger.info(invoiceData, "htlcReceived(): invoice settled, invoice: " + invoiceData.pr + " scTxId: " + invoiceData.txIds.init);
268
- await this.removeSwapData(invoiceData);
269
- }
270
- }
271
- /**
272
- *
273
- * Checks if the lightning invoice is in HELD state (htlcs received but yet unclaimed)
274
- *
275
- * @param paymentHash
276
- * @throws {DefinedRuntimeError} Will throw if the lightning invoice is not found, or if it isn't in the HELD state
277
- * @returns the fetched lightning invoice
278
- */
279
- async checkInvoiceStatus(paymentHash) {
280
- const invoice = await this.lightning.getInvoice(paymentHash);
281
- const isInvoiceFound = invoice != null;
282
- if (!isInvoiceFound)
283
- throw {
284
- _httpStatus: 200,
285
- code: 10001,
286
- msg: "Invoice expired/canceled"
287
- };
288
- const arr = invoice.description.split("-");
289
- if (arr.length < 3 || arr[1] !== "GAS")
290
- throw {
291
- _httpStatus: 200,
292
- code: 10001,
293
- msg: "Invoice expired/canceled"
294
- };
295
- const chainIdentifier = arr[0];
296
- const address = arr[2];
297
- const { chainInterface } = this.getChain(chainIdentifier);
298
- if (!chainInterface.isValidAddress(address, true))
299
- throw {
300
- _httpStatus: 200,
301
- code: 10001,
302
- msg: "Invoice expired/canceled"
303
- };
304
- switch (invoice.status) {
305
- case "held":
306
- return invoice;
307
- case "canceled":
308
- throw {
309
- _httpStatus: 200,
310
- code: 10001,
311
- msg: "Invoice expired/canceled"
312
- };
313
- case "confirmed":
314
- throw {
315
- _httpStatus: 200,
316
- code: 10000,
317
- msg: "Invoice already paid",
318
- data: {
319
- txId: this.processedTxIds.get(paymentHash)
320
- }
321
- };
322
- case "unpaid":
323
- throw {
324
- _httpStatus: 200,
325
- code: 10010,
326
- msg: "Invoice yet unpaid"
327
- };
328
- default:
329
- throw new Error("Lightning invoice invalid state!");
330
- }
331
- }
332
- startRestServer(restServer) {
333
- const createInvoice = (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
334
- var _a;
335
- const metadata = { request: {}, times: {} };
336
- const chainIdentifier = req.query.chain;
337
- const { signer, chainInterface } = this.getChain(chainIdentifier);
338
- metadata.times.requestReceived = Date.now();
339
- /**
340
- * address: string solana address of the recipient
341
- * amount: string amount (in lamports/smart chain base units) of the invoice
342
- */
343
- (_a = req.query).token ?? (_a.token = chainInterface.getNativeCurrencyAddress());
344
- const parsedBody = (0, SchemaVerifier_1.verifySchema)(req.query, {
345
- address: (val) => val != null &&
346
- typeof (val) === "string" &&
347
- chainInterface.isValidAddress(val, true) ? val : null,
348
- token: (val) => val != null &&
349
- typeof (val) === "string" &&
350
- this.isTokenSupported(chainIdentifier, val) ? val : null,
351
- amount: SchemaVerifier_1.FieldTypeEnum.BigInt,
352
- exactIn: (val) => val === "true" ? true :
353
- (val === "false" || val === undefined) ? false : null
354
- });
355
- if (parsedBody == null)
356
- throw {
357
- code: 20100,
358
- msg: "Invalid request body"
359
- };
360
- metadata.request = parsedBody;
361
- const requestedAmount = { input: parsedBody.exactIn, amount: parsedBody.amount, token: parsedBody.token };
362
- const request = {
363
- chainIdentifier,
364
- raw: req,
365
- parsed: parsedBody,
366
- metadata
367
- };
368
- const useToken = parsedBody.token;
369
- this.checkTooManyInflightSwaps();
370
- //Check request params
371
- const fees = await this.AmountAssertions.preCheckFromBtcAmounts(this.type, request, requestedAmount);
372
- metadata.times.requestChecked = Date.now();
373
- //Create abortController for parallel prefetches
374
- const responseStream = res.responseStream;
375
- const abortController = (0, Utils_1.getAbortController)(responseStream);
376
- //Pre-fetch data
377
- const pricePrefetchPromise = this.swapPricing.preFetchPrice(useToken, chainIdentifier).catch(e => {
378
- this.logger.error("pricePrefetchPromise(): pricePrefetch error: ", e);
379
- abortController.abort(e);
380
- return null;
381
- });
382
- const balancePrefetch = chainInterface.getBalance(signer.getAddress(), useToken).catch(e => {
383
- this.logger.error("getBalancePrefetch(): balancePrefetch error: ", e);
384
- abortController.abort(e);
385
- return null;
386
- });
387
- const nativeBalancePrefetch = useToken === chainInterface.getNativeCurrencyAddress() ?
388
- balancePrefetch : this.prefetchNativeBalanceIfNeeded(chainIdentifier, abortController);
389
- const channelsPrefetch = this.LightningAssertions.getChannelsPrefetch(abortController);
390
- await this.checkNativeBalance(chainIdentifier, nativeBalancePrefetch, abortController.signal);
391
- //Check valid amount specified (min/max)
392
- const { amountBD, swapFee, swapFeeInToken, totalInToken } = await this.AmountAssertions.checkFromBtcAmount(this.type, request, { ...requestedAmount, pricePrefetch: pricePrefetchPromise }, fees, abortController.signal);
393
- metadata.times.priceCalculated = Date.now();
394
- //Check if we have enough funds to honor the request
395
- await this.checkBalance(totalInToken, balancePrefetch, abortController.signal);
396
- await this.LightningAssertions.checkInboundLiquidity(amountBD, channelsPrefetch, abortController.signal);
397
- metadata.times.balanceChecked = Date.now();
398
- const secret = (0, crypto_1.randomBytes)(32);
399
- const hash = (0, crypto_1.createHash)("sha256").update(secret).digest();
400
- const hodlInvoiceObj = {
401
- description: chainIdentifier + "-GAS-" + parsedBody.address,
402
- cltvDelta: Number(this.config.minCltv) + 5,
403
- expiresAt: Date.now() + (this.config.invoiceTimeoutSeconds * 1000),
404
- id: hash.toString("hex"),
405
- mtokens: amountBD * 1000n
406
- };
407
- metadata.invoiceRequest = hodlInvoiceObj;
408
- const hodlInvoice = await this.lightning.createHodlInvoice(hodlInvoiceObj);
409
- abortController.signal.throwIfAborted();
410
- metadata.times.invoiceCreated = Date.now();
411
- metadata.invoiceResponse = { ...hodlInvoice };
412
- const createdSwap = new FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap(chainIdentifier, hodlInvoice.request, hodlInvoice.mtokens, swapFee, swapFeeInToken, totalInToken, secret.toString("hex"), parsedBody.address, useToken);
413
- metadata.times.swapCreated = Date.now();
414
- createdSwap.metadata = metadata;
415
- await PluginManager_1.PluginManager.swapCreate(createdSwap);
416
- await this.storageManager.saveData(hash.toString("hex"), null, createdSwap);
417
- this.subscribeToInvoice(createdSwap);
418
- this.swapLogger.info(createdSwap, "REST: /createInvoice: Created swap invoice: " + hodlInvoice.request + " amount: " + amountBD.toString(10));
419
- res.status(200).json({
420
- msg: "Success",
421
- code: 10000,
422
- data: {
423
- pr: hodlInvoice.request,
424
- amountSats: amountBD.toString(10),
425
- swapFeeSats: swapFee.toString(10),
426
- swapFee: swapFeeInToken.toString(10),
427
- total: totalInToken.toString(10),
428
- intermediaryKey: signer.getAddress()
429
- }
430
- });
431
- });
432
- restServer.get(this.path + "/createInvoice", createInvoice);
433
- const getInvoiceStatus = (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
434
- /**
435
- * paymentHash: string payment hash of the invoice
436
- */
437
- const parsedBody = (0, SchemaVerifier_1.verifySchema)({ ...req.body, ...req.query }, {
438
- paymentHash: (val) => val != null &&
439
- typeof (val) === "string" &&
440
- val.length === 64 &&
441
- Utils_1.HEX_REGEX.test(val) ? val : null,
442
- });
443
- await this.checkInvoiceStatus(parsedBody.paymentHash);
444
- const invoiceData = await this.storageManager.getData(parsedBody.paymentHash, null);
445
- if (invoiceData == null)
446
- throw {
447
- _httpStatus: 200,
448
- code: 10001,
449
- msg: "Invoice expired/canceled"
450
- };
451
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED ||
452
- invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
453
- throw {
454
- _httpStatus: 200,
455
- code: 10001,
456
- msg: "Invoice expired/canceled"
457
- };
458
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED)
459
- throw {
460
- _httpStatus: 200,
461
- code: 10010,
462
- msg: "Invoice yet unpaid"
463
- };
464
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
465
- throw {
466
- _httpStatus: 200,
467
- code: 10011,
468
- msg: "Invoice received, payment processing"
469
- };
470
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT)
471
- throw {
472
- _httpStatus: 200,
473
- code: 10012,
474
- msg: "Tx sent",
475
- data: {
476
- txId: invoiceData.txIds.init
477
- }
478
- };
479
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED)
480
- throw {
481
- _httpStatus: 200,
482
- code: 10000,
483
- msg: "Success, tx confirmed",
484
- data: {
485
- txId: invoiceData.txIds.init
486
- }
487
- };
488
- if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED)
489
- throw {
490
- _httpStatus: 200,
491
- code: 10000,
492
- msg: "Success, tx confirmed - invoice settled",
493
- data: {
494
- txId: invoiceData.txIds.init
495
- }
496
- };
497
- });
498
- restServer.get(this.path + "/getInvoiceStatus", getInvoiceStatus);
499
- this.logger.info("started at path: ", this.path);
500
- }
501
- async init() {
502
- await this.storageManager.loadData(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap);
503
- //Check if all swaps contain a valid amount
504
- for (let { obj: swap } of await this.storageManager.query([])) {
505
- if (swap.amount == null) {
506
- const parsedPR = await this.lightning.parsePaymentRequest(swap.pr);
507
- swap.amount = (parsedPR.mtokens + 999n) / 1000n;
508
- }
509
- }
510
- await PluginManager_1.PluginManager.serviceInitialize(this);
511
- }
512
- getInfoData() {
513
- return {
514
- minCltv: Number(this.config.minCltv)
515
- };
516
- }
517
- }
518
- exports.FromBtcLnTrusted = FromBtcLnTrusted;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FromBtcLnTrusted = void 0;
4
+ const crypto_1 = require("crypto");
5
+ const FromBtcLnTrustedSwap_1 = require("./FromBtcLnTrustedSwap");
6
+ const SwapHandler_1 = require("../../SwapHandler");
7
+ const Utils_1 = require("../../../utils/Utils");
8
+ const SchemaVerifier_1 = require("../../../utils/paramcoders/SchemaVerifier");
9
+ const PluginManager_1 = require("../../../plugins/PluginManager");
10
+ const FromBtcAmountAssertions_1 = require("../../assertions/FromBtcAmountAssertions");
11
+ const LightningAssertions_1 = require("../../assertions/LightningAssertions");
12
+ const IPlugin_1 = require("../../../plugins/IPlugin");
13
+ /**
14
+ * Swap handler handling from BTCLN swaps using submarine swaps
15
+ */
16
+ class FromBtcLnTrusted extends SwapHandler_1.SwapHandler {
17
+ constructor(storageDirectory, path, chains, lightning, swapPricing, config) {
18
+ super(storageDirectory, path, chains, swapPricing);
19
+ this.type = SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED;
20
+ this.inflightSwapStates = new Set([FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED, FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT, FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED]);
21
+ this.activeSubscriptions = new Map();
22
+ this.processedTxIds = new Map();
23
+ this.lightning = lightning;
24
+ this.LightningAssertions = new LightningAssertions_1.LightningAssertions(this.logger, lightning);
25
+ this.AmountAssertions = new FromBtcAmountAssertions_1.FromBtcAmountAssertions(config, swapPricing);
26
+ this.config = config;
27
+ this.config.invoiceTimeoutSeconds = this.config.invoiceTimeoutSeconds || 90;
28
+ }
29
+ /**
30
+ * Unsubscribe from the pending lightning network invoice
31
+ *
32
+ * @param paymentHash
33
+ * @private
34
+ */
35
+ unsubscribeInvoice(paymentHash) {
36
+ const controller = this.activeSubscriptions.get(paymentHash);
37
+ if (controller == null)
38
+ return false;
39
+ controller.abort("Unsubscribed");
40
+ this.activeSubscriptions.delete(paymentHash);
41
+ return true;
42
+ }
43
+ /**
44
+ * Subscribe to a pending lightning network invoice
45
+ *
46
+ * @param invoiceData
47
+ */
48
+ subscribeToInvoice(invoiceData) {
49
+ const hash = invoiceData.getIdentifierHash();
50
+ //Already subscribed
51
+ if (this.activeSubscriptions.has(hash))
52
+ return;
53
+ const abortController = new AbortController();
54
+ this.lightning.waitForInvoice(hash, abortController.signal).then(invoice => {
55
+ this.swapLogger.debug(invoiceData, "subscribeToInvoice(): invoice_updated: ", invoice);
56
+ if (invoice.status !== "held")
57
+ return;
58
+ this.htlcReceived(invoiceData, invoice).catch(e => this.swapLogger.error(invoiceData, "subscribeToInvoice(): Error calling htlcReceived(): ", e));
59
+ this.activeSubscriptions.delete(hash);
60
+ });
61
+ this.swapLogger.debug(invoiceData, "subscribeToInvoice(): Subscribed to invoice payment");
62
+ this.activeSubscriptions.set(hash, abortController);
63
+ }
64
+ /**
65
+ *
66
+ * @param swap
67
+ * @protected
68
+ * @returns {Promise<boolean>} Whether the invoice should be cancelled
69
+ */
70
+ async processPastSwap(swap) {
71
+ if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED)
72
+ return true;
73
+ if (swap.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
74
+ return true;
75
+ const parsedPR = await this.lightning.parsePaymentRequest(swap.pr);
76
+ const invoice = await this.lightning.getInvoice(parsedPR.id);
77
+ switch (invoice.status) {
78
+ case "held":
79
+ try {
80
+ await this.htlcReceived(swap, invoice);
81
+ //Result is either FromBtcLnTrustedSwapState.RECEIVED or FromBtcLnTrustedSwapState.CANCELED
82
+ }
83
+ catch (e) {
84
+ this.swapLogger.error(swap, "processPastSwap(): Error calling htlcReceived(): ", e);
85
+ }
86
+ return false;
87
+ case "confirmed":
88
+ return false;
89
+ default:
90
+ const isInvoiceExpired = parsedPR.expiryEpochMillis < Date.now();
91
+ if (isInvoiceExpired) {
92
+ await swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
93
+ return true;
94
+ }
95
+ this.subscribeToInvoice(swap);
96
+ return false;
97
+ }
98
+ }
99
+ async cancelInvoices(swaps) {
100
+ for (let swap of swaps) {
101
+ //Cancel invoices
102
+ try {
103
+ const paymentHash = swap.getIdentifierHash();
104
+ await this.lightning.cancelHodlInvoice(paymentHash);
105
+ this.unsubscribeInvoice(paymentHash);
106
+ this.swapLogger.info(swap, "cancelInvoices(): invoice cancelled!");
107
+ await this.removeSwapData(swap);
108
+ }
109
+ catch (e) {
110
+ this.swapLogger.error(swap, "cancelInvoices(): cannot cancel hodl invoice id", e);
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Checks past swaps, refunds and deletes ones that are already expired.
116
+ */
117
+ async processPastSwaps() {
118
+ const cancelInvoices = [];
119
+ const queriedData = await this.storageManager.query([
120
+ {
121
+ key: "state",
122
+ value: [
123
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED,
124
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED,
125
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT,
126
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED,
127
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED,
128
+ FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED,
129
+ ]
130
+ }
131
+ ]);
132
+ for (let { obj: swap } of queriedData) {
133
+ if (await this.processPastSwap(swap))
134
+ cancelInvoices.push(swap);
135
+ }
136
+ await this.cancelInvoices(cancelInvoices);
137
+ }
138
+ async cancelSwapAndInvoice(swap) {
139
+ if (swap.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
140
+ return;
141
+ await swap.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED);
142
+ const paymentHash = swap.getIdentifierHash();
143
+ await this.lightning.cancelHodlInvoice(paymentHash);
144
+ this.unsubscribeInvoice(paymentHash);
145
+ await this.removeSwapData(swap);
146
+ this.swapLogger.info(swap, "cancelSwapAndInvoice(): swap removed & invoice cancelled, invoice: ", swap.pr);
147
+ }
148
+ /**
149
+ * Saves the state of received HTLC of the lightning payment
150
+ *
151
+ * @param invoiceData
152
+ * @param invoice
153
+ */
154
+ async htlcReceived(invoiceData, invoice) {
155
+ const { signer, chainInterface } = this.getChain(invoiceData.chainIdentifier);
156
+ //Important to prevent race condition and issuing 2 signed init messages at the same time
157
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED) {
158
+ try {
159
+ this.checkTooManyInflightSwaps();
160
+ }
161
+ catch (e) {
162
+ await this.cancelSwapAndInvoice(invoiceData);
163
+ throw e;
164
+ }
165
+ if (invoiceData.metadata != null)
166
+ invoiceData.metadata.times.htlcReceived = Date.now();
167
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
168
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
169
+ }
170
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
171
+ const balance = chainInterface.getBalance(signer.getAddress(), invoiceData.token);
172
+ try {
173
+ await this.checkBalance(invoiceData.output, balance, null);
174
+ if (invoiceData.metadata != null)
175
+ invoiceData.metadata.times.htlcBalanceChecked = Date.now();
176
+ }
177
+ catch (e) {
178
+ await this.cancelSwapAndInvoice(invoiceData);
179
+ throw e;
180
+ }
181
+ if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
182
+ return;
183
+ const txns = await chainInterface.txsTransfer(signer.getAddress(), invoiceData.token, invoiceData.output, invoiceData.dstAddress);
184
+ let unlock = invoiceData.lock(Infinity);
185
+ if (unlock == null)
186
+ return;
187
+ const pluginCheckResult = await PluginManager_1.PluginManager.onHandlePreFromBtcExecute(SwapHandler_1.SwapHandlerType.FROM_BTCLN_TRUSTED, invoiceData);
188
+ if ((0, IPlugin_1.isQuoteThrow)(pluginCheckResult)) {
189
+ await this.cancelSwapAndInvoice(invoiceData);
190
+ unlock();
191
+ throw {
192
+ code: 29999,
193
+ msg: pluginCheckResult.message
194
+ };
195
+ }
196
+ if (invoiceData.state !== FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
197
+ unlock();
198
+ return;
199
+ }
200
+ const result = await chainInterface.sendAndConfirm(signer, txns, true, null, false, async (txId, rawTx) => {
201
+ invoiceData.txIds = { init: txId };
202
+ invoiceData.scRawTx = rawTx;
203
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED) {
204
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT);
205
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
206
+ }
207
+ }).catch(e => this.swapLogger.error(invoiceData, "htlcReceived(): Error sending transfer txns", e));
208
+ if (result == null) {
209
+ //Cancel invoice
210
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
211
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
212
+ await this.lightning.cancelHodlInvoice(invoice.id);
213
+ this.unsubscribeInvoice(invoice.id);
214
+ await this.removeSwapData(invoiceData);
215
+ this.swapLogger.info(invoiceData, "htlcReceived(): transaction sending failed, refunding lightning: ", invoiceData.pr);
216
+ throw {
217
+ code: 20002,
218
+ msg: "Transaction sending failed"
219
+ };
220
+ }
221
+ else {
222
+ //Successfully paid
223
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
224
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
225
+ }
226
+ unlock();
227
+ unlock = null;
228
+ }
229
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT) {
230
+ if (invoiceData.isLocked())
231
+ return;
232
+ const txStatus = await chainInterface.getTxStatus(invoiceData.scRawTx);
233
+ if (txStatus === "not_found") {
234
+ //Retry
235
+ invoiceData.txIds = { init: null };
236
+ invoiceData.scRawTx = null;
237
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED);
238
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
239
+ }
240
+ if (txStatus === "reverted") {
241
+ //Cancel invoice
242
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED);
243
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
244
+ await this.lightning.cancelHodlInvoice(invoice.id);
245
+ this.unsubscribeInvoice(invoice.id);
246
+ await this.removeSwapData(invoiceData);
247
+ this.swapLogger.info(invoiceData, "htlcReceived(): transaction reverted, refunding lightning: ", invoiceData.pr);
248
+ throw {
249
+ code: 20002,
250
+ msg: "Transaction reverted"
251
+ };
252
+ }
253
+ if (txStatus === "success") {
254
+ //Successfully paid
255
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED);
256
+ await this.storageManager.saveData(invoice.id, null, invoiceData);
257
+ }
258
+ }
259
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED) {
260
+ await this.lightning.settleHodlInvoice(invoiceData.secret);
261
+ if (invoiceData.metadata != null)
262
+ invoiceData.metadata.times.htlcSettled = Date.now();
263
+ const paymentHash = invoiceData.getIdentifierHash();
264
+ this.processedTxIds.set(paymentHash, invoiceData.txIds.init);
265
+ await invoiceData.setState(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED);
266
+ this.unsubscribeInvoice(paymentHash);
267
+ this.swapLogger.info(invoiceData, "htlcReceived(): invoice settled, invoice: " + invoiceData.pr + " scTxId: " + invoiceData.txIds.init);
268
+ await this.removeSwapData(invoiceData);
269
+ }
270
+ }
271
+ /**
272
+ *
273
+ * Checks if the lightning invoice is in HELD state (htlcs received but yet unclaimed)
274
+ *
275
+ * @param paymentHash
276
+ * @throws {DefinedRuntimeError} Will throw if the lightning invoice is not found, or if it isn't in the HELD state
277
+ * @returns the fetched lightning invoice
278
+ */
279
+ async checkInvoiceStatus(paymentHash) {
280
+ const invoice = await this.lightning.getInvoice(paymentHash);
281
+ const isInvoiceFound = invoice != null;
282
+ if (!isInvoiceFound)
283
+ throw {
284
+ _httpStatus: 200,
285
+ code: 10001,
286
+ msg: "Invoice expired/canceled"
287
+ };
288
+ const arr = invoice.description.split("-");
289
+ if (arr.length < 3 || arr[1] !== "GAS")
290
+ throw {
291
+ _httpStatus: 200,
292
+ code: 10001,
293
+ msg: "Invoice expired/canceled"
294
+ };
295
+ const chainIdentifier = arr[0];
296
+ const address = arr[2];
297
+ const { chainInterface } = this.getChain(chainIdentifier);
298
+ if (!chainInterface.isValidAddress(address, true))
299
+ throw {
300
+ _httpStatus: 200,
301
+ code: 10001,
302
+ msg: "Invoice expired/canceled"
303
+ };
304
+ switch (invoice.status) {
305
+ case "held":
306
+ return invoice;
307
+ case "canceled":
308
+ throw {
309
+ _httpStatus: 200,
310
+ code: 10001,
311
+ msg: "Invoice expired/canceled"
312
+ };
313
+ case "confirmed":
314
+ throw {
315
+ _httpStatus: 200,
316
+ code: 10000,
317
+ msg: "Invoice already paid",
318
+ data: {
319
+ txId: this.processedTxIds.get(paymentHash)
320
+ }
321
+ };
322
+ case "unpaid":
323
+ throw {
324
+ _httpStatus: 200,
325
+ code: 10010,
326
+ msg: "Invoice yet unpaid"
327
+ };
328
+ default:
329
+ throw new Error("Lightning invoice invalid state!");
330
+ }
331
+ }
332
+ startRestServer(restServer) {
333
+ const createInvoice = (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
334
+ var _a;
335
+ const metadata = { request: {}, times: {} };
336
+ const chainIdentifier = req.query.chain;
337
+ const { signer, chainInterface } = this.getChain(chainIdentifier);
338
+ metadata.times.requestReceived = Date.now();
339
+ /**
340
+ * address: string solana address of the recipient
341
+ * amount: string amount (in lamports/smart chain base units) of the invoice
342
+ */
343
+ (_a = req.query).token ?? (_a.token = chainInterface.getNativeCurrencyAddress());
344
+ const parsedBody = (0, SchemaVerifier_1.verifySchema)(req.query, {
345
+ address: (val) => val != null &&
346
+ typeof (val) === "string" &&
347
+ chainInterface.isValidAddress(val, true) ? val : null,
348
+ token: (val) => val != null &&
349
+ typeof (val) === "string" &&
350
+ this.isTokenSupported(chainIdentifier, val) ? val : null,
351
+ amount: SchemaVerifier_1.FieldTypeEnum.BigInt,
352
+ exactIn: (val) => val === "true" ? true :
353
+ (val === "false" || val === undefined) ? false : null
354
+ });
355
+ if (parsedBody == null)
356
+ throw {
357
+ code: 20100,
358
+ msg: "Invalid request body"
359
+ };
360
+ metadata.request = parsedBody;
361
+ const requestedAmount = { input: parsedBody.exactIn, amount: parsedBody.amount, token: parsedBody.token };
362
+ const request = {
363
+ chainIdentifier,
364
+ raw: req,
365
+ parsed: parsedBody,
366
+ metadata
367
+ };
368
+ const useToken = parsedBody.token;
369
+ this.checkTooManyInflightSwaps();
370
+ //Check request params
371
+ const fees = await this.AmountAssertions.preCheckFromBtcAmounts(this.type, request, requestedAmount);
372
+ metadata.times.requestChecked = Date.now();
373
+ //Create abortController for parallel prefetches
374
+ const responseStream = res.responseStream;
375
+ const abortController = (0, Utils_1.getAbortController)(responseStream);
376
+ //Pre-fetch data
377
+ const pricePrefetchPromise = this.swapPricing.preFetchPrice(useToken, chainIdentifier).catch(e => {
378
+ this.logger.error("pricePrefetchPromise(): pricePrefetch error: ", e);
379
+ abortController.abort(e);
380
+ return null;
381
+ });
382
+ const balancePrefetch = chainInterface.getBalance(signer.getAddress(), useToken).catch(e => {
383
+ this.logger.error("getBalancePrefetch(): balancePrefetch error: ", e);
384
+ abortController.abort(e);
385
+ return null;
386
+ });
387
+ const nativeBalancePrefetch = useToken === chainInterface.getNativeCurrencyAddress() ?
388
+ balancePrefetch : this.prefetchNativeBalanceIfNeeded(chainIdentifier, abortController);
389
+ const channelsPrefetch = this.LightningAssertions.getChannelsPrefetch(abortController);
390
+ await this.checkNativeBalance(chainIdentifier, nativeBalancePrefetch, abortController.signal);
391
+ //Check valid amount specified (min/max)
392
+ const { amountBD, swapFee, swapFeeInToken, totalInToken } = await this.AmountAssertions.checkFromBtcAmount(this.type, request, { ...requestedAmount, pricePrefetch: pricePrefetchPromise }, fees, abortController.signal);
393
+ metadata.times.priceCalculated = Date.now();
394
+ //Check if we have enough funds to honor the request
395
+ await this.checkBalance(totalInToken, balancePrefetch, abortController.signal);
396
+ await this.LightningAssertions.checkInboundLiquidity(amountBD, channelsPrefetch, abortController.signal);
397
+ metadata.times.balanceChecked = Date.now();
398
+ const secret = (0, crypto_1.randomBytes)(32);
399
+ const hash = (0, crypto_1.createHash)("sha256").update(secret).digest();
400
+ const hodlInvoiceObj = {
401
+ description: chainIdentifier + "-GAS-" + parsedBody.address,
402
+ cltvDelta: Number(this.config.minCltv) + 5,
403
+ expiresAt: Date.now() + (this.config.invoiceTimeoutSeconds * 1000),
404
+ id: hash.toString("hex"),
405
+ mtokens: amountBD * 1000n
406
+ };
407
+ metadata.invoiceRequest = hodlInvoiceObj;
408
+ const hodlInvoice = await this.lightning.createHodlInvoice(hodlInvoiceObj);
409
+ abortController.signal.throwIfAborted();
410
+ metadata.times.invoiceCreated = Date.now();
411
+ metadata.invoiceResponse = { ...hodlInvoice };
412
+ const createdSwap = new FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap(chainIdentifier, hodlInvoice.request, hodlInvoice.mtokens, swapFee, swapFeeInToken, totalInToken, secret.toString("hex"), parsedBody.address, useToken);
413
+ metadata.times.swapCreated = Date.now();
414
+ createdSwap.metadata = metadata;
415
+ await PluginManager_1.PluginManager.swapCreate(createdSwap);
416
+ await this.storageManager.saveData(hash.toString("hex"), null, createdSwap);
417
+ this.subscribeToInvoice(createdSwap);
418
+ this.swapLogger.info(createdSwap, "REST: /createInvoice: Created swap invoice: " + hodlInvoice.request + " amount: " + amountBD.toString(10));
419
+ res.status(200).json({
420
+ msg: "Success",
421
+ code: 10000,
422
+ data: {
423
+ pr: hodlInvoice.request,
424
+ amountSats: amountBD.toString(10),
425
+ swapFeeSats: swapFee.toString(10),
426
+ swapFee: swapFeeInToken.toString(10),
427
+ total: totalInToken.toString(10),
428
+ intermediaryKey: signer.getAddress()
429
+ }
430
+ });
431
+ });
432
+ restServer.get(this.path + "/createInvoice", createInvoice);
433
+ const getInvoiceStatus = (0, Utils_1.expressHandlerWrapper)(async (req, res) => {
434
+ /**
435
+ * paymentHash: string payment hash of the invoice
436
+ */
437
+ const parsedBody = (0, SchemaVerifier_1.verifySchema)({ ...req.body, ...req.query }, {
438
+ paymentHash: (val) => val != null &&
439
+ typeof (val) === "string" &&
440
+ val.length === 64 &&
441
+ Utils_1.HEX_REGEX.test(val) ? val : null,
442
+ });
443
+ await this.checkInvoiceStatus(parsedBody.paymentHash);
444
+ const invoiceData = await this.storageManager.getData(parsedBody.paymentHash, null);
445
+ if (invoiceData == null)
446
+ throw {
447
+ _httpStatus: 200,
448
+ code: 10001,
449
+ msg: "Invoice expired/canceled"
450
+ };
451
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CANCELED ||
452
+ invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.REFUNDED)
453
+ throw {
454
+ _httpStatus: 200,
455
+ code: 10001,
456
+ msg: "Invoice expired/canceled"
457
+ };
458
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CREATED)
459
+ throw {
460
+ _httpStatus: 200,
461
+ code: 10010,
462
+ msg: "Invoice yet unpaid"
463
+ };
464
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.RECEIVED)
465
+ throw {
466
+ _httpStatus: 200,
467
+ code: 10011,
468
+ msg: "Invoice received, payment processing"
469
+ };
470
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SENT)
471
+ throw {
472
+ _httpStatus: 200,
473
+ code: 10012,
474
+ msg: "Tx sent",
475
+ data: {
476
+ txId: invoiceData.txIds.init
477
+ }
478
+ };
479
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.CONFIRMED)
480
+ throw {
481
+ _httpStatus: 200,
482
+ code: 10000,
483
+ msg: "Success, tx confirmed",
484
+ data: {
485
+ txId: invoiceData.txIds.init
486
+ }
487
+ };
488
+ if (invoiceData.state === FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwapState.SETTLED)
489
+ throw {
490
+ _httpStatus: 200,
491
+ code: 10000,
492
+ msg: "Success, tx confirmed - invoice settled",
493
+ data: {
494
+ txId: invoiceData.txIds.init
495
+ }
496
+ };
497
+ });
498
+ restServer.get(this.path + "/getInvoiceStatus", getInvoiceStatus);
499
+ this.logger.info("started at path: ", this.path);
500
+ }
501
+ async init() {
502
+ await this.storageManager.loadData(FromBtcLnTrustedSwap_1.FromBtcLnTrustedSwap);
503
+ //Check if all swaps contain a valid amount
504
+ for (let { obj: swap } of await this.storageManager.query([])) {
505
+ if (swap.amount == null) {
506
+ const parsedPR = await this.lightning.parsePaymentRequest(swap.pr);
507
+ swap.amount = (parsedPR.mtokens + 999n) / 1000n;
508
+ }
509
+ }
510
+ await PluginManager_1.PluginManager.serviceInitialize(this);
511
+ }
512
+ getInfoData() {
513
+ return {
514
+ minCltv: Number(this.config.minCltv)
515
+ };
516
+ }
517
+ }
518
+ exports.FromBtcLnTrusted = FromBtcLnTrusted;