@0xbow/privacy-pools-core-sdk 1.0.3 → 1.0.4

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 (29) hide show
  1. package/dist/esm/{fetchArtifacts.esm-aHubC6Nb.js → fetchArtifacts.esm-C_DNv-_D.js} +2 -2
  2. package/dist/esm/{fetchArtifacts.esm-aHubC6Nb.js.map → fetchArtifacts.esm-C_DNv-_D.js.map} +1 -1
  3. package/dist/esm/{fetchArtifacts.node-DUdhNM9Z.js → fetchArtifacts.node-BBPNjgiT.js} +2 -2
  4. package/dist/esm/{fetchArtifacts.node-DUdhNM9Z.js.map → fetchArtifacts.node-BBPNjgiT.js.map} +1 -1
  5. package/dist/esm/{index-BQLhaPQL.js → index-BxzIe_IR.js} +44 -19
  6. package/dist/esm/index-BxzIe_IR.js.map +1 -0
  7. package/dist/esm/index.mjs +1 -1
  8. package/dist/index.d.mts +6 -4
  9. package/dist/node/{fetchArtifacts.esm-CRX34p8g.js → fetchArtifacts.esm-l-EDo53-.js} +2 -2
  10. package/dist/node/{fetchArtifacts.esm-CRX34p8g.js.map → fetchArtifacts.esm-l-EDo53-.js.map} +1 -1
  11. package/dist/node/{fetchArtifacts.node-CuPs4jZ1.js → fetchArtifacts.node-DYwQHSF4.js} +2 -2
  12. package/dist/node/{fetchArtifacts.node-CuPs4jZ1.js.map → fetchArtifacts.node-DYwQHSF4.js.map} +1 -1
  13. package/dist/node/{index-DB1uYJPF.js → index-DGsIfUGw.js} +44 -19
  14. package/dist/node/index-DGsIfUGw.js.map +1 -0
  15. package/dist/node/index.mjs +1 -1
  16. package/dist/types/core/account.service.d.ts +6 -4
  17. package/dist/types/{fetchArtifacts.esm-CzBDJOwj.js → fetchArtifacts.esm-IMTIZwq7.js} +1 -1
  18. package/dist/types/{fetchArtifacts.node-CtMsXhR9.js → fetchArtifacts.node-BcXsBNCT.js} +1 -1
  19. package/dist/types/{index-BL6xN-P5.js → index-DbuAhDci.js} +43 -18
  20. package/dist/types/index.js +1 -1
  21. package/dist/types/utils/concurrency.d.ts +15 -0
  22. package/package.json +2 -1
  23. package/src/core/account.service.ts +35 -26
  24. package/src/core/contracts.service.ts +2 -6
  25. package/src/providers/blockchainProvider.ts +1 -3
  26. package/src/utils/concurrency.ts +32 -0
  27. package/dist/esm/index-BQLhaPQL.js.map +0 -1
  28. package/dist/node/index-DB1uYJPF.js.map +0 -1
  29. package/dist/types/core/test.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- export { n as AccountError, A as AccountService, B as BlockchainProvider, o as CircuitName, j as Circuits, C as CommitmentService, m as ContractError, k as ContractInteractionsService, D as DataService, E as ErrorCode, I as InvalidRpcUrl, P as PrivacyPoolSDK, l as ProofError, S as SDKError, W as WithdrawalService, e as bigintToHash, f as bigintToHex, i as calculateContext, a as generateDepositSecrets, g as generateMasterKeys, d as generateMerkleProof, b as generateWithdrawalSecrets, c as getCommitment, h as hashPrecommitment } from './index-DB1uYJPF.js';
1
+ export { n as AccountError, A as AccountService, B as BlockchainProvider, o as CircuitName, j as Circuits, C as CommitmentService, m as ContractError, k as ContractInteractionsService, D as DataService, E as ErrorCode, I as InvalidRpcUrl, P as PrivacyPoolSDK, l as ProofError, S as SDKError, W as WithdrawalService, e as bigintToHash, f as bigintToHex, i as calculateContext, a as generateDepositSecrets, g as generateMasterKeys, d as generateMerkleProof, b as generateWithdrawalSecrets, c as getCommitment, h as hashPrecommitment } from './index-DGsIfUGw.js';
2
2
  import 'viem/accounts';
3
3
  import 'buffer';
4
4
  import 'http';
@@ -223,13 +223,14 @@ export declare class AccountService {
223
223
  */
224
224
  getRagequitEvents(pool: PoolInfo): Promise<Map<Hash, RagequitEvent>>;
225
225
  /**
226
- * Fetches events for a given set of pools
226
+ * Fetches events for a given set of pools with concurrency control
227
227
  *
228
228
  * @param pools - The pools to fetch events for
229
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
229
230
  *
230
231
  * @returns A map of pool scopes to their events
231
232
  */
232
- getEvents(pools: PoolInfo[]): Promise<PoolEventsResult>;
233
+ getEvents(pools: PoolInfo[], maxConcurrency?: number): Promise<PoolEventsResult>;
233
234
  /**
234
235
  * Processes deposit events for a given scope and adds them to the account
235
236
  * Deterministically generate deposit secrets and check if they match on-chain deposits
@@ -279,10 +280,11 @@ export declare class AccountService {
279
280
  * @param dataService - The data service to use for fetching events
280
281
  * @param source - The source to use for initializing the account. Either a mnemonic or an existing account service instance
281
282
  * @param pools - The pools to fetch events for
283
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
282
284
  *
283
285
  * @remarks
284
286
  * This method performs the following steps for each pool:
285
- * 1. Fetches deposit, withdrawal, and ragequit events for each pool
287
+ * 1. Fetches deposit, withdrawal, and ragequit events for each pool (with concurrency control)
286
288
  * 2. Processes deposit events and creates pool accounts
287
289
  * 3. Processes withdrawal events and adds commitments to pool accounts
288
290
  * 4. Processes ragequit events and adds ragequit to pool accounts
@@ -298,7 +300,7 @@ export declare class AccountService {
298
300
  mnemonic: string;
299
301
  } | {
300
302
  service: AccountService;
301
- }, pools: PoolInfo[]): Promise<{
303
+ }, pools: PoolInfo[], maxConcurrency?: number): Promise<{
302
304
  account: AccountService;
303
305
  errors: PoolEventsError[];
304
306
  }>;
@@ -1,4 +1,4 @@
1
- import { F as FetchArtifact } from './index-BL6xN-P5.js';
1
+ import { F as FetchArtifact } from './index-DbuAhDci.js';
2
2
  import 'viem/accounts';
3
3
  import 'buffer';
4
4
  import 'http';
@@ -1,4 +1,4 @@
1
- import { F as FetchArtifact } from './index-BL6xN-P5.js';
1
+ import { F as FetchArtifact } from './index-DbuAhDci.js';
2
2
  import 'viem/accounts';
3
3
  import 'buffer';
4
4
  import 'http';
@@ -51070,10 +51070,10 @@ const circuitToAsset = {
51070
51070
 
51071
51071
  async function importFetchVersionedArtifact(isBrowser) {
51072
51072
  if (isBrowser) {
51073
- return import('./fetchArtifacts.esm-CzBDJOwj.js');
51073
+ return import('./fetchArtifacts.esm-IMTIZwq7.js');
51074
51074
  }
51075
51075
  else {
51076
- return import('./fetchArtifacts.node-CtMsXhR9.js');
51076
+ return import('./fetchArtifacts.node-BcXsBNCT.js');
51077
51077
  }
51078
51078
  }
51079
51079
 
@@ -76385,6 +76385,31 @@ class Logger {
76385
76385
  }
76386
76386
  }
76387
76387
 
76388
+ /**
76389
+ * Executes an array of promise-returning functions with a maximum concurrency limit.
76390
+ * This prevents overwhelming RPC endpoints with too many concurrent requests.
76391
+ *
76392
+ * @param tasks - Array of functions that return promises
76393
+ * @param maxConcurrency - Maximum number of concurrent executions (default: 5)
76394
+ * @returns Promise that resolves to an array of settled results
76395
+ *
76396
+ * @example
76397
+ * ```typescript
76398
+ * const tasks = pools.map(pool => () => fetchPoolData(pool));
76399
+ * const results = await batchWithConcurrency(tasks, 5);
76400
+ * ```
76401
+ */
76402
+ async function batchWithConcurrency(tasks, maxConcurrency = 5) {
76403
+ const results = [];
76404
+ // Process tasks in batches
76405
+ for (let i = 0; i < tasks.length; i += maxConcurrency) {
76406
+ const batch = tasks.slice(i, i + maxConcurrency);
76407
+ const batchResults = await Promise.allSettled(batch.map(task => task()));
76408
+ results.push(...batchResults);
76409
+ }
76410
+ return results;
76411
+ }
76412
+
76388
76413
  class DataError extends SDKError {
76389
76414
  constructor(message, code = ErrorCode.NETWORK_ERROR, details) {
76390
76415
  super(message, code, details);
@@ -76441,7 +76466,7 @@ class AccountService {
76441
76466
  */
76442
76467
  constructor(dataService, config) {
76443
76468
  this.dataService = dataService;
76444
- this.logger = new Logger({ prefix: "Account", level: LogLevel.DEBUG });
76469
+ this.logger = new Logger({ prefix: "Account" });
76445
76470
  if ("mnemonic" in config) {
76446
76471
  this.account = this._initializeAccount(config.mnemonic);
76447
76472
  }
@@ -76656,12 +76681,6 @@ class AccountService {
76656
76681
  addPoolAccount(scope, value, nullifier, secret, label, blockNumber, txHash) {
76657
76682
  const precommitment = this._hashPrecommitment(nullifier, secret);
76658
76683
  const commitment = this._hashCommitment(value, label, precommitment);
76659
- this.logger.debug(`Commitment calculation details`, {
76660
- value,
76661
- label,
76662
- precommitment,
76663
- commitment,
76664
- });
76665
76684
  const newAccount = {
76666
76685
  label,
76667
76686
  deposit: {
@@ -76727,7 +76746,6 @@ class AccountService {
76727
76746
  blockNumber,
76728
76747
  txHash,
76729
76748
  };
76730
- this.logger.debug(`adding the following commitment`, { precommitment, hash: this._hashCommitment(value, parentCommitment.label, precommitment), });
76731
76749
  foundAccount.children.push(newCommitment);
76732
76750
  this.logger.info(`Added new commitment with value ${value} to account with label ${parentCommitment.label}`);
76733
76751
  return newCommitment;
@@ -76835,15 +76853,17 @@ class AccountService {
76835
76853
  }
76836
76854
  }
76837
76855
  /**
76838
- * Fetches events for a given set of pools
76856
+ * Fetches events for a given set of pools with concurrency control
76839
76857
  *
76840
76858
  * @param pools - The pools to fetch events for
76859
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
76841
76860
  *
76842
76861
  * @returns A map of pool scopes to their events
76843
76862
  */
76844
- async getEvents(pools) {
76863
+ async getEvents(pools, maxConcurrency = 5) {
76845
76864
  const events = new Map();
76846
- const poolEventResults = await Promise.allSettled(pools.map(async (pool) => {
76865
+ // Create tasks for batched execution
76866
+ const tasks = pools.map((pool) => async () => {
76847
76867
  this.logger.info(`Fetching events for pool`, {
76848
76868
  poolAddress: pool.address,
76849
76869
  poolChainId: pool.chainId,
@@ -76860,7 +76880,9 @@ class AccountService {
76860
76880
  withdrawalEvents,
76861
76881
  ragequitEvents,
76862
76882
  };
76863
- }));
76883
+ });
76884
+ // Execute with concurrency control
76885
+ const poolEventResults = await batchWithConcurrency(tasks, maxConcurrency);
76864
76886
  for (const result of poolEventResults) {
76865
76887
  if (result.status === "fulfilled") {
76866
76888
  const { scope, depositEvents, withdrawalEvents, ragequitEvents } = result.value;
@@ -76999,10 +77021,11 @@ class AccountService {
76999
77021
  * @param dataService - The data service to use for fetching events
77000
77022
  * @param source - The source to use for initializing the account. Either a mnemonic or an existing account service instance
77001
77023
  * @param pools - The pools to fetch events for
77024
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
77002
77025
  *
77003
77026
  * @remarks
77004
77027
  * This method performs the following steps for each pool:
77005
- * 1. Fetches deposit, withdrawal, and ragequit events for each pool
77028
+ * 1. Fetches deposit, withdrawal, and ragequit events for each pool (with concurrency control)
77006
77029
  * 2. Processes deposit events and creates pool accounts
77007
77030
  * 3. Processes withdrawal events and adds commitments to pool accounts
77008
77031
  * 4. Processes ragequit events and adds ragequit to pool accounts
@@ -77014,7 +77037,7 @@ class AccountService {
77014
77037
  *
77015
77038
  * @throws {AccountError} If account state reconstruction fails or if duplicate pools are found
77016
77039
  */
77017
- static async initializeWithEvents(dataService, source, pools) {
77040
+ static async initializeWithEvents(dataService, source, pools, maxConcurrency = 5) {
77018
77041
  // Log the start of the history retrieval process
77019
77042
  const logger = new Logger({ prefix: "Account" });
77020
77043
  logger.info(`Fetching events for pools`, { poolLength: pools.length });
@@ -77030,7 +77053,7 @@ class AccountService {
77030
77053
  const account = new AccountService(dataService, "mnemonic" in source
77031
77054
  ? { mnemonic: source.mnemonic }
77032
77055
  : { account: source.service.account });
77033
- const events = await account.getEvents(pools);
77056
+ const events = await account.getEvents(pools, maxConcurrency);
77034
77057
  for (const [scope, result] of events.entries()) {
77035
77058
  if ("reason" in result) {
77036
77059
  errors.push(result);
@@ -77241,7 +77264,9 @@ class DataService {
77241
77264
  throw new Error(`Missing RPC URL for chain ${config.chainId}`);
77242
77265
  }
77243
77266
  const client = createPublicClient({
77244
- transport: http(config.rpcUrl),
77267
+ transport: http(config.rpcUrl, {
77268
+ timeout: 20_000,
77269
+ }),
77245
77270
  });
77246
77271
  this.clients.set(config.chainId, client);
77247
77272
  }
@@ -1,4 +1,4 @@
1
- export { n as AccountError, A as AccountService, B as BlockchainProvider, o as CircuitName, j as Circuits, C as CommitmentService, m as ContractError, k as ContractInteractionsService, D as DataService, E as ErrorCode, I as InvalidRpcUrl, P as PrivacyPoolSDK, l as ProofError, S as SDKError, W as WithdrawalService, e as bigintToHash, f as bigintToHex, i as calculateContext, a as generateDepositSecrets, g as generateMasterKeys, d as generateMerkleProof, b as generateWithdrawalSecrets, c as getCommitment, h as hashPrecommitment } from './index-BL6xN-P5.js';
1
+ export { n as AccountError, A as AccountService, B as BlockchainProvider, o as CircuitName, j as Circuits, C as CommitmentService, m as ContractError, k as ContractInteractionsService, D as DataService, E as ErrorCode, I as InvalidRpcUrl, P as PrivacyPoolSDK, l as ProofError, S as SDKError, W as WithdrawalService, e as bigintToHash, f as bigintToHex, i as calculateContext, a as generateDepositSecrets, g as generateMasterKeys, d as generateMerkleProof, b as generateWithdrawalSecrets, c as getCommitment, h as hashPrecommitment } from './index-DbuAhDci.js';
2
2
  import 'viem/accounts';
3
3
  import 'buffer';
4
4
  import 'http';
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Executes an array of promise-returning functions with a maximum concurrency limit.
3
+ * This prevents overwhelming RPC endpoints with too many concurrent requests.
4
+ *
5
+ * @param tasks - Array of functions that return promises
6
+ * @param maxConcurrency - Maximum number of concurrent executions (default: 5)
7
+ * @returns Promise that resolves to an array of settled results
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const tasks = pools.map(pool => () => fetchPoolData(pool));
12
+ * const results = await batchWithConcurrency(tasks, 5);
13
+ * ```
14
+ */
15
+ export declare function batchWithConcurrency<T>(tasks: (() => Promise<T>)[], maxConcurrency?: number): Promise<PromiseSettledResult<T>[]>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0xbow/privacy-pools-core-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.4",
4
4
  "description": "Typescript SDK for the Privacy Pool protocol",
5
5
  "repository": "https://github.com/0xbow-io/privacy-pools-core",
6
6
  "license": "Apache-2.0",
@@ -69,6 +69,7 @@
69
69
  "@types/node": "20.3.1",
70
70
  "@types/snarkjs": "0.7.9",
71
71
  "commitlint": "19.4.1",
72
+ "dotenv": "^17.3.1",
72
73
  "globals": "15.14.0",
73
74
  "husky": "9.1.5",
74
75
  "lint-staged": "15.2.10",
@@ -18,6 +18,7 @@ import {
18
18
  } from "../types/events.js";
19
19
 
20
20
  import { Logger } from "../utils/logger.js";
21
+ import { batchWithConcurrency } from "../utils/concurrency.js";
21
22
  import { AccountError } from "../errors/account.error.js";
22
23
  import { ErrorCode } from "../errors/base.error.js";
23
24
  import { EventError } from "../errors/events.error.js";
@@ -561,38 +562,44 @@ export class AccountService {
561
562
  }
562
563
 
563
564
  /**
564
- * Fetches events for a given set of pools
565
+ * Fetches events for a given set of pools with concurrency control
565
566
  *
566
567
  * @param pools - The pools to fetch events for
568
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
567
569
  *
568
570
  * @returns A map of pool scopes to their events
569
571
  */
570
- public async getEvents(pools: PoolInfo[]): Promise<PoolEventsResult> {
572
+ public async getEvents(
573
+ pools: PoolInfo[],
574
+ maxConcurrency: number = 5
575
+ ): Promise<PoolEventsResult> {
571
576
  const events: PoolEventsResult = new Map();
572
577
 
573
- const poolEventResults = await Promise.allSettled(
574
- pools.map(async (pool) => {
575
- this.logger.info(`Fetching events for pool`, {
576
- poolAddress: pool.address,
577
- poolChainId: pool.chainId,
578
- poolDeploymentBlock: pool.deploymentBlock,
579
- });
578
+ // Create tasks for batched execution
579
+ const tasks = pools.map((pool) => async () => {
580
+ this.logger.info(`Fetching events for pool`, {
581
+ poolAddress: pool.address,
582
+ poolChainId: pool.chainId,
583
+ poolDeploymentBlock: pool.deploymentBlock,
584
+ });
580
585
 
581
- const [depositEvents, withdrawalEvents, ragequitEvents] =
582
- await Promise.all([
583
- this.getDepositEvents(pool),
584
- this.getWithdrawalEvents(pool),
585
- this.getRagequitEvents(pool),
586
- ]);
586
+ const [depositEvents, withdrawalEvents, ragequitEvents] =
587
+ await Promise.all([
588
+ this.getDepositEvents(pool),
589
+ this.getWithdrawalEvents(pool),
590
+ this.getRagequitEvents(pool),
591
+ ]);
587
592
 
588
- return {
589
- scope: pool.scope,
590
- depositEvents,
591
- withdrawalEvents,
592
- ragequitEvents,
593
- };
594
- })
595
- );
593
+ return {
594
+ scope: pool.scope,
595
+ depositEvents,
596
+ withdrawalEvents,
597
+ ragequitEvents,
598
+ };
599
+ });
600
+
601
+ // Execute with concurrency control
602
+ const poolEventResults = await batchWithConcurrency(tasks, maxConcurrency);
596
603
 
597
604
  for (const result of poolEventResults) {
598
605
  if (result.status === "fulfilled") {
@@ -783,10 +790,11 @@ export class AccountService {
783
790
  * @param dataService - The data service to use for fetching events
784
791
  * @param source - The source to use for initializing the account. Either a mnemonic or an existing account service instance
785
792
  * @param pools - The pools to fetch events for
793
+ * @param maxConcurrency - Maximum number of concurrent pool fetches (default: 5)
786
794
  *
787
795
  * @remarks
788
796
  * This method performs the following steps for each pool:
789
- * 1. Fetches deposit, withdrawal, and ragequit events for each pool
797
+ * 1. Fetches deposit, withdrawal, and ragequit events for each pool (with concurrency control)
790
798
  * 2. Processes deposit events and creates pool accounts
791
799
  * 3. Processes withdrawal events and adds commitments to pool accounts
792
800
  * 4. Processes ragequit events and adds ragequit to pool accounts
@@ -807,7 +815,8 @@ export class AccountService {
807
815
  | {
808
816
  service: AccountService;
809
817
  },
810
- pools: PoolInfo[]
818
+ pools: PoolInfo[],
819
+ maxConcurrency: number = 5
811
820
  ): Promise<{ account: AccountService; errors: PoolEventsError[] }> {
812
821
  // Log the start of the history retrieval process
813
822
  const logger = new Logger({ prefix: "Account" });
@@ -830,7 +839,7 @@ export class AccountService {
830
839
  : { account: source.service.account }
831
840
  );
832
841
 
833
- const events = await account.getEvents(pools);
842
+ const events = await account.getEvents(pools, maxConcurrency);
834
843
 
835
844
  for (const [scope, result] of events.entries()) {
836
845
  if ("reason" in result) {
@@ -55,17 +55,13 @@ export class ContractInteractionsService implements ContractInteractions {
55
55
 
56
56
  this.walletClient = createWalletClient({
57
57
  chain: chain,
58
- transport: http(rpcUrl, {
59
- timeout: 20_000,
60
- }),
58
+ transport: http(rpcUrl),
61
59
  account: this.account,
62
60
  });
63
61
 
64
62
  this.publicClient = createPublicClient({
65
63
  chain: chain,
66
- transport: http(rpcUrl, {
67
- timeout: 20_000,
68
- }),
64
+ transport: http(rpcUrl),
69
65
  });
70
66
 
71
67
  this.entrypointAddress = entrypointAddress;
@@ -15,9 +15,7 @@ export class BlockchainProvider implements IBlockchainProvider {
15
15
 
16
16
  this.client = createPublicClient({
17
17
  chain: mainnet,
18
- transport: http(rpcUrl, {
19
- timeout: 20_000,
20
- }),
18
+ transport: http(rpcUrl),
21
19
  });
22
20
  }
23
21
 
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Executes an array of promise-returning functions with a maximum concurrency limit.
3
+ * This prevents overwhelming RPC endpoints with too many concurrent requests.
4
+ *
5
+ * @param tasks - Array of functions that return promises
6
+ * @param maxConcurrency - Maximum number of concurrent executions (default: 5)
7
+ * @returns Promise that resolves to an array of settled results
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const tasks = pools.map(pool => () => fetchPoolData(pool));
12
+ * const results = await batchWithConcurrency(tasks, 5);
13
+ * ```
14
+ */
15
+ export async function batchWithConcurrency<T>(
16
+ tasks: (() => Promise<T>)[],
17
+ maxConcurrency: number = 5
18
+ ): Promise<PromiseSettledResult<T>[]> {
19
+ const results: PromiseSettledResult<T>[] = [];
20
+
21
+ // Process tasks in batches
22
+ for (let i = 0; i < tasks.length; i += maxConcurrency) {
23
+ const batch = tasks.slice(i, i + maxConcurrency);
24
+ const batchResults = await Promise.allSettled(
25
+ batch.map(task => task())
26
+ );
27
+ results.push(...batchResults);
28
+ }
29
+
30
+ return results;
31
+ }
32
+