@atomiqlabs/chain-solana 7.2.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 (105) hide show
  1. package/LICENSE +201 -0
  2. package/dist/index.d.ts +28 -0
  3. package/dist/index.js +44 -0
  4. package/dist/solana/SolanaChainType.d.ts +9 -0
  5. package/dist/solana/SolanaChainType.js +2 -0
  6. package/dist/solana/base/SolanaAction.d.ts +26 -0
  7. package/dist/solana/base/SolanaAction.js +99 -0
  8. package/dist/solana/base/SolanaBase.d.ts +36 -0
  9. package/dist/solana/base/SolanaBase.js +30 -0
  10. package/dist/solana/base/SolanaModule.d.ts +14 -0
  11. package/dist/solana/base/SolanaModule.js +13 -0
  12. package/dist/solana/base/modules/SolanaAddresses.d.ts +9 -0
  13. package/dist/solana/base/modules/SolanaAddresses.js +23 -0
  14. package/dist/solana/base/modules/SolanaBlocks.d.ts +28 -0
  15. package/dist/solana/base/modules/SolanaBlocks.js +83 -0
  16. package/dist/solana/base/modules/SolanaEvents.d.ts +25 -0
  17. package/dist/solana/base/modules/SolanaEvents.js +69 -0
  18. package/dist/solana/base/modules/SolanaFees.d.ts +121 -0
  19. package/dist/solana/base/modules/SolanaFees.js +393 -0
  20. package/dist/solana/base/modules/SolanaSignatures.d.ts +23 -0
  21. package/dist/solana/base/modules/SolanaSignatures.js +39 -0
  22. package/dist/solana/base/modules/SolanaSlots.d.ts +31 -0
  23. package/dist/solana/base/modules/SolanaSlots.js +81 -0
  24. package/dist/solana/base/modules/SolanaTokens.d.ts +134 -0
  25. package/dist/solana/base/modules/SolanaTokens.js +269 -0
  26. package/dist/solana/base/modules/SolanaTransactions.d.ts +124 -0
  27. package/dist/solana/base/modules/SolanaTransactions.js +354 -0
  28. package/dist/solana/btcrelay/SolanaBtcRelay.d.ts +229 -0
  29. package/dist/solana/btcrelay/SolanaBtcRelay.js +477 -0
  30. package/dist/solana/btcrelay/headers/SolanaBtcHeader.d.ts +29 -0
  31. package/dist/solana/btcrelay/headers/SolanaBtcHeader.js +34 -0
  32. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.d.ts +46 -0
  33. package/dist/solana/btcrelay/headers/SolanaBtcStoredHeader.js +78 -0
  34. package/dist/solana/btcrelay/program/programIdl.json +671 -0
  35. package/dist/solana/events/SolanaChainEvents.d.ts +84 -0
  36. package/dist/solana/events/SolanaChainEvents.js +268 -0
  37. package/dist/solana/events/SolanaChainEventsBrowser.d.ts +85 -0
  38. package/dist/solana/events/SolanaChainEventsBrowser.js +202 -0
  39. package/dist/solana/program/SolanaProgramBase.d.ts +34 -0
  40. package/dist/solana/program/SolanaProgramBase.js +43 -0
  41. package/dist/solana/program/modules/SolanaProgramEvents.d.ts +58 -0
  42. package/dist/solana/program/modules/SolanaProgramEvents.js +114 -0
  43. package/dist/solana/swaps/SolanaSwapData.d.ts +55 -0
  44. package/dist/solana/swaps/SolanaSwapData.js +251 -0
  45. package/dist/solana/swaps/SolanaSwapModule.d.ts +9 -0
  46. package/dist/solana/swaps/SolanaSwapModule.js +12 -0
  47. package/dist/solana/swaps/SolanaSwapProgram.d.ts +218 -0
  48. package/dist/solana/swaps/SolanaSwapProgram.js +523 -0
  49. package/dist/solana/swaps/SwapTypeEnum.d.ts +11 -0
  50. package/dist/solana/swaps/SwapTypeEnum.js +42 -0
  51. package/dist/solana/swaps/modules/SolanaDataAccount.d.ts +94 -0
  52. package/dist/solana/swaps/modules/SolanaDataAccount.js +255 -0
  53. package/dist/solana/swaps/modules/SolanaLpVault.d.ts +72 -0
  54. package/dist/solana/swaps/modules/SolanaLpVault.js +196 -0
  55. package/dist/solana/swaps/modules/SwapClaim.d.ts +129 -0
  56. package/dist/solana/swaps/modules/SwapClaim.js +307 -0
  57. package/dist/solana/swaps/modules/SwapInit.d.ts +212 -0
  58. package/dist/solana/swaps/modules/SwapInit.js +508 -0
  59. package/dist/solana/swaps/modules/SwapRefund.d.ts +83 -0
  60. package/dist/solana/swaps/modules/SwapRefund.js +264 -0
  61. package/dist/solana/swaps/programIdl.json +945 -0
  62. package/dist/solana/swaps/programTypes.d.ts +943 -0
  63. package/dist/solana/swaps/programTypes.js +945 -0
  64. package/dist/solana/wallet/SolanaKeypairWallet.d.ts +9 -0
  65. package/dist/solana/wallet/SolanaKeypairWallet.js +33 -0
  66. package/dist/solana/wallet/SolanaSigner.d.ts +10 -0
  67. package/dist/solana/wallet/SolanaSigner.js +16 -0
  68. package/dist/utils/Utils.d.ts +43 -0
  69. package/dist/utils/Utils.js +143 -0
  70. package/package.json +40 -0
  71. package/src/index.ts +35 -0
  72. package/src/solana/SolanaChainType.ts +20 -0
  73. package/src/solana/base/SolanaAction.ts +109 -0
  74. package/src/solana/base/SolanaBase.ts +57 -0
  75. package/src/solana/base/SolanaModule.ts +21 -0
  76. package/src/solana/base/modules/SolanaAddresses.ts +22 -0
  77. package/src/solana/base/modules/SolanaBlocks.ts +79 -0
  78. package/src/solana/base/modules/SolanaEvents.ts +58 -0
  79. package/src/solana/base/modules/SolanaFees.ts +445 -0
  80. package/src/solana/base/modules/SolanaSignatures.ts +40 -0
  81. package/src/solana/base/modules/SolanaSlots.ts +83 -0
  82. package/src/solana/base/modules/SolanaTokens.ts +310 -0
  83. package/src/solana/base/modules/SolanaTransactions.ts +366 -0
  84. package/src/solana/btcrelay/SolanaBtcRelay.ts +591 -0
  85. package/src/solana/btcrelay/headers/SolanaBtcHeader.ts +58 -0
  86. package/src/solana/btcrelay/headers/SolanaBtcStoredHeader.ts +103 -0
  87. package/src/solana/btcrelay/program/programIdl.json +671 -0
  88. package/src/solana/events/SolanaChainEvents.ts +286 -0
  89. package/src/solana/events/SolanaChainEventsBrowser.ts +251 -0
  90. package/src/solana/program/SolanaProgramBase.ts +77 -0
  91. package/src/solana/program/modules/SolanaProgramEvents.ts +140 -0
  92. package/src/solana/swaps/SolanaSwapData.ts +360 -0
  93. package/src/solana/swaps/SolanaSwapModule.ts +17 -0
  94. package/src/solana/swaps/SolanaSwapProgram.ts +739 -0
  95. package/src/solana/swaps/SwapTypeEnum.ts +30 -0
  96. package/src/solana/swaps/modules/SolanaDataAccount.ts +309 -0
  97. package/src/solana/swaps/modules/SolanaLpVault.ts +216 -0
  98. package/src/solana/swaps/modules/SwapClaim.ts +397 -0
  99. package/src/solana/swaps/modules/SwapInit.ts +621 -0
  100. package/src/solana/swaps/modules/SwapRefund.ts +316 -0
  101. package/src/solana/swaps/programIdl.json +945 -0
  102. package/src/solana/swaps/programTypes.ts +1885 -0
  103. package/src/solana/wallet/SolanaKeypairWallet.ts +36 -0
  104. package/src/solana/wallet/SolanaSigner.ts +23 -0
  105. package/src/utils/Utils.ts +145 -0
@@ -0,0 +1,124 @@
1
+ /// <reference types="node" />
2
+ import { Finality, SendOptions, Signer, Transaction } from "@solana/web3.js";
3
+ import { SolanaModule } from "../SolanaModule";
4
+ import { Buffer } from "buffer";
5
+ import { SolanaSigner } from "../../wallet/SolanaSigner";
6
+ export type SolanaTx = {
7
+ tx: Transaction;
8
+ signers: Signer[];
9
+ };
10
+ export declare class SolanaTransactions extends SolanaModule {
11
+ private cbkBeforeTxSigned;
12
+ /**
13
+ * Callback for sending transaction, returns not null if it was successfully able to send the transaction, and null
14
+ * if the transaction should be sent through other means)
15
+ * @private
16
+ */
17
+ private cbkSendTransaction;
18
+ /**
19
+ * Sends raw solana transaction, first through the cbkSendTransaction callback (for e.g. sending the transaction
20
+ * to a different specific RPC), the through the Fees handler (for e.g. Jito transaction) and last through the
21
+ * underlying provider's Connection instance (the usual way). Only sends the transaction through one channel.
22
+ *
23
+ * @param data
24
+ * @param options
25
+ * @private
26
+ */
27
+ private sendRawTransaction;
28
+ /**
29
+ * Waits for the transaction to confirm by periodically checking the transaction status over HTTP, also
30
+ * re-sends the transaction at regular intervals
31
+ *
32
+ * @param solanaTx solana tx to wait for confirmation for
33
+ * @param finality wait for this finality
34
+ * @param abortSignal signal to abort waiting for tx confirmation
35
+ * @private
36
+ */
37
+ private txConfirmationAndResendWatchdog;
38
+ /**
39
+ * Waits for the transaction to confirm from WS, sometimes the WS rejects even though the transaction was confirmed
40
+ * this therefore also runs an ultimate check on the transaction in case the WS handler rejects, checking if it
41
+ * really was expired
42
+ *
43
+ * @param solanaTx solana tx to wait for confirmation for
44
+ * @param finality wait for this finality
45
+ * @param abortSignal signal to abort waiting for tx confirmation
46
+ * @private
47
+ */
48
+ private txConfirmFromWebsocket;
49
+ /**
50
+ * Waits for transaction confirmation using WS subscription and occasional HTTP polling, also re-sends
51
+ * the transaction at regular interval
52
+ *
53
+ * @param solanaTx solana transaction to wait for confirmation for & keep re-sending until it confirms
54
+ * @param abortSignal signal to abort waiting for tx confirmation
55
+ * @param finality wait for specific finality
56
+ * @private
57
+ */
58
+ private confirmTransaction;
59
+ /**
60
+ * Prepares solana transactions, assigns recentBlockhash if needed, applies Phantom hotfix,
61
+ * sets feePayer to ourselves, calls beforeTxSigned callback & signs transaction with provided signers array
62
+ *
63
+ * @param signer
64
+ * @param txs
65
+ * @private
66
+ */
67
+ private prepareTransactions;
68
+ /**
69
+ * Sends out a signed transaction to the RPC
70
+ *
71
+ * @param solTx solana tx to send
72
+ * @param options send options to be passed to the RPC
73
+ * @param onBeforePublish a callback called before every transaction is published
74
+ * @private
75
+ */
76
+ private sendSignedTransaction;
77
+ /**
78
+ * Prepares (adds recent blockhash if required, applies Phantom hotfix),
79
+ * signs (all together using signAllTransactions() calls), sends (in parallel or sequentially) &
80
+ * optionally waits for confirmation of a batch of solana transactions
81
+ *
82
+ * @param signer
83
+ * @param txs transactions to send
84
+ * @param waitForConfirmation whether to wait for transaction confirmations (this also makes sure the transactions
85
+ * are re-sent at regular intervals)
86
+ * @param abortSignal abort signal to abort waiting for transaction confirmations
87
+ * @param parallel whether the send all the transaction at once in parallel or sequentially (such that transactions
88
+ * are executed in order)
89
+ * @param onBeforePublish a callback called before every transaction is published
90
+ */
91
+ sendAndConfirm(signer: SolanaSigner, txs: SolanaTx[], waitForConfirmation?: boolean, abortSignal?: AbortSignal, parallel?: boolean, onBeforePublish?: (txId: string, rawTx: string) => Promise<void>): Promise<string[]>;
92
+ /**
93
+ * Serializes the solana transaction, saves the transaction, signers & last valid blockheight
94
+ *
95
+ * @param tx
96
+ */
97
+ serializeTx(tx: SolanaTx): Promise<string>;
98
+ /**
99
+ * Deserializes saved solana transaction, extracting the transaction, signers & last valid blockheight
100
+ *
101
+ * @param txData
102
+ */
103
+ deserializeTx(txData: string): Promise<SolanaTx>;
104
+ /**
105
+ * Gets the status of the raw solana transaction, this also checks transaction expiry & can therefore report tx
106
+ * in "pending" status, however pending status doesn't necessarily mean that the transaction was sent (again,
107
+ * no mempool on Solana, cannot check that), this function is preferred against getTxIdStatus
108
+ *
109
+ * @param tx
110
+ */
111
+ getTxStatus(tx: string): Promise<"pending" | "success" | "not_found" | "reverted">;
112
+ /**
113
+ * Gets the status of the solana transaction with a specific txId, this cannot report whether the transaction is
114
+ * "pending" because Solana has no concept of mempool & only confirmed transactions are accessible
115
+ *
116
+ * @param txId
117
+ * @param finality
118
+ */
119
+ getTxIdStatus(txId: string, finality?: Finality): Promise<"success" | "not_found" | "reverted">;
120
+ onBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): void;
121
+ offBeforeTxSigned(callback: (tx: SolanaTx) => Promise<void>): boolean;
122
+ onSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): void;
123
+ offSendTransaction(callback: (tx: Buffer, options?: SendOptions) => Promise<string>): boolean;
124
+ }
@@ -0,0 +1,354 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SolanaTransactions = void 0;
13
+ const web3_js_1 = require("@solana/web3.js");
14
+ const SolanaModule_1 = require("../SolanaModule");
15
+ const bs58 = require("bs58");
16
+ const Utils_1 = require("../../../utils/Utils");
17
+ const buffer_1 = require("buffer");
18
+ class SolanaTransactions extends SolanaModule_1.SolanaModule {
19
+ /**
20
+ * Sends raw solana transaction, first through the cbkSendTransaction callback (for e.g. sending the transaction
21
+ * to a different specific RPC), the through the Fees handler (for e.g. Jito transaction) and last through the
22
+ * underlying provider's Connection instance (the usual way). Only sends the transaction through one channel.
23
+ *
24
+ * @param data
25
+ * @param options
26
+ * @private
27
+ */
28
+ sendRawTransaction(data, options) {
29
+ return __awaiter(this, void 0, void 0, function* () {
30
+ let result = null;
31
+ options !== null && options !== void 0 ? options : (options = {});
32
+ options.maxRetries = 0;
33
+ if (this.cbkSendTransaction != null)
34
+ result = yield this.cbkSendTransaction(data, options);
35
+ if (result == null)
36
+ result = yield this.root.Fees.submitTx(data, options);
37
+ if (result == null)
38
+ result = yield this.connection.sendRawTransaction(data, options);
39
+ // this.logger.debug("sendRawTransaction(): tx sent, signature: "+result);
40
+ return result;
41
+ });
42
+ }
43
+ /**
44
+ * Waits for the transaction to confirm by periodically checking the transaction status over HTTP, also
45
+ * re-sends the transaction at regular intervals
46
+ *
47
+ * @param solanaTx solana tx to wait for confirmation for
48
+ * @param finality wait for this finality
49
+ * @param abortSignal signal to abort waiting for tx confirmation
50
+ * @private
51
+ */
52
+ txConfirmationAndResendWatchdog(solanaTx, finality, abortSignal) {
53
+ const rawTx = solanaTx.tx.serialize();
54
+ const signature = bs58.encode(solanaTx.tx.signature);
55
+ return new Promise((resolve, reject) => {
56
+ var _a;
57
+ let watchdogInterval;
58
+ watchdogInterval = setInterval(() => __awaiter(this, void 0, void 0, function* () {
59
+ const result = yield this.sendRawTransaction(rawTx, { skipPreflight: true }).catch(e => this.logger.error("txConfirmationAndResendWatchdog(): transaction re-sent error: ", e));
60
+ this.logger.debug("txConfirmationAndResendWatchdog(): transaction re-sent: " + result);
61
+ const status = yield this.getTxIdStatus(signature, finality).catch(e => this.logger.error("txConfirmationAndResendWatchdog(): get tx id status error: ", e));
62
+ if (status == null || status === "not_found")
63
+ return;
64
+ if (status === "success") {
65
+ this.logger.info("txConfirmationAndResendWatchdog(): transaction confirmed from HTTP polling, signature: " + signature);
66
+ resolve(signature);
67
+ }
68
+ if (status === "reverted")
69
+ reject(new Error("Transaction reverted!"));
70
+ clearInterval(watchdogInterval);
71
+ }), ((_a = this.retryPolicy) === null || _a === void 0 ? void 0 : _a.transactionResendInterval) || 3000);
72
+ if (abortSignal != null)
73
+ abortSignal.addEventListener("abort", () => {
74
+ clearInterval(watchdogInterval);
75
+ reject(abortSignal.reason);
76
+ });
77
+ });
78
+ }
79
+ /**
80
+ * Waits for the transaction to confirm from WS, sometimes the WS rejects even though the transaction was confirmed
81
+ * this therefore also runs an ultimate check on the transaction in case the WS handler rejects, checking if it
82
+ * really was expired
83
+ *
84
+ * @param solanaTx solana tx to wait for confirmation for
85
+ * @param finality wait for this finality
86
+ * @param abortSignal signal to abort waiting for tx confirmation
87
+ * @private
88
+ */
89
+ txConfirmFromWebsocket(solanaTx, finality, abortSignal) {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ const signature = bs58.encode(solanaTx.tx.signature);
92
+ let result;
93
+ try {
94
+ result = yield this.connection.confirmTransaction({
95
+ signature: signature,
96
+ blockhash: solanaTx.tx.recentBlockhash,
97
+ lastValidBlockHeight: solanaTx.tx.lastValidBlockHeight,
98
+ abortSignal
99
+ }, finality);
100
+ this.logger.info("txConfirmFromWebsocket(): transaction confirmed from WS, signature: " + signature);
101
+ }
102
+ catch (err) {
103
+ if (abortSignal != null && abortSignal.aborted)
104
+ throw err;
105
+ this.logger.debug("txConfirmFromWebsocket(): transaction rejected from WS, running ultimate check, expiry blockheight: " + solanaTx.tx.lastValidBlockHeight + " signature: " + signature + " error: " + err);
106
+ const status = yield (0, Utils_1.tryWithRetries)(() => this.getTxIdStatus(signature, finality));
107
+ this.logger.info("txConfirmFromWebsocket(): transaction status: " + status + " signature: " + signature);
108
+ if (status === "success")
109
+ return signature;
110
+ if (status === "reverted")
111
+ throw new Error("Transaction reverted!");
112
+ if (err instanceof web3_js_1.TransactionExpiredBlockheightExceededError || err.toString().startsWith("TransactionExpiredBlockheightExceededError")) {
113
+ throw new Error("Transaction expired before confirmation, please try again!");
114
+ }
115
+ else {
116
+ throw err;
117
+ }
118
+ }
119
+ if (result.value.err != null)
120
+ throw new Error("Transaction reverted!");
121
+ return signature;
122
+ });
123
+ }
124
+ /**
125
+ * Waits for transaction confirmation using WS subscription and occasional HTTP polling, also re-sends
126
+ * the transaction at regular interval
127
+ *
128
+ * @param solanaTx solana transaction to wait for confirmation for & keep re-sending until it confirms
129
+ * @param abortSignal signal to abort waiting for tx confirmation
130
+ * @param finality wait for specific finality
131
+ * @private
132
+ */
133
+ confirmTransaction(solanaTx, abortSignal, finality) {
134
+ return __awaiter(this, void 0, void 0, function* () {
135
+ const abortController = new AbortController();
136
+ if (abortSignal != null)
137
+ abortSignal.addEventListener("abort", () => {
138
+ abortController.abort();
139
+ });
140
+ let txSignature;
141
+ try {
142
+ txSignature = yield Promise.race([
143
+ this.txConfirmationAndResendWatchdog(solanaTx, finality, abortController.signal),
144
+ this.txConfirmFromWebsocket(solanaTx, finality, abortController.signal)
145
+ ]);
146
+ }
147
+ catch (e) {
148
+ abortController.abort(e);
149
+ throw e;
150
+ }
151
+ // this.logger.info("confirmTransaction(): transaction confirmed, signature: "+txSignature);
152
+ abortController.abort();
153
+ });
154
+ }
155
+ /**
156
+ * Prepares solana transactions, assigns recentBlockhash if needed, applies Phantom hotfix,
157
+ * sets feePayer to ourselves, calls beforeTxSigned callback & signs transaction with provided signers array
158
+ *
159
+ * @param signer
160
+ * @param txs
161
+ * @private
162
+ */
163
+ prepareTransactions(signer, txs) {
164
+ return __awaiter(this, void 0, void 0, function* () {
165
+ let latestBlockData = null;
166
+ for (let tx of txs) {
167
+ if (tx.tx.recentBlockhash == null) {
168
+ if (latestBlockData == null) {
169
+ latestBlockData = yield (0, Utils_1.tryWithRetries)(() => this.connection.getLatestBlockhash("confirmed"), this.retryPolicy);
170
+ this.logger.debug("prepareTransactions(): fetched latest block data for transactions," +
171
+ " blockhash: " + latestBlockData.blockhash + " expiry blockheight: " + latestBlockData.lastValidBlockHeight);
172
+ }
173
+ tx.tx.recentBlockhash = latestBlockData.blockhash;
174
+ tx.tx.lastValidBlockHeight = latestBlockData.lastValidBlockHeight;
175
+ }
176
+ //This is a hotfix for Phantom adding compute unit price instruction on the first position & breaking
177
+ // required instructions order (e.g. btc relay verify needs to be 0th instruction in a tx)
178
+ if (signer.keypair == null && tx.tx.signatures.length === 0) {
179
+ const foundIx = tx.tx.instructions.find(ix => ix.programId.equals(web3_js_1.ComputeBudgetProgram.programId) && web3_js_1.ComputeBudgetInstruction.decodeInstructionType(ix) === "SetComputeUnitPrice");
180
+ if (foundIx == null)
181
+ tx.tx.instructions.splice(tx.tx.instructions.length - 1, 0, web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: 1 }));
182
+ }
183
+ tx.tx.feePayer = signer.getPublicKey();
184
+ if (this.cbkBeforeTxSigned != null)
185
+ yield this.cbkBeforeTxSigned(tx);
186
+ if (tx.signers != null && tx.signers.length > 0)
187
+ for (let signer of tx.signers)
188
+ tx.tx.sign(signer);
189
+ }
190
+ });
191
+ }
192
+ /**
193
+ * Sends out a signed transaction to the RPC
194
+ *
195
+ * @param solTx solana tx to send
196
+ * @param options send options to be passed to the RPC
197
+ * @param onBeforePublish a callback called before every transaction is published
198
+ * @private
199
+ */
200
+ sendSignedTransaction(solTx, options, onBeforePublish) {
201
+ return __awaiter(this, void 0, void 0, function* () {
202
+ if (onBeforePublish != null)
203
+ yield onBeforePublish(bs58.encode(solTx.tx.signature), yield this.serializeTx(solTx));
204
+ const serializedTx = solTx.tx.serialize();
205
+ this.logger.debug("sendSignedTransaction(): sending transaction: " + serializedTx.toString("hex") +
206
+ " signature: " + bs58.encode(solTx.tx.signature));
207
+ const txResult = yield (0, Utils_1.tryWithRetries)(() => this.sendRawTransaction(serializedTx, options), this.retryPolicy);
208
+ this.logger.info("sendSignedTransaction(): tx sent, signature: " + txResult);
209
+ return txResult;
210
+ });
211
+ }
212
+ /**
213
+ * Prepares (adds recent blockhash if required, applies Phantom hotfix),
214
+ * signs (all together using signAllTransactions() calls), sends (in parallel or sequentially) &
215
+ * optionally waits for confirmation of a batch of solana transactions
216
+ *
217
+ * @param signer
218
+ * @param txs transactions to send
219
+ * @param waitForConfirmation whether to wait for transaction confirmations (this also makes sure the transactions
220
+ * are re-sent at regular intervals)
221
+ * @param abortSignal abort signal to abort waiting for transaction confirmations
222
+ * @param parallel whether the send all the transaction at once in parallel or sequentially (such that transactions
223
+ * are executed in order)
224
+ * @param onBeforePublish a callback called before every transaction is published
225
+ */
226
+ sendAndConfirm(signer, txs, waitForConfirmation, abortSignal, parallel, onBeforePublish) {
227
+ return __awaiter(this, void 0, void 0, function* () {
228
+ yield this.prepareTransactions(signer, txs);
229
+ const signedTxs = yield signer.wallet.signAllTransactions(txs.map(e => e.tx));
230
+ signedTxs.forEach((tx, index) => {
231
+ const solTx = txs[index];
232
+ tx.lastValidBlockHeight = solTx.tx.lastValidBlockHeight;
233
+ solTx.tx = tx;
234
+ });
235
+ const options = {
236
+ skipPreflight: true
237
+ };
238
+ this.logger.debug("sendAndConfirm(): sending transactions, count: " + txs.length +
239
+ " waitForConfirmation: " + waitForConfirmation + " parallel: " + parallel);
240
+ const signatures = [];
241
+ if (parallel) {
242
+ const promises = [];
243
+ for (let solTx of txs) {
244
+ const signature = yield this.sendSignedTransaction(solTx, options, onBeforePublish);
245
+ if (waitForConfirmation)
246
+ promises.push(this.confirmTransaction(solTx, abortSignal, "confirmed"));
247
+ signatures.push(signature);
248
+ }
249
+ if (promises.length > 0)
250
+ yield Promise.all(promises);
251
+ }
252
+ else {
253
+ for (let i = 0; i < txs.length; i++) {
254
+ const solTx = txs[i];
255
+ const signature = yield this.sendSignedTransaction(solTx, options, onBeforePublish);
256
+ const confirmPromise = this.confirmTransaction(solTx, abortSignal, "confirmed");
257
+ //Don't await the last promise when !waitForConfirmation
258
+ if (i < txs.length - 1 || waitForConfirmation)
259
+ yield confirmPromise;
260
+ signatures.push(signature);
261
+ }
262
+ }
263
+ this.logger.info("sendAndConfirm(): sent transactions, count: " + txs.length +
264
+ " waitForConfirmation: " + waitForConfirmation + " parallel: " + parallel);
265
+ return signatures;
266
+ });
267
+ }
268
+ /**
269
+ * Serializes the solana transaction, saves the transaction, signers & last valid blockheight
270
+ *
271
+ * @param tx
272
+ */
273
+ serializeTx(tx) {
274
+ return Promise.resolve(JSON.stringify({
275
+ tx: tx.tx.serialize().toString("hex"),
276
+ signers: tx.signers.map(e => buffer_1.Buffer.from(e.secretKey).toString("hex")),
277
+ lastValidBlockheight: tx.tx.lastValidBlockHeight
278
+ }));
279
+ }
280
+ /**
281
+ * Deserializes saved solana transaction, extracting the transaction, signers & last valid blockheight
282
+ *
283
+ * @param txData
284
+ */
285
+ deserializeTx(txData) {
286
+ const jsonParsed = JSON.parse(txData);
287
+ const transaction = web3_js_1.Transaction.from(buffer_1.Buffer.from(jsonParsed.tx, "hex"));
288
+ transaction.lastValidBlockHeight = jsonParsed.lastValidBlockheight;
289
+ return Promise.resolve({
290
+ tx: transaction,
291
+ signers: jsonParsed.signers.map(e => web3_js_1.Keypair.fromSecretKey(buffer_1.Buffer.from(e, "hex"))),
292
+ });
293
+ }
294
+ /**
295
+ * Gets the status of the raw solana transaction, this also checks transaction expiry & can therefore report tx
296
+ * in "pending" status, however pending status doesn't necessarily mean that the transaction was sent (again,
297
+ * no mempool on Solana, cannot check that), this function is preferred against getTxIdStatus
298
+ *
299
+ * @param tx
300
+ */
301
+ getTxStatus(tx) {
302
+ return __awaiter(this, void 0, void 0, function* () {
303
+ const parsedTx = yield this.deserializeTx(tx);
304
+ const txReceipt = yield this.connection.getTransaction(bs58.encode(parsedTx.tx.signature), {
305
+ commitment: "confirmed",
306
+ maxSupportedTransactionVersion: 0
307
+ });
308
+ if (txReceipt == null) {
309
+ const currentBlockheight = yield this.connection.getBlockHeight("processed");
310
+ if (currentBlockheight > parsedTx.tx.lastValidBlockHeight)
311
+ return "not_found";
312
+ return "pending";
313
+ }
314
+ if (txReceipt.meta.err)
315
+ return "reverted";
316
+ return "success";
317
+ });
318
+ }
319
+ /**
320
+ * Gets the status of the solana transaction with a specific txId, this cannot report whether the transaction is
321
+ * "pending" because Solana has no concept of mempool & only confirmed transactions are accessible
322
+ *
323
+ * @param txId
324
+ * @param finality
325
+ */
326
+ getTxIdStatus(txId, finality) {
327
+ return __awaiter(this, void 0, void 0, function* () {
328
+ const txReceipt = yield this.connection.getTransaction(txId, {
329
+ commitment: finality || "confirmed",
330
+ maxSupportedTransactionVersion: 0
331
+ });
332
+ if (txReceipt == null)
333
+ return "not_found";
334
+ if (txReceipt.meta.err)
335
+ return "reverted";
336
+ return "success";
337
+ });
338
+ }
339
+ onBeforeTxSigned(callback) {
340
+ this.cbkBeforeTxSigned = callback;
341
+ }
342
+ offBeforeTxSigned(callback) {
343
+ this.cbkBeforeTxSigned = null;
344
+ return true;
345
+ }
346
+ onSendTransaction(callback) {
347
+ this.cbkSendTransaction = callback;
348
+ }
349
+ offSendTransaction(callback) {
350
+ this.cbkSendTransaction = null;
351
+ return true;
352
+ }
353
+ }
354
+ exports.SolanaTransactions = SolanaTransactions;