@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,56 +1,56 @@
1
- import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
2
- import {Keypair, PublicKey, Transaction, VersionedTransaction} from "@solana/web3.js";
3
-
4
- /**
5
- * Keypair-based wallet implementation for Solana
6
- * @category Wallets
7
- */
8
- export class SolanaKeypairWallet implements Wallet {
9
-
10
- /**
11
- * Underlying signer keypair.
12
- */
13
- readonly payer: Keypair;
14
-
15
- constructor(payer: Keypair) {
16
- this.payer = payer;
17
- }
18
-
19
- /**
20
- * Public key of the wrapped payer keypair.
21
- */
22
- get publicKey(): PublicKey {
23
- return this.payer.publicKey;
24
- }
25
-
26
- /**
27
- * Signs all provided transactions with the wrapped keypair.
28
- *
29
- * @param txs Transactions to sign
30
- */
31
- signAllTransactions<T extends Transaction | VersionedTransaction>(txs: T[]): Promise<T[]> {
32
- txs.forEach((tx) => {
33
- if(tx instanceof Transaction) {
34
- tx.partialSign(this.payer);
35
- } else if(tx instanceof VersionedTransaction) {
36
- tx.sign([this.payer]);
37
- }
38
- });
39
- return Promise.resolve(txs);
40
- }
41
-
42
- /**
43
- * Signs a single transaction with the wrapped keypair.
44
- *
45
- * @param tx Transaction to sign
46
- */
47
- signTransaction<T extends Transaction | VersionedTransaction>(tx: T): Promise<T> {
48
- if(tx instanceof Transaction) {
49
- tx.partialSign(this.payer);
50
- } else if(tx instanceof VersionedTransaction) {
51
- tx.sign([this.payer]);
52
- }
53
- return Promise.resolve(tx);
54
- }
55
-
56
- }
1
+ import {Wallet} from "@coral-xyz/anchor/dist/cjs/provider";
2
+ import {Keypair, PublicKey, Transaction, VersionedTransaction} from "@solana/web3.js";
3
+
4
+ /**
5
+ * Keypair-based wallet implementation for Solana
6
+ * @category Wallets
7
+ */
8
+ export class SolanaKeypairWallet implements Wallet {
9
+
10
+ /**
11
+ * Underlying signer keypair.
12
+ */
13
+ readonly payer: Keypair;
14
+
15
+ constructor(payer: Keypair) {
16
+ this.payer = payer;
17
+ }
18
+
19
+ /**
20
+ * Public key of the wrapped payer keypair.
21
+ */
22
+ get publicKey(): PublicKey {
23
+ return this.payer.publicKey;
24
+ }
25
+
26
+ /**
27
+ * Signs all provided transactions with the wrapped keypair.
28
+ *
29
+ * @param txs Transactions to sign
30
+ */
31
+ signAllTransactions<T extends Transaction | VersionedTransaction>(txs: T[]): Promise<T[]> {
32
+ txs.forEach((tx) => {
33
+ if(tx instanceof Transaction) {
34
+ tx.partialSign(this.payer);
35
+ } else if(tx instanceof VersionedTransaction) {
36
+ tx.sign([this.payer]);
37
+ }
38
+ });
39
+ return Promise.resolve(txs);
40
+ }
41
+
42
+ /**
43
+ * Signs a single transaction with the wrapped keypair.
44
+ *
45
+ * @param tx Transaction to sign
46
+ */
47
+ signTransaction<T extends Transaction | VersionedTransaction>(tx: T): Promise<T> {
48
+ if(tx instanceof Transaction) {
49
+ tx.partialSign(this.payer);
50
+ } else if(tx instanceof VersionedTransaction) {
51
+ tx.sign([this.payer]);
52
+ }
53
+ return Promise.resolve(tx);
54
+ }
55
+
56
+ }
@@ -1,43 +1,43 @@
1
- import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
2
- import {AbstractSigner} from "@atomiqlabs/base";
3
- import {PublicKey, Signer} from "@solana/web3.js";
4
-
5
- /**
6
- * Solana signer implementation wrapping an Anchor Wallet
7
- * @category Wallets
8
- */
9
- export class SolanaSigner implements AbstractSigner {
10
- /**
11
- * @inheritDoc
12
- */
13
- type = "AtomiqAbstractSigner" as const;
14
-
15
- /**
16
- * Wrapped wallet implementation used for signing.
17
- */
18
- wallet: Wallet;
19
- /**
20
- * Optional raw keypair signer when available.
21
- */
22
- keypair?: Signer;
23
-
24
- constructor(wallet: Wallet, keypair?: Signer) {
25
- this.wallet = wallet;
26
- this.keypair = keypair;
27
- }
28
-
29
- /**
30
- * Returns public key of the wrapped wallet.
31
- */
32
- getPublicKey(): PublicKey {
33
- return this.wallet.publicKey;
34
- }
35
-
36
- /**
37
- * @inheritDoc
38
- */
39
- getAddress(): string {
40
- return this.wallet.publicKey.toString();
41
- }
42
-
43
- }
1
+ import { Wallet } from "@coral-xyz/anchor/dist/cjs/provider";
2
+ import {AbstractSigner} from "@atomiqlabs/base";
3
+ import {PublicKey, Signer} from "@solana/web3.js";
4
+
5
+ /**
6
+ * Solana signer implementation wrapping an Anchor Wallet
7
+ * @category Wallets
8
+ */
9
+ export class SolanaSigner implements AbstractSigner {
10
+ /**
11
+ * @inheritDoc
12
+ */
13
+ type = "AtomiqAbstractSigner" as const;
14
+
15
+ /**
16
+ * Wrapped wallet implementation used for signing.
17
+ */
18
+ wallet: Wallet;
19
+ /**
20
+ * Optional raw keypair signer when available.
21
+ */
22
+ keypair?: Signer;
23
+
24
+ constructor(wallet: Wallet, keypair?: Signer) {
25
+ this.wallet = wallet;
26
+ this.keypair = keypair;
27
+ }
28
+
29
+ /**
30
+ * Returns public key of the wrapped wallet.
31
+ */
32
+ getPublicKey(): PublicKey {
33
+ return this.wallet.publicKey;
34
+ }
35
+
36
+ /**
37
+ * @inheritDoc
38
+ */
39
+ getAddress(): string {
40
+ return this.wallet.publicKey.toString();
41
+ }
42
+
43
+ }
@@ -1,194 +1,194 @@
1
- import {ComputeBudgetProgram, PublicKey, Transaction} from "@solana/web3.js";
2
- import * as BN from "bn.js";
3
- import {Buffer} from "buffer";
4
- import {sha256} from "@noble/hashes/sha2";
5
-
6
- export type Serialized<T> = {
7
- [K in keyof T as T[K] extends Function ? never : K]:
8
- T[K] extends infer U
9
- ? U extends PublicKey | BN
10
- ? string
11
- : U extends object
12
- ? Serialized<U>
13
- : U
14
- : never;
15
- };
16
-
17
- export function timeoutPromise(timeoutMillis: number, abortSignal?: AbortSignal): Promise<void> {
18
- return new Promise((resolve, reject) => {
19
- const timeout = setTimeout(resolve, timeoutMillis)
20
- if(abortSignal!=null) abortSignal.addEventListener("abort", () => {
21
- clearTimeout(timeout);
22
- reject(new Error("Aborted"));
23
- })
24
- });
25
- }
26
-
27
- export function onceAsync<T>(executor: () => Promise<T>): () => Promise<T> {
28
- let promise: Promise<T>;
29
-
30
- return () => {
31
- if(promise==null) {
32
- promise = executor();
33
- return promise;
34
- } else {
35
- return promise.catch(() => promise = executor());
36
- }
37
- }
38
- }
39
-
40
- export function getLogger(prefix: string) {
41
- return {
42
- debug: (msg: string, ...args: any[]) => (global as any).atomiqLogLevel >= 3 && console.debug(prefix+msg, ...args),
43
- info: (msg: string, ...args: any[]) => (global as any).atomiqLogLevel >= 2 && console.info(prefix+msg, ...args),
44
- warn: (msg: string, ...args: any[]) => ((global as any).atomiqLogLevel==null || (global as any).atomiqLogLevel >= 1) && console.warn(prefix+msg, ...args),
45
- error: (msg: string, ...args: any[]) => ((global as any).atomiqLogLevel==null || (global as any).atomiqLogLevel >= 0) && console.error(prefix+msg, ...args)
46
- };
47
- }
48
- const logger = getLogger("Utils: ");
49
-
50
- export async function tryWithRetries<T>(func: () => Promise<T>, retryPolicy?: {
51
- maxRetries?: number, delay?: number, exponential?: boolean
52
- }, errorAllowed?: (e: any) => boolean, abortSignal?: AbortSignal): Promise<T> {
53
- retryPolicy = retryPolicy || {};
54
- retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
55
- retryPolicy.delay = retryPolicy.delay || 500;
56
- retryPolicy.exponential = retryPolicy.exponential==null ? true : retryPolicy.exponential;
57
-
58
- let err = null;
59
-
60
- for(let i=0;i<retryPolicy.maxRetries;i++) {
61
- try {
62
- const resp: T = await func();
63
- return resp;
64
- } catch (e) {
65
- if(errorAllowed!=null && errorAllowed(e)) throw e;
66
- err = e;
67
- logger.error("tryWithRetries(): error on try number: "+i, e);
68
- }
69
- if(abortSignal!=null && abortSignal.aborted) throw new Error("Aborted");
70
- if(i!==retryPolicy.maxRetries-1) {
71
- await timeoutPromise(
72
- retryPolicy.exponential ? retryPolicy.delay*Math.pow(2, i) : retryPolicy.delay,
73
- abortSignal
74
- );
75
- }
76
- }
77
-
78
- throw err;
79
- }
80
-
81
- export class SolanaTxUtils {
82
- // COMPACT ARRAY
83
- private static LOW_VALUE = 127; // 0x7f
84
- private static HIGH_VALUE = 16383; // 0x3fff
85
-
86
- /**
87
- * Compact u16 array header size
88
- * @param n elements in the compact array
89
- * @returns size in bytes of array header
90
- */
91
- private static compactHeader(n: number): number {
92
- return (n <= SolanaTxUtils.LOW_VALUE ? 1 : n <= SolanaTxUtils.HIGH_VALUE ? 2 : 3);
93
- }
94
-
95
- /**
96
- * Compact u16 array size
97
- * @param n elements in the compact array
98
- * @param size bytes per each element
99
- * @returns size in bytes of array
100
- */
101
- private static compactArraySize(n: number, size: number): number {
102
- return SolanaTxUtils.compactHeader(n) + n * size;
103
- }
104
-
105
- /**
106
- * Returns # number of non-compute budget related instructions
107
- *
108
- * @param tx
109
- */
110
- public static getNonComputeBudgetIxs(tx: Transaction): number {
111
- let counter = 0;
112
- for(let ix of tx.instructions) {
113
- if(!ix.programId.equals(ComputeBudgetProgram.programId)) counter++;
114
- }
115
- return counter;
116
- }
117
-
118
- /**
119
- * @param tx a solana transaction
120
- * @param feePayer the publicKey of the signer
121
- * @returns size in bytes of the transaction
122
- */
123
- public static getTxSize(tx: Transaction, feePayer: PublicKey): number {
124
- const feePayerPk = [feePayer.toBase58()];
125
-
126
- const signers = new Set<string>(feePayerPk);
127
- const accounts = new Set<string>(feePayerPk);
128
-
129
- const ixsSize = tx.instructions.reduce((acc, ix) => {
130
- ix.keys.forEach(({ pubkey, isSigner }) => {
131
- const pk = pubkey.toBase58();
132
- if (isSigner) signers.add(pk);
133
- accounts.add(pk);
134
- });
135
-
136
- accounts.add(ix.programId.toBase58());
137
-
138
- const nIndexes = ix.keys.length;
139
- const opaqueData = ix.data.length;
140
-
141
- return (
142
- acc +
143
- 1 + // PID index
144
- SolanaTxUtils.compactArraySize(nIndexes, 1) +
145
- SolanaTxUtils.compactArraySize(opaqueData, 1)
146
- );
147
- }, 0);
148
-
149
- return (
150
- SolanaTxUtils.compactArraySize(signers.size, 64) + // signatures
151
- 3 + // header
152
- SolanaTxUtils.compactArraySize(accounts.size, 32) + // accounts
153
- 32 + // blockhash
154
- SolanaTxUtils.compactHeader(tx.instructions.length) + // instructions
155
- ixsSize
156
- );
157
- };
158
- }
159
-
160
- export function toClaimHash(paymentHash: string, nonce: bigint, confirmations: number): string {
161
- return paymentHash+
162
- nonce.toString(16).padStart(16, "0")+
163
- confirmations.toString(16).padStart(4, "0");
164
- }
165
-
166
- export function fromClaimHash(claimHash: string): {paymentHash: string, nonce: BN, confirmations: number} {
167
- if(claimHash.length!==84) throw new Error("Claim hash invalid length: "+claimHash.length);
168
- return {
169
- paymentHash: claimHash.slice(0, 64),
170
- nonce: new BN(claimHash.slice(64, 80), "hex"),
171
- confirmations: parseInt(claimHash.slice(80, 84), 16)
172
- }
173
- }
174
-
175
- export function toEscrowHash(paymentHash: string, sequence: BN): string {
176
- return Buffer.from(sha256(Buffer.concat([
177
- Buffer.from(paymentHash, "hex"),
178
- sequence.toArrayLike(Buffer, "be", 8)
179
- ]))).toString("hex");
180
- }
181
-
182
- export function toBN(value: bigint): BN;
183
- export function toBN(value: null): null;
184
- export function toBN(value: bigint | null): BN | null {
185
- if(value==null) return null;
186
- return new BN(value.toString(10));
187
- }
188
-
189
- export function toBigInt(value: BN): bigint;
190
- export function toBigInt(value: null): null;
191
- export function toBigInt(value: BN | null): bigint | null {
192
- if(value==null) return null;
193
- return BigInt(value.toString(10));
194
- }
1
+ import {ComputeBudgetProgram, PublicKey, Transaction} from "@solana/web3.js";
2
+ import * as BN from "bn.js";
3
+ import {Buffer} from "buffer";
4
+ import {sha256} from "@noble/hashes/sha2";
5
+
6
+ export type Serialized<T> = {
7
+ [K in keyof T as T[K] extends Function ? never : K]:
8
+ T[K] extends infer U
9
+ ? U extends PublicKey | BN
10
+ ? string
11
+ : U extends object
12
+ ? Serialized<U>
13
+ : U
14
+ : never;
15
+ };
16
+
17
+ export function timeoutPromise(timeoutMillis: number, abortSignal?: AbortSignal): Promise<void> {
18
+ return new Promise((resolve, reject) => {
19
+ const timeout = setTimeout(resolve, timeoutMillis)
20
+ if(abortSignal!=null) abortSignal.addEventListener("abort", () => {
21
+ clearTimeout(timeout);
22
+ reject(new Error("Aborted"));
23
+ })
24
+ });
25
+ }
26
+
27
+ export function onceAsync<T>(executor: () => Promise<T>): () => Promise<T> {
28
+ let promise: Promise<T>;
29
+
30
+ return () => {
31
+ if(promise==null) {
32
+ promise = executor();
33
+ return promise;
34
+ } else {
35
+ return promise.catch(() => promise = executor());
36
+ }
37
+ }
38
+ }
39
+
40
+ export function getLogger(prefix: string) {
41
+ return {
42
+ debug: (msg: string, ...args: any[]) => (global as any).atomiqLogLevel >= 3 && console.debug(prefix+msg, ...args),
43
+ info: (msg: string, ...args: any[]) => (global as any).atomiqLogLevel >= 2 && console.info(prefix+msg, ...args),
44
+ warn: (msg: string, ...args: any[]) => ((global as any).atomiqLogLevel==null || (global as any).atomiqLogLevel >= 1) && console.warn(prefix+msg, ...args),
45
+ error: (msg: string, ...args: any[]) => ((global as any).atomiqLogLevel==null || (global as any).atomiqLogLevel >= 0) && console.error(prefix+msg, ...args)
46
+ };
47
+ }
48
+ const logger = getLogger("Utils: ");
49
+
50
+ export async function tryWithRetries<T>(func: () => Promise<T>, retryPolicy?: {
51
+ maxRetries?: number, delay?: number, exponential?: boolean
52
+ }, errorAllowed?: (e: any) => boolean, abortSignal?: AbortSignal): Promise<T> {
53
+ retryPolicy = retryPolicy || {};
54
+ retryPolicy.maxRetries = retryPolicy.maxRetries || 5;
55
+ retryPolicy.delay = retryPolicy.delay || 500;
56
+ retryPolicy.exponential = retryPolicy.exponential==null ? true : retryPolicy.exponential;
57
+
58
+ let err = null;
59
+
60
+ for(let i=0;i<retryPolicy.maxRetries;i++) {
61
+ try {
62
+ const resp: T = await func();
63
+ return resp;
64
+ } catch (e) {
65
+ if(errorAllowed!=null && errorAllowed(e)) throw e;
66
+ err = e;
67
+ logger.error("tryWithRetries(): error on try number: "+i, e);
68
+ }
69
+ if(abortSignal!=null && abortSignal.aborted) throw new Error("Aborted");
70
+ if(i!==retryPolicy.maxRetries-1) {
71
+ await timeoutPromise(
72
+ retryPolicy.exponential ? retryPolicy.delay*Math.pow(2, i) : retryPolicy.delay,
73
+ abortSignal
74
+ );
75
+ }
76
+ }
77
+
78
+ throw err;
79
+ }
80
+
81
+ export class SolanaTxUtils {
82
+ // COMPACT ARRAY
83
+ private static LOW_VALUE = 127; // 0x7f
84
+ private static HIGH_VALUE = 16383; // 0x3fff
85
+
86
+ /**
87
+ * Compact u16 array header size
88
+ * @param n elements in the compact array
89
+ * @returns size in bytes of array header
90
+ */
91
+ private static compactHeader(n: number): number {
92
+ return (n <= SolanaTxUtils.LOW_VALUE ? 1 : n <= SolanaTxUtils.HIGH_VALUE ? 2 : 3);
93
+ }
94
+
95
+ /**
96
+ * Compact u16 array size
97
+ * @param n elements in the compact array
98
+ * @param size bytes per each element
99
+ * @returns size in bytes of array
100
+ */
101
+ private static compactArraySize(n: number, size: number): number {
102
+ return SolanaTxUtils.compactHeader(n) + n * size;
103
+ }
104
+
105
+ /**
106
+ * Returns # number of non-compute budget related instructions
107
+ *
108
+ * @param tx
109
+ */
110
+ public static getNonComputeBudgetIxs(tx: Transaction): number {
111
+ let counter = 0;
112
+ for(let ix of tx.instructions) {
113
+ if(!ix.programId.equals(ComputeBudgetProgram.programId)) counter++;
114
+ }
115
+ return counter;
116
+ }
117
+
118
+ /**
119
+ * @param tx a solana transaction
120
+ * @param feePayer the publicKey of the signer
121
+ * @returns size in bytes of the transaction
122
+ */
123
+ public static getTxSize(tx: Transaction, feePayer: PublicKey): number {
124
+ const feePayerPk = [feePayer.toBase58()];
125
+
126
+ const signers = new Set<string>(feePayerPk);
127
+ const accounts = new Set<string>(feePayerPk);
128
+
129
+ const ixsSize = tx.instructions.reduce((acc, ix) => {
130
+ ix.keys.forEach(({ pubkey, isSigner }) => {
131
+ const pk = pubkey.toBase58();
132
+ if (isSigner) signers.add(pk);
133
+ accounts.add(pk);
134
+ });
135
+
136
+ accounts.add(ix.programId.toBase58());
137
+
138
+ const nIndexes = ix.keys.length;
139
+ const opaqueData = ix.data.length;
140
+
141
+ return (
142
+ acc +
143
+ 1 + // PID index
144
+ SolanaTxUtils.compactArraySize(nIndexes, 1) +
145
+ SolanaTxUtils.compactArraySize(opaqueData, 1)
146
+ );
147
+ }, 0);
148
+
149
+ return (
150
+ SolanaTxUtils.compactArraySize(signers.size, 64) + // signatures
151
+ 3 + // header
152
+ SolanaTxUtils.compactArraySize(accounts.size, 32) + // accounts
153
+ 32 + // blockhash
154
+ SolanaTxUtils.compactHeader(tx.instructions.length) + // instructions
155
+ ixsSize
156
+ );
157
+ };
158
+ }
159
+
160
+ export function toClaimHash(paymentHash: string, nonce: bigint, confirmations: number): string {
161
+ return paymentHash+
162
+ nonce.toString(16).padStart(16, "0")+
163
+ confirmations.toString(16).padStart(4, "0");
164
+ }
165
+
166
+ export function fromClaimHash(claimHash: string): {paymentHash: string, nonce: BN, confirmations: number} {
167
+ if(claimHash.length!==84) throw new Error("Claim hash invalid length: "+claimHash.length);
168
+ return {
169
+ paymentHash: claimHash.slice(0, 64),
170
+ nonce: new BN(claimHash.slice(64, 80), "hex"),
171
+ confirmations: parseInt(claimHash.slice(80, 84), 16)
172
+ }
173
+ }
174
+
175
+ export function toEscrowHash(paymentHash: string, sequence: BN): string {
176
+ return Buffer.from(sha256(Buffer.concat([
177
+ Buffer.from(paymentHash, "hex"),
178
+ sequence.toArrayLike(Buffer, "be", 8)
179
+ ]))).toString("hex");
180
+ }
181
+
182
+ export function toBN(value: bigint): BN;
183
+ export function toBN(value: null): null;
184
+ export function toBN(value: bigint | null): BN | null {
185
+ if(value==null) return null;
186
+ return new BN(value.toString(10));
187
+ }
188
+
189
+ export function toBigInt(value: BN): bigint;
190
+ export function toBigInt(value: null): null;
191
+ export function toBigInt(value: BN | null): bigint | null {
192
+ if(value==null) return null;
193
+ return BigInt(value.toString(10));
194
+ }