@atomiqlabs/chain-solana 12.0.14 → 12.0.15

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 (114) hide show
  1. package/LICENSE +201 -201
  2. package/dist/index.d.ts +29 -29
  3. package/dist/index.js +45 -45
  4. package/dist/solana/SolanaChainType.d.ts +11 -11
  5. package/dist/solana/SolanaChainType.js +2 -2
  6. package/dist/solana/SolanaChains.d.ts +20 -20
  7. package/dist/solana/SolanaChains.js +25 -25
  8. package/dist/solana/SolanaInitializer.d.ts +18 -18
  9. package/dist/solana/SolanaInitializer.js +63 -63
  10. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +228 -228
  11. package/dist/solana/btcrelay/SolanaBtcRelay.js +441 -441
  12. package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +29 -29
  13. package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +34 -34
  14. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +46 -46
  15. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +78 -78
  16. package/dist/solana/btcrelay/program/programIdl.json +671 -671
  17. package/dist/solana/chain/SolanaAction.d.ts +26 -26
  18. package/dist/solana/chain/SolanaAction.js +86 -86
  19. package/dist/solana/chain/SolanaChainInterface.d.ts +65 -65
  20. package/dist/solana/chain/SolanaChainInterface.js +125 -125
  21. package/dist/solana/chain/SolanaModule.d.ts +14 -14
  22. package/dist/solana/chain/SolanaModule.js +13 -13
  23. package/dist/solana/chain/modules/SolanaAddresses.d.ts +8 -8
  24. package/dist/solana/chain/modules/SolanaAddresses.js +22 -22
  25. package/dist/solana/chain/modules/SolanaBlocks.d.ts +28 -28
  26. package/dist/solana/chain/modules/SolanaBlocks.js +72 -72
  27. package/dist/solana/chain/modules/SolanaEvents.d.ts +68 -68
  28. package/dist/solana/chain/modules/SolanaEvents.js +238 -238
  29. package/dist/solana/chain/modules/SolanaFees.d.ts +121 -121
  30. package/dist/solana/chain/modules/SolanaFees.js +379 -379
  31. package/dist/solana/chain/modules/SolanaSignatures.d.ts +23 -23
  32. package/dist/solana/chain/modules/SolanaSignatures.js +39 -39
  33. package/dist/solana/chain/modules/SolanaSlots.d.ts +31 -31
  34. package/dist/solana/chain/modules/SolanaSlots.js +68 -68
  35. package/dist/solana/chain/modules/SolanaTokens.d.ts +136 -136
  36. package/dist/solana/chain/modules/SolanaTokens.js +248 -248
  37. package/dist/solana/chain/modules/SolanaTransactions.d.ts +124 -124
  38. package/dist/solana/chain/modules/SolanaTransactions.js +323 -323
  39. package/dist/solana/events/SolanaChainEvents.d.ts +88 -88
  40. package/dist/solana/events/SolanaChainEvents.js +256 -256
  41. package/dist/solana/events/SolanaChainEventsBrowser.d.ts +75 -75
  42. package/dist/solana/events/SolanaChainEventsBrowser.js +172 -172
  43. package/dist/solana/program/SolanaProgramBase.d.ts +40 -40
  44. package/dist/solana/program/SolanaProgramBase.js +43 -43
  45. package/dist/solana/program/SolanaProgramModule.d.ts +8 -8
  46. package/dist/solana/program/SolanaProgramModule.js +11 -11
  47. package/dist/solana/program/modules/SolanaProgramEvents.d.ts +53 -53
  48. package/dist/solana/program/modules/SolanaProgramEvents.js +114 -114
  49. package/dist/solana/swaps/SolanaSwapData.d.ts +71 -71
  50. package/dist/solana/swaps/SolanaSwapData.js +292 -292
  51. package/dist/solana/swaps/SolanaSwapModule.d.ts +10 -10
  52. package/dist/solana/swaps/SolanaSwapModule.js +11 -11
  53. package/dist/solana/swaps/SolanaSwapProgram.d.ts +224 -224
  54. package/dist/solana/swaps/SolanaSwapProgram.js +570 -570
  55. package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -11
  56. package/dist/solana/swaps/SwapTypeEnum.js +42 -42
  57. package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +94 -94
  58. package/dist/solana/swaps/modules/SolanaDataAccount.js +231 -231
  59. package/dist/solana/swaps/modules/SolanaLpVault.d.ts +71 -71
  60. package/dist/solana/swaps/modules/SolanaLpVault.js +173 -173
  61. package/dist/solana/swaps/modules/SwapClaim.d.ts +129 -129
  62. package/dist/solana/swaps/modules/SwapClaim.js +291 -291
  63. package/dist/solana/swaps/modules/SwapInit.d.ts +217 -217
  64. package/dist/solana/swaps/modules/SwapInit.js +519 -519
  65. package/dist/solana/swaps/modules/SwapRefund.d.ts +82 -82
  66. package/dist/solana/swaps/modules/SwapRefund.js +262 -262
  67. package/dist/solana/swaps/programIdl.json +945 -945
  68. package/dist/solana/swaps/programTypes.d.ts +943 -943
  69. package/dist/solana/swaps/programTypes.js +945 -945
  70. package/dist/solana/wallet/SolanaKeypairWallet.d.ts +9 -9
  71. package/dist/solana/wallet/SolanaKeypairWallet.js +33 -33
  72. package/dist/solana/wallet/SolanaSigner.d.ts +11 -11
  73. package/dist/solana/wallet/SolanaSigner.js +17 -17
  74. package/dist/utils/Utils.d.ts +53 -53
  75. package/dist/utils/Utils.js +170 -170
  76. package/package.json +41 -41
  77. package/src/index.ts +36 -36
  78. package/src/solana/SolanaChainType.ts +27 -27
  79. package/src/solana/SolanaChains.ts +23 -23
  80. package/src/solana/SolanaInitializer.ts +102 -102
  81. package/src/solana/btcrelay/SolanaBtcRelay.ts +589 -589
  82. package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +57 -57
  83. package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +102 -102
  84. package/src/solana/btcrelay/program/programIdl.json +670 -670
  85. package/src/solana/chain/SolanaAction.ts +108 -108
  86. package/src/solana/chain/SolanaChainInterface.ts +192 -192
  87. package/src/solana/chain/SolanaModule.ts +20 -20
  88. package/src/solana/chain/modules/SolanaAddresses.ts +20 -20
  89. package/src/solana/chain/modules/SolanaBlocks.ts +78 -78
  90. package/src/solana/chain/modules/SolanaEvents.ts +270 -270
  91. package/src/solana/chain/modules/SolanaFees.ts +450 -450
  92. package/src/solana/chain/modules/SolanaSignatures.ts +39 -39
  93. package/src/solana/chain/modules/SolanaSlots.ts +82 -82
  94. package/src/solana/chain/modules/SolanaTokens.ts +307 -307
  95. package/src/solana/chain/modules/SolanaTransactions.ts +365 -365
  96. package/src/solana/events/SolanaChainEvents.ts +299 -299
  97. package/src/solana/events/SolanaChainEventsBrowser.ts +209 -209
  98. package/src/solana/program/SolanaProgramBase.ts +79 -79
  99. package/src/solana/program/SolanaProgramModule.ts +15 -15
  100. package/src/solana/program/modules/SolanaProgramEvents.ts +155 -155
  101. package/src/solana/swaps/SolanaSwapData.ts +430 -430
  102. package/src/solana/swaps/SolanaSwapModule.ts +16 -16
  103. package/src/solana/swaps/SolanaSwapProgram.ts +854 -854
  104. package/src/solana/swaps/SwapTypeEnum.ts +29 -29
  105. package/src/solana/swaps/modules/SolanaDataAccount.ts +307 -307
  106. package/src/solana/swaps/modules/SolanaLpVault.ts +215 -215
  107. package/src/solana/swaps/modules/SwapClaim.ts +389 -389
  108. package/src/solana/swaps/modules/SwapInit.ts +663 -663
  109. package/src/solana/swaps/modules/SwapRefund.ts +323 -323
  110. package/src/solana/swaps/programIdl.json +944 -944
  111. package/src/solana/swaps/programTypes.ts +1885 -1885
  112. package/src/solana/wallet/SolanaKeypairWallet.ts +36 -36
  113. package/src/solana/wallet/SolanaSigner.ts +24 -24
  114. package/src/utils/Utils.ts +180 -180
@@ -1,262 +1,262 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SwapRefund = void 0;
4
- const SolanaSwapModule_1 = require("../SolanaSwapModule");
5
- const sha2_1 = require("@noble/hashes/sha2");
6
- const tweetnacl_1 = require("tweetnacl");
7
- const base_1 = require("@atomiqlabs/base");
8
- const web3_js_1 = require("@solana/web3.js");
9
- const spl_token_1 = require("@solana/spl-token");
10
- const SolanaAction_1 = require("../../chain/SolanaAction");
11
- const Utils_1 = require("../../../utils/Utils");
12
- const buffer_1 = require("buffer");
13
- const SolanaTokens_1 = require("../../chain/modules/SolanaTokens");
14
- const BN = require("bn.js");
15
- class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
16
- /**
17
- * Action for generic Refund instruction
18
- *
19
- * @param swapData
20
- * @param refundAuthTimeout optional refund authorization timeout (should be 0 for refunding expired swaps)
21
- * @constructor
22
- * @private
23
- */
24
- async Refund(swapData, refundAuthTimeout) {
25
- const accounts = {
26
- offerer: swapData.offerer,
27
- claimer: swapData.claimer,
28
- escrowState: this.program.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")),
29
- claimerUserData: !swapData.payOut ? this.program.SwapUserVault(swapData.claimer, swapData.token) : null,
30
- ixSysvar: refundAuthTimeout != null ? web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY : null
31
- };
32
- const useTimeout = refundAuthTimeout != null ? refundAuthTimeout : 0n;
33
- if (swapData.isPayIn()) {
34
- const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.offerer);
35
- return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, await this.swapProgram.methods
36
- .offererRefundPayIn((0, Utils_1.toBN)(useTimeout))
37
- .accounts({
38
- ...accounts,
39
- offererAta: ata,
40
- vault: this.program.SwapVault(swapData.token),
41
- vaultAuthority: this.program.SwapVaultAuthority,
42
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID
43
- })
44
- .instruction(), SwapRefund.CUCosts.REFUND_PAY_OUT);
45
- }
46
- else {
47
- return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, await this.swapProgram.methods
48
- .offererRefund((0, Utils_1.toBN)(useTimeout))
49
- .accounts({
50
- ...accounts,
51
- offererUserData: this.program.SwapUserVault(swapData.offerer, swapData.token)
52
- })
53
- .instruction(), SwapRefund.CUCosts.REFUND);
54
- }
55
- }
56
- /**
57
- * Action for refunding with signature, adds the Ed25519 verify instruction
58
- *
59
- * @param swapData
60
- * @param timeout
61
- * @param prefix
62
- * @param signature
63
- * @constructor
64
- * @private
65
- */
66
- async RefundWithSignature(swapData, timeout, prefix, signature) {
67
- const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root, web3_js_1.Ed25519Program.createInstructionWithPublicKey({
68
- message: this.getRefundMessage(swapData, prefix, timeout),
69
- publicKey: swapData.claimer.toBuffer(),
70
- signature: signature
71
- }), 0, null, null, true);
72
- action.addAction(await this.Refund(swapData, BigInt(timeout)));
73
- return action;
74
- }
75
- /**
76
- * Gets the message to be signed as a refund authorization
77
- *
78
- * @param swapData
79
- * @param prefix
80
- * @param timeout
81
- * @private
82
- */
83
- getRefundMessage(swapData, prefix, timeout) {
84
- const messageBuffers = [
85
- buffer_1.Buffer.from(prefix, "ascii"),
86
- swapData.amount.toArrayLike(buffer_1.Buffer, "le", 8),
87
- swapData.expiry.toArrayLike(buffer_1.Buffer, "le", 8),
88
- swapData.sequence.toArrayLike(buffer_1.Buffer, "le", 8),
89
- buffer_1.Buffer.from(swapData.paymentHash, "hex"),
90
- new BN(timeout).toArrayLike(buffer_1.Buffer, "le", 8)
91
- ];
92
- return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat(messageBuffers)));
93
- }
94
- /**
95
- * Checks whether we should unwrap the WSOL to SOL when refunding the swap
96
- *
97
- * @param swapData
98
- * @private
99
- */
100
- shouldUnwrap(swapData) {
101
- return swapData.isPayIn() &&
102
- swapData.token.equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS) &&
103
- swapData.offerer.equals(swapData.offerer);
104
- }
105
- signSwapRefund(signer, swapData, authorizationTimeout) {
106
- if (signer.keypair == null)
107
- throw new Error("Unsupported");
108
- if (!signer.getPublicKey().equals(swapData.claimer))
109
- throw new Error("Invalid signer, public key mismatch!");
110
- const authPrefix = "refund";
111
- const authTimeout = Math.floor(Date.now() / 1000) + authorizationTimeout;
112
- const messageBuffer = this.getRefundMessage(swapData, authPrefix, authTimeout.toString(10));
113
- const signature = tweetnacl_1.sign.detached(messageBuffer, signer.keypair.secretKey);
114
- return Promise.resolve({
115
- prefix: authPrefix,
116
- timeout: authTimeout.toString(10),
117
- signature: buffer_1.Buffer.from(signature).toString("hex")
118
- });
119
- }
120
- isSignatureValid(swapData, timeout, prefix, signature) {
121
- if (prefix !== "refund")
122
- throw new base_1.SignatureVerificationError("Invalid prefix");
123
- const expiryTimestamp = BigInt(timeout);
124
- const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
125
- const isExpired = (expiryTimestamp - currentTimestamp) < BigInt(this.program.authGracePeriod);
126
- if (isExpired)
127
- throw new base_1.SignatureVerificationError("Authorization expired!");
128
- const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
129
- const messageBuffer = this.getRefundMessage(swapData, prefix, timeout);
130
- if (!tweetnacl_1.sign.detached.verify(messageBuffer, signatureBuffer, swapData.claimer.toBuffer())) {
131
- throw new base_1.SignatureVerificationError("Invalid signature!");
132
- }
133
- return Promise.resolve(messageBuffer);
134
- }
135
- /**
136
- * Creates transactions required for refunding timed out swap, also unwraps WSOL to SOL
137
- *
138
- * @param swapData swap data to refund
139
- * @param check whether to check if swap is already expired and refundable
140
- * @param initAta should initialize ATA if it doesn't exist
141
- * @param feeRate fee rate to be used for the transactions
142
- */
143
- async txsRefund(swapData, check, initAta, feeRate) {
144
- if (check && !await (0, Utils_1.tryWithRetries)(() => this.program.isRequestRefundable(swapData.offerer.toString(), swapData), this.retryPolicy)) {
145
- throw new base_1.SwapDataVerificationError("Not refundable yet!");
146
- }
147
- const shouldInitAta = swapData.isPayIn() && !await this.root.Tokens.ataExists(swapData.offererAta);
148
- if (shouldInitAta && !initAta)
149
- throw new base_1.SwapDataVerificationError("ATA not initialized");
150
- if (feeRate == null)
151
- feeRate = await this.program.getRefundFeeRate(swapData);
152
- const shouldUnwrap = this.shouldUnwrap(swapData);
153
- const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root);
154
- if (shouldInitAta) {
155
- const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
156
- if (initAction == null)
157
- throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
158
- action.addAction(initAction);
159
- }
160
- action.add(await this.Refund(swapData));
161
- if (shouldUnwrap)
162
- action.add(this.root.Tokens.Unwrap(swapData.offerer));
163
- this.logger.debug("txsRefund(): creating claim transaction, swap: " + swapData.getClaimHash() +
164
- " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap);
165
- return [await action.tx(feeRate)];
166
- }
167
- /**
168
- * Creates transactions required for refunding the swap with authorization signature, also unwraps WSOL to SOL
169
- *
170
- * @param swapData swap data to refund
171
- * @param timeout signature timeout
172
- * @param prefix signature prefix of the counterparty
173
- * @param signature signature of the counterparty
174
- * @param check whether to check if swap is committed before attempting refund
175
- * @param initAta should initialize ATA if it doesn't exist
176
- * @param feeRate fee rate to be used for the transactions
177
- */
178
- async txsRefundWithAuthorization(swapData, timeout, prefix, signature, check, initAta, feeRate) {
179
- if (check && !await (0, Utils_1.tryWithRetries)(() => this.program.isCommited(swapData), this.retryPolicy)) {
180
- throw new base_1.SwapDataVerificationError("Not correctly committed");
181
- }
182
- await (0, Utils_1.tryWithRetries)(() => this.isSignatureValid(swapData, timeout, prefix, signature), this.retryPolicy, (e) => e instanceof base_1.SignatureVerificationError);
183
- const shouldInitAta = swapData.isPayIn() && !await this.root.Tokens.ataExists(swapData.offererAta);
184
- if (shouldInitAta && !initAta)
185
- throw new base_1.SwapDataVerificationError("ATA not initialized");
186
- if (feeRate == null)
187
- feeRate = await this.program.getRefundFeeRate(swapData);
188
- const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
189
- const shouldUnwrap = this.shouldUnwrap(swapData);
190
- const action = await this.RefundWithSignature(swapData, timeout, prefix, signatureBuffer);
191
- if (shouldInitAta) {
192
- const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
193
- if (initAction == null)
194
- throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
195
- action.addAction(initAction, 1); //Need to add it after the Ed25519 verify IX, but before the actual refund IX
196
- }
197
- if (shouldUnwrap)
198
- action.add(this.root.Tokens.Unwrap(swapData.offerer));
199
- this.logger.debug("txsRefundWithAuthorization(): creating claim transaction, swap: " + swapData.getClaimHash() +
200
- " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap +
201
- " auth expiry: " + timeout + " signature: " + signature);
202
- //Push a random keypair to the TX signer such that pesky Phantom
203
- // doesn't fuck up the instructions order!
204
- const tx = await action.tx(feeRate);
205
- const signer = web3_js_1.Keypair.generate();
206
- tx.tx.instructions.find(val => val.programId.equals(this.program.program.programId)).keys.push({
207
- pubkey: signer.publicKey,
208
- isSigner: true,
209
- isWritable: false
210
- });
211
- (tx.signers ?? (tx.signers = [])).push(signer);
212
- return [tx];
213
- }
214
- getRefundFeeRate(swapData) {
215
- const accounts = [];
216
- if (swapData.payIn) {
217
- if (swapData.token != null)
218
- accounts.push(this.program.SwapVault(swapData.token));
219
- if (swapData.offerer != null)
220
- accounts.push(swapData.offerer);
221
- if (swapData.claimer != null)
222
- accounts.push(swapData.claimer);
223
- if (swapData.offererAta != null && !swapData.offererAta.equals(web3_js_1.PublicKey.default))
224
- accounts.push(swapData.offererAta);
225
- }
226
- else {
227
- if (swapData.offerer != null) {
228
- accounts.push(swapData.offerer);
229
- if (swapData.token != null)
230
- accounts.push(this.program.SwapUserVault(swapData.offerer, swapData.token));
231
- }
232
- if (swapData.claimer != null)
233
- accounts.push(swapData.claimer);
234
- }
235
- if (swapData.paymentHash != null)
236
- accounts.push(this.program.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")));
237
- return this.root.Fees.getFeeRate(accounts);
238
- }
239
- /**
240
- * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
241
- * ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
242
- */
243
- async getRefundFee(swapData, feeRate) {
244
- return BigInt(swapData == null || swapData.payIn ? SolanaTokens_1.SolanaTokens.SPL_ATA_RENT_EXEMPT : 0) +
245
- await this.getRawRefundFee(swapData, feeRate);
246
- }
247
- /**
248
- * Get the estimated solana transaction fee of the refund transaction
249
- */
250
- async getRawRefundFee(swapData, feeRate) {
251
- if (swapData == null)
252
- return 15000n;
253
- feeRate = feeRate || await this.getRefundFeeRate(swapData);
254
- const computeBudget = swapData.payIn ? SwapRefund.CUCosts.REFUND_PAY_OUT : SwapRefund.CUCosts.REFUND;
255
- return 15000n + this.root.Fees.getPriorityFee(computeBudget, feeRate);
256
- }
257
- }
258
- exports.SwapRefund = SwapRefund;
259
- SwapRefund.CUCosts = {
260
- REFUND: 15000,
261
- REFUND_PAY_OUT: 50000
262
- };
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SwapRefund = void 0;
4
+ const SolanaSwapModule_1 = require("../SolanaSwapModule");
5
+ const sha2_1 = require("@noble/hashes/sha2");
6
+ const tweetnacl_1 = require("tweetnacl");
7
+ const base_1 = require("@atomiqlabs/base");
8
+ const web3_js_1 = require("@solana/web3.js");
9
+ const spl_token_1 = require("@solana/spl-token");
10
+ const SolanaAction_1 = require("../../chain/SolanaAction");
11
+ const Utils_1 = require("../../../utils/Utils");
12
+ const buffer_1 = require("buffer");
13
+ const SolanaTokens_1 = require("../../chain/modules/SolanaTokens");
14
+ const BN = require("bn.js");
15
+ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
16
+ /**
17
+ * Action for generic Refund instruction
18
+ *
19
+ * @param swapData
20
+ * @param refundAuthTimeout optional refund authorization timeout (should be 0 for refunding expired swaps)
21
+ * @constructor
22
+ * @private
23
+ */
24
+ async Refund(swapData, refundAuthTimeout) {
25
+ const accounts = {
26
+ offerer: swapData.offerer,
27
+ claimer: swapData.claimer,
28
+ escrowState: this.program.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")),
29
+ claimerUserData: !swapData.payOut ? this.program.SwapUserVault(swapData.claimer, swapData.token) : null,
30
+ ixSysvar: refundAuthTimeout != null ? web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY : null
31
+ };
32
+ const useTimeout = refundAuthTimeout != null ? refundAuthTimeout : 0n;
33
+ if (swapData.isPayIn()) {
34
+ const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.offerer);
35
+ return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, await this.swapProgram.methods
36
+ .offererRefundPayIn((0, Utils_1.toBN)(useTimeout))
37
+ .accounts({
38
+ ...accounts,
39
+ offererAta: ata,
40
+ vault: this.program.SwapVault(swapData.token),
41
+ vaultAuthority: this.program.SwapVaultAuthority,
42
+ tokenProgram: spl_token_1.TOKEN_PROGRAM_ID
43
+ })
44
+ .instruction(), SwapRefund.CUCosts.REFUND_PAY_OUT);
45
+ }
46
+ else {
47
+ return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, await this.swapProgram.methods
48
+ .offererRefund((0, Utils_1.toBN)(useTimeout))
49
+ .accounts({
50
+ ...accounts,
51
+ offererUserData: this.program.SwapUserVault(swapData.offerer, swapData.token)
52
+ })
53
+ .instruction(), SwapRefund.CUCosts.REFUND);
54
+ }
55
+ }
56
+ /**
57
+ * Action for refunding with signature, adds the Ed25519 verify instruction
58
+ *
59
+ * @param swapData
60
+ * @param timeout
61
+ * @param prefix
62
+ * @param signature
63
+ * @constructor
64
+ * @private
65
+ */
66
+ async RefundWithSignature(swapData, timeout, prefix, signature) {
67
+ const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root, web3_js_1.Ed25519Program.createInstructionWithPublicKey({
68
+ message: this.getRefundMessage(swapData, prefix, timeout),
69
+ publicKey: swapData.claimer.toBuffer(),
70
+ signature: signature
71
+ }), 0, null, null, true);
72
+ action.addAction(await this.Refund(swapData, BigInt(timeout)));
73
+ return action;
74
+ }
75
+ /**
76
+ * Gets the message to be signed as a refund authorization
77
+ *
78
+ * @param swapData
79
+ * @param prefix
80
+ * @param timeout
81
+ * @private
82
+ */
83
+ getRefundMessage(swapData, prefix, timeout) {
84
+ const messageBuffers = [
85
+ buffer_1.Buffer.from(prefix, "ascii"),
86
+ swapData.amount.toArrayLike(buffer_1.Buffer, "le", 8),
87
+ swapData.expiry.toArrayLike(buffer_1.Buffer, "le", 8),
88
+ swapData.sequence.toArrayLike(buffer_1.Buffer, "le", 8),
89
+ buffer_1.Buffer.from(swapData.paymentHash, "hex"),
90
+ new BN(timeout).toArrayLike(buffer_1.Buffer, "le", 8)
91
+ ];
92
+ return buffer_1.Buffer.from((0, sha2_1.sha256)(buffer_1.Buffer.concat(messageBuffers)));
93
+ }
94
+ /**
95
+ * Checks whether we should unwrap the WSOL to SOL when refunding the swap
96
+ *
97
+ * @param swapData
98
+ * @private
99
+ */
100
+ shouldUnwrap(swapData) {
101
+ return swapData.isPayIn() &&
102
+ swapData.token.equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS) &&
103
+ swapData.offerer.equals(swapData.offerer);
104
+ }
105
+ signSwapRefund(signer, swapData, authorizationTimeout) {
106
+ if (signer.keypair == null)
107
+ throw new Error("Unsupported");
108
+ if (!signer.getPublicKey().equals(swapData.claimer))
109
+ throw new Error("Invalid signer, public key mismatch!");
110
+ const authPrefix = "refund";
111
+ const authTimeout = Math.floor(Date.now() / 1000) + authorizationTimeout;
112
+ const messageBuffer = this.getRefundMessage(swapData, authPrefix, authTimeout.toString(10));
113
+ const signature = tweetnacl_1.sign.detached(messageBuffer, signer.keypair.secretKey);
114
+ return Promise.resolve({
115
+ prefix: authPrefix,
116
+ timeout: authTimeout.toString(10),
117
+ signature: buffer_1.Buffer.from(signature).toString("hex")
118
+ });
119
+ }
120
+ isSignatureValid(swapData, timeout, prefix, signature) {
121
+ if (prefix !== "refund")
122
+ throw new base_1.SignatureVerificationError("Invalid prefix");
123
+ const expiryTimestamp = BigInt(timeout);
124
+ const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
125
+ const isExpired = (expiryTimestamp - currentTimestamp) < BigInt(this.program.authGracePeriod);
126
+ if (isExpired)
127
+ throw new base_1.SignatureVerificationError("Authorization expired!");
128
+ const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
129
+ const messageBuffer = this.getRefundMessage(swapData, prefix, timeout);
130
+ if (!tweetnacl_1.sign.detached.verify(messageBuffer, signatureBuffer, swapData.claimer.toBuffer())) {
131
+ throw new base_1.SignatureVerificationError("Invalid signature!");
132
+ }
133
+ return Promise.resolve(messageBuffer);
134
+ }
135
+ /**
136
+ * Creates transactions required for refunding timed out swap, also unwraps WSOL to SOL
137
+ *
138
+ * @param swapData swap data to refund
139
+ * @param check whether to check if swap is already expired and refundable
140
+ * @param initAta should initialize ATA if it doesn't exist
141
+ * @param feeRate fee rate to be used for the transactions
142
+ */
143
+ async txsRefund(swapData, check, initAta, feeRate) {
144
+ if (check && !await (0, Utils_1.tryWithRetries)(() => this.program.isRequestRefundable(swapData.offerer.toString(), swapData), this.retryPolicy)) {
145
+ throw new base_1.SwapDataVerificationError("Not refundable yet!");
146
+ }
147
+ const shouldInitAta = swapData.isPayIn() && !await this.root.Tokens.ataExists(swapData.offererAta);
148
+ if (shouldInitAta && !initAta)
149
+ throw new base_1.SwapDataVerificationError("ATA not initialized");
150
+ if (feeRate == null)
151
+ feeRate = await this.program.getRefundFeeRate(swapData);
152
+ const shouldUnwrap = this.shouldUnwrap(swapData);
153
+ const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root);
154
+ if (shouldInitAta) {
155
+ const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
156
+ if (initAction == null)
157
+ throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
158
+ action.addAction(initAction);
159
+ }
160
+ action.add(await this.Refund(swapData));
161
+ if (shouldUnwrap)
162
+ action.add(this.root.Tokens.Unwrap(swapData.offerer));
163
+ this.logger.debug("txsRefund(): creating claim transaction, swap: " + swapData.getClaimHash() +
164
+ " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap);
165
+ return [await action.tx(feeRate)];
166
+ }
167
+ /**
168
+ * Creates transactions required for refunding the swap with authorization signature, also unwraps WSOL to SOL
169
+ *
170
+ * @param swapData swap data to refund
171
+ * @param timeout signature timeout
172
+ * @param prefix signature prefix of the counterparty
173
+ * @param signature signature of the counterparty
174
+ * @param check whether to check if swap is committed before attempting refund
175
+ * @param initAta should initialize ATA if it doesn't exist
176
+ * @param feeRate fee rate to be used for the transactions
177
+ */
178
+ async txsRefundWithAuthorization(swapData, timeout, prefix, signature, check, initAta, feeRate) {
179
+ if (check && !await (0, Utils_1.tryWithRetries)(() => this.program.isCommited(swapData), this.retryPolicy)) {
180
+ throw new base_1.SwapDataVerificationError("Not correctly committed");
181
+ }
182
+ await (0, Utils_1.tryWithRetries)(() => this.isSignatureValid(swapData, timeout, prefix, signature), this.retryPolicy, (e) => e instanceof base_1.SignatureVerificationError);
183
+ const shouldInitAta = swapData.isPayIn() && !await this.root.Tokens.ataExists(swapData.offererAta);
184
+ if (shouldInitAta && !initAta)
185
+ throw new base_1.SwapDataVerificationError("ATA not initialized");
186
+ if (feeRate == null)
187
+ feeRate = await this.program.getRefundFeeRate(swapData);
188
+ const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
189
+ const shouldUnwrap = this.shouldUnwrap(swapData);
190
+ const action = await this.RefundWithSignature(swapData, timeout, prefix, signatureBuffer);
191
+ if (shouldInitAta) {
192
+ const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
193
+ if (initAction == null)
194
+ throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
195
+ action.addAction(initAction, 1); //Need to add it after the Ed25519 verify IX, but before the actual refund IX
196
+ }
197
+ if (shouldUnwrap)
198
+ action.add(this.root.Tokens.Unwrap(swapData.offerer));
199
+ this.logger.debug("txsRefundWithAuthorization(): creating claim transaction, swap: " + swapData.getClaimHash() +
200
+ " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap +
201
+ " auth expiry: " + timeout + " signature: " + signature);
202
+ //Push a random keypair to the TX signer such that pesky Phantom
203
+ // doesn't fuck up the instructions order!
204
+ const tx = await action.tx(feeRate);
205
+ const signer = web3_js_1.Keypair.generate();
206
+ tx.tx.instructions.find(val => val.programId.equals(this.program.program.programId)).keys.push({
207
+ pubkey: signer.publicKey,
208
+ isSigner: true,
209
+ isWritable: false
210
+ });
211
+ (tx.signers ?? (tx.signers = [])).push(signer);
212
+ return [tx];
213
+ }
214
+ getRefundFeeRate(swapData) {
215
+ const accounts = [];
216
+ if (swapData.payIn) {
217
+ if (swapData.token != null)
218
+ accounts.push(this.program.SwapVault(swapData.token));
219
+ if (swapData.offerer != null)
220
+ accounts.push(swapData.offerer);
221
+ if (swapData.claimer != null)
222
+ accounts.push(swapData.claimer);
223
+ if (swapData.offererAta != null && !swapData.offererAta.equals(web3_js_1.PublicKey.default))
224
+ accounts.push(swapData.offererAta);
225
+ }
226
+ else {
227
+ if (swapData.offerer != null) {
228
+ accounts.push(swapData.offerer);
229
+ if (swapData.token != null)
230
+ accounts.push(this.program.SwapUserVault(swapData.offerer, swapData.token));
231
+ }
232
+ if (swapData.claimer != null)
233
+ accounts.push(swapData.claimer);
234
+ }
235
+ if (swapData.paymentHash != null)
236
+ accounts.push(this.program.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")));
237
+ return this.root.Fees.getFeeRate(accounts);
238
+ }
239
+ /**
240
+ * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
241
+ * ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
242
+ */
243
+ async getRefundFee(swapData, feeRate) {
244
+ return BigInt(swapData == null || swapData.payIn ? SolanaTokens_1.SolanaTokens.SPL_ATA_RENT_EXEMPT : 0) +
245
+ await this.getRawRefundFee(swapData, feeRate);
246
+ }
247
+ /**
248
+ * Get the estimated solana transaction fee of the refund transaction
249
+ */
250
+ async getRawRefundFee(swapData, feeRate) {
251
+ if (swapData == null)
252
+ return 15000n;
253
+ feeRate = feeRate || await this.getRefundFeeRate(swapData);
254
+ const computeBudget = swapData.payIn ? SwapRefund.CUCosts.REFUND_PAY_OUT : SwapRefund.CUCosts.REFUND;
255
+ return 15000n + this.root.Fees.getPriorityFee(computeBudget, feeRate);
256
+ }
257
+ }
258
+ exports.SwapRefund = SwapRefund;
259
+ SwapRefund.CUCosts = {
260
+ REFUND: 15000,
261
+ REFUND_PAY_OUT: 50000
262
+ };