@atomiqlabs/chain-solana 7.3.8 → 8.0.0-beta.0

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 (57) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/solana/SolanaChains.d.ts +14 -0
  4. package/dist/solana/SolanaChains.js +18 -0
  5. package/dist/solana/SolanaInitializer.d.ts +18 -0
  6. package/dist/solana/SolanaInitializer.js +59 -0
  7. package/dist/solana/base/SolanaAction.js +25 -38
  8. package/dist/solana/base/modules/SolanaBlocks.js +18 -29
  9. package/dist/solana/base/modules/SolanaEvents.js +15 -26
  10. package/dist/solana/base/modules/SolanaFees.d.ts +4 -5
  11. package/dist/solana/base/modules/SolanaFees.js +168 -182
  12. package/dist/solana/base/modules/SolanaSlots.js +16 -29
  13. package/dist/solana/base/modules/SolanaTokens.d.ts +6 -7
  14. package/dist/solana/base/modules/SolanaTokens.js +63 -84
  15. package/dist/solana/base/modules/SolanaTransactions.d.ts +2 -2
  16. package/dist/solana/base/modules/SolanaTransactions.js +143 -165
  17. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +2 -3
  18. package/dist/solana/btcrelay/SolanaBtcRelay.js +185 -221
  19. package/dist/solana/events/SolanaChainEvents.js +113 -138
  20. package/dist/solana/events/SolanaChainEventsBrowser.js +56 -65
  21. package/dist/solana/program/modules/SolanaProgramEvents.js +13 -24
  22. package/dist/solana/swaps/SolanaSwapData.d.ts +15 -11
  23. package/dist/solana/swaps/SolanaSwapData.js +29 -13
  24. package/dist/solana/swaps/SolanaSwapProgram.d.ts +40 -41
  25. package/dist/solana/swaps/SolanaSwapProgram.js +212 -221
  26. package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +2 -3
  27. package/dist/solana/swaps/modules/SolanaDataAccount.js +117 -141
  28. package/dist/solana/swaps/modules/SolanaLpVault.d.ts +4 -5
  29. package/dist/solana/swaps/modules/SolanaLpVault.js +87 -110
  30. package/dist/solana/swaps/modules/SwapClaim.d.ts +4 -4
  31. package/dist/solana/swaps/modules/SwapClaim.js +122 -134
  32. package/dist/solana/swaps/modules/SwapInit.d.ts +2 -3
  33. package/dist/solana/swaps/modules/SwapInit.js +254 -285
  34. package/dist/solana/swaps/modules/SwapRefund.d.ts +2 -3
  35. package/dist/solana/swaps/modules/SwapRefund.js +103 -113
  36. package/dist/utils/Utils.d.ts +10 -0
  37. package/dist/utils/Utils.js +62 -35
  38. package/package.json +9 -6
  39. package/src/index.ts +1 -0
  40. package/src/solana/SolanaChains.ts +16 -0
  41. package/src/solana/SolanaInitializer.ts +98 -0
  42. package/src/solana/base/SolanaBase.ts +1 -2
  43. package/src/solana/base/modules/SolanaEvents.ts +0 -1
  44. package/src/solana/base/modules/SolanaFees.ts +35 -31
  45. package/src/solana/base/modules/SolanaTokens.ts +26 -27
  46. package/src/solana/base/modules/SolanaTransactions.ts +33 -28
  47. package/src/solana/btcrelay/SolanaBtcRelay.ts +6 -10
  48. package/src/solana/events/SolanaChainEventsBrowser.ts +14 -10
  49. package/src/solana/program/modules/SolanaProgramEvents.ts +1 -1
  50. package/src/solana/swaps/SolanaSwapData.ts +38 -19
  51. package/src/solana/swaps/SolanaSwapProgram.ts +133 -105
  52. package/src/solana/swaps/modules/SolanaDataAccount.ts +4 -6
  53. package/src/solana/swaps/modules/SolanaLpVault.ts +18 -18
  54. package/src/solana/swaps/modules/SwapClaim.ts +14 -17
  55. package/src/solana/swaps/modules/SwapInit.ts +35 -38
  56. package/src/solana/swaps/modules/SwapRefund.ts +20 -23
  57. package/src/utils/Utils.ts +35 -0
@@ -1,7 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { SolanaSwapModule } from "../SolanaSwapModule";
3
3
  import { SolanaSwapData } from "../SolanaSwapData";
4
- import * as BN from "bn.js";
5
4
  import { SolanaTx } from "../../base/modules/SolanaTransactions";
6
5
  import { Buffer } from "buffer";
7
6
  import { SolanaSigner } from "../../wallet/SolanaSigner";
@@ -75,9 +74,9 @@ export declare class SwapRefund extends SolanaSwapModule {
75
74
  * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
76
75
  * ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
77
76
  */
78
- getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN>;
77
+ getRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
79
78
  /**
80
79
  * Get the estimated solana transaction fee of the refund transaction
81
80
  */
82
- getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<BN>;
81
+ getRawRefundFee(swapData: SolanaSwapData, feeRate?: string): Promise<bigint>;
83
82
  }
@@ -1,25 +1,17 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.SwapRefund = void 0;
13
4
  const SolanaSwapModule_1 = require("../SolanaSwapModule");
14
5
  const createHash = require("create-hash");
15
6
  const tweetnacl_1 = require("tweetnacl");
16
7
  const base_1 = require("@atomiqlabs/base");
17
- const BN = require("bn.js");
18
8
  const web3_js_1 = require("@solana/web3.js");
19
9
  const spl_token_1 = require("@solana/spl-token");
20
10
  const SolanaAction_1 = require("../../base/SolanaAction");
21
11
  const Utils_1 = require("../../../utils/Utils");
22
12
  const buffer_1 = require("buffer");
13
+ const SolanaTokens_1 = require("../../base/modules/SolanaTokens");
14
+ const BN = require("bn.js");
23
15
  class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
24
16
  /**
25
17
  * Action for generic Refund instruction
@@ -29,30 +21,37 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
29
21
  * @constructor
30
22
  * @private
31
23
  */
32
- Refund(swapData, refundAuthTimeout) {
33
- return __awaiter(this, void 0, void 0, function* () {
34
- const accounts = {
35
- offerer: swapData.offerer,
36
- claimer: swapData.claimer,
37
- escrowState: this.root.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")),
38
- claimerUserData: !swapData.payOut ? this.root.SwapUserVault(swapData.claimer, swapData.token) : null,
39
- ixSysvar: refundAuthTimeout != null ? web3_js_1.SYSVAR_INSTRUCTIONS_PUBKEY : null
40
- };
41
- const useTimeout = refundAuthTimeout != null ? refundAuthTimeout : new BN(0);
42
- if (swapData.isPayIn()) {
43
- const ata = (0, spl_token_1.getAssociatedTokenAddressSync)(swapData.token, swapData.offerer);
44
- return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, yield this.program.methods
45
- .offererRefundPayIn(useTimeout)
46
- .accounts(Object.assign(Object.assign({}, accounts), { offererAta: ata, vault: this.root.SwapVault(swapData.token), vaultAuthority: this.root.SwapVaultAuthority, tokenProgram: spl_token_1.TOKEN_PROGRAM_ID }))
47
- .instruction(), SwapRefund.CUCosts.REFUND_PAY_OUT);
48
- }
49
- else {
50
- return new SolanaAction_1.SolanaAction(swapData.offerer, this.root, yield this.program.methods
51
- .offererRefund(useTimeout)
52
- .accounts(Object.assign(Object.assign({}, accounts), { offererUserData: this.root.SwapUserVault(swapData.offerer, swapData.token) }))
53
- .instruction(), SwapRefund.CUCosts.REFUND);
54
- }
55
- });
24
+ async Refund(swapData, refundAuthTimeout) {
25
+ const accounts = {
26
+ offerer: swapData.offerer,
27
+ claimer: swapData.claimer,
28
+ escrowState: this.root.SwapEscrowState(buffer_1.Buffer.from(swapData.paymentHash, "hex")),
29
+ claimerUserData: !swapData.payOut ? this.root.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.program.methods
36
+ .offererRefundPayIn((0, Utils_1.toBN)(useTimeout))
37
+ .accounts({
38
+ ...accounts,
39
+ offererAta: ata,
40
+ vault: this.root.SwapVault(swapData.token),
41
+ vaultAuthority: this.root.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.program.methods
48
+ .offererRefund((0, Utils_1.toBN)(useTimeout))
49
+ .accounts({
50
+ ...accounts,
51
+ offererUserData: this.root.SwapUserVault(swapData.offerer, swapData.token)
52
+ })
53
+ .instruction(), SwapRefund.CUCosts.REFUND);
54
+ }
56
55
  }
57
56
  /**
58
57
  * Action for refunding with signature, adds the Ed25519 verify instruction
@@ -64,16 +63,14 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
64
63
  * @constructor
65
64
  * @private
66
65
  */
67
- RefundWithSignature(swapData, timeout, prefix, signature) {
68
- return __awaiter(this, void 0, void 0, function* () {
69
- const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root, web3_js_1.Ed25519Program.createInstructionWithPublicKey({
70
- message: this.getRefundMessage(swapData, prefix, timeout),
71
- publicKey: swapData.claimer.toBuffer(),
72
- signature: signature
73
- }), 0, null, null, true);
74
- action.addAction(yield this.Refund(swapData, new BN(timeout)));
75
- return action;
76
- });
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;
77
74
  }
78
75
  /**
79
76
  * Gets the message to be signed as a refund authorization
@@ -102,7 +99,7 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
102
99
  */
103
100
  shouldUnwrap(swapData) {
104
101
  return swapData.isPayIn() &&
105
- swapData.token.equals(this.root.Tokens.WSOL_ADDRESS) &&
102
+ swapData.token.equals(SolanaTokens_1.SolanaTokens.WSOL_ADDRESS) &&
106
103
  swapData.offerer.equals(swapData.offerer);
107
104
  }
108
105
  signSwapRefund(signer, swapData, authorizationTimeout) {
@@ -123,9 +120,9 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
123
120
  isSignatureValid(swapData, timeout, prefix, signature) {
124
121
  if (prefix !== "refund")
125
122
  throw new base_1.SignatureVerificationError("Invalid prefix");
126
- const expiryTimestamp = new BN(timeout);
127
- const currentTimestamp = new BN(Math.floor(Date.now() / 1000));
128
- const isExpired = expiryTimestamp.sub(currentTimestamp).lt(new BN(this.root.authGracePeriod));
123
+ const expiryTimestamp = BigInt(timeout);
124
+ const currentTimestamp = BigInt(Math.floor(Date.now() / 1000));
125
+ const isExpired = (expiryTimestamp - currentTimestamp) < BigInt(this.root.authGracePeriod);
129
126
  if (isExpired)
130
127
  throw new base_1.SignatureVerificationError("Authorization expired!");
131
128
  const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
@@ -143,31 +140,29 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
143
140
  * @param initAta should initialize ATA if it doesn't exist
144
141
  * @param feeRate fee rate to be used for the transactions
145
142
  */
146
- txsRefund(swapData, check, initAta, feeRate) {
147
- return __awaiter(this, void 0, void 0, function* () {
148
- if (check && !(yield (0, Utils_1.tryWithRetries)(() => this.root.isRequestRefundable(swapData.offerer.toString(), swapData), this.retryPolicy))) {
149
- throw new base_1.SwapDataVerificationError("Not refundable yet!");
150
- }
151
- const shouldInitAta = swapData.isPayIn() && !(yield this.root.Tokens.ataExists(swapData.offererAta));
152
- if (shouldInitAta && !initAta)
153
- throw new base_1.SwapDataVerificationError("ATA not initialized");
154
- if (feeRate == null)
155
- feeRate = yield this.root.getRefundFeeRate(swapData);
156
- const shouldUnwrap = this.shouldUnwrap(swapData);
157
- const action = new SolanaAction_1.SolanaAction(swapData.offerer, this.root);
158
- if (shouldInitAta) {
159
- const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
160
- if (initAction == null)
161
- throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
162
- action.addAction(initAction);
163
- }
164
- action.add(yield this.Refund(swapData));
165
- if (shouldUnwrap)
166
- action.add(this.root.Tokens.Unwrap(swapData.offerer));
167
- this.logger.debug("txsRefund(): creating claim transaction, swap: " + swapData.getHash() +
168
- " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap);
169
- return [yield action.tx(feeRate)];
170
- });
143
+ async txsRefund(swapData, check, initAta, feeRate) {
144
+ if (check && !await (0, Utils_1.tryWithRetries)(() => this.root.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.root.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)];
171
166
  }
172
167
  /**
173
168
  * Creates transactions required for refunding the swap with authorization signature, also unwraps WSOL to SOL
@@ -180,34 +175,32 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
180
175
  * @param initAta should initialize ATA if it doesn't exist
181
176
  * @param feeRate fee rate to be used for the transactions
182
177
  */
183
- txsRefundWithAuthorization(swapData, timeout, prefix, signature, check, initAta, feeRate) {
184
- return __awaiter(this, void 0, void 0, function* () {
185
- if (check && !(yield (0, Utils_1.tryWithRetries)(() => this.root.isCommited(swapData), this.retryPolicy))) {
186
- throw new base_1.SwapDataVerificationError("Not correctly committed");
187
- }
188
- yield (0, Utils_1.tryWithRetries)(() => this.isSignatureValid(swapData, timeout, prefix, signature), this.retryPolicy, (e) => e instanceof base_1.SignatureVerificationError);
189
- const shouldInitAta = swapData.isPayIn() && !(yield this.root.Tokens.ataExists(swapData.offererAta));
190
- if (shouldInitAta && !initAta)
191
- throw new base_1.SwapDataVerificationError("ATA not initialized");
192
- if (feeRate == null)
193
- feeRate = yield this.root.getRefundFeeRate(swapData);
194
- console.log("[SolanaSwapProgram] txsRefundsWithAuthorization: feeRate: ", feeRate);
195
- const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
196
- const shouldUnwrap = this.shouldUnwrap(swapData);
197
- const action = yield this.RefundWithSignature(swapData, timeout, prefix, signatureBuffer);
198
- if (shouldInitAta) {
199
- const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
200
- if (initAction == null)
201
- throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
202
- action.addAction(initAction, 1); //Need to add it after the Ed25519 verify IX, but before the actual refund IX
203
- }
204
- if (shouldUnwrap)
205
- action.add(this.root.Tokens.Unwrap(swapData.offerer));
206
- this.logger.debug("txsRefundWithAuthorization(): creating claim transaction, swap: " + swapData.getHash() +
207
- " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap +
208
- " auth expiry: " + timeout + " signature: " + signature);
209
- return [yield action.tx(feeRate)];
210
- });
178
+ async txsRefundWithAuthorization(swapData, timeout, prefix, signature, check, initAta, feeRate) {
179
+ if (check && !await (0, Utils_1.tryWithRetries)(() => this.root.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.root.getRefundFeeRate(swapData);
188
+ console.log("[SolanaSwapProgram] txsRefundsWithAuthorization: feeRate: ", feeRate);
189
+ const signatureBuffer = buffer_1.Buffer.from(signature, "hex");
190
+ const shouldUnwrap = this.shouldUnwrap(swapData);
191
+ const action = await this.RefundWithSignature(swapData, timeout, prefix, signatureBuffer);
192
+ if (shouldInitAta) {
193
+ const initAction = this.root.Tokens.InitAta(swapData.offerer, swapData.offerer, swapData.token, swapData.offererAta);
194
+ if (initAction == null)
195
+ throw new base_1.SwapDataVerificationError("Invalid claimer token account address");
196
+ action.addAction(initAction, 1); //Need to add it after the Ed25519 verify IX, but before the actual refund IX
197
+ }
198
+ if (shouldUnwrap)
199
+ action.add(this.root.Tokens.Unwrap(swapData.offerer));
200
+ this.logger.debug("txsRefundWithAuthorization(): creating claim transaction, swap: " + swapData.getClaimHash() +
201
+ " initializingAta: " + shouldInitAta + " unwrapping: " + shouldUnwrap +
202
+ " auth expiry: " + timeout + " signature: " + signature);
203
+ return [await action.tx(feeRate)];
211
204
  }
212
205
  getRefundFeeRate(swapData) {
213
206
  const accounts = [];
@@ -238,22 +231,19 @@ class SwapRefund extends SolanaSwapModule_1.SolanaSwapModule {
238
231
  * Get the estimated solana transaction fee of the refund transaction, in the worst case scenario in case where the
239
232
  * ATA needs to be initialized again (i.e. adding the ATA rent exempt lamports to the fee)
240
233
  */
241
- getRefundFee(swapData, feeRate) {
242
- return __awaiter(this, void 0, void 0, function* () {
243
- return new BN(swapData == null || swapData.payIn ? this.root.Tokens.SPL_ATA_RENT_EXEMPT : 0).add(yield this.getRawRefundFee(swapData, feeRate));
244
- });
234
+ async getRefundFee(swapData, feeRate) {
235
+ return BigInt(swapData == null || swapData.payIn ? SolanaTokens_1.SolanaTokens.SPL_ATA_RENT_EXEMPT : 0) +
236
+ await this.getRawRefundFee(swapData, feeRate);
245
237
  }
246
238
  /**
247
239
  * Get the estimated solana transaction fee of the refund transaction
248
240
  */
249
- getRawRefundFee(swapData, feeRate) {
250
- return __awaiter(this, void 0, void 0, function* () {
251
- if (swapData == null)
252
- return new BN(10000);
253
- feeRate = feeRate || (yield this.getRefundFeeRate(swapData));
254
- const computeBudget = swapData.payIn ? SwapRefund.CUCosts.REFUND_PAY_OUT : SwapRefund.CUCosts.REFUND;
255
- return new BN(10000).add(this.root.Fees.getPriorityFee(computeBudget, feeRate));
256
- });
241
+ async getRawRefundFee(swapData, feeRate) {
242
+ if (swapData == null)
243
+ return 10000n;
244
+ feeRate = feeRate || await this.getRefundFeeRate(swapData);
245
+ const computeBudget = swapData.payIn ? SwapRefund.CUCosts.REFUND_PAY_OUT : SwapRefund.CUCosts.REFUND;
246
+ return 10000n + this.root.Fees.getPriorityFee(computeBudget, feeRate);
257
247
  }
258
248
  }
259
249
  exports.SwapRefund = SwapRefund;
@@ -1,4 +1,5 @@
1
1
  import { PublicKey, Transaction } from "@solana/web3.js";
2
+ import * as BN from "bn.js";
2
3
  export declare function timeoutPromise(timeoutMillis: number, abortSignal?: AbortSignal): Promise<void>;
3
4
  export declare function onceAsync<T>(executor: () => Promise<T>): () => Promise<T>;
4
5
  export declare function getLogger(prefix: string): {
@@ -41,3 +42,12 @@ export declare class SolanaTxUtils {
41
42
  */
42
43
  static getTxSize(tx: Transaction, feePayer: PublicKey): number;
43
44
  }
45
+ export declare function toClaimHash(paymentHash: string, nonce: bigint, confirmations: number): string;
46
+ export declare function fromClaimHash(claimHash: string): {
47
+ paymentHash: string;
48
+ nonce: BN;
49
+ confirmations: number;
50
+ };
51
+ export declare function toEscrowHash(paymentHash: string, sequence: BN): string;
52
+ export declare function toBN(value: bigint): BN;
53
+ export declare function toBigInt(value: BN): bigint;
@@ -1,16 +1,10 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.SolanaTxUtils = exports.tryWithRetries = exports.getLogger = exports.onceAsync = exports.timeoutPromise = void 0;
3
+ exports.toBigInt = exports.toBN = exports.toEscrowHash = exports.fromClaimHash = exports.toClaimHash = exports.SolanaTxUtils = exports.tryWithRetries = exports.getLogger = exports.onceAsync = exports.timeoutPromise = void 0;
13
4
  const web3_js_1 = require("@solana/web3.js");
5
+ const BN = require("bn.js");
6
+ const buffer_1 = require("buffer");
7
+ const createHash = require("create-hash");
14
8
  function timeoutPromise(timeoutMillis, abortSignal) {
15
9
  return new Promise((resolve, reject) => {
16
10
  const timeout = setTimeout(resolve, timeoutMillis);
@@ -45,32 +39,30 @@ function getLogger(prefix) {
45
39
  }
46
40
  exports.getLogger = getLogger;
47
41
  const logger = getLogger("Utils: ");
48
- function tryWithRetries(func, retryPolicy, errorAllowed, abortSignal) {
49
- return __awaiter(this, void 0, void 0, function* () {
50
- retryPolicy = retryPolicy || {};
51
- retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
52
- retryPolicy.delay = retryPolicy.delay || 500;
53
- retryPolicy.exponential = retryPolicy.exponential == null ? true : retryPolicy.exponential;
54
- let err = null;
55
- for (let i = 0; i < retryPolicy.maxRetries; i++) {
56
- try {
57
- const resp = yield func();
58
- return resp;
59
- }
60
- catch (e) {
61
- if (errorAllowed != null && errorAllowed(e))
62
- throw e;
63
- err = e;
64
- logger.error("tryWithRetries(): error on try number: " + i, e);
65
- }
66
- if (abortSignal != null && abortSignal.aborted)
67
- throw new Error("Aborted");
68
- if (i !== retryPolicy.maxRetries - 1) {
69
- yield timeoutPromise(retryPolicy.exponential ? retryPolicy.delay * Math.pow(2, i) : retryPolicy.delay, abortSignal);
70
- }
42
+ async function tryWithRetries(func, retryPolicy, errorAllowed, abortSignal) {
43
+ retryPolicy = retryPolicy || {};
44
+ retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
45
+ retryPolicy.delay = retryPolicy.delay || 500;
46
+ retryPolicy.exponential = retryPolicy.exponential == null ? true : retryPolicy.exponential;
47
+ let err = null;
48
+ for (let i = 0; i < retryPolicy.maxRetries; i++) {
49
+ try {
50
+ const resp = await func();
51
+ return resp;
71
52
  }
72
- throw err;
73
- });
53
+ catch (e) {
54
+ if (errorAllowed != null && errorAllowed(e))
55
+ throw e;
56
+ err = e;
57
+ logger.error("tryWithRetries(): error on try number: " + i, e);
58
+ }
59
+ if (abortSignal != null && abortSignal.aborted)
60
+ throw new Error("Aborted");
61
+ if (i !== retryPolicy.maxRetries - 1) {
62
+ await timeoutPromise(retryPolicy.exponential ? retryPolicy.delay * Math.pow(2, i) : retryPolicy.delay, abortSignal);
63
+ }
64
+ }
65
+ throw err;
74
66
  }
75
67
  exports.tryWithRetries = tryWithRetries;
76
68
  class SolanaTxUtils {
@@ -141,3 +133,38 @@ exports.SolanaTxUtils = SolanaTxUtils;
141
133
  // COMPACT ARRAY
142
134
  SolanaTxUtils.LOW_VALUE = 127; // 0x7f
143
135
  SolanaTxUtils.HIGH_VALUE = 16383; // 0x3fff
136
+ function toClaimHash(paymentHash, nonce, confirmations) {
137
+ return paymentHash +
138
+ nonce.toString(16).padStart(16, "0") +
139
+ confirmations.toString(16).padStart(4, "0");
140
+ }
141
+ exports.toClaimHash = toClaimHash;
142
+ function fromClaimHash(claimHash) {
143
+ if (claimHash.length !== 84)
144
+ throw new Error("Claim hash invalid length: " + claimHash.length);
145
+ return {
146
+ paymentHash: claimHash.slice(0, 64),
147
+ nonce: new BN(claimHash.slice(64, 80), "hex"),
148
+ confirmations: parseInt(claimHash.slice(80, 84), 16)
149
+ };
150
+ }
151
+ exports.fromClaimHash = fromClaimHash;
152
+ function toEscrowHash(paymentHash, sequence) {
153
+ return createHash("sha256").update(buffer_1.Buffer.concat([
154
+ buffer_1.Buffer.from(paymentHash, "hex"),
155
+ sequence.toArrayLike(buffer_1.Buffer, "be", 8)
156
+ ])).digest().toString("hex");
157
+ }
158
+ exports.toEscrowHash = toEscrowHash;
159
+ function toBN(value) {
160
+ if (value == null)
161
+ return null;
162
+ return new BN(value.toString(10));
163
+ }
164
+ exports.toBN = toBN;
165
+ function toBigInt(value) {
166
+ if (value == null)
167
+ return null;
168
+ return BigInt(value.toString(10));
169
+ }
170
+ exports.toBigInt = toBigInt;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atomiqlabs/chain-solana",
3
- "version": "7.3.8",
3
+ "version": "8.0.0-beta.0",
4
4
  "description": "Solana specific base implementation",
5
5
  "main": "./dist/index.js",
6
6
  "types:": "./dist/index.d.ts",
@@ -22,18 +22,21 @@
22
22
  "author": "adambor",
23
23
  "license": "ISC",
24
24
  "dependencies": {
25
- "@atomiqlabs/base": "7.2.2",
26
- "@coral-xyz/anchor": "0.29.0",
27
- "@solana/spl-token": "0.3.9",
28
- "@solana/web3.js": "1.95.2",
25
+ "@atomiqlabs/base": "8.0.0-beta.0",
29
26
  "bn.js": "5.2.1",
27
+ "bs58": "4.0.1",
30
28
  "buffer": "6.0.3",
31
29
  "create-hash": "1.2.0",
32
30
  "randombytes": "2.1.0",
33
31
  "tweetnacl": "1.0.3"
34
32
  },
33
+ "peerDependencies": {
34
+ "@coral-xyz/anchor": "^0.29.0",
35
+ "@solana/spl-token": "^0.3.9",
36
+ "@solana/web3.js": "^1.95.2"
37
+ },
35
38
  "devDependencies": {
36
- "@types/bn.js": "5.1.5",
39
+ "@types/bn.js": "5.1.6",
37
40
  "@types/node": "18.15.11",
38
41
  "typescript": "4.9.5"
39
42
  }
package/src/index.ts CHANGED
@@ -31,5 +31,6 @@ export * from "./solana/wallet/SolanaKeypairWallet";
31
31
  export * from "./solana/wallet/SolanaSigner";
32
32
 
33
33
  export * from "./solana/SolanaChainType";
34
+ export * from "./solana/SolanaInitializer";
34
35
 
35
36
  export * from "./utils/Utils";
@@ -0,0 +1,16 @@
1
+ import {BitcoinNetwork} from "@atomiqlabs/base";
2
+
3
+ export const SolanaChains = {
4
+ [BitcoinNetwork.TESTNET]: {
5
+ addresses: {
6
+ swapContract: "4hfUykhqmD7ZRvNh1HuzVKEY7ToENixtdUKZspNDCrEM",
7
+ btcRelayContract: "3KHSHFpEK6bsjg3bqcxQ9qssJYtRCMi2S9TYVe4q6CQc"
8
+ }
9
+ },
10
+ [BitcoinNetwork.MAINNET]: {
11
+ addresses: {
12
+ swapContract: "4hfUykhqmD7ZRvNh1HuzVKEY7ToENixtdUKZspNDCrEM",
13
+ btcRelayContract: "3KHSHFpEK6bsjg3bqcxQ9qssJYtRCMi2S9TYVe4q6CQc"
14
+ }
15
+ }
16
+ } as const;
@@ -0,0 +1,98 @@
1
+ import {
2
+ BaseTokenType,
3
+ BitcoinNetwork,
4
+ BitcoinRpc,
5
+ ChainData,
6
+ ChainInitializer,
7
+ IStorageManager,
8
+ StorageObject
9
+ } from "@atomiqlabs/base";
10
+ import {Connection} from "@solana/web3.js";
11
+ import {StoredDataAccount} from "./swaps/modules/SolanaDataAccount";
12
+ import {SolanaRetryPolicy} from "./base/SolanaBase";
13
+ import {SolanaFees} from "./base/modules/SolanaFees";
14
+ import {SolanaChainType} from "./SolanaChainType";
15
+ import {SolanaBtcRelay} from "./btcrelay/SolanaBtcRelay";
16
+ import {SolanaChains} from "./SolanaChains";
17
+ import {SolanaSwapProgram} from "./swaps/SolanaSwapProgram";
18
+ import {SolanaChainEventsBrowser} from "./events/SolanaChainEventsBrowser";
19
+ import {SolanaSwapData} from "./swaps/SolanaSwapData";
20
+
21
+ const chainId = "SOLANA" as const;
22
+
23
+ export type SolanaAssetsType = BaseTokenType<"WBTC" | "USDC" | "USDT" | "SOL" | "BONK">;
24
+ const SolanaAssets: SolanaAssetsType = {
25
+ WBTC: {
26
+ address: "3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh",
27
+ decimals: 8
28
+ },
29
+ USDC: {
30
+ address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
31
+ decimals: 6
32
+ },
33
+ USDT: {
34
+ address: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
35
+ decimals: 6
36
+ },
37
+ SOL: {
38
+ address: "So11111111111111111111111111111111111111112",
39
+ decimals: 9
40
+ },
41
+ BONK: {
42
+ address: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
43
+ decimals: 5
44
+ }
45
+ } as const;
46
+
47
+ export type SolanaSwapperOptions = {
48
+ rpcUrl: string | Connection,
49
+ dataAccountStorage?: IStorageManager<StoredDataAccount>,
50
+ retryPolicy?: SolanaRetryPolicy,
51
+
52
+ btcRelayContract?: string,
53
+ swapContract?: string,
54
+
55
+ fees?: SolanaFees
56
+ };
57
+
58
+ export function initializeSolana(
59
+ options: SolanaSwapperOptions,
60
+ bitcoinRpc: BitcoinRpc<any>,
61
+ network: BitcoinNetwork,
62
+ storageCtor: <T extends StorageObject>(name: string) => IStorageManager<T>
63
+ ): ChainData<SolanaChainType> {
64
+ const connection = typeof(options.rpcUrl)==="string" ?
65
+ new Connection(options.rpcUrl) :
66
+ options.rpcUrl;
67
+
68
+ const Fees = options.fees ?? new SolanaFees(connection, 200000, 4, 100);
69
+ const btcRelay = new SolanaBtcRelay(connection, bitcoinRpc, options.btcRelayContract ?? SolanaChains[network].addresses.btcRelayContract, Fees);
70
+ const swapContract = new SolanaSwapProgram(
71
+ connection,
72
+ btcRelay,
73
+ options.dataAccountStorage || storageCtor("solAccounts"),
74
+ options.swapContract ?? SolanaChains[network].addresses.swapContract,
75
+ options.retryPolicy ?? {transactionResendInterval: 1000},
76
+ Fees
77
+ );
78
+ const chainEvents = new SolanaChainEventsBrowser(connection, swapContract);
79
+
80
+ return {
81
+ chainId,
82
+ btcRelay,
83
+ swapContract,
84
+ chainEvents,
85
+ swapDataConstructor: SolanaSwapData,
86
+ //These are defined here to keep the data from old SolLightning-sdk, not needed for other chains
87
+ storagePrefix: "SOLv4-"+network+"-"
88
+ };
89
+ }
90
+
91
+ export type SolanaInitializerType = ChainInitializer<SolanaSwapperOptions, SolanaChainType, SolanaAssetsType>;
92
+ export const SolanaInitializer: SolanaInitializerType = {
93
+ chainId,
94
+ chainType: null as SolanaChainType,
95
+ initializer: initializeSolana,
96
+ tokens: SolanaAssets,
97
+ options: null as SolanaSwapperOptions
98
+ } as const;
@@ -1,5 +1,4 @@
1
- import {Connection, Signer} from "@solana/web3.js";
2
- import {AnchorProvider} from "@coral-xyz/anchor";
1
+ import {Connection} from "@solana/web3.js";
3
2
  import {SolanaFees} from "./modules/SolanaFees";
4
3
  import {SolanaBlocks} from "./modules/SolanaBlocks";
5
4
  import {SolanaSlots} from "./modules/SolanaSlots";
@@ -1,6 +1,5 @@
1
1
  import {SolanaModule} from "../SolanaModule";
2
2
  import {ConfirmedSignatureInfo, PublicKey} from "@solana/web3.js";
3
- import {log} from "node:util";
4
3
 
5
4
  export class SolanaEvents extends SolanaModule {
6
5