@streamflow/common 6.3.2 → 6.3.3

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.
@@ -1,5 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  import { AccountInfo, BlockhashWithExpiryBlockHeight, Commitment, Context, PublicKey } from "@solana/web3.js";
3
+ import PQueue from "p-queue";
3
4
  export interface ITransactionSolanaExt {
4
5
  computePrice?: number;
5
6
  computeLimit?: number;
@@ -25,6 +26,10 @@ export interface ConfirmationParams {
25
26
  context: Context;
26
27
  commitment?: Commitment;
27
28
  }
29
+ export interface ThrottleParams {
30
+ sendRate?: number;
31
+ sendThrottler?: PQueue;
32
+ }
28
33
  export declare class TransactionFailedError extends Error {
29
34
  constructor(m: string);
30
35
  }
@@ -1,7 +1,9 @@
1
1
  import { Mint } from "@solana/spl-token";
2
2
  import { SignerWalletAdapter } from "@solana/wallet-adapter-base";
3
3
  import { BlockhashWithExpiryBlockHeight, Commitment, Connection, Keypair, PublicKey, Transaction, TransactionInstruction, SignatureStatus, VersionedTransaction, Context, RpcResponseAndContext, SimulatedTransactionResponse } from "@solana/web3.js";
4
- import { Account, AtaParams, ConfirmationParams, ITransactionSolanaExt } from "./types";
4
+ import PQueue from "p-queue";
5
+ import { Account, AtaParams, ConfirmationParams, ITransactionSolanaExt, ThrottleParams } from "./types";
6
+ export declare const buildSendThrottler: (sendRate: number) => PQueue;
5
7
  /**
6
8
  * Wrapper function for Solana web3 getProgramAccounts with slightly better call interface
7
9
  * @param {Connection} connection - Solana web3 connection object.
@@ -49,10 +51,11 @@ export declare function signTransaction<T extends Transaction | VersionedTransac
49
51
  * @param connection - Solana client connection
50
52
  * @param invoker - Keypair used as signer
51
53
  * @param tx - Transaction instance
52
- * @param {ConfirmationParams} confirmationParams - Confirmation Params that will be used for execution
54
+ * @param confirmationParams - Confirmation Params that will be used for execution
55
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
53
56
  * @returns Transaction signature
54
57
  */
55
- export declare function signAndExecuteTransaction(connection: Connection, invoker: Keypair | SignerWalletAdapter, tx: Transaction | VersionedTransaction, confirmationParams: ConfirmationParams): Promise<string>;
58
+ export declare function signAndExecuteTransaction(connection: Connection, invoker: Keypair | SignerWalletAdapter, tx: Transaction | VersionedTransaction, confirmationParams: ConfirmationParams, throttleParams: ThrottleParams): Promise<string>;
56
59
  /**
57
60
  * Sends and confirms Transaction
58
61
  * Uses custom confirmation logic that:
@@ -64,20 +67,36 @@ export declare function signAndExecuteTransaction(connection: Connection, invoke
64
67
  * - otherwise there is a chance of marking a landed tx as failed if it was broadcasted at least once
65
68
  * @param connection - Solana client connection
66
69
  * @param tx - Transaction instance
67
- * @param {ConfirmationParams} confirmationParams - Confirmation Params that will be used for execution
70
+ * @param confirmationParams - Confirmation Params that will be used for execution
71
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
68
72
  * @returns Transaction signature
69
73
  */
70
- export declare function executeTransaction(connection: Connection, tx: Transaction | VersionedTransaction, confirmationParams: ConfirmationParams): Promise<string>;
74
+ export declare function executeTransaction(connection: Connection, tx: Transaction | VersionedTransaction, confirmationParams: ConfirmationParams, throttleParams: ThrottleParams): Promise<string>;
75
+ /**
76
+ * Launches a PromisePool with all transaction being executed at the same time, allows to throttle all TXs through one Queue
77
+ * @param connection - Solana client connection
78
+ * @param txs - Transactions
79
+ * @param confirmationParams - Confirmation Params that will be used for execution
80
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
81
+ * @param throttleParams.sendRate - rate
82
+ * @param throttleParams.sendThrottler - throttler instance
83
+ * @returns Raw Promise Results - should be handled by the consumer and unwrapped accordingly
84
+ */
85
+ export declare function executeMultipleTransactions(connection: Connection, txs: (Transaction | VersionedTransaction)[], confirmationParams: ConfirmationParams, { sendRate, sendThrottler }: ThrottleParams): Promise<PromiseSettledResult<string>[]>;
71
86
  /**
72
87
  * Sends and confirm transaction in a loop, constantly re-broadcsting the tx until Blockheight expires.
73
88
  * - we add additional 30 bocks to account for validators in an PRC pool divergence
74
89
  * @param connection - Solana client connection
75
90
  * @param tx - Transaction instance
76
- * @param hash - blockhash information, the same hash should be used in the Transaction
77
- * @param context - context at which blockhash has been retrieve
78
- * @param commitment - optional commitment that will be used for simulation and confirmation
79
- */
80
- export declare function sendAndConfirmTransaction(connection: Connection, tx: Transaction | VersionedTransaction, { hash, context, commitment }: ConfirmationParams): Promise<string>;
91
+ * @param confirmationParams - Confirmation Params that will be used for execution
92
+ * @param confirmationParams.hash - blockhash information, the same hash should be used in the Transaction
93
+ * @param confirmationParams.context - context at which blockhash has been retrieve
94
+ * @param confirmationParams.commitment - optional commitment that will be used for simulation and confirmation
95
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
96
+ * @param throttleParams.sendRate - rate
97
+ * @param throttleParams.sendThrottler - throttler instance
98
+ */
99
+ export declare function sendAndConfirmTransaction(connection: Connection, tx: Transaction | VersionedTransaction, { hash, context, commitment }: ConfirmationParams, { sendRate, sendThrottler }: ThrottleParams): Promise<string>;
81
100
  export declare function simulateTransaction(connection: Connection, tx: Transaction | VersionedTransaction): Promise<RpcResponseAndContext<SimulatedTransactionResponse>>;
82
101
  /**
83
102
  * Confirms and validates transaction success once
@@ -122,9 +141,10 @@ export declare function generateCreateAtaBatchTx(connection: Connection, payer:
122
141
  * @param invoker - Transaction invoker and payer
123
142
  * @param paramsBatch - Array of Params for an each ATA account: {mint, owner}
124
143
  * @param commitment - optional commitment that will be used to fetch Blockhash
144
+ * @param rate - throttle rate for tx sending
125
145
  * @returns Transaction signature
126
146
  */
127
- export declare function createAtaBatch(connection: Connection, invoker: Keypair | SignerWalletAdapter, paramsBatch: AtaParams[], commitment?: Commitment): Promise<string>;
147
+ export declare function createAtaBatch(connection: Connection, invoker: Keypair | SignerWalletAdapter, paramsBatch: AtaParams[], commitment?: Commitment, rate?: number): Promise<string>;
128
148
  /**
129
149
  * Utility function that checks whether associated token accounts exist and return instructions to populate them if not
130
150
  * @param connection - Solana client connection
@@ -50,13 +50,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
50
50
  return (mod && mod.__esModule) ? mod : { "default": mod };
51
51
  };
52
52
  Object.defineProperty(exports, "__esModule", { value: true });
53
- exports.getMintAndProgram = exports.prepareBaseInstructions = exports.checkOrCreateAtaBatch = exports.createAtaBatch = exports.generateCreateAtaBatchTx = exports.enrichAtaParams = exports.ataBatchExist = exports.ata = exports.confirmAndEnsureTransaction = exports.simulateTransaction = exports.sendAndConfirmTransaction = exports.executeTransaction = exports.signAndExecuteTransaction = exports.signTransaction = exports.prepareTransaction = exports.isTransactionVersioned = exports.isSignerKeypair = exports.isSignerWallet = exports.getProgramAccounts = void 0;
53
+ exports.getMintAndProgram = exports.prepareBaseInstructions = exports.checkOrCreateAtaBatch = exports.createAtaBatch = exports.generateCreateAtaBatchTx = exports.enrichAtaParams = exports.ataBatchExist = exports.ata = exports.confirmAndEnsureTransaction = exports.simulateTransaction = exports.sendAndConfirmTransaction = exports.executeMultipleTransactions = exports.executeTransaction = exports.signAndExecuteTransaction = exports.signTransaction = exports.prepareTransaction = exports.isTransactionVersioned = exports.isSignerKeypair = exports.isSignerWallet = exports.getProgramAccounts = exports.buildSendThrottler = void 0;
54
54
  var spl_token_1 = require("@solana/spl-token");
55
55
  var web3_js_1 = require("@solana/web3.js");
56
56
  var bs58_1 = __importDefault(require("bs58"));
57
+ var p_queue_1 = __importDefault(require("p-queue"));
57
58
  var types_1 = require("./types");
58
59
  var utils_1 = require("../utils");
59
60
  var SIMULATE_TRIES = 3;
61
+ var buildSendThrottler = function (sendRate) {
62
+ return new p_queue_1.default({ concurrency: sendRate, intervalCap: 1, interval: 1000 });
63
+ };
64
+ exports.buildSendThrottler = buildSendThrottler;
60
65
  /**
61
66
  * Wrapper function for Solana web3 getProgramAccounts with slightly better call interface
62
67
  * @param {Connection} connection - Solana web3 connection object.
@@ -181,10 +186,11 @@ exports.signTransaction = signTransaction;
181
186
  * @param connection - Solana client connection
182
187
  * @param invoker - Keypair used as signer
183
188
  * @param tx - Transaction instance
184
- * @param {ConfirmationParams} confirmationParams - Confirmation Params that will be used for execution
189
+ * @param confirmationParams - Confirmation Params that will be used for execution
190
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
185
191
  * @returns Transaction signature
186
192
  */
187
- function signAndExecuteTransaction(connection, invoker, tx, confirmationParams) {
193
+ function signAndExecuteTransaction(connection, invoker, tx, confirmationParams, throttleParams) {
188
194
  return __awaiter(this, void 0, void 0, function () {
189
195
  var signedTx;
190
196
  return __generator(this, function (_a) {
@@ -192,7 +198,7 @@ function signAndExecuteTransaction(connection, invoker, tx, confirmationParams)
192
198
  case 0: return [4 /*yield*/, signTransaction(invoker, tx)];
193
199
  case 1:
194
200
  signedTx = _a.sent();
195
- return [2 /*return*/, executeTransaction(connection, signedTx, confirmationParams)];
201
+ return [2 /*return*/, executeTransaction(connection, signedTx, confirmationParams, throttleParams)];
196
202
  }
197
203
  });
198
204
  });
@@ -209,10 +215,11 @@ exports.signAndExecuteTransaction = signAndExecuteTransaction;
209
215
  * - otherwise there is a chance of marking a landed tx as failed if it was broadcasted at least once
210
216
  * @param connection - Solana client connection
211
217
  * @param tx - Transaction instance
212
- * @param {ConfirmationParams} confirmationParams - Confirmation Params that will be used for execution
218
+ * @param confirmationParams - Confirmation Params that will be used for execution
219
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
213
220
  * @returns Transaction signature
214
221
  */
215
- function executeTransaction(connection, tx, confirmationParams) {
222
+ function executeTransaction(connection, tx, confirmationParams, throttleParams) {
216
223
  return __awaiter(this, void 0, void 0, function () {
217
224
  return __generator(this, function (_a) {
218
225
  switch (_a.label) {
@@ -223,27 +230,57 @@ function executeTransaction(connection, tx, confirmationParams) {
223
230
  return [4 /*yield*/, simulateTransaction(connection, tx)];
224
231
  case 1:
225
232
  _a.sent();
226
- return [2 /*return*/, sendAndConfirmTransaction(connection, tx, confirmationParams)];
233
+ return [2 /*return*/, sendAndConfirmTransaction(connection, tx, confirmationParams, throttleParams)];
227
234
  }
228
235
  });
229
236
  });
230
237
  }
231
238
  exports.executeTransaction = executeTransaction;
239
+ /**
240
+ * Launches a PromisePool with all transaction being executed at the same time, allows to throttle all TXs through one Queue
241
+ * @param connection - Solana client connection
242
+ * @param txs - Transactions
243
+ * @param confirmationParams - Confirmation Params that will be used for execution
244
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
245
+ * @param throttleParams.sendRate - rate
246
+ * @param throttleParams.sendThrottler - throttler instance
247
+ * @returns Raw Promise Results - should be handled by the consumer and unwrapped accordingly
248
+ */
249
+ function executeMultipleTransactions(connection, txs, confirmationParams, _a) {
250
+ var _b = _a.sendRate, sendRate = _b === void 0 ? 1 : _b, sendThrottler = _a.sendThrottler;
251
+ return __awaiter(this, void 0, void 0, function () {
252
+ return __generator(this, function (_c) {
253
+ if (!sendThrottler) {
254
+ sendThrottler = (0, exports.buildSendThrottler)(sendRate);
255
+ }
256
+ return [2 /*return*/, Promise.allSettled(txs.map(function (tx) {
257
+ return executeTransaction(connection, tx, confirmationParams, { sendRate: sendRate, sendThrottler: sendThrottler });
258
+ }))];
259
+ });
260
+ });
261
+ }
262
+ exports.executeMultipleTransactions = executeMultipleTransactions;
232
263
  /**
233
264
  * Sends and confirm transaction in a loop, constantly re-broadcsting the tx until Blockheight expires.
234
265
  * - we add additional 30 bocks to account for validators in an PRC pool divergence
235
266
  * @param connection - Solana client connection
236
267
  * @param tx - Transaction instance
237
- * @param hash - blockhash information, the same hash should be used in the Transaction
238
- * @param context - context at which blockhash has been retrieve
239
- * @param commitment - optional commitment that will be used for simulation and confirmation
268
+ * @param confirmationParams - Confirmation Params that will be used for execution
269
+ * @param confirmationParams.hash - blockhash information, the same hash should be used in the Transaction
270
+ * @param confirmationParams.context - context at which blockhash has been retrieve
271
+ * @param confirmationParams.commitment - optional commitment that will be used for simulation and confirmation
272
+ * @param throttleParams - rate or throttler instance to throttle TX sending - to not spam the blockchain too much
273
+ * @param throttleParams.sendRate - rate
274
+ * @param throttleParams.sendThrottler - throttler instance
240
275
  */
241
- function sendAndConfirmTransaction(connection, tx, _a) {
276
+ function sendAndConfirmTransaction(connection, tx, _a, _b) {
242
277
  var hash = _a.hash, context = _a.context, commitment = _a.commitment;
278
+ var _c = _b.sendRate, sendRate = _c === void 0 ? 1 : _c, sendThrottler = _b.sendThrottler;
243
279
  return __awaiter(this, void 0, void 0, function () {
244
280
  var isVersioned, signature, blockheight, transactionSent, rawTransaction, e_1, value, e_2, _e_1;
245
- return __generator(this, function (_b) {
246
- switch (_b.label) {
281
+ var _this = this;
282
+ return __generator(this, function (_d) {
283
+ switch (_d.label) {
247
284
  case 0:
248
285
  isVersioned = isTransactionVersioned(tx);
249
286
  if (isVersioned) {
@@ -252,71 +289,78 @@ function sendAndConfirmTransaction(connection, tx, _a) {
252
289
  else {
253
290
  signature = bs58_1.default.encode(tx.signature);
254
291
  }
292
+ if (!sendThrottler) {
293
+ sendThrottler = (0, exports.buildSendThrottler)(sendRate);
294
+ }
255
295
  return [4 /*yield*/, connection.getBlockHeight(commitment)];
256
296
  case 1:
257
- blockheight = _b.sent();
297
+ blockheight = _d.sent();
258
298
  transactionSent = false;
259
299
  rawTransaction = tx.serialize();
260
- _b.label = 2;
300
+ _d.label = 2;
261
301
  case 2:
262
302
  if (!(blockheight < hash.lastValidBlockHeight + 15)) return [3 /*break*/, 20];
263
- _b.label = 3;
303
+ _d.label = 3;
264
304
  case 3:
265
- _b.trys.push([3, 6, , 9]);
305
+ _d.trys.push([3, 6, , 9]);
266
306
  if (!(blockheight < hash.lastValidBlockHeight || !transactionSent)) return [3 /*break*/, 5];
267
- return [4 /*yield*/, connection.sendRawTransaction(rawTransaction, {
268
- maxRetries: 0,
269
- minContextSlot: context.slot,
270
- preflightCommitment: commitment,
271
- skipPreflight: true,
272
- })];
307
+ return [4 /*yield*/, sendThrottler.add(function () { return __awaiter(_this, void 0, void 0, function () {
308
+ return __generator(this, function (_a) {
309
+ return [2 /*return*/, connection.sendRawTransaction(rawTransaction, {
310
+ maxRetries: 0,
311
+ minContextSlot: context.slot,
312
+ preflightCommitment: commitment,
313
+ skipPreflight: true,
314
+ })];
315
+ });
316
+ }); })];
273
317
  case 4:
274
- _b.sent();
318
+ _d.sent();
275
319
  transactionSent = true;
276
- _b.label = 5;
320
+ _d.label = 5;
277
321
  case 5: return [3 /*break*/, 9];
278
322
  case 6:
279
- e_1 = _b.sent();
323
+ e_1 = _d.sent();
280
324
  if (!(transactionSent ||
281
325
  (e_1 instanceof web3_js_1.SendTransactionError && e_1.message.includes("Minimum context slot has not been reached")))) return [3 /*break*/, 8];
282
326
  return [4 /*yield*/, (0, utils_1.sleep)(500)];
283
327
  case 7:
284
- _b.sent();
328
+ _d.sent();
285
329
  return [3 /*break*/, 2];
286
330
  case 8: throw e_1;
287
331
  case 9: return [4 /*yield*/, (0, utils_1.sleep)(500)];
288
332
  case 10:
289
- _b.sent();
290
- _b.label = 11;
333
+ _d.sent();
334
+ _d.label = 11;
291
335
  case 11:
292
- _b.trys.push([11, 13, , 15]);
336
+ _d.trys.push([11, 13, , 15]);
293
337
  return [4 /*yield*/, confirmAndEnsureTransaction(connection, signature)];
294
338
  case 12:
295
- value = _b.sent();
339
+ value = _d.sent();
296
340
  if (value) {
297
341
  return [2 /*return*/, signature];
298
342
  }
299
343
  return [3 /*break*/, 15];
300
344
  case 13:
301
- e_2 = _b.sent();
345
+ e_2 = _d.sent();
302
346
  if (e_2 instanceof types_1.TransactionFailedError) {
303
347
  throw e_2;
304
348
  }
305
349
  return [4 /*yield*/, (0, utils_1.sleep)(500)];
306
350
  case 14:
307
- _b.sent();
351
+ _d.sent();
308
352
  return [3 /*break*/, 15];
309
353
  case 15:
310
- _b.trys.push([15, 17, , 19]);
354
+ _d.trys.push([15, 17, , 19]);
311
355
  return [4 /*yield*/, connection.getBlockHeight(commitment)];
312
356
  case 16:
313
- blockheight = _b.sent();
357
+ blockheight = _d.sent();
314
358
  return [3 /*break*/, 19];
315
359
  case 17:
316
- _e_1 = _b.sent();
360
+ _e_1 = _d.sent();
317
361
  return [4 /*yield*/, (0, utils_1.sleep)(500)];
318
362
  case 18:
319
- _b.sent();
363
+ _d.sent();
320
364
  return [3 /*break*/, 19];
321
365
  case 19: return [3 /*break*/, 2];
322
366
  case 20: throw new Error("Transaction ".concat(signature, " expired."));
@@ -543,9 +587,10 @@ exports.generateCreateAtaBatchTx = generateCreateAtaBatchTx;
543
587
  * @param invoker - Transaction invoker and payer
544
588
  * @param paramsBatch - Array of Params for an each ATA account: {mint, owner}
545
589
  * @param commitment - optional commitment that will be used to fetch Blockhash
590
+ * @param rate - throttle rate for tx sending
546
591
  * @returns Transaction signature
547
592
  */
548
- function createAtaBatch(connection, invoker, paramsBatch, commitment) {
593
+ function createAtaBatch(connection, invoker, paramsBatch, commitment, rate) {
549
594
  return __awaiter(this, void 0, void 0, function () {
550
595
  var _a, tx, hash, context, _b, _c;
551
596
  return __generator(this, function (_d) {
@@ -558,7 +603,7 @@ function createAtaBatch(connection, invoker, paramsBatch, commitment) {
558
603
  case 1: return [4 /*yield*/, _b.apply(void 0, _c.concat([_d.sent(), commitment]))];
559
604
  case 2:
560
605
  _a = _d.sent(), tx = _a.tx, hash = _a.hash, context = _a.context;
561
- return [2 /*return*/, signAndExecuteTransaction(connection, invoker, tx, { hash: hash, context: context, commitment: commitment })];
606
+ return [2 /*return*/, signAndExecuteTransaction(connection, invoker, tx, { hash: hash, context: context, commitment: commitment }, { sendRate: rate })];
562
607
  }
563
608
  });
564
609
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamflow/common",
3
- "version": "6.3.2",
3
+ "version": "6.3.3",
4
4
  "description": "Common utilities and types used by streamflow packages.",
5
5
  "homepage": "https://github.com/streamflow-finance/js-sdk/",
6
6
  "main": "dist/index.js",
@@ -23,9 +23,9 @@
23
23
  "lint-config": "eslint --print-config",
24
24
  "prepublishOnly": "npm run lint && npm run build"
25
25
  },
26
- "gitHead": "8fa0da9107e1a1b9ea900d1f7159169c0d256d31",
26
+ "gitHead": "01ceb912ed61adfb1055d9d1ea64e61f98a183eb",
27
27
  "devDependencies": {
28
- "@streamflow/eslint-config": "6.3.2",
28
+ "@streamflow/eslint-config": "6.3.3",
29
29
  "@types/bn.js": "5.1.1",
30
30
  "@types/jest": "29.2.4",
31
31
  "date-fns": "2.28.0",
@@ -42,6 +42,7 @@
42
42
  "aptos": "1.4.0",
43
43
  "bn.js": "5.2.1",
44
44
  "borsh": "^2.0.0",
45
- "bs58": "5.0.0"
45
+ "bs58": "5.0.0",
46
+ "p-queue": "^6.6.2"
46
47
  }
47
48
  }