@atomiqlabs/lp-lib 14.0.0-dev.3 → 14.0.0-dev.30

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 (169) 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 +42 -40
  5. package/dist/index.js +58 -56
  6. package/dist/info/InfoHandler.d.ts +17 -17
  7. package/dist/info/InfoHandler.js +61 -61
  8. package/dist/plugins/IPlugin.d.ts +143 -143
  9. package/dist/plugins/IPlugin.js +34 -34
  10. package/dist/plugins/PluginManager.d.ts +112 -112
  11. package/dist/plugins/PluginManager.js +259 -259
  12. package/dist/prices/BinanceSwapPrice.d.ts +26 -26
  13. package/dist/prices/BinanceSwapPrice.js +92 -92
  14. package/dist/prices/CoinGeckoSwapPrice.d.ts +30 -30
  15. package/dist/prices/CoinGeckoSwapPrice.js +64 -64
  16. package/dist/prices/ISwapPrice.d.ts +43 -43
  17. package/dist/prices/ISwapPrice.js +55 -55
  18. package/dist/prices/OKXSwapPrice.d.ts +26 -26
  19. package/dist/prices/OKXSwapPrice.js +92 -92
  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 -106
  24. package/dist/storagemanager/StorageManager.d.ts +13 -13
  25. package/dist/storagemanager/StorageManager.js +64 -59
  26. package/dist/swaps/SwapHandler.d.ts +153 -152
  27. package/dist/swaps/SwapHandler.js +160 -159
  28. package/dist/swaps/SwapHandlerSwap.d.ts +79 -79
  29. package/dist/swaps/SwapHandlerSwap.js +78 -78
  30. package/dist/swaps/assertions/AmountAssertions.d.ts +28 -28
  31. package/dist/swaps/assertions/AmountAssertions.js +72 -72
  32. package/dist/swaps/assertions/FromBtcAmountAssertions.d.ts +76 -76
  33. package/dist/swaps/assertions/FromBtcAmountAssertions.js +180 -172
  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 +150 -150
  38. package/dist/swaps/escrow/EscrowHandler.d.ts +51 -51
  39. package/dist/swaps/escrow/EscrowHandler.js +158 -158
  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 -101
  45. package/dist/swaps/escrow/FromBtcBaseSwapHandler.js +210 -207
  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 +83 -83
  51. package/dist/swaps/escrow/frombtc_abstract/FromBtcAbs.js +318 -318
  52. package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.d.ts +21 -21
  53. package/dist/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.js +50 -50
  54. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.d.ts +107 -107
  55. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.js +675 -648
  56. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.d.ts +33 -32
  57. package/dist/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.js +91 -88
  58. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.d.ts +111 -0
  59. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.js +684 -0
  60. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.d.ts +55 -0
  61. package/dist/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.js +120 -0
  62. package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.d.ts +171 -171
  63. package/dist/swaps/escrow/tobtc_abstract/ToBtcAbs.js +729 -706
  64. package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.d.ts +28 -26
  65. package/dist/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.js +64 -62
  66. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.d.ts +177 -177
  67. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.js +865 -861
  68. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.d.ts +24 -23
  69. package/dist/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.js +58 -56
  70. package/dist/swaps/spv_vault_swap/SpvVault.d.ts +42 -41
  71. package/dist/swaps/spv_vault_swap/SpvVault.js +111 -111
  72. package/dist/swaps/spv_vault_swap/SpvVaultSwap.d.ts +68 -67
  73. package/dist/swaps/spv_vault_swap/SpvVaultSwap.js +158 -158
  74. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.d.ts +68 -68
  75. package/dist/swaps/spv_vault_swap/SpvVaultSwapHandler.js +519 -490
  76. package/dist/swaps/spv_vault_swap/SpvVaults.d.ts +56 -52
  77. package/dist/swaps/spv_vault_swap/SpvVaults.js +397 -364
  78. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.d.ts +51 -51
  79. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrusted.js +650 -650
  80. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.d.ts +52 -52
  81. package/dist/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.js +118 -118
  82. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.d.ts +76 -76
  83. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.js +494 -494
  84. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.d.ts +34 -34
  85. package/dist/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.js +81 -81
  86. package/dist/utils/BitcoinUtils.d.ts +6 -0
  87. package/dist/utils/BitcoinUtils.js +75 -0
  88. package/dist/utils/Utils.d.ts +29 -29
  89. package/dist/utils/Utils.js +89 -89
  90. package/dist/utils/paramcoders/IParamReader.d.ts +5 -5
  91. package/dist/utils/paramcoders/IParamReader.js +2 -2
  92. package/dist/utils/paramcoders/IParamWriter.d.ts +4 -4
  93. package/dist/utils/paramcoders/IParamWriter.js +2 -2
  94. package/dist/utils/paramcoders/LegacyParamEncoder.d.ts +10 -10
  95. package/dist/utils/paramcoders/LegacyParamEncoder.js +22 -22
  96. package/dist/utils/paramcoders/ParamDecoder.d.ts +25 -25
  97. package/dist/utils/paramcoders/ParamDecoder.js +222 -222
  98. package/dist/utils/paramcoders/ParamEncoder.d.ts +9 -9
  99. package/dist/utils/paramcoders/ParamEncoder.js +22 -22
  100. package/dist/utils/paramcoders/SchemaVerifier.d.ts +21 -21
  101. package/dist/utils/paramcoders/SchemaVerifier.js +84 -84
  102. package/dist/utils/paramcoders/server/ServerParamDecoder.d.ts +8 -8
  103. package/dist/utils/paramcoders/server/ServerParamDecoder.js +107 -107
  104. package/dist/utils/paramcoders/server/ServerParamEncoder.d.ts +11 -11
  105. package/dist/utils/paramcoders/server/ServerParamEncoder.js +65 -65
  106. package/dist/wallets/IBitcoinWallet.d.ts +67 -67
  107. package/dist/wallets/IBitcoinWallet.js +2 -2
  108. package/dist/wallets/ILightningWallet.d.ts +117 -117
  109. package/dist/wallets/ILightningWallet.js +37 -37
  110. package/dist/wallets/ISpvVaultSigner.d.ts +7 -7
  111. package/dist/wallets/ISpvVaultSigner.js +2 -2
  112. package/package.json +36 -36
  113. package/src/fees/IBtcFeeEstimator.ts +6 -6
  114. package/src/index.ts +53 -51
  115. package/src/info/InfoHandler.ts +106 -106
  116. package/src/plugins/IPlugin.ts +168 -168
  117. package/src/plugins/PluginManager.ts +336 -336
  118. package/src/prices/BinanceSwapPrice.ts +113 -113
  119. package/src/prices/CoinGeckoSwapPrice.ts +87 -87
  120. package/src/prices/ISwapPrice.ts +88 -88
  121. package/src/prices/OKXSwapPrice.ts +113 -113
  122. package/src/storage/IIntermediaryStorage.ts +19 -19
  123. package/src/storagemanager/IntermediaryStorageManager.ts +118 -112
  124. package/src/storagemanager/StorageManager.ts +78 -72
  125. package/src/swaps/SwapHandler.ts +277 -276
  126. package/src/swaps/SwapHandlerSwap.ts +141 -141
  127. package/src/swaps/assertions/AmountAssertions.ts +76 -76
  128. package/src/swaps/assertions/FromBtcAmountAssertions.ts +246 -238
  129. package/src/swaps/assertions/LightningAssertions.ts +103 -103
  130. package/src/swaps/assertions/ToBtcAmountAssertions.ts +203 -203
  131. package/src/swaps/escrow/EscrowHandler.ts +179 -179
  132. package/src/swaps/escrow/EscrowHandlerSwap.ts +86 -86
  133. package/src/swaps/escrow/FromBtcBaseSwap.ts +38 -38
  134. package/src/swaps/escrow/FromBtcBaseSwapHandler.ts +286 -283
  135. package/src/swaps/escrow/ToBtcBaseSwap.ts +85 -85
  136. package/src/swaps/escrow/ToBtcBaseSwapHandler.ts +129 -129
  137. package/src/swaps/escrow/frombtc_abstract/FromBtcAbs.ts +452 -452
  138. package/src/swaps/escrow/frombtc_abstract/FromBtcSwapAbs.ts +61 -61
  139. package/src/swaps/escrow/frombtcln_abstract/FromBtcLnAbs.ts +856 -828
  140. package/src/swaps/escrow/frombtcln_abstract/FromBtcLnSwapAbs.ts +141 -137
  141. package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAuto.ts +850 -0
  142. package/src/swaps/escrow/frombtcln_autoinit/FromBtcLnAutoSwap.ts +196 -0
  143. package/src/swaps/escrow/tobtc_abstract/ToBtcAbs.ts +904 -879
  144. package/src/swaps/escrow/tobtc_abstract/ToBtcSwapAbs.ts +108 -102
  145. package/src/swaps/escrow/tobtcln_abstract/ToBtcLnAbs.ts +1116 -1110
  146. package/src/swaps/escrow/tobtcln_abstract/ToBtcLnSwapAbs.ts +80 -77
  147. package/src/swaps/spv_vault_swap/SpvVault.ts +143 -143
  148. package/src/swaps/spv_vault_swap/SpvVaultSwap.ts +228 -225
  149. package/src/swaps/spv_vault_swap/SpvVaultSwapHandler.ts +656 -626
  150. package/src/swaps/spv_vault_swap/SpvVaults.ts +473 -435
  151. package/src/swaps/trusted/frombtc_trusted/FromBtcTrusted.ts +747 -747
  152. package/src/swaps/trusted/frombtc_trusted/FromBtcTrustedSwap.ts +185 -185
  153. package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrusted.ts +590 -590
  154. package/src/swaps/trusted/frombtcln_trusted/FromBtcLnTrustedSwap.ts +121 -121
  155. package/src/utils/BitcoinUtils.ts +71 -0
  156. package/src/utils/Utils.ts +104 -104
  157. package/src/utils/paramcoders/IParamReader.ts +7 -7
  158. package/src/utils/paramcoders/IParamWriter.ts +8 -8
  159. package/src/utils/paramcoders/LegacyParamEncoder.ts +27 -27
  160. package/src/utils/paramcoders/ParamDecoder.ts +218 -218
  161. package/src/utils/paramcoders/ParamEncoder.ts +29 -29
  162. package/src/utils/paramcoders/SchemaVerifier.ts +96 -96
  163. package/src/utils/paramcoders/server/ServerParamDecoder.ts +118 -118
  164. package/src/utils/paramcoders/server/ServerParamEncoder.ts +75 -75
  165. package/src/wallets/IBitcoinWallet.ts +68 -68
  166. package/src/wallets/ILightningWallet.ts +178 -178
  167. package/src/wallets/ISpvVaultSigner.ts +10 -10
  168. package/dist/wallets/ISpvVaultWallet.d.ts +0 -42
  169. package/dist/wallets/ISpvVaultWallet.js +0 -2
@@ -1,364 +1,397 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SpvVaults = exports.VAULT_DUST_AMOUNT = void 0;
4
- const SpvVault_1 = require("./SpvVault");
5
- const Utils_1 = require("../../utils/Utils");
6
- const PluginManager_1 = require("../../plugins/PluginManager");
7
- const AmountAssertions_1 = require("../assertions/AmountAssertions");
8
- const btc_signer_1 = require("@scure/btc-signer");
9
- exports.VAULT_DUST_AMOUNT = 600;
10
- const VAULT_INIT_CONFIRMATIONS = 2;
11
- const BTC_FINALIZATION_CONFIRMATIONS = 6;
12
- class SpvVaults {
13
- constructor(vaultStorage, bitcoin, vaultSigner, bitcoinRpc, getChain, config) {
14
- this.logger = (0, Utils_1.getLogger)("SpvVaults: ");
15
- this.vaultStorage = vaultStorage;
16
- this.bitcoin = bitcoin;
17
- this.vaultSigner = vaultSigner;
18
- this.bitcoinRpc = bitcoinRpc;
19
- this.getChain = getChain;
20
- this.config = config;
21
- }
22
- async processDepositEvent(vault, event) {
23
- vault.update(event);
24
- await this.saveVault(vault);
25
- }
26
- async processOpenEvent(vault, event) {
27
- if (vault.state === SpvVault_1.SpvVaultState.BTC_CONFIRMED) {
28
- vault.state = SpvVault_1.SpvVaultState.OPENED;
29
- }
30
- vault.update(event);
31
- await this.saveVault(vault);
32
- }
33
- async processCloseEvent(vault, event) {
34
- if (vault.state === SpvVault_1.SpvVaultState.OPENED) {
35
- vault.state = SpvVault_1.SpvVaultState.CLOSED;
36
- }
37
- vault.update(event);
38
- await this.saveVault(vault);
39
- }
40
- async processClaimEvent(vault, swap, event) {
41
- //Update vault
42
- const foundPendingWithdrawal = vault.pendingWithdrawals.findIndex(val => val.btcTx.txid === event.btcTxId);
43
- if (foundPendingWithdrawal !== -1)
44
- vault.pendingWithdrawals.splice(foundPendingWithdrawal, 1);
45
- vault.update(event);
46
- await this.saveVault(vault);
47
- }
48
- async createVaults(chainId, count, token, confirmations = 2, feeRate) {
49
- const { signer, chainInterface, tokenMultipliers, spvVaultContract } = this.getChain(chainId);
50
- const signerAddress = signer.getAddress();
51
- //Check vaultId of the latest saved vault
52
- let latestVaultId = -1n;
53
- for (let key in this.vaultStorage.data) {
54
- const vault = this.vaultStorage.data[key];
55
- if (vault.chainId !== chainId)
56
- continue;
57
- if (vault.data.getOwner() !== signerAddress)
58
- continue;
59
- if (vault.data.getVaultId() > latestVaultId)
60
- latestVaultId = vault.data.getVaultId();
61
- }
62
- latestVaultId++;
63
- const vaultAddreses = [];
64
- for (let i = 0; i < count; i++) {
65
- const vaultId = latestVaultId + BigInt(i);
66
- const address = await this.vaultSigner.getAddress(chainId, vaultId);
67
- vaultAddreses.push({ vaultId, address });
68
- }
69
- //Construct transaction
70
- const txResult = await this.bitcoin.getSignedMultiTransaction(vaultAddreses.map(val => {
71
- return { address: val.address, amount: exports.VAULT_DUST_AMOUNT };
72
- }), feeRate);
73
- const nativeToken = chainInterface.getNativeCurrencyAddress();
74
- const vaults = await Promise.all(vaultAddreses.map(async (val, index) => {
75
- const vaultData = await spvVaultContract.createVaultData(signerAddress, val.vaultId, txResult.txId + ":" + index, confirmations, [
76
- { token, multiplier: tokenMultipliers?.[token] ?? 1n },
77
- { token: nativeToken, multiplier: tokenMultipliers?.[nativeToken] ?? 1n }
78
- ]);
79
- return new SpvVault_1.SpvVault(chainId, vaultData, val.address);
80
- }));
81
- //Save vaults
82
- if (this.vaultStorage.saveDataArr != null) {
83
- await this.vaultStorage.saveDataArr(vaults.map(val => {
84
- return { id: val.getIdentifier(), object: val };
85
- }));
86
- }
87
- else {
88
- for (let vault of vaults) {
89
- await this.vaultStorage.saveData(vault.getIdentifier(), vault);
90
- }
91
- }
92
- //Send bitcoin tx
93
- await this.bitcoin.sendRawTransaction(txResult.raw);
94
- this.logger.info("createVaults(): Funding " + count + " vaults, bitcoin txId: " + txResult.txId);
95
- return {
96
- vaultsCreated: vaults.map(val => val.data.getVaultId()),
97
- btcTxId: txResult.txId
98
- };
99
- }
100
- async listVaults(chainId, token) {
101
- return Object.keys(this.vaultStorage.data)
102
- .map(key => this.vaultStorage.data[key])
103
- .filter(val => chainId == null ? true : val.chainId === chainId)
104
- .filter(val => val.data.getOwner() === this.getChain(val.chainId)?.signer?.getAddress())
105
- .filter(val => token == null ? true : val.data.getTokenData()[0].token === token);
106
- }
107
- async fundVault(vault, tokenAmounts) {
108
- if (vault.state !== SpvVault_1.SpvVaultState.OPENED)
109
- throw new Error("Vault not opened!");
110
- this.logger.info("fundVault(): Depositing tokens to the vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", "));
111
- const { signer, spvVaultContract } = this.getChain(vault.chainId);
112
- const txId = await spvVaultContract.deposit(signer, vault.data, tokenAmounts, { waitForConfirmation: true });
113
- this.logger.info("fundVault(): Tokens deposited to vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", ") + ", txId: " + txId);
114
- return txId;
115
- }
116
- async withdrawFromVault(vault, tokenAmounts, feeRate) {
117
- tokenAmounts.forEach((rawAmount, index) => {
118
- if (vault.balances[index] == null)
119
- throw new Error("Token not found in the vault");
120
- if (vault.balances[index].rawAmount < rawAmount)
121
- throw new Error("Not enough balance in the vault");
122
- });
123
- if (!vault.isReady())
124
- throw new Error("Vault not ready, wait for the latest swap to get at least 1 confirmation!");
125
- const { signer, spvVaultContract } = this.getChain(vault.chainId);
126
- const latestUtxo = vault.getLatestUtxo();
127
- const [txId, voutStr] = latestUtxo.split(":");
128
- const opReturnData = spvVaultContract.toOpReturnData(signer.getAddress(), tokenAmounts);
129
- let opReturnScript;
130
- if (opReturnData.length < 76) {
131
- opReturnScript = Buffer.concat([
132
- Buffer.from([0x6a, opReturnData.length]),
133
- opReturnData
134
- ]);
135
- }
136
- else {
137
- opReturnScript = Buffer.concat([
138
- Buffer.from([0x6a, 0x4c, opReturnData.length]),
139
- opReturnData
140
- ]);
141
- }
142
- let psbt = new btc_signer_1.Transaction({
143
- allowUnknownOutputs: true
144
- });
145
- psbt.addInput({
146
- txid: txId,
147
- index: parseInt(voutStr),
148
- witnessUtxo: {
149
- amount: BigInt(exports.VAULT_DUST_AMOUNT),
150
- script: this.bitcoin.toOutputScript(vault.btcAddress)
151
- }
152
- });
153
- psbt.addOutput({
154
- amount: BigInt(exports.VAULT_DUST_AMOUNT),
155
- script: this.bitcoin.toOutputScript(vault.btcAddress)
156
- });
157
- psbt.addOutput({
158
- amount: 0n,
159
- script: opReturnScript
160
- });
161
- psbt = await this.bitcoin.fundPsbt(psbt, feeRate);
162
- if (psbt.inputsLength < 2)
163
- throw new Error("PSBT needs at least 2 inputs!");
164
- psbt.updateInput(0, { sequence: 0x80000000 });
165
- psbt.updateInput(1, { sequence: 0x80000000 });
166
- psbt = await this.vaultSigner.signPsbt(vault.chainId, vault.data.getVaultId(), psbt, [0]);
167
- const res = await this.bitcoin.signPsbt(psbt);
168
- const parsedTransaction = await this.bitcoinRpc.parseTransaction(res.raw);
169
- const withdrawalData = await spvVaultContract.getWithdrawalData(parsedTransaction);
170
- if (withdrawalData.getSpentVaultUtxo() !== vault.getLatestUtxo()) {
171
- throw new Error("Latest vault UTXO already spent! Please try again later.");
172
- }
173
- vault.addWithdrawal(withdrawalData);
174
- await this.saveVault(vault);
175
- try {
176
- await this.bitcoin.sendRawTransaction(res.raw);
177
- }
178
- catch (e) {
179
- vault.removeWithdrawal(withdrawalData);
180
- await this.saveVault(vault);
181
- throw e;
182
- }
183
- return res.txId;
184
- }
185
- async checkVaults() {
186
- const vaults = Object.keys(this.vaultStorage.data).map(key => this.vaultStorage.data[key]);
187
- const claimWithdrawals = [];
188
- for (let vault of vaults) {
189
- const { signer, spvVaultContract, chainInterface } = this.getChain(vault.chainId);
190
- if (vault.data.getOwner() !== signer.getAddress())
191
- continue;
192
- if (vault.state === SpvVault_1.SpvVaultState.BTC_INITIATED) {
193
- //Check if btc tx confirmed
194
- const txId = vault.initialUtxo.split(":")[0];
195
- const btcTx = await this.bitcoinRpc.getTransaction(txId);
196
- if (btcTx.confirmations >= VAULT_INIT_CONFIRMATIONS) {
197
- //Double-check the state here to prevent race condition
198
- if (vault.state === SpvVault_1.SpvVaultState.BTC_INITIATED) {
199
- vault.state = SpvVault_1.SpvVaultState.BTC_CONFIRMED;
200
- await this.saveVault(vault);
201
- }
202
- this.logger.info("checkVaults(): Vault ID " + vault.data.getVaultId().toString(10) + " confirmed on bitcoin, opening vault on " + vault.chainId);
203
- }
204
- }
205
- if (vault.state === SpvVault_1.SpvVaultState.BTC_CONFIRMED) {
206
- //Check if open txs were sent already
207
- if (vault.scOpenTx != null) {
208
- //Check if confirmed
209
- const status = await chainInterface.getTxStatus(vault.scOpenTx.rawTx);
210
- if (status === "pending")
211
- return;
212
- if (status === "success") {
213
- vault.state = SpvVault_1.SpvVaultState.OPENED;
214
- await this.saveVault(vault);
215
- return;
216
- }
217
- }
218
- const txs = await spvVaultContract.txsOpen(signer.getAddress(), vault.data);
219
- let numTx = 0;
220
- const txIds = await chainInterface.sendAndConfirm(signer, txs, true, undefined, false, async (txId, rawTx) => {
221
- numTx++;
222
- if (numTx === txs.length) {
223
- //Final tx
224
- vault.scOpenTx = { txId, rawTx };
225
- await this.saveVault(vault);
226
- }
227
- });
228
- this.logger.info("checkVaults(): Vault ID " + vault.data.getVaultId().toString(10) + " opened on " + vault.chainId + " txId: " + txIds.join(", "));
229
- vault.state = SpvVault_1.SpvVaultState.OPENED;
230
- await this.saveVault(vault);
231
- }
232
- if (vault.state === SpvVault_1.SpvVaultState.OPENED) {
233
- let changed = false;
234
- //Check if some of the pendingWithdrawals got confirmed
235
- let latestOwnWithdrawalIndex = -1;
236
- let latestConfirmedWithdrawalIndex = -1;
237
- for (let i = 0; i < vault.pendingWithdrawals.length; i++) {
238
- const pendingWithdrawal = vault.pendingWithdrawals[i];
239
- //Check all the pending withdrawals that were not finalized yet
240
- if (pendingWithdrawal.btcTx.confirmations == null || pendingWithdrawal.btcTx.confirmations < BTC_FINALIZATION_CONFIRMATIONS) {
241
- const btcTx = await this.bitcoinRpc.getTransaction(pendingWithdrawal.btcTx.txid);
242
- if (btcTx == null) {
243
- //Probable double-spend, remove from pending withdrawals
244
- const index = vault.pendingWithdrawals.indexOf(pendingWithdrawal);
245
- if (index === -1) {
246
- this.logger.warn("checkVaults(): Tried to remove pending withdrawal txId: " + pendingWithdrawal.btcTx.txid + ", but doesn't exist anymore!");
247
- }
248
- else {
249
- vault.pendingWithdrawals.splice(index, 1);
250
- }
251
- changed = true;
252
- }
253
- else {
254
- //Update confirmations count
255
- if (pendingWithdrawal.btcTx.confirmations !== btcTx.confirmations ||
256
- pendingWithdrawal.btcTx.blockhash !== btcTx.blockhash) {
257
- pendingWithdrawal.btcTx.confirmations = btcTx.confirmations;
258
- pendingWithdrawal.btcTx.blockhash = btcTx.blockhash;
259
- changed = true;
260
- }
261
- }
262
- }
263
- //Check it has enough confirmations
264
- if (pendingWithdrawal.btcTx.confirmations >= vault.data.getConfirmations()) {
265
- latestConfirmedWithdrawalIndex = i;
266
- //Check if the pending withdrawals contain a withdrawal to our own address
267
- if (pendingWithdrawal.isRecipient(signer.getAddress())) {
268
- latestOwnWithdrawalIndex = i;
269
- }
270
- }
271
- }
272
- if (changed) {
273
- await this.saveVault(vault);
274
- }
275
- if (this.config.maxUnclaimedWithdrawals != null && latestConfirmedWithdrawalIndex + 1 >= this.config.maxUnclaimedWithdrawals) {
276
- this.logger.info("checkVaults(): Processing withdrawals by self, because a lot of them are unclaimed!");
277
- claimWithdrawals.push({ vault, withdrawals: vault.pendingWithdrawals.slice(0, latestConfirmedWithdrawalIndex + 1) });
278
- }
279
- else if (latestOwnWithdrawalIndex !== -1) {
280
- claimWithdrawals.push({ vault, withdrawals: vault.pendingWithdrawals.slice(0, latestOwnWithdrawalIndex + 1) });
281
- }
282
- }
283
- }
284
- for (let { vault, withdrawals } of claimWithdrawals) {
285
- if (!await this.claimWithdrawals(vault, withdrawals)) {
286
- this.logger.error("checkVaults(): Cannot process withdrawals " + withdrawals.map(val => val.btcTx.txid).join(", ") + " for vault: " + vault.data.getVaultId());
287
- break;
288
- }
289
- }
290
- }
291
- async claimWithdrawals(vault, withdrawal) {
292
- const { signer, spvVaultContract } = this.getChain(vault.chainId);
293
- try {
294
- const txId = await spvVaultContract.claim(signer, vault.data, withdrawal.map(tx => {
295
- return { tx };
296
- }), undefined, true, { waitForConfirmation: true });
297
- this.logger.info("claimWithdrawal(): Successfully claimed withdrawals, btcTxIds: " + withdrawal.map(val => val.btcTx.txid).join(", ") + " smartChainTxId: " + txId);
298
- return true;
299
- }
300
- catch (e) {
301
- this.logger.error("claimWithdrawal(): Tried to claim but got error: ", e);
302
- return false;
303
- }
304
- }
305
- async getVault(chainId, owner, vaultId) {
306
- return this.vaultStorage.data[chainId + "_" + owner + "_" + vaultId.toString(10)];
307
- }
308
- /**
309
- * Returns a ready-to-use vault for a specific request
310
- *
311
- * @param chainIdentifier
312
- * @param totalSats
313
- * @param token
314
- * @param amount
315
- * @param gasToken
316
- * @param gasTokenAmount
317
- * @protected
318
- */
319
- async findVaultForSwap(chainIdentifier, totalSats, token, amount, gasToken, gasTokenAmount) {
320
- const { signer } = this.getChain(chainIdentifier);
321
- const pluginResponse = await PluginManager_1.PluginManager.onVaultSelection(chainIdentifier, totalSats, { token, amount }, { token: gasToken, amount: gasTokenAmount });
322
- if (pluginResponse != null) {
323
- AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(pluginResponse);
324
- return pluginResponse;
325
- }
326
- const candidates = Object.keys(this.vaultStorage.data)
327
- .map(key => this.vaultStorage.data[key])
328
- .filter(vault => vault.chainId === chainIdentifier && vault.data.getOwner() === signer.getAddress() && vault.isReady())
329
- .filter(vault => {
330
- const token0 = vault.balances[0];
331
- if (token0.token !== token || token0.scaledAmount < amount)
332
- return false;
333
- if (gasToken != null && gasTokenAmount !== 0n) {
334
- const token1 = vault.balances[1];
335
- if (token1.token !== gasToken || token1.scaledAmount < gasTokenAmount)
336
- return false;
337
- }
338
- return true;
339
- });
340
- candidates.sort((a, b) => (0, Utils_1.bigIntSorter)(a.balances[0].scaledAmount, b.balances[0].scaledAmount));
341
- const result = candidates[0];
342
- if (result == null)
343
- throw {
344
- code: 20301,
345
- msg: "No suitable swap vault found, try again later!"
346
- };
347
- return result;
348
- }
349
- saveVault(vault) {
350
- return this.vaultStorage.saveData(vault.getIdentifier(), vault);
351
- }
352
- async startVaultsWatchdog() {
353
- let rerun;
354
- rerun = async () => {
355
- await this.checkVaults().catch(e => this.logger.error("startVaultsWatchdog(): Error when periodically checking SPV vaults: ", e));
356
- setTimeout(rerun, this.config.vaultsCheckInterval);
357
- };
358
- await rerun();
359
- }
360
- async init() {
361
- const vaults = await this.vaultStorage.loadData(SpvVault_1.SpvVault);
362
- }
363
- }
364
- exports.SpvVaults = SpvVaults;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpvVaults = exports.VAULT_DUST_AMOUNT = void 0;
4
+ const SpvVault_1 = require("./SpvVault");
5
+ const Utils_1 = require("../../utils/Utils");
6
+ const PluginManager_1 = require("../../plugins/PluginManager");
7
+ const AmountAssertions_1 = require("../assertions/AmountAssertions");
8
+ const btc_signer_1 = require("@scure/btc-signer");
9
+ const BitcoinUtils_1 = require("../../utils/BitcoinUtils");
10
+ exports.VAULT_DUST_AMOUNT = 600;
11
+ const VAULT_INIT_CONFIRMATIONS = 2;
12
+ const MAX_PARALLEL_VAULTS_OPENING = 10;
13
+ class SpvVaults {
14
+ constructor(vaultStorage, bitcoin, vaultSigner, bitcoinRpc, chains, config) {
15
+ this.logger = (0, Utils_1.getLogger)("SpvVaults: ");
16
+ this.vaultStorage = vaultStorage;
17
+ this.bitcoin = bitcoin;
18
+ this.vaultSigner = vaultSigner;
19
+ this.bitcoinRpc = bitcoinRpc;
20
+ this.chains = chains;
21
+ this.config = config;
22
+ for (let chainId in chains.chains) {
23
+ const { chainInterface } = chains.chains[chainId];
24
+ chainInterface.onBeforeTxReplace(async (oldTx, oldTxId, newTx, newTxId) => {
25
+ for (let key in this.vaultStorage.data) {
26
+ const vaultData = this.vaultStorage.data[key];
27
+ if (vaultData.scOpenTxs != null && vaultData.scOpenTxs[oldTxId] != null) {
28
+ vaultData.scOpenTxs[newTxId] = newTx;
29
+ await this.saveVault(vaultData);
30
+ break;
31
+ }
32
+ }
33
+ });
34
+ }
35
+ }
36
+ async processDepositEvent(vault, event) {
37
+ vault.update(event);
38
+ await this.saveVault(vault);
39
+ }
40
+ async processOpenEvent(vault, event) {
41
+ if (vault.state === SpvVault_1.SpvVaultState.BTC_CONFIRMED) {
42
+ vault.state = SpvVault_1.SpvVaultState.OPENED;
43
+ }
44
+ vault.update(event);
45
+ await this.saveVault(vault);
46
+ }
47
+ async processCloseEvent(vault, event) {
48
+ if (vault.state === SpvVault_1.SpvVaultState.OPENED) {
49
+ vault.state = SpvVault_1.SpvVaultState.CLOSED;
50
+ }
51
+ vault.update(event);
52
+ await this.saveVault(vault);
53
+ }
54
+ async processClaimEvent(vault, swap, event) {
55
+ //Update vault
56
+ const foundPendingWithdrawal = vault.pendingWithdrawals.findIndex(val => val.btcTx.txid === event.btcTxId);
57
+ if (foundPendingWithdrawal !== -1)
58
+ vault.pendingWithdrawals.splice(foundPendingWithdrawal, 1);
59
+ vault.update(event);
60
+ await this.saveVault(vault);
61
+ }
62
+ async createVaults(chainId, count, token, confirmations = 2, feeRate) {
63
+ const { signer, chainInterface, tokenMultipliers, spvVaultContract } = this.chains.chains[chainId];
64
+ const signerAddress = signer.getAddress();
65
+ //Check vaultId of the latest saved vault
66
+ let latestVaultId = -1n;
67
+ for (let key in this.vaultStorage.data) {
68
+ const vault = this.vaultStorage.data[key];
69
+ if (vault.chainId !== chainId)
70
+ continue;
71
+ if (vault.data.getOwner() !== signerAddress)
72
+ continue;
73
+ if (vault.data.getVaultId() > latestVaultId)
74
+ latestVaultId = vault.data.getVaultId();
75
+ }
76
+ latestVaultId++;
77
+ const vaultAddreses = [];
78
+ for (let i = 0; i < count; i++) {
79
+ const vaultId = latestVaultId + BigInt(i);
80
+ const address = await this.vaultSigner.getAddress(chainId, vaultId);
81
+ vaultAddreses.push({ vaultId, address });
82
+ }
83
+ //Construct transaction
84
+ const txResult = await this.bitcoin.getSignedMultiTransaction(vaultAddreses.map(val => {
85
+ return { address: val.address, amount: exports.VAULT_DUST_AMOUNT };
86
+ }), feeRate);
87
+ const nativeToken = chainInterface.getNativeCurrencyAddress();
88
+ const vaults = await Promise.all(vaultAddreses.map(async (val, index) => {
89
+ const vaultData = await spvVaultContract.createVaultData(signerAddress, val.vaultId, txResult.txId + ":" + index, confirmations, [
90
+ { token, multiplier: tokenMultipliers?.[token] ?? 1n },
91
+ { token: nativeToken, multiplier: tokenMultipliers?.[nativeToken] ?? 1n }
92
+ ]);
93
+ return new SpvVault_1.SpvVault(chainId, vaultData, val.address);
94
+ }));
95
+ //Save vaults
96
+ if (this.vaultStorage.saveDataArr != null) {
97
+ await this.vaultStorage.saveDataArr(vaults.map(val => {
98
+ return { id: val.getIdentifier(), object: val };
99
+ }));
100
+ }
101
+ else {
102
+ for (let vault of vaults) {
103
+ await this.vaultStorage.saveData(vault.getIdentifier(), vault);
104
+ }
105
+ }
106
+ //Send bitcoin tx
107
+ await this.bitcoin.sendRawTransaction(txResult.raw);
108
+ this.logger.info("createVaults(): Funding " + count + " vaults, bitcoin txId: " + txResult.txId);
109
+ return {
110
+ vaultsCreated: vaults.map(val => val.data.getVaultId()),
111
+ btcTxId: txResult.txId
112
+ };
113
+ }
114
+ async listVaults(chainId, token) {
115
+ return Object.keys(this.vaultStorage.data)
116
+ .map(key => this.vaultStorage.data[key])
117
+ .filter(val => chainId == null ? true : val.chainId === chainId)
118
+ .filter(val => val.data.getOwner() === this.chains.chains[val.chainId]?.signer?.getAddress())
119
+ .filter(val => token == null ? true : val.data.getTokenData()[0].token === token);
120
+ }
121
+ async fundVault(vault, tokenAmounts) {
122
+ if (vault.state !== SpvVault_1.SpvVaultState.OPENED)
123
+ throw new Error("Vault not opened!");
124
+ this.logger.info("fundVault(): Depositing tokens to the vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", "));
125
+ const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
126
+ const txId = await spvVaultContract.deposit(signer, vault.data, tokenAmounts, { waitForConfirmation: true });
127
+ this.logger.info("fundVault(): Tokens deposited to vault " + vault.data.getVaultId().toString(10) + ", amounts: " + tokenAmounts.map(val => val.toString(10)).join(", ") + ", txId: " + txId);
128
+ return txId;
129
+ }
130
+ async withdrawFromVault(vault, tokenAmounts, feeRate) {
131
+ tokenAmounts.forEach((rawAmount, index) => {
132
+ if (vault.balances[index] == null)
133
+ throw new Error("Token not found in the vault");
134
+ if (vault.balances[index].rawAmount < rawAmount)
135
+ throw new Error("Not enough balance in the vault");
136
+ });
137
+ if (!vault.isReady())
138
+ throw new Error("Vault not ready, wait for the latest swap to get at least 1 confirmation!");
139
+ const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
140
+ const latestUtxo = vault.getLatestUtxo();
141
+ const [txId, voutStr] = latestUtxo.split(":");
142
+ const opReturnData = spvVaultContract.toOpReturnData(signer.getAddress(), tokenAmounts);
143
+ let opReturnScript;
144
+ if (opReturnData.length < 76) {
145
+ opReturnScript = Buffer.concat([
146
+ Buffer.from([0x6a, opReturnData.length]),
147
+ opReturnData
148
+ ]);
149
+ }
150
+ else {
151
+ opReturnScript = Buffer.concat([
152
+ Buffer.from([0x6a, 0x4c, opReturnData.length]),
153
+ opReturnData
154
+ ]);
155
+ }
156
+ let psbt = new btc_signer_1.Transaction({
157
+ allowUnknownOutputs: true
158
+ });
159
+ psbt.addInput({
160
+ txid: txId,
161
+ index: parseInt(voutStr),
162
+ witnessUtxo: {
163
+ amount: BigInt(exports.VAULT_DUST_AMOUNT),
164
+ script: this.bitcoin.toOutputScript(vault.btcAddress)
165
+ }
166
+ });
167
+ psbt.addOutput({
168
+ amount: BigInt(exports.VAULT_DUST_AMOUNT),
169
+ script: this.bitcoin.toOutputScript(vault.btcAddress)
170
+ });
171
+ psbt.addOutput({
172
+ amount: 0n,
173
+ script: opReturnScript
174
+ });
175
+ psbt = await this.bitcoin.fundPsbt(psbt, feeRate);
176
+ if (psbt.inputsLength < 2)
177
+ throw new Error("PSBT needs at least 2 inputs!");
178
+ psbt.updateInput(0, { sequence: 0x80000000 });
179
+ psbt.updateInput(1, { sequence: 0x80000000 });
180
+ psbt = await this.vaultSigner.signPsbt(vault.chainId, vault.data.getVaultId(), psbt, [0]);
181
+ const res = await this.bitcoin.signPsbt(psbt);
182
+ const parsedTransaction = await this.bitcoinRpc.parseTransaction(res.raw);
183
+ const withdrawalData = await spvVaultContract.getWithdrawalData(parsedTransaction);
184
+ if (withdrawalData.getSpentVaultUtxo() !== vault.getLatestUtxo()) {
185
+ throw new Error("Latest vault UTXO already spent! Please try again later.");
186
+ }
187
+ withdrawalData.sending = true;
188
+ vault.addWithdrawal(withdrawalData);
189
+ await this.saveVault(vault);
190
+ try {
191
+ await this.bitcoin.sendRawTransaction(res.raw);
192
+ withdrawalData.sending = false;
193
+ }
194
+ catch (e) {
195
+ withdrawalData.sending = false;
196
+ vault.removeWithdrawal(withdrawalData);
197
+ await this.saveVault(vault);
198
+ throw e;
199
+ }
200
+ return res.txId;
201
+ }
202
+ async checkVaults() {
203
+ const vaults = Object.keys(this.vaultStorage.data).map(key => this.vaultStorage.data[key]);
204
+ const claimWithdrawals = [];
205
+ let promises = [];
206
+ for (let vault of vaults) {
207
+ const { signer, spvVaultContract, chainInterface } = this.chains.chains[vault.chainId];
208
+ if (vault.data.getOwner() !== signer.getAddress())
209
+ continue;
210
+ if (vault.state === SpvVault_1.SpvVaultState.BTC_INITIATED) {
211
+ //Check if btc tx confirmed
212
+ const txId = vault.initialUtxo.split(":")[0];
213
+ const btcTx = await this.bitcoinRpc.getTransaction(txId);
214
+ if (btcTx.confirmations >= VAULT_INIT_CONFIRMATIONS) {
215
+ //Double-check the state here to prevent race condition
216
+ if (vault.state === SpvVault_1.SpvVaultState.BTC_INITIATED) {
217
+ vault.state = SpvVault_1.SpvVaultState.BTC_CONFIRMED;
218
+ await this.saveVault(vault);
219
+ }
220
+ this.logger.info("checkVaults(): Vault ID " + vault.data.getVaultId().toString(10) + " confirmed on bitcoin, opening vault on " + vault.chainId);
221
+ }
222
+ }
223
+ if (vault.state === SpvVault_1.SpvVaultState.BTC_CONFIRMED) {
224
+ //Check if open txs were sent already
225
+ if (vault.scOpenTxs != null) {
226
+ //Check if confirmed
227
+ let _continue = false;
228
+ for (let txId in vault.scOpenTxs) {
229
+ const tx = vault.scOpenTxs[txId];
230
+ const status = await chainInterface.getTxStatus(tx);
231
+ if (status === "pending") {
232
+ _continue = true;
233
+ break;
234
+ }
235
+ if (status === "success") {
236
+ vault.state = SpvVault_1.SpvVaultState.OPENED;
237
+ await this.saveVault(vault);
238
+ _continue = true;
239
+ break;
240
+ }
241
+ }
242
+ if (_continue)
243
+ continue;
244
+ }
245
+ const txs = await spvVaultContract.txsOpen(signer.getAddress(), vault.data);
246
+ let numTx = 0;
247
+ promises.push(chainInterface.sendAndConfirm(signer, txs, true, undefined, true, async (txId, rawTx) => {
248
+ numTx++;
249
+ if (numTx === txs.length) {
250
+ //Final tx
251
+ vault.scOpenTxs = { [txId]: rawTx };
252
+ await this.saveVault(vault);
253
+ }
254
+ }).then(txIds => {
255
+ this.logger.info("checkVaults(): Vault ID " + vault.data.getVaultId().toString(10) + " opened on " + vault.chainId + " txId: " + txIds.join(", "));
256
+ vault.state = SpvVault_1.SpvVaultState.OPENED;
257
+ return this.saveVault(vault);
258
+ }));
259
+ if (promises.length >= MAX_PARALLEL_VAULTS_OPENING) {
260
+ await Promise.all(promises);
261
+ promises = [];
262
+ }
263
+ continue;
264
+ }
265
+ if (vault.state === SpvVault_1.SpvVaultState.OPENED) {
266
+ let changed = false;
267
+ //Check if some of the pendingWithdrawals got confirmed
268
+ let latestOwnWithdrawalIndex = -1;
269
+ let latestConfirmedWithdrawalIndex = -1;
270
+ for (let i = 0; i < vault.pendingWithdrawals.length; i++) {
271
+ const pendingWithdrawal = vault.pendingWithdrawals[i];
272
+ if (pendingWithdrawal.sending)
273
+ continue;
274
+ //Check all the pending withdrawals that were not finalized yet
275
+ const btcTx = await (0, BitcoinUtils_1.checkTransactionReplacedRpc)(pendingWithdrawal.btcTx.txid, pendingWithdrawal.btcTx.raw, this.bitcoinRpc);
276
+ if (btcTx == null) {
277
+ //Probable double-spend, remove from pending withdrawals
278
+ const index = vault.pendingWithdrawals.indexOf(pendingWithdrawal);
279
+ if (index === -1) {
280
+ this.logger.warn("checkVaults(): Tried to remove pending withdrawal txId: " + pendingWithdrawal.btcTx.txid + ", but doesn't exist anymore!");
281
+ }
282
+ else {
283
+ vault.pendingWithdrawals.splice(index, 1);
284
+ }
285
+ changed = true;
286
+ }
287
+ else {
288
+ //Update confirmations count
289
+ if (pendingWithdrawal.btcTx.confirmations !== btcTx.confirmations ||
290
+ pendingWithdrawal.btcTx.blockhash !== btcTx.blockhash) {
291
+ pendingWithdrawal.btcTx.confirmations = btcTx.confirmations;
292
+ pendingWithdrawal.btcTx.blockhash = btcTx.blockhash;
293
+ changed = true;
294
+ }
295
+ }
296
+ //Check it has enough confirmations
297
+ if (pendingWithdrawal.btcTx.confirmations >= vault.data.getConfirmations()) {
298
+ latestConfirmedWithdrawalIndex = i;
299
+ //Check if the pending withdrawals contain a withdrawal to our own address
300
+ if (pendingWithdrawal.isRecipient(signer.getAddress())) {
301
+ latestOwnWithdrawalIndex = i;
302
+ }
303
+ }
304
+ }
305
+ if (changed) {
306
+ await this.saveVault(vault);
307
+ }
308
+ if (this.config.maxUnclaimedWithdrawals != null && latestConfirmedWithdrawalIndex + 1 >= this.config.maxUnclaimedWithdrawals) {
309
+ this.logger.info("checkVaults(): Processing withdrawals by self, because a lot of them are unclaimed!");
310
+ claimWithdrawals.push({ vault, withdrawals: vault.pendingWithdrawals.slice(0, latestConfirmedWithdrawalIndex + 1) });
311
+ }
312
+ else if (latestOwnWithdrawalIndex !== -1) {
313
+ claimWithdrawals.push({ vault, withdrawals: vault.pendingWithdrawals.slice(0, latestOwnWithdrawalIndex + 1) });
314
+ }
315
+ }
316
+ }
317
+ for (let { vault, withdrawals } of claimWithdrawals) {
318
+ if (!await this.claimWithdrawals(vault, withdrawals)) {
319
+ this.logger.error("checkVaults(): Cannot process withdrawals " + withdrawals.map(val => val.btcTx.txid).join(", ") + " for vault: " + vault.data.getVaultId());
320
+ break;
321
+ }
322
+ }
323
+ }
324
+ async claimWithdrawals(vault, withdrawal) {
325
+ const { signer, spvVaultContract } = this.chains.chains[vault.chainId];
326
+ try {
327
+ const txId = await spvVaultContract.claim(signer, vault.data, withdrawal.map(tx => {
328
+ return { tx };
329
+ }), undefined, true, { waitForConfirmation: true });
330
+ this.logger.info("claimWithdrawal(): Successfully claimed withdrawals, btcTxIds: " + withdrawal.map(val => val.btcTx.txid).join(", ") + " smartChainTxId: " + txId);
331
+ return true;
332
+ }
333
+ catch (e) {
334
+ this.logger.error("claimWithdrawal(): Tried to claim but got error: ", e);
335
+ return false;
336
+ }
337
+ }
338
+ async getVault(chainId, owner, vaultId) {
339
+ return this.vaultStorage.data[chainId + "_" + owner + "_" + vaultId.toString(10)];
340
+ }
341
+ /**
342
+ * Returns a ready-to-use vault for a specific request
343
+ *
344
+ * @param chainIdentifier
345
+ * @param totalSats
346
+ * @param token
347
+ * @param amount
348
+ * @param gasToken
349
+ * @param gasTokenAmount
350
+ * @protected
351
+ */
352
+ async findVaultForSwap(chainIdentifier, totalSats, token, amount, gasToken, gasTokenAmount) {
353
+ const { signer } = this.chains.chains[chainIdentifier];
354
+ const pluginResponse = await PluginManager_1.PluginManager.onVaultSelection(chainIdentifier, totalSats, { token, amount }, { token: gasToken, amount: gasTokenAmount });
355
+ if (pluginResponse != null) {
356
+ AmountAssertions_1.AmountAssertions.handlePluginErrorResponses(pluginResponse);
357
+ return pluginResponse;
358
+ }
359
+ const candidates = Object.keys(this.vaultStorage.data)
360
+ .map(key => this.vaultStorage.data[key])
361
+ .filter(vault => vault.chainId === chainIdentifier && vault.data.getOwner() === signer.getAddress() && vault.isReady())
362
+ .filter(vault => {
363
+ const token0 = vault.balances[0];
364
+ if (token0.token !== token || token0.scaledAmount < amount)
365
+ return false;
366
+ if (gasToken != null && gasTokenAmount !== 0n) {
367
+ const token1 = vault.balances[1];
368
+ if (token1.token !== gasToken || token1.scaledAmount < gasTokenAmount)
369
+ return false;
370
+ }
371
+ return true;
372
+ });
373
+ candidates.sort((a, b) => (0, Utils_1.bigIntSorter)(a.balances[0].scaledAmount, b.balances[0].scaledAmount));
374
+ const result = candidates[0];
375
+ if (result == null)
376
+ throw {
377
+ code: 20301,
378
+ msg: "No suitable swap vault found, try again later!"
379
+ };
380
+ return result;
381
+ }
382
+ saveVault(vault) {
383
+ return this.vaultStorage.saveData(vault.getIdentifier(), vault);
384
+ }
385
+ async startVaultsWatchdog() {
386
+ let rerun;
387
+ rerun = async () => {
388
+ await this.checkVaults().catch(e => this.logger.error("startVaultsWatchdog(): Error when periodically checking SPV vaults: ", e));
389
+ setTimeout(rerun, this.config.vaultsCheckInterval);
390
+ };
391
+ await rerun();
392
+ }
393
+ async init() {
394
+ const vaults = await this.vaultStorage.loadData(SpvVault_1.SpvVault);
395
+ }
396
+ }
397
+ exports.SpvVaults = SpvVaults;