@atomiqlabs/chain-solana 13.5.13 → 13.5.14

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 (131) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +73 -73
  3. package/dist/index.d.ts +81 -81
  4. package/dist/index.js +102 -102
  5. package/dist/node/index.d.ts +9 -9
  6. package/dist/node/index.js +13 -13
  7. package/dist/solana/SolanaChainType.d.ts +15 -15
  8. package/dist/solana/SolanaChainType.js +2 -2
  9. package/dist/solana/SolanaChains.d.ts +12 -12
  10. package/dist/solana/SolanaChains.js +45 -45
  11. package/dist/solana/SolanaInitializer.d.ts +94 -94
  12. package/dist/solana/SolanaInitializer.js +174 -174
  13. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +222 -222
  14. package/dist/solana/btcrelay/SolanaBtcRelay.js +455 -455
  15. package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +84 -84
  16. package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +70 -70
  17. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +92 -92
  18. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +109 -109
  19. package/dist/solana/btcrelay/program/programIdl.json +671 -671
  20. package/dist/solana/chain/SolanaAction.d.ts +26 -26
  21. package/dist/solana/chain/SolanaAction.js +87 -87
  22. package/dist/solana/chain/SolanaChainInterface.d.ts +224 -224
  23. package/dist/solana/chain/SolanaChainInterface.js +275 -275
  24. package/dist/solana/chain/SolanaModule.d.ts +14 -14
  25. package/dist/solana/chain/SolanaModule.js +13 -13
  26. package/dist/solana/chain/modules/SolanaAddresses.d.ts +8 -8
  27. package/dist/solana/chain/modules/SolanaAddresses.js +22 -22
  28. package/dist/solana/chain/modules/SolanaBlocks.d.ts +32 -32
  29. package/dist/solana/chain/modules/SolanaBlocks.js +78 -78
  30. package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
  31. package/dist/solana/chain/modules/SolanaEvents.js +238 -238
  32. package/dist/solana/chain/modules/SolanaFees.d.ts +189 -189
  33. package/dist/solana/chain/modules/SolanaFees.js +434 -434
  34. package/dist/solana/chain/modules/SolanaSignatures.d.ts +24 -24
  35. package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
  36. package/dist/solana/chain/modules/SolanaSlots.d.ts +33 -33
  37. package/dist/solana/chain/modules/SolanaSlots.js +72 -72
  38. package/dist/solana/chain/modules/SolanaTokens.d.ts +123 -123
  39. package/dist/solana/chain/modules/SolanaTokens.js +242 -242
  40. package/dist/solana/chain/modules/SolanaTransactions.d.ts +149 -149
  41. package/dist/solana/chain/modules/SolanaTransactions.js +445 -445
  42. package/dist/solana/connection/ConnectionWithRetries.d.ts +35 -35
  43. package/dist/solana/connection/ConnectionWithRetries.js +86 -71
  44. package/dist/solana/events/SolanaChainEvents.d.ts +45 -45
  45. package/dist/solana/events/SolanaChainEvents.js +108 -108
  46. package/dist/solana/events/SolanaChainEventsBrowser.d.ts +205 -205
  47. package/dist/solana/events/SolanaChainEventsBrowser.js +404 -404
  48. package/dist/solana/program/SolanaProgramBase.d.ts +73 -73
  49. package/dist/solana/program/SolanaProgramBase.js +54 -54
  50. package/dist/solana/program/SolanaProgramModule.d.ts +8 -8
  51. package/dist/solana/program/SolanaProgramModule.js +11 -11
  52. package/dist/solana/program/modules/SolanaProgramEvents.d.ts +53 -53
  53. package/dist/solana/program/modules/SolanaProgramEvents.js +117 -117
  54. package/dist/solana/swaps/SolanaSwapData.d.ts +333 -333
  55. package/dist/solana/swaps/SolanaSwapData.js +535 -535
  56. package/dist/solana/swaps/SolanaSwapModule.d.ts +11 -11
  57. package/dist/solana/swaps/SolanaSwapModule.js +12 -12
  58. package/dist/solana/swaps/SolanaSwapProgram.d.ts +376 -376
  59. package/dist/solana/swaps/SolanaSwapProgram.js +769 -769
  60. package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
  61. package/dist/solana/swaps/SwapTypeEnum.js +43 -43
  62. package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +95 -95
  63. package/dist/solana/swaps/modules/SolanaDataAccount.js +232 -232
  64. package/dist/solana/swaps/modules/SolanaLpVault.d.ts +69 -69
  65. package/dist/solana/swaps/modules/SolanaLpVault.js +171 -171
  66. package/dist/solana/swaps/modules/SwapClaim.d.ts +126 -126
  67. package/dist/solana/swaps/modules/SwapClaim.js +294 -294
  68. package/dist/solana/swaps/modules/SwapInit.d.ts +213 -213
  69. package/dist/solana/swaps/modules/SwapInit.js +658 -658
  70. package/dist/solana/swaps/modules/SwapRefund.d.ts +87 -87
  71. package/dist/solana/swaps/modules/SwapRefund.js +293 -293
  72. package/dist/solana/swaps/programIdl.json +945 -945
  73. package/dist/solana/swaps/programTypes.d.ts +943 -943
  74. package/dist/solana/swaps/programTypes.js +945 -945
  75. package/dist/solana/swaps/v1/programIdl.json +945 -945
  76. package/dist/solana/swaps/v1/programTypes.d.ts +943 -943
  77. package/dist/solana/swaps/v1/programTypes.js +945 -945
  78. package/dist/solana/swaps/v2/programIdl.json +952 -952
  79. package/dist/solana/swaps/v2/programTypes.d.ts +950 -950
  80. package/dist/solana/swaps/v2/programTypes.js +952 -952
  81. package/dist/solana/wallet/SolanaKeypairWallet.d.ts +29 -29
  82. package/dist/solana/wallet/SolanaKeypairWallet.js +50 -50
  83. package/dist/solana/wallet/SolanaSigner.d.ts +30 -30
  84. package/dist/solana/wallet/SolanaSigner.js +30 -30
  85. package/dist/utils/Utils.d.ts +58 -58
  86. package/dist/utils/Utils.js +170 -170
  87. package/node/index.d.ts +1 -1
  88. package/node/index.js +3 -3
  89. package/package.json +46 -46
  90. package/src/index.ts +87 -87
  91. package/src/node/index.ts +9 -9
  92. package/src/solana/SolanaChainType.ts +32 -32
  93. package/src/solana/SolanaChains.ts +46 -46
  94. package/src/solana/SolanaInitializer.ts +278 -278
  95. package/src/solana/btcrelay/SolanaBtcRelay.ts +615 -615
  96. package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +116 -116
  97. package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +148 -148
  98. package/src/solana/btcrelay/program/programIdl.json +670 -670
  99. package/src/solana/chain/SolanaAction.ts +109 -109
  100. package/src/solana/chain/SolanaChainInterface.ts +404 -404
  101. package/src/solana/chain/SolanaModule.ts +20 -20
  102. package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
  103. package/src/solana/chain/modules/SolanaBlocks.ts +89 -89
  104. package/src/solana/chain/modules/SolanaEvents.ts +271 -271
  105. package/src/solana/chain/modules/SolanaFees.ts +522 -522
  106. package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
  107. package/src/solana/chain/modules/SolanaSlots.ts +85 -85
  108. package/src/solana/chain/modules/SolanaTokens.ts +300 -300
  109. package/src/solana/chain/modules/SolanaTransactions.ts +503 -503
  110. package/src/solana/connection/ConnectionWithRetries.ts +113 -96
  111. package/src/solana/events/SolanaChainEvents.ts +127 -127
  112. package/src/solana/events/SolanaChainEventsBrowser.ts +495 -495
  113. package/src/solana/program/SolanaProgramBase.ts +119 -119
  114. package/src/solana/program/SolanaProgramModule.ts +15 -15
  115. package/src/solana/program/modules/SolanaProgramEvents.ts +157 -157
  116. package/src/solana/swaps/SolanaSwapData.ts +735 -735
  117. package/src/solana/swaps/SolanaSwapModule.ts +19 -19
  118. package/src/solana/swaps/SolanaSwapProgram.ts +1074 -1074
  119. package/src/solana/swaps/SwapTypeEnum.ts +30 -30
  120. package/src/solana/swaps/modules/SolanaDataAccount.ts +302 -302
  121. package/src/solana/swaps/modules/SolanaLpVault.ts +208 -208
  122. package/src/solana/swaps/modules/SwapClaim.ts +387 -387
  123. package/src/solana/swaps/modules/SwapInit.ts +785 -785
  124. package/src/solana/swaps/modules/SwapRefund.ts +353 -353
  125. package/src/solana/swaps/v1/programIdl.json +944 -944
  126. package/src/solana/swaps/v1/programTypes.ts +1885 -1885
  127. package/src/solana/swaps/v2/programIdl.json +951 -951
  128. package/src/solana/swaps/v2/programTypes.ts +1899 -1899
  129. package/src/solana/wallet/SolanaKeypairWallet.ts +56 -56
  130. package/src/solana/wallet/SolanaSigner.ts +43 -43
  131. package/src/utils/Utils.ts +194 -194
@@ -1,769 +1,769 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SolanaSwapProgram = exports.isSwapProgramV2 = exports.isSwapProgramV1 = void 0;
4
- const SolanaSwapData_1 = require("./SolanaSwapData");
5
- const web3_js_1 = require("@solana/web3.js");
6
- const sha2_1 = require("@noble/hashes/sha2");
7
- const programIdlV1 = require("./v1/programIdl.json");
8
- const programIdlV2 = require("./v2/programIdl.json");
9
- const base_1 = require("@atomiqlabs/base");
10
- const spl_token_1 = require("@solana/spl-token");
11
- const SolanaProgramBase_1 = require("../program/SolanaProgramBase");
12
- const SwapInit_1 = require("./modules/SwapInit");
13
- const SolanaDataAccount_1 = require("./modules/SolanaDataAccount");
14
- const SwapRefund_1 = require("./modules/SwapRefund");
15
- const SwapClaim_1 = require("./modules/SwapClaim");
16
- const SolanaLpVault_1 = require("./modules/SolanaLpVault");
17
- const buffer_1 = require("buffer");
18
- const Utils_1 = require("../../utils/Utils");
19
- const SolanaTokens_1 = require("../chain/modules/SolanaTokens");
20
- const BN = require("bn.js");
21
- const SolanaChains_1 = require("../SolanaChains");
22
- function isSwapProgramV1(obj) {
23
- return obj.idl.version === "0.1.0";
24
- }
25
- exports.isSwapProgramV1 = isSwapProgramV1;
26
- function isSwapProgramV2(obj) {
27
- return obj.idl.version === "0.2.0";
28
- }
29
- exports.isSwapProgramV2 = isSwapProgramV2;
30
- function toPublicKeyOrNull(str) {
31
- return str == null ? undefined : new web3_js_1.PublicKey(str);
32
- }
33
- const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
34
- /**
35
- * Solana swap (escrow manager) program representation handling PrTLC (on-chain) and HTLC (lightning) based swaps.
36
- *
37
- * @category Swaps
38
- */
39
- class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
40
- constructor(chainInterface, btcRelay, storage, programAddress, bitcoinNetwork, version) {
41
- version ?? (version = "v1");
42
- if (bitcoinNetwork != null && programAddress == null) {
43
- programAddress = SolanaChains_1.SolanaChains[bitcoinNetwork]?.addresses[version ?? "v1"]?.swapContract;
44
- }
45
- super(chainInterface, version === "v1" ? programIdlV1 : programIdlV2, programAddress);
46
- this._SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId); // Only necessary for V1 program
47
- this._SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
48
- this._SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
49
- this._SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
50
- ////////////////////////
51
- //// Timeouts
52
- /**
53
- * @inheritDoc
54
- */
55
- this.chainId = "SOLANA";
56
- /**
57
- * @inheritDoc
58
- */
59
- this.claimWithSecretTimeout = 45;
60
- /**
61
- * @inheritDoc
62
- */
63
- this.claimWithTxDataTimeout = 120;
64
- /**
65
- * @inheritDoc
66
- */
67
- this.refundTimeout = 45;
68
- /**
69
- * Grace period (seconds) applied to claimer-side expiry checks.
70
- */
71
- this.claimGracePeriod = 10 * 60;
72
- /**
73
- * Grace period (seconds) applied to offerer-side expiry checks.
74
- */
75
- this.refundGracePeriod = 10 * 60;
76
- /**
77
- * Authorization grace period in seconds.
78
- * @internal
79
- */
80
- this._authGracePeriod = 30;
81
- this.version = version;
82
- this.ESCROW_STATE_RENT_EXEMPT = this.version === "v1" ? 2658720 : 2665680;
83
- this.supportsInitWithoutClaimer = (this.version !== "v1");
84
- this.Init = new SwapInit_1.SwapInit(chainInterface, this);
85
- this.Refund = new SwapRefund_1.SwapRefund(chainInterface, this);
86
- this.Claim = new SwapClaim_1.SwapClaim(chainInterface, this, btcRelay);
87
- this._DataAccount = new SolanaDataAccount_1.SolanaDataAccount(chainInterface, this, storage);
88
- this.LpVault = new SolanaLpVault_1.SolanaLpVault(chainInterface, this);
89
- }
90
- /**
91
- * @inheritDoc
92
- */
93
- async start() {
94
- await this._DataAccount.init();
95
- }
96
- /**
97
- * @inheritDoc
98
- */
99
- getClaimableDeposits(signer) {
100
- return this._DataAccount.getDataAccountsInfo(new web3_js_1.PublicKey(signer));
101
- }
102
- /**
103
- * @inheritDoc
104
- */
105
- claimDeposits(signer) {
106
- return this._DataAccount.sweepDataAccounts(signer);
107
- }
108
- ////////////////////////////////////////////
109
- //// Signatures
110
- /**
111
- * @inheritDoc
112
- */
113
- preFetchForInitSignatureVerification(data) {
114
- return this.Init.preFetchForInitSignatureVerification(data);
115
- }
116
- /**
117
- * @inheritDoc
118
- */
119
- preFetchBlockDataForSignatures() {
120
- return this.Init.preFetchBlockDataForSignatures();
121
- }
122
- /**
123
- * @inheritDoc
124
- */
125
- getInitSignature(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
126
- return this.Init.signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate);
127
- }
128
- /**
129
- * @inheritDoc
130
- */
131
- isValidInitAuthorization(signer, swapData, sig, feeRate, preFetchedData) {
132
- return this.Init.isSignatureValid(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, feeRate, preFetchedData);
133
- }
134
- /**
135
- * @inheritDoc
136
- */
137
- getInitAuthorizationExpiry(swapData, sig, preFetchedData) {
138
- return this.Init.getSignatureExpiry(sig.timeout, sig.signature, preFetchedData);
139
- }
140
- /**
141
- * @inheritDoc
142
- */
143
- isInitAuthorizationExpired(swapData, sig) {
144
- return this.Init.isSignatureExpired(sig.signature, sig.timeout);
145
- }
146
- /**
147
- * @inheritDoc
148
- */
149
- getRefundSignature(signer, swapData, authorizationTimeout) {
150
- return this.Refund.signSwapRefund(signer, swapData, authorizationTimeout);
151
- }
152
- /**
153
- * @inheritDoc
154
- */
155
- isValidRefundAuthorization(swapData, sig) {
156
- return this.Refund.isSignatureValid(swapData, sig.timeout, sig.prefix, sig.signature);
157
- }
158
- /**
159
- * @inheritDoc
160
- */
161
- getDataSignature(signer, data) {
162
- return this._Chain.Signatures.getDataSignature(signer, data);
163
- }
164
- /**
165
- * @inheritDoc
166
- */
167
- isValidDataSignature(data, signature, publicKey) {
168
- return this._Chain.Signatures.isValidDataSignature(data, signature, publicKey);
169
- }
170
- ////////////////////////////////////////////
171
- //// Swap data utils
172
- /**
173
- * @inheritDoc
174
- */
175
- async isClaimable(signer, data) {
176
- if (!data.isClaimer(signer))
177
- return false;
178
- if (await this.isExpired(signer, data))
179
- return false;
180
- return await this.isCommited(data);
181
- }
182
- /**
183
- * @inheritDoc
184
- */
185
- async isCommited(swapData) {
186
- const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
187
- const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHash));
188
- if (account == null)
189
- return false;
190
- return swapData.correctPDA(account);
191
- }
192
- /**
193
- * @inheritDoc
194
- */
195
- isExpired(signer, data, refundSide) {
196
- let currentTimestamp = new BN(Math.floor(Date.now() / 1000));
197
- if (data.isClaimer(signer) && !refundSide) {
198
- currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
199
- }
200
- else {
201
- currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
202
- }
203
- return Promise.resolve(data.expiry.lt(currentTimestamp));
204
- }
205
- /**
206
- * @inheritDoc
207
- */
208
- async isRequestRefundable(signer, data) {
209
- //V1 Swap can only be refunded by the offerer
210
- if (isSwapProgramV1(this.program) && !data.isOfferer(signer))
211
- return false;
212
- if (!(await this.isExpired(signer, data, true)))
213
- return false;
214
- return await this.isCommited(data);
215
- }
216
- /**
217
- * @inheritDoc
218
- */
219
- getHashForOnchain(outputScript, amount, confirmations, nonce) {
220
- nonce ?? (nonce = 0n);
221
- const paymentHash = buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
222
- base_1.BigIntBufferUtils.toBuffer(nonce, "le", 8),
223
- base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
224
- outputScript
225
- ]))).toString("hex");
226
- return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(paymentHash, nonce, confirmations), "hex");
227
- }
228
- /**
229
- * @inheritDoc
230
- */
231
- getHashForHtlc(swapHash) {
232
- return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(swapHash.toString("hex"), 0n, 0), "hex");
233
- }
234
- /**
235
- * @inheritDoc
236
- */
237
- getHashForTxId(txId, confirmations) {
238
- return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(buffer_1.Buffer.from(txId, "hex").reverse().toString("hex"), 0n, confirmations), "hex");
239
- }
240
- ////////////////////////////////////////////
241
- //// Swap data getters
242
- /**
243
- * @inheritDoc
244
- */
245
- async getCommitStatus(signer, data) {
246
- const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(data.paymentHash, "hex"));
247
- const [escrowState, isExpired] = await Promise.all([
248
- this.program.account.escrowState.fetchNullable(escrowStateKey),
249
- this.isExpired(signer, data)
250
- ]);
251
- const getInitTxId = (0, Utils_1.onceAsync)(async () => {
252
- const txId = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
253
- if (event.name === "InitializeEvent") {
254
- const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
255
- if (paymentHash !== data.paymentHash)
256
- return null;
257
- if (!event.data.sequence.eq(data.sequence))
258
- return null;
259
- return tx.transaction.signatures[0];
260
- }
261
- });
262
- if (txId == null)
263
- throw new Error("Initialize event not found!");
264
- return txId;
265
- });
266
- if (escrowState != null) {
267
- if (data.correctPDA(escrowState)) {
268
- if (data.isOfferer(signer) && isExpired)
269
- return { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId };
270
- return { type: base_1.SwapCommitStateType.COMMITED, getInitTxId };
271
- }
272
- if (data.isOfferer(signer) && isExpired)
273
- return { type: base_1.SwapCommitStateType.EXPIRED };
274
- return { type: base_1.SwapCommitStateType.NOT_COMMITED };
275
- }
276
- //Check if paid or what
277
- const status = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
278
- if (event.name === "ClaimEvent") {
279
- const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
280
- if (paymentHash !== data.paymentHash)
281
- return null;
282
- if (!event.data.sequence.eq(data.sequence))
283
- return null;
284
- return {
285
- type: base_1.SwapCommitStateType.PAID,
286
- getInitTxId,
287
- getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
288
- getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
289
- getTxBlock: () => Promise.resolve({
290
- blockHeight: tx.slot,
291
- blockTime: tx.blockTime
292
- })
293
- };
294
- }
295
- if (event.name === "RefundEvent") {
296
- const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
297
- if (paymentHash !== data.paymentHash)
298
- return null;
299
- if (!event.data.sequence.eq(data.sequence))
300
- return null;
301
- return {
302
- type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
303
- getInitTxId,
304
- getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
305
- getTxBlock: () => Promise.resolve({
306
- blockHeight: tx.slot,
307
- blockTime: tx.blockTime
308
- })
309
- };
310
- }
311
- });
312
- if (status != null)
313
- return status;
314
- if (isExpired)
315
- return { type: base_1.SwapCommitStateType.EXPIRED };
316
- return { type: base_1.SwapCommitStateType.NOT_COMMITED };
317
- }
318
- /**
319
- * @inheritDoc
320
- */
321
- async getCommitStatuses(request) {
322
- const result = {};
323
- let promises = [];
324
- for (let { signer, swapData } of request) {
325
- promises.push(this.getCommitStatus(signer, swapData).then(val => {
326
- result[swapData.getEscrowHash()] = val;
327
- }));
328
- if (promises.length >= MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
329
- await Promise.all(promises);
330
- promises = [];
331
- }
332
- }
333
- await Promise.all(promises);
334
- return result;
335
- }
336
- /**
337
- * @inheritDoc
338
- */
339
- async getClaimHashStatus(claimHash) {
340
- const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHash);
341
- const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(paymentHash, "hex"));
342
- const abortController = new AbortController();
343
- //Start fetching events before checking escrow PDA, this call is used when quoting, so saving 100ms here helps a lot!
344
- const eventsPromise = this._Events.findInEvents(escrowStateKey, async (event) => {
345
- if (event.name === "ClaimEvent")
346
- return base_1.SwapCommitStateType.PAID;
347
- if (event.name === "RefundEvent")
348
- return base_1.SwapCommitStateType.NOT_COMMITED;
349
- }, abortController.signal).catch(e => {
350
- abortController.abort(e);
351
- return null;
352
- });
353
- const escrowState = await this.program.account.escrowState.fetchNullable(escrowStateKey);
354
- abortController.signal.throwIfAborted();
355
- if (escrowState != null) {
356
- abortController.abort();
357
- return base_1.SwapCommitStateType.COMMITED;
358
- }
359
- //Check if paid or what
360
- const eventsStatus = await eventsPromise;
361
- abortController.signal.throwIfAborted();
362
- if (eventsStatus != null)
363
- return eventsStatus;
364
- return base_1.SwapCommitStateType.NOT_COMMITED;
365
- }
366
- /**
367
- * @inheritDoc
368
- */
369
- async getCommitedData(claimHashHex) {
370
- const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHashHex);
371
- const paymentHashBuffer = buffer_1.Buffer.from(paymentHash, "hex");
372
- const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHashBuffer));
373
- if (account == null)
374
- return null;
375
- return SolanaSwapData_1.SolanaSwapData.fromEscrowState(this.program.programId, this.version, account);
376
- }
377
- /**
378
- * @inheritDoc
379
- */
380
- async getHistoricalSwaps(signer, startBlockheight) {
381
- let latestBlockheight;
382
- const events = [];
383
- await this._Events.findInEvents(new web3_js_1.PublicKey(signer), async (event, tx) => {
384
- if (latestBlockheight == null)
385
- latestBlockheight = tx.slot;
386
- events.push({ event, tx });
387
- }, undefined, undefined, startBlockheight);
388
- this.logger.debug(`getHistoricalSwaps(): Found ${events.length} atomiq related events!`);
389
- const swapsOpened = {};
390
- const resultingSwaps = {};
391
- events.reverse();
392
- for (let { event, tx } of events) {
393
- const txSignature = tx.transaction.signatures[0];
394
- const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
395
- const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, event.data.sequence);
396
- if (event.name === "InitializeEvent") {
397
- //Parse swap data from initialize event
398
- const txoHash = buffer_1.Buffer.from(event.data.txoHash).toString("hex");
399
- const instructions = this._Events.decodeInstructions(tx.transaction.message);
400
- if (instructions == null) {
401
- this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot parse instructions!`);
402
- continue;
403
- }
404
- const initIx = instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
405
- if (initIx == null) {
406
- this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because init instruction not found!`);
407
- continue;
408
- }
409
- swapsOpened[escrowHash] = {
410
- data: SolanaSwapData_1.SolanaSwapData.fromInstruction(this.program.programId, this.version, initIx, txoHash),
411
- getInitTxId: () => Promise.resolve(txSignature),
412
- getTxBlock: () => Promise.resolve({
413
- blockHeight: tx.slot,
414
- blockTime: tx.blockTime
415
- })
416
- };
417
- }
418
- if (event.name === "ClaimEvent") {
419
- const foundSwapData = swapsOpened[escrowHash];
420
- delete swapsOpened[escrowHash];
421
- resultingSwaps[escrowHash] = {
422
- init: foundSwapData,
423
- state: {
424
- type: base_1.SwapCommitStateType.PAID,
425
- getInitTxId: foundSwapData?.getInitTxId,
426
- getClaimTxId: () => Promise.resolve(txSignature),
427
- getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
428
- getTxBlock: () => Promise.resolve({
429
- blockHeight: tx.slot,
430
- blockTime: tx.blockTime
431
- })
432
- }
433
- };
434
- }
435
- if (event.name === "RefundEvent") {
436
- const foundSwapData = swapsOpened[escrowHash];
437
- delete swapsOpened[escrowHash];
438
- const isExpired = foundSwapData != null && await this.isExpired(signer, foundSwapData.data);
439
- resultingSwaps[escrowHash] = {
440
- init: foundSwapData,
441
- state: {
442
- type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
443
- getInitTxId: foundSwapData?.getInitTxId,
444
- getRefundTxId: () => Promise.resolve(txSignature),
445
- getTxBlock: () => Promise.resolve({
446
- blockHeight: tx.slot,
447
- blockTime: tx.blockTime
448
- })
449
- }
450
- };
451
- }
452
- }
453
- this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
454
- this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
455
- for (let escrowHash in swapsOpened) {
456
- const foundSwapData = swapsOpened[escrowHash];
457
- const isExpired = await this.isExpired(signer, foundSwapData.data);
458
- resultingSwaps[escrowHash] = {
459
- init: foundSwapData,
460
- state: foundSwapData.data.isOfferer(signer) && isExpired
461
- ? { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId: foundSwapData.getInitTxId }
462
- : { type: base_1.SwapCommitStateType.COMMITED, getInitTxId: foundSwapData.getInitTxId }
463
- };
464
- }
465
- return {
466
- swaps: resultingSwaps,
467
- latestBlockheight: latestBlockheight ?? startBlockheight
468
- };
469
- }
470
- ////////////////////////////////////////////
471
- //// Swap data initializer
472
- /**
473
- * @inheritDoc
474
- */
475
- createSwapData(type, offerer, claimer, token, amount, claimHash, sequence, expiry, payIn, payOut, securityDeposit, claimerBounty, depositToken) {
476
- if (depositToken != null) {
477
- if (!new web3_js_1.PublicKey(depositToken).equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS))
478
- throw new Error("Only SOL supported as deposit token!");
479
- }
480
- const tokenAddr = new web3_js_1.PublicKey(token);
481
- const offererKey = new web3_js_1.PublicKey(offerer);
482
- const claimerKey = new web3_js_1.PublicKey(claimer);
483
- const { paymentHash, nonce, confirmations } = (0, Utils_1.fromClaimHash)(claimHash);
484
- const swapData = new SolanaSwapData_1.SolanaSwapData({
485
- programId: this.program.programId,
486
- version: this.version,
487
- offerer: offererKey,
488
- claimer: claimerKey,
489
- token: tokenAddr,
490
- amount: (0, Utils_1.toBN)(amount),
491
- paymentHash,
492
- sequence: (0, Utils_1.toBN)(sequence),
493
- expiry: (0, Utils_1.toBN)(expiry),
494
- nonce,
495
- confirmations,
496
- payOut,
497
- kind: SolanaSwapData_1.SolanaSwapData.typeToKind(type),
498
- payIn,
499
- offererAta: payIn ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, offererKey) : web3_js_1.PublicKey.default,
500
- claimerAta: payOut ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, claimerKey) : web3_js_1.PublicKey.default,
501
- securityDeposit: (0, Utils_1.toBN)(securityDeposit),
502
- claimerBounty: (0, Utils_1.toBN)(claimerBounty)
503
- });
504
- return Promise.resolve(swapData);
505
- }
506
- ////////////////////////////////////////////
507
- //// Utils
508
- /**
509
- * @inheritDoc
510
- */
511
- async getBalance(signer, tokenAddress, inContract) {
512
- if (!inContract) {
513
- return await this._Chain.getBalance(signer, tokenAddress);
514
- }
515
- const token = new web3_js_1.PublicKey(tokenAddress);
516
- const publicKey = new web3_js_1.PublicKey(signer);
517
- return await this.getIntermediaryBalance(publicKey, token);
518
- }
519
- /**
520
- * @inheritDoc
521
- */
522
- getIntermediaryData(address, token) {
523
- return this.LpVault.getIntermediaryData(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
524
- }
525
- /**
526
- * @inheritDoc
527
- */
528
- getIntermediaryReputation(address, token) {
529
- return this.LpVault.getIntermediaryReputation(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
530
- }
531
- /**
532
- * Returns intermediary vault balance for a specific token.
533
- *
534
- * @param address Intermediary address
535
- * @param token Token mint
536
- */
537
- getIntermediaryBalance(address, token) {
538
- return this.LpVault.getIntermediaryBalance(address, token);
539
- }
540
- ////////////////////////////////////////////
541
- //// Transaction initializers
542
- /**
543
- * @inheritDoc
544
- */
545
- async txsClaimWithSecret(signer, swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck) {
546
- return this.Claim.txsClaimWithSecret(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer.getPublicKey(), swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck);
547
- }
548
- /**
549
- * @inheritDoc
550
- */
551
- async txsClaimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, feeRate) {
552
- if (swapData.confirmations !== requiredConfirmations)
553
- throw new Error("Invalid requiredConfirmations provided!");
554
- const { txs } = await this.Claim.txsClaimWithTxData(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, feeRate);
555
- return txs;
556
- }
557
- /**
558
- * @inheritDoc
559
- */
560
- txsRefund(signer, swapData, check, initAta, feeRate) {
561
- return this.Refund.txsRefund(new web3_js_1.PublicKey(signer), swapData, check, initAta, feeRate);
562
- }
563
- /**
564
- * @inheritDoc
565
- */
566
- txsRefundWithAuthorization(signer, swapData, sig, check, initAta, feeRate) {
567
- return this.Refund.txsRefundWithAuthorization(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, check, initAta, feeRate);
568
- }
569
- /**
570
- * @inheritDoc
571
- */
572
- txsInit(sender, swapData, sig, skipChecks, feeRate) {
573
- if (swapData.isPayIn()) {
574
- return this.Init.txsInitPayIn(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
575
- }
576
- else {
577
- return this.Init.txsInit(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
578
- }
579
- }
580
- /**
581
- * @inheritDoc
582
- */
583
- txsWithdraw(signer, token, amount, feeRate) {
584
- return this.LpVault.txsWithdraw(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
585
- }
586
- /**
587
- * @inheritDoc
588
- */
589
- txsDeposit(signer, token, amount, feeRate) {
590
- return this.LpVault.txsDeposit(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
591
- }
592
- ////////////////////////////////////////////
593
- //// Executors
594
- /**
595
- * @inheritDoc
596
- */
597
- async claimWithSecret(signer, swapData, secret, checkExpiry, initAta, txOptions) {
598
- const result = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, checkExpiry, initAta, txOptions?.feeRate);
599
- const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
600
- return signature;
601
- }
602
- /**
603
- * @inheritDoc
604
- */
605
- async claimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, txOptions) {
606
- if (requiredConfirmations !== swapData.confirmations)
607
- throw new Error("Invalid requiredConfirmations provided!");
608
- const { txs, claimTxIndex, storageAcc } = await this.Claim.txsClaimWithTxData(signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, txOptions?.feeRate);
609
- const signatures = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal);
610
- await this._DataAccount.removeDataAccount(storageAcc);
611
- return signatures[claimTxIndex] ?? signatures[0];
612
- }
613
- /**
614
- * @inheritDoc
615
- */
616
- async refund(signer, swapData, check, initAta, txOptions) {
617
- let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
618
- const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
619
- return signature;
620
- }
621
- /**
622
- * @inheritDoc
623
- */
624
- async refundWithAuthorization(signer, swapData, signature, check, initAta, txOptions) {
625
- let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
626
- const [txSignature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
627
- return txSignature;
628
- }
629
- /**
630
- * @inheritDoc
631
- */
632
- async init(signer, swapData, signature, skipChecks, txOptions) {
633
- const result = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
634
- const signatures = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
635
- return signatures[signatures.length - 1];
636
- }
637
- /**
638
- * @inheritDoc
639
- */
640
- async initAndClaimWithSecret(signer, swapData, signature, secret, skipChecks, txOptions) {
641
- if (!signer.getPublicKey().equals(swapData.claimer))
642
- throw new Error("Invalid signer provided!");
643
- const txsCommit = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
644
- let txsClaim;
645
- if (isSwapProgramV1(this.program)) {
646
- // In V1 the initialize instruction has to contain the ATA initialization, hence we can skip checking it in claim
647
- txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
648
- }
649
- else {
650
- // In V2 the initialize instruction doesn't necessarily contain the ATA initialization, hence the claim instruction needs to
651
- // check and initialize the ATA if needed
652
- txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, true, txOptions?.feeRate, false);
653
- }
654
- const signatures = await this._Chain.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
655
- return [signatures[txsCommit.length - 1], signatures[signatures.length - 1]];
656
- }
657
- /**
658
- * @inheritDoc
659
- */
660
- async withdraw(signer, token, amount, txOptions) {
661
- const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
662
- const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
663
- return txId;
664
- }
665
- /**
666
- * @inheritDoc
667
- */
668
- async deposit(signer, token, amount, txOptions) {
669
- const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
670
- const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
671
- return txId;
672
- }
673
- ////////////////////////////////////////////
674
- //// Fees
675
- /**
676
- * @inheritDoc
677
- */
678
- getInitPayInFeeRate(offerer, claimer, token, claimHash) {
679
- const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
680
- return this.Init.getInitPayInFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
681
- }
682
- /**
683
- * @inheritDoc
684
- */
685
- getInitFeeRate(offerer, claimer, token, claimHash) {
686
- const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
687
- return this.Init.getInitFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
688
- }
689
- /**
690
- * @inheritDoc
691
- */
692
- getRefundFeeRate(swapData) {
693
- return this.Refund.getRefundFeeRate(swapData);
694
- }
695
- /**
696
- * @inheritDoc
697
- */
698
- getClaimFeeRate(signer, swapData) {
699
- return this.Claim.getClaimFeeRate(new web3_js_1.PublicKey(signer), swapData);
700
- }
701
- /**
702
- * @inheritDoc
703
- */
704
- getClaimFee(signer, swapData, feeRate) {
705
- return this.Claim.getClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
706
- }
707
- /**
708
- * @inheritDoc
709
- */
710
- getRawClaimFee(signer, swapData, feeRate) {
711
- return this.Claim.getRawClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
712
- }
713
- /**
714
- * @inheritDoc
715
- */
716
- getCommitFee(signer, swapData, feeRate) {
717
- return this.Init.getInitFee(swapData, feeRate);
718
- }
719
- /**
720
- * @inheritDoc
721
- */
722
- getRawCommitFee(signer, swapData, feeRate) {
723
- return this.Init.getRawInitFee(swapData, feeRate);
724
- }
725
- /**
726
- * @inheritDoc
727
- */
728
- getRefundFee(signer, swapData, feeRate) {
729
- return this.Refund.getRefundFee(swapData, feeRate);
730
- }
731
- /**
732
- * @inheritDoc
733
- */
734
- getRawRefundFee(signer, swapData, feeRate) {
735
- return this.Refund.getRawRefundFee(swapData, feeRate);
736
- }
737
- /**
738
- * @inheritDoc
739
- */
740
- getExtraData(outputScript, amount, confirmations, nonce) {
741
- return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
742
- base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
743
- outputScript
744
- ])));
745
- }
746
- }
747
- exports.SolanaSwapProgram = SolanaSwapProgram;
748
- ////////////////////////
749
- //// PDA accessors
750
- /**
751
- * PDA of the swap vault authority.
752
- * @internal
753
- */
754
- SolanaSwapProgram._SwapVaultAuthority = SolanaProgramBase_1.SolanaProgramBase._pda("authority"); // Only necessary for V1 program
755
- /**
756
- * PDA helper for global token vault accounts.
757
- * @internal
758
- */
759
- SolanaSwapProgram._SwapVault = SolanaProgramBase_1.SolanaProgramBase._pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
760
- /**
761
- * PDA helper for per-user token vault accounts.
762
- * @internal
763
- */
764
- SolanaSwapProgram._SwapUserVault = SolanaProgramBase_1.SolanaProgramBase._pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
765
- /**
766
- * PDA helper for escrow state accounts.
767
- * @internal
768
- */
769
- SolanaSwapProgram._SwapEscrowState = SolanaProgramBase_1.SolanaProgramBase._pda("state", (hash) => [hash]);
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SolanaSwapProgram = exports.isSwapProgramV2 = exports.isSwapProgramV1 = void 0;
4
+ const SolanaSwapData_1 = require("./SolanaSwapData");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const sha2_1 = require("@noble/hashes/sha2");
7
+ const programIdlV1 = require("./v1/programIdl.json");
8
+ const programIdlV2 = require("./v2/programIdl.json");
9
+ const base_1 = require("@atomiqlabs/base");
10
+ const spl_token_1 = require("@solana/spl-token");
11
+ const SolanaProgramBase_1 = require("../program/SolanaProgramBase");
12
+ const SwapInit_1 = require("./modules/SwapInit");
13
+ const SolanaDataAccount_1 = require("./modules/SolanaDataAccount");
14
+ const SwapRefund_1 = require("./modules/SwapRefund");
15
+ const SwapClaim_1 = require("./modules/SwapClaim");
16
+ const SolanaLpVault_1 = require("./modules/SolanaLpVault");
17
+ const buffer_1 = require("buffer");
18
+ const Utils_1 = require("../../utils/Utils");
19
+ const SolanaTokens_1 = require("../chain/modules/SolanaTokens");
20
+ const BN = require("bn.js");
21
+ const SolanaChains_1 = require("../SolanaChains");
22
+ function isSwapProgramV1(obj) {
23
+ return obj.idl.version === "0.1.0";
24
+ }
25
+ exports.isSwapProgramV1 = isSwapProgramV1;
26
+ function isSwapProgramV2(obj) {
27
+ return obj.idl.version === "0.2.0";
28
+ }
29
+ exports.isSwapProgramV2 = isSwapProgramV2;
30
+ function toPublicKeyOrNull(str) {
31
+ return str == null ? undefined : new web3_js_1.PublicKey(str);
32
+ }
33
+ const MAX_PARALLEL_COMMIT_STATUS_CHECKS = 5;
34
+ /**
35
+ * Solana swap (escrow manager) program representation handling PrTLC (on-chain) and HTLC (lightning) based swaps.
36
+ *
37
+ * @category Swaps
38
+ */
39
+ class SolanaSwapProgram extends SolanaProgramBase_1.SolanaProgramBase {
40
+ constructor(chainInterface, btcRelay, storage, programAddress, bitcoinNetwork, version) {
41
+ version ?? (version = "v1");
42
+ if (bitcoinNetwork != null && programAddress == null) {
43
+ programAddress = SolanaChains_1.SolanaChains[bitcoinNetwork]?.addresses[version ?? "v1"]?.swapContract;
44
+ }
45
+ super(chainInterface, version === "v1" ? programIdlV1 : programIdlV2, programAddress);
46
+ this._SwapVaultAuthority = SolanaSwapProgram._SwapVaultAuthority(this.program.programId); // Only necessary for V1 program
47
+ this._SwapVault = SolanaSwapProgram._SwapVault.bind(this, this.program.programId);
48
+ this._SwapUserVault = SolanaSwapProgram._SwapUserVault.bind(this, this.program.programId);
49
+ this._SwapEscrowState = SolanaSwapProgram._SwapEscrowState.bind(this, this.program.programId);
50
+ ////////////////////////
51
+ //// Timeouts
52
+ /**
53
+ * @inheritDoc
54
+ */
55
+ this.chainId = "SOLANA";
56
+ /**
57
+ * @inheritDoc
58
+ */
59
+ this.claimWithSecretTimeout = 45;
60
+ /**
61
+ * @inheritDoc
62
+ */
63
+ this.claimWithTxDataTimeout = 120;
64
+ /**
65
+ * @inheritDoc
66
+ */
67
+ this.refundTimeout = 45;
68
+ /**
69
+ * Grace period (seconds) applied to claimer-side expiry checks.
70
+ */
71
+ this.claimGracePeriod = 10 * 60;
72
+ /**
73
+ * Grace period (seconds) applied to offerer-side expiry checks.
74
+ */
75
+ this.refundGracePeriod = 10 * 60;
76
+ /**
77
+ * Authorization grace period in seconds.
78
+ * @internal
79
+ */
80
+ this._authGracePeriod = 30;
81
+ this.version = version;
82
+ this.ESCROW_STATE_RENT_EXEMPT = this.version === "v1" ? 2658720 : 2665680;
83
+ this.supportsInitWithoutClaimer = (this.version !== "v1");
84
+ this.Init = new SwapInit_1.SwapInit(chainInterface, this);
85
+ this.Refund = new SwapRefund_1.SwapRefund(chainInterface, this);
86
+ this.Claim = new SwapClaim_1.SwapClaim(chainInterface, this, btcRelay);
87
+ this._DataAccount = new SolanaDataAccount_1.SolanaDataAccount(chainInterface, this, storage);
88
+ this.LpVault = new SolanaLpVault_1.SolanaLpVault(chainInterface, this);
89
+ }
90
+ /**
91
+ * @inheritDoc
92
+ */
93
+ async start() {
94
+ await this._DataAccount.init();
95
+ }
96
+ /**
97
+ * @inheritDoc
98
+ */
99
+ getClaimableDeposits(signer) {
100
+ return this._DataAccount.getDataAccountsInfo(new web3_js_1.PublicKey(signer));
101
+ }
102
+ /**
103
+ * @inheritDoc
104
+ */
105
+ claimDeposits(signer) {
106
+ return this._DataAccount.sweepDataAccounts(signer);
107
+ }
108
+ ////////////////////////////////////////////
109
+ //// Signatures
110
+ /**
111
+ * @inheritDoc
112
+ */
113
+ preFetchForInitSignatureVerification(data) {
114
+ return this.Init.preFetchForInitSignatureVerification(data);
115
+ }
116
+ /**
117
+ * @inheritDoc
118
+ */
119
+ preFetchBlockDataForSignatures() {
120
+ return this.Init.preFetchBlockDataForSignatures();
121
+ }
122
+ /**
123
+ * @inheritDoc
124
+ */
125
+ getInitSignature(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate) {
126
+ return this.Init.signSwapInitialization(signer, swapData, authorizationTimeout, preFetchedBlockData, feeRate);
127
+ }
128
+ /**
129
+ * @inheritDoc
130
+ */
131
+ isValidInitAuthorization(signer, swapData, sig, feeRate, preFetchedData) {
132
+ return this.Init.isSignatureValid(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, feeRate, preFetchedData);
133
+ }
134
+ /**
135
+ * @inheritDoc
136
+ */
137
+ getInitAuthorizationExpiry(swapData, sig, preFetchedData) {
138
+ return this.Init.getSignatureExpiry(sig.timeout, sig.signature, preFetchedData);
139
+ }
140
+ /**
141
+ * @inheritDoc
142
+ */
143
+ isInitAuthorizationExpired(swapData, sig) {
144
+ return this.Init.isSignatureExpired(sig.signature, sig.timeout);
145
+ }
146
+ /**
147
+ * @inheritDoc
148
+ */
149
+ getRefundSignature(signer, swapData, authorizationTimeout) {
150
+ return this.Refund.signSwapRefund(signer, swapData, authorizationTimeout);
151
+ }
152
+ /**
153
+ * @inheritDoc
154
+ */
155
+ isValidRefundAuthorization(swapData, sig) {
156
+ return this.Refund.isSignatureValid(swapData, sig.timeout, sig.prefix, sig.signature);
157
+ }
158
+ /**
159
+ * @inheritDoc
160
+ */
161
+ getDataSignature(signer, data) {
162
+ return this._Chain.Signatures.getDataSignature(signer, data);
163
+ }
164
+ /**
165
+ * @inheritDoc
166
+ */
167
+ isValidDataSignature(data, signature, publicKey) {
168
+ return this._Chain.Signatures.isValidDataSignature(data, signature, publicKey);
169
+ }
170
+ ////////////////////////////////////////////
171
+ //// Swap data utils
172
+ /**
173
+ * @inheritDoc
174
+ */
175
+ async isClaimable(signer, data) {
176
+ if (!data.isClaimer(signer))
177
+ return false;
178
+ if (await this.isExpired(signer, data))
179
+ return false;
180
+ return await this.isCommited(data);
181
+ }
182
+ /**
183
+ * @inheritDoc
184
+ */
185
+ async isCommited(swapData) {
186
+ const paymentHash = buffer_1.Buffer.from(swapData.paymentHash, "hex");
187
+ const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHash));
188
+ if (account == null)
189
+ return false;
190
+ return swapData.correctPDA(account);
191
+ }
192
+ /**
193
+ * @inheritDoc
194
+ */
195
+ isExpired(signer, data, refundSide) {
196
+ let currentTimestamp = new BN(Math.floor(Date.now() / 1000));
197
+ if (data.isClaimer(signer) && !refundSide) {
198
+ currentTimestamp = currentTimestamp.add(new BN(this.claimGracePeriod));
199
+ }
200
+ else {
201
+ currentTimestamp = currentTimestamp.sub(new BN(this.refundGracePeriod));
202
+ }
203
+ return Promise.resolve(data.expiry.lt(currentTimestamp));
204
+ }
205
+ /**
206
+ * @inheritDoc
207
+ */
208
+ async isRequestRefundable(signer, data) {
209
+ //V1 Swap can only be refunded by the offerer
210
+ if (isSwapProgramV1(this.program) && !data.isOfferer(signer))
211
+ return false;
212
+ if (!(await this.isExpired(signer, data, true)))
213
+ return false;
214
+ return await this.isCommited(data);
215
+ }
216
+ /**
217
+ * @inheritDoc
218
+ */
219
+ getHashForOnchain(outputScript, amount, confirmations, nonce) {
220
+ nonce ?? (nonce = 0n);
221
+ const paymentHash = buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
222
+ base_1.BigIntBufferUtils.toBuffer(nonce, "le", 8),
223
+ base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
224
+ outputScript
225
+ ]))).toString("hex");
226
+ return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(paymentHash, nonce, confirmations), "hex");
227
+ }
228
+ /**
229
+ * @inheritDoc
230
+ */
231
+ getHashForHtlc(swapHash) {
232
+ return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(swapHash.toString("hex"), 0n, 0), "hex");
233
+ }
234
+ /**
235
+ * @inheritDoc
236
+ */
237
+ getHashForTxId(txId, confirmations) {
238
+ return buffer_1.Buffer.from((0, Utils_1.toClaimHash)(buffer_1.Buffer.from(txId, "hex").reverse().toString("hex"), 0n, confirmations), "hex");
239
+ }
240
+ ////////////////////////////////////////////
241
+ //// Swap data getters
242
+ /**
243
+ * @inheritDoc
244
+ */
245
+ async getCommitStatus(signer, data) {
246
+ const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(data.paymentHash, "hex"));
247
+ const [escrowState, isExpired] = await Promise.all([
248
+ this.program.account.escrowState.fetchNullable(escrowStateKey),
249
+ this.isExpired(signer, data)
250
+ ]);
251
+ const getInitTxId = (0, Utils_1.onceAsync)(async () => {
252
+ const txId = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
253
+ if (event.name === "InitializeEvent") {
254
+ const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
255
+ if (paymentHash !== data.paymentHash)
256
+ return null;
257
+ if (!event.data.sequence.eq(data.sequence))
258
+ return null;
259
+ return tx.transaction.signatures[0];
260
+ }
261
+ });
262
+ if (txId == null)
263
+ throw new Error("Initialize event not found!");
264
+ return txId;
265
+ });
266
+ if (escrowState != null) {
267
+ if (data.correctPDA(escrowState)) {
268
+ if (data.isOfferer(signer) && isExpired)
269
+ return { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId };
270
+ return { type: base_1.SwapCommitStateType.COMMITED, getInitTxId };
271
+ }
272
+ if (data.isOfferer(signer) && isExpired)
273
+ return { type: base_1.SwapCommitStateType.EXPIRED };
274
+ return { type: base_1.SwapCommitStateType.NOT_COMMITED };
275
+ }
276
+ //Check if paid or what
277
+ const status = await this._Events.findInEvents(escrowStateKey, async (event, tx) => {
278
+ if (event.name === "ClaimEvent") {
279
+ const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
280
+ if (paymentHash !== data.paymentHash)
281
+ return null;
282
+ if (!event.data.sequence.eq(data.sequence))
283
+ return null;
284
+ return {
285
+ type: base_1.SwapCommitStateType.PAID,
286
+ getInitTxId,
287
+ getClaimTxId: () => Promise.resolve(tx.transaction.signatures[0]),
288
+ getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
289
+ getTxBlock: () => Promise.resolve({
290
+ blockHeight: tx.slot,
291
+ blockTime: tx.blockTime
292
+ })
293
+ };
294
+ }
295
+ if (event.name === "RefundEvent") {
296
+ const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
297
+ if (paymentHash !== data.paymentHash)
298
+ return null;
299
+ if (!event.data.sequence.eq(data.sequence))
300
+ return null;
301
+ return {
302
+ type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
303
+ getInitTxId,
304
+ getRefundTxId: () => Promise.resolve(tx.transaction.signatures[0]),
305
+ getTxBlock: () => Promise.resolve({
306
+ blockHeight: tx.slot,
307
+ blockTime: tx.blockTime
308
+ })
309
+ };
310
+ }
311
+ });
312
+ if (status != null)
313
+ return status;
314
+ if (isExpired)
315
+ return { type: base_1.SwapCommitStateType.EXPIRED };
316
+ return { type: base_1.SwapCommitStateType.NOT_COMMITED };
317
+ }
318
+ /**
319
+ * @inheritDoc
320
+ */
321
+ async getCommitStatuses(request) {
322
+ const result = {};
323
+ let promises = [];
324
+ for (let { signer, swapData } of request) {
325
+ promises.push(this.getCommitStatus(signer, swapData).then(val => {
326
+ result[swapData.getEscrowHash()] = val;
327
+ }));
328
+ if (promises.length >= MAX_PARALLEL_COMMIT_STATUS_CHECKS) {
329
+ await Promise.all(promises);
330
+ promises = [];
331
+ }
332
+ }
333
+ await Promise.all(promises);
334
+ return result;
335
+ }
336
+ /**
337
+ * @inheritDoc
338
+ */
339
+ async getClaimHashStatus(claimHash) {
340
+ const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHash);
341
+ const escrowStateKey = this._SwapEscrowState(buffer_1.Buffer.from(paymentHash, "hex"));
342
+ const abortController = new AbortController();
343
+ //Start fetching events before checking escrow PDA, this call is used when quoting, so saving 100ms here helps a lot!
344
+ const eventsPromise = this._Events.findInEvents(escrowStateKey, async (event) => {
345
+ if (event.name === "ClaimEvent")
346
+ return base_1.SwapCommitStateType.PAID;
347
+ if (event.name === "RefundEvent")
348
+ return base_1.SwapCommitStateType.NOT_COMMITED;
349
+ }, abortController.signal).catch(e => {
350
+ abortController.abort(e);
351
+ return null;
352
+ });
353
+ const escrowState = await this.program.account.escrowState.fetchNullable(escrowStateKey);
354
+ abortController.signal.throwIfAborted();
355
+ if (escrowState != null) {
356
+ abortController.abort();
357
+ return base_1.SwapCommitStateType.COMMITED;
358
+ }
359
+ //Check if paid or what
360
+ const eventsStatus = await eventsPromise;
361
+ abortController.signal.throwIfAborted();
362
+ if (eventsStatus != null)
363
+ return eventsStatus;
364
+ return base_1.SwapCommitStateType.NOT_COMMITED;
365
+ }
366
+ /**
367
+ * @inheritDoc
368
+ */
369
+ async getCommitedData(claimHashHex) {
370
+ const { paymentHash } = (0, Utils_1.fromClaimHash)(claimHashHex);
371
+ const paymentHashBuffer = buffer_1.Buffer.from(paymentHash, "hex");
372
+ const account = await this.program.account.escrowState.fetchNullable(this._SwapEscrowState(paymentHashBuffer));
373
+ if (account == null)
374
+ return null;
375
+ return SolanaSwapData_1.SolanaSwapData.fromEscrowState(this.program.programId, this.version, account);
376
+ }
377
+ /**
378
+ * @inheritDoc
379
+ */
380
+ async getHistoricalSwaps(signer, startBlockheight) {
381
+ let latestBlockheight;
382
+ const events = [];
383
+ await this._Events.findInEvents(new web3_js_1.PublicKey(signer), async (event, tx) => {
384
+ if (latestBlockheight == null)
385
+ latestBlockheight = tx.slot;
386
+ events.push({ event, tx });
387
+ }, undefined, undefined, startBlockheight);
388
+ this.logger.debug(`getHistoricalSwaps(): Found ${events.length} atomiq related events!`);
389
+ const swapsOpened = {};
390
+ const resultingSwaps = {};
391
+ events.reverse();
392
+ for (let { event, tx } of events) {
393
+ const txSignature = tx.transaction.signatures[0];
394
+ const paymentHash = buffer_1.Buffer.from(event.data.hash).toString("hex");
395
+ const escrowHash = (0, Utils_1.toEscrowHash)(paymentHash, event.data.sequence);
396
+ if (event.name === "InitializeEvent") {
397
+ //Parse swap data from initialize event
398
+ const txoHash = buffer_1.Buffer.from(event.data.txoHash).toString("hex");
399
+ const instructions = this._Events.decodeInstructions(tx.transaction.message);
400
+ if (instructions == null) {
401
+ this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because cannot parse instructions!`);
402
+ continue;
403
+ }
404
+ const initIx = instructions.find(ix => ix != null && (ix.name === "offererInitializePayIn" || ix.name === "offererInitialize"));
405
+ if (initIx == null) {
406
+ this.logger.warn(`getHistoricalSwaps(): Skipping tx ${txSignature} because init instruction not found!`);
407
+ continue;
408
+ }
409
+ swapsOpened[escrowHash] = {
410
+ data: SolanaSwapData_1.SolanaSwapData.fromInstruction(this.program.programId, this.version, initIx, txoHash),
411
+ getInitTxId: () => Promise.resolve(txSignature),
412
+ getTxBlock: () => Promise.resolve({
413
+ blockHeight: tx.slot,
414
+ blockTime: tx.blockTime
415
+ })
416
+ };
417
+ }
418
+ if (event.name === "ClaimEvent") {
419
+ const foundSwapData = swapsOpened[escrowHash];
420
+ delete swapsOpened[escrowHash];
421
+ resultingSwaps[escrowHash] = {
422
+ init: foundSwapData,
423
+ state: {
424
+ type: base_1.SwapCommitStateType.PAID,
425
+ getInitTxId: foundSwapData?.getInitTxId,
426
+ getClaimTxId: () => Promise.resolve(txSignature),
427
+ getClaimResult: () => Promise.resolve(buffer_1.Buffer.from(event.data.secret).toString("hex")),
428
+ getTxBlock: () => Promise.resolve({
429
+ blockHeight: tx.slot,
430
+ blockTime: tx.blockTime
431
+ })
432
+ }
433
+ };
434
+ }
435
+ if (event.name === "RefundEvent") {
436
+ const foundSwapData = swapsOpened[escrowHash];
437
+ delete swapsOpened[escrowHash];
438
+ const isExpired = foundSwapData != null && await this.isExpired(signer, foundSwapData.data);
439
+ resultingSwaps[escrowHash] = {
440
+ init: foundSwapData,
441
+ state: {
442
+ type: isExpired ? base_1.SwapCommitStateType.EXPIRED : base_1.SwapCommitStateType.NOT_COMMITED,
443
+ getInitTxId: foundSwapData?.getInitTxId,
444
+ getRefundTxId: () => Promise.resolve(txSignature),
445
+ getTxBlock: () => Promise.resolve({
446
+ blockHeight: tx.slot,
447
+ blockTime: tx.blockTime
448
+ })
449
+ }
450
+ };
451
+ }
452
+ }
453
+ this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(resultingSwaps).length} settled swaps!`);
454
+ this.logger.debug(`getHistoricalSwaps(): Found ${Object.keys(swapsOpened).length} unsettled swaps!`);
455
+ for (let escrowHash in swapsOpened) {
456
+ const foundSwapData = swapsOpened[escrowHash];
457
+ const isExpired = await this.isExpired(signer, foundSwapData.data);
458
+ resultingSwaps[escrowHash] = {
459
+ init: foundSwapData,
460
+ state: foundSwapData.data.isOfferer(signer) && isExpired
461
+ ? { type: base_1.SwapCommitStateType.REFUNDABLE, getInitTxId: foundSwapData.getInitTxId }
462
+ : { type: base_1.SwapCommitStateType.COMMITED, getInitTxId: foundSwapData.getInitTxId }
463
+ };
464
+ }
465
+ return {
466
+ swaps: resultingSwaps,
467
+ latestBlockheight: latestBlockheight ?? startBlockheight
468
+ };
469
+ }
470
+ ////////////////////////////////////////////
471
+ //// Swap data initializer
472
+ /**
473
+ * @inheritDoc
474
+ */
475
+ createSwapData(type, offerer, claimer, token, amount, claimHash, sequence, expiry, payIn, payOut, securityDeposit, claimerBounty, depositToken) {
476
+ if (depositToken != null) {
477
+ if (!new web3_js_1.PublicKey(depositToken).equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS))
478
+ throw new Error("Only SOL supported as deposit token!");
479
+ }
480
+ const tokenAddr = new web3_js_1.PublicKey(token);
481
+ const offererKey = new web3_js_1.PublicKey(offerer);
482
+ const claimerKey = new web3_js_1.PublicKey(claimer);
483
+ const { paymentHash, nonce, confirmations } = (0, Utils_1.fromClaimHash)(claimHash);
484
+ const swapData = new SolanaSwapData_1.SolanaSwapData({
485
+ programId: this.program.programId,
486
+ version: this.version,
487
+ offerer: offererKey,
488
+ claimer: claimerKey,
489
+ token: tokenAddr,
490
+ amount: (0, Utils_1.toBN)(amount),
491
+ paymentHash,
492
+ sequence: (0, Utils_1.toBN)(sequence),
493
+ expiry: (0, Utils_1.toBN)(expiry),
494
+ nonce,
495
+ confirmations,
496
+ payOut,
497
+ kind: SolanaSwapData_1.SolanaSwapData.typeToKind(type),
498
+ payIn,
499
+ offererAta: payIn ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, offererKey) : web3_js_1.PublicKey.default,
500
+ claimerAta: payOut ? (0, spl_token_1.getAssociatedTokenAddressSync)(tokenAddr, claimerKey) : web3_js_1.PublicKey.default,
501
+ securityDeposit: (0, Utils_1.toBN)(securityDeposit),
502
+ claimerBounty: (0, Utils_1.toBN)(claimerBounty)
503
+ });
504
+ return Promise.resolve(swapData);
505
+ }
506
+ ////////////////////////////////////////////
507
+ //// Utils
508
+ /**
509
+ * @inheritDoc
510
+ */
511
+ async getBalance(signer, tokenAddress, inContract) {
512
+ if (!inContract) {
513
+ return await this._Chain.getBalance(signer, tokenAddress);
514
+ }
515
+ const token = new web3_js_1.PublicKey(tokenAddress);
516
+ const publicKey = new web3_js_1.PublicKey(signer);
517
+ return await this.getIntermediaryBalance(publicKey, token);
518
+ }
519
+ /**
520
+ * @inheritDoc
521
+ */
522
+ getIntermediaryData(address, token) {
523
+ return this.LpVault.getIntermediaryData(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
524
+ }
525
+ /**
526
+ * @inheritDoc
527
+ */
528
+ getIntermediaryReputation(address, token) {
529
+ return this.LpVault.getIntermediaryReputation(new web3_js_1.PublicKey(address), new web3_js_1.PublicKey(token));
530
+ }
531
+ /**
532
+ * Returns intermediary vault balance for a specific token.
533
+ *
534
+ * @param address Intermediary address
535
+ * @param token Token mint
536
+ */
537
+ getIntermediaryBalance(address, token) {
538
+ return this.LpVault.getIntermediaryBalance(address, token);
539
+ }
540
+ ////////////////////////////////////////////
541
+ //// Transaction initializers
542
+ /**
543
+ * @inheritDoc
544
+ */
545
+ async txsClaimWithSecret(signer, swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck) {
546
+ return this.Claim.txsClaimWithSecret(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer.getPublicKey(), swapData, secret, checkExpiry, initAta, feeRate, skipAtaCheck);
547
+ }
548
+ /**
549
+ * @inheritDoc
550
+ */
551
+ async txsClaimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, feeRate) {
552
+ if (swapData.confirmations !== requiredConfirmations)
553
+ throw new Error("Invalid requiredConfirmations provided!");
554
+ const { txs } = await this.Claim.txsClaimWithTxData(typeof (signer) === "string" ? new web3_js_1.PublicKey(signer) : signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, feeRate);
555
+ return txs;
556
+ }
557
+ /**
558
+ * @inheritDoc
559
+ */
560
+ txsRefund(signer, swapData, check, initAta, feeRate) {
561
+ return this.Refund.txsRefund(new web3_js_1.PublicKey(signer), swapData, check, initAta, feeRate);
562
+ }
563
+ /**
564
+ * @inheritDoc
565
+ */
566
+ txsRefundWithAuthorization(signer, swapData, sig, check, initAta, feeRate) {
567
+ return this.Refund.txsRefundWithAuthorization(new web3_js_1.PublicKey(signer), swapData, sig.timeout, sig.prefix, sig.signature, check, initAta, feeRate);
568
+ }
569
+ /**
570
+ * @inheritDoc
571
+ */
572
+ txsInit(sender, swapData, sig, skipChecks, feeRate) {
573
+ if (swapData.isPayIn()) {
574
+ return this.Init.txsInitPayIn(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
575
+ }
576
+ else {
577
+ return this.Init.txsInit(new web3_js_1.PublicKey(sender), swapData, sig.timeout, sig.prefix, sig.signature, skipChecks, feeRate);
578
+ }
579
+ }
580
+ /**
581
+ * @inheritDoc
582
+ */
583
+ txsWithdraw(signer, token, amount, feeRate) {
584
+ return this.LpVault.txsWithdraw(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
585
+ }
586
+ /**
587
+ * @inheritDoc
588
+ */
589
+ txsDeposit(signer, token, amount, feeRate) {
590
+ return this.LpVault.txsDeposit(new web3_js_1.PublicKey(signer), new web3_js_1.PublicKey(token), amount, feeRate);
591
+ }
592
+ ////////////////////////////////////////////
593
+ //// Executors
594
+ /**
595
+ * @inheritDoc
596
+ */
597
+ async claimWithSecret(signer, swapData, secret, checkExpiry, initAta, txOptions) {
598
+ const result = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, checkExpiry, initAta, txOptions?.feeRate);
599
+ const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
600
+ return signature;
601
+ }
602
+ /**
603
+ * @inheritDoc
604
+ */
605
+ async claimWithTxData(signer, swapData, tx, requiredConfirmations, vout, commitedHeader, synchronizer, initAta, txOptions) {
606
+ if (requiredConfirmations !== swapData.confirmations)
607
+ throw new Error("Invalid requiredConfirmations provided!");
608
+ const { txs, claimTxIndex, storageAcc } = await this.Claim.txsClaimWithTxData(signer, swapData, tx, vout, commitedHeader, synchronizer, initAta, txOptions?.feeRate);
609
+ const signatures = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal);
610
+ await this._DataAccount.removeDataAccount(storageAcc);
611
+ return signatures[claimTxIndex] ?? signatures[0];
612
+ }
613
+ /**
614
+ * @inheritDoc
615
+ */
616
+ async refund(signer, swapData, check, initAta, txOptions) {
617
+ let result = await this.txsRefund(signer.getAddress(), swapData, check, initAta, txOptions?.feeRate);
618
+ const [signature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
619
+ return signature;
620
+ }
621
+ /**
622
+ * @inheritDoc
623
+ */
624
+ async refundWithAuthorization(signer, swapData, signature, check, initAta, txOptions) {
625
+ let result = await this.txsRefundWithAuthorization(signer.getAddress(), swapData, signature, check, initAta, txOptions?.feeRate);
626
+ const [txSignature] = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
627
+ return txSignature;
628
+ }
629
+ /**
630
+ * @inheritDoc
631
+ */
632
+ async init(signer, swapData, signature, skipChecks, txOptions) {
633
+ const result = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
634
+ const signatures = await this._Chain.sendAndConfirm(signer, result, txOptions?.waitForConfirmation, txOptions?.abortSignal);
635
+ return signatures[signatures.length - 1];
636
+ }
637
+ /**
638
+ * @inheritDoc
639
+ */
640
+ async initAndClaimWithSecret(signer, swapData, signature, secret, skipChecks, txOptions) {
641
+ if (!signer.getPublicKey().equals(swapData.claimer))
642
+ throw new Error("Invalid signer provided!");
643
+ const txsCommit = await this.txsInit(signer.getAddress(), swapData, signature, skipChecks, txOptions?.feeRate);
644
+ let txsClaim;
645
+ if (isSwapProgramV1(this.program)) {
646
+ // In V1 the initialize instruction has to contain the ATA initialization, hence we can skip checking it in claim
647
+ txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, false, txOptions?.feeRate, true);
648
+ }
649
+ else {
650
+ // In V2 the initialize instruction doesn't necessarily contain the ATA initialization, hence the claim instruction needs to
651
+ // check and initialize the ATA if needed
652
+ txsClaim = await this.Claim.txsClaimWithSecret(signer.getPublicKey(), swapData, secret, true, true, txOptions?.feeRate, false);
653
+ }
654
+ const signatures = await this._Chain.sendAndConfirm(signer, txsCommit.concat(txsClaim), txOptions?.waitForConfirmation, txOptions?.abortSignal);
655
+ return [signatures[txsCommit.length - 1], signatures[signatures.length - 1]];
656
+ }
657
+ /**
658
+ * @inheritDoc
659
+ */
660
+ async withdraw(signer, token, amount, txOptions) {
661
+ const txs = await this.LpVault.txsWithdraw(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
662
+ const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
663
+ return txId;
664
+ }
665
+ /**
666
+ * @inheritDoc
667
+ */
668
+ async deposit(signer, token, amount, txOptions) {
669
+ const txs = await this.LpVault.txsDeposit(signer.getPublicKey(), new web3_js_1.PublicKey(token), amount, txOptions?.feeRate);
670
+ const [txId] = await this._Chain.sendAndConfirm(signer, txs, txOptions?.waitForConfirmation, txOptions?.abortSignal, false);
671
+ return txId;
672
+ }
673
+ ////////////////////////////////////////////
674
+ //// Fees
675
+ /**
676
+ * @inheritDoc
677
+ */
678
+ getInitPayInFeeRate(offerer, claimer, token, claimHash) {
679
+ const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
680
+ return this.Init.getInitPayInFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
681
+ }
682
+ /**
683
+ * @inheritDoc
684
+ */
685
+ getInitFeeRate(offerer, claimer, token, claimHash) {
686
+ const paymentHash = claimHash == null ? undefined : (0, Utils_1.fromClaimHash)(claimHash).paymentHash;
687
+ return this.Init.getInitFeeRate(toPublicKeyOrNull(offerer), toPublicKeyOrNull(claimer), toPublicKeyOrNull(token), paymentHash);
688
+ }
689
+ /**
690
+ * @inheritDoc
691
+ */
692
+ getRefundFeeRate(swapData) {
693
+ return this.Refund.getRefundFeeRate(swapData);
694
+ }
695
+ /**
696
+ * @inheritDoc
697
+ */
698
+ getClaimFeeRate(signer, swapData) {
699
+ return this.Claim.getClaimFeeRate(new web3_js_1.PublicKey(signer), swapData);
700
+ }
701
+ /**
702
+ * @inheritDoc
703
+ */
704
+ getClaimFee(signer, swapData, feeRate) {
705
+ return this.Claim.getClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
706
+ }
707
+ /**
708
+ * @inheritDoc
709
+ */
710
+ getRawClaimFee(signer, swapData, feeRate) {
711
+ return this.Claim.getRawClaimFee(new web3_js_1.PublicKey(signer), swapData, feeRate);
712
+ }
713
+ /**
714
+ * @inheritDoc
715
+ */
716
+ getCommitFee(signer, swapData, feeRate) {
717
+ return this.Init.getInitFee(swapData, feeRate);
718
+ }
719
+ /**
720
+ * @inheritDoc
721
+ */
722
+ getRawCommitFee(signer, swapData, feeRate) {
723
+ return this.Init.getRawInitFee(swapData, feeRate);
724
+ }
725
+ /**
726
+ * @inheritDoc
727
+ */
728
+ getRefundFee(signer, swapData, feeRate) {
729
+ return this.Refund.getRefundFee(swapData, feeRate);
730
+ }
731
+ /**
732
+ * @inheritDoc
733
+ */
734
+ getRawRefundFee(signer, swapData, feeRate) {
735
+ return this.Refund.getRawRefundFee(swapData, feeRate);
736
+ }
737
+ /**
738
+ * @inheritDoc
739
+ */
740
+ getExtraData(outputScript, amount, confirmations, nonce) {
741
+ return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat([
742
+ base_1.BigIntBufferUtils.toBuffer(amount, "le", 8),
743
+ outputScript
744
+ ])));
745
+ }
746
+ }
747
+ exports.SolanaSwapProgram = SolanaSwapProgram;
748
+ ////////////////////////
749
+ //// PDA accessors
750
+ /**
751
+ * PDA of the swap vault authority.
752
+ * @internal
753
+ */
754
+ SolanaSwapProgram._SwapVaultAuthority = SolanaProgramBase_1.SolanaProgramBase._pda("authority"); // Only necessary for V1 program
755
+ /**
756
+ * PDA helper for global token vault accounts.
757
+ * @internal
758
+ */
759
+ SolanaSwapProgram._SwapVault = SolanaProgramBase_1.SolanaProgramBase._pda("vault", (tokenAddress) => [tokenAddress.toBuffer()]);
760
+ /**
761
+ * PDA helper for per-user token vault accounts.
762
+ * @internal
763
+ */
764
+ SolanaSwapProgram._SwapUserVault = SolanaProgramBase_1.SolanaProgramBase._pda("uservault", (publicKey, tokenAddress) => [publicKey.toBuffer(), tokenAddress.toBuffer()]);
765
+ /**
766
+ * PDA helper for escrow state accounts.
767
+ * @internal
768
+ */
769
+ SolanaSwapProgram._SwapEscrowState = SolanaProgramBase_1.SolanaProgramBase._pda("state", (hash) => [hash]);