@obolnetwork/obol-sdk 2.12.2 → 2.12.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 (37) hide show
  1. package/dist/browser/src/index.js +70 -11
  2. package/dist/browser/src/index.js.map +1 -1
  3. package/dist/cjs/src/index.js +71 -11
  4. package/dist/cjs/src/index.js.map +1 -1
  5. package/dist/cjs/src/verification/clusterLockValidationWorker.js +38 -7
  6. package/dist/cjs/src/verification/clusterLockValidationWorker.js.map +1 -1
  7. package/dist/cjs/src/verification/parallelPool.js +25 -5
  8. package/dist/cjs/src/verification/parallelPool.js.map +1 -1
  9. package/dist/esm/src/{chunk-YSXFCSVK.js → chunk-FGMJVLIN.js} +37 -6
  10. package/dist/esm/src/chunk-FGMJVLIN.js.map +1 -0
  11. package/dist/esm/src/{chunk-T74RX3N2.js → chunk-YZWJJHPO.js} +8 -4
  12. package/dist/esm/src/chunk-YZWJJHPO.js.map +1 -0
  13. package/dist/esm/src/index.js +33 -6
  14. package/dist/esm/src/index.js.map +1 -1
  15. package/dist/esm/src/verification/clusterLockValidationWorker.js +9 -3
  16. package/dist/esm/src/verification/clusterLockValidationWorker.js.map +1 -1
  17. package/dist/esm/src/verification/parallelPool.js +1 -1
  18. package/dist/types/src/errors.d.ts +17 -7
  19. package/dist/types/src/index.d.ts +1 -1
  20. package/dist/types/src/services.d.ts +6 -3
  21. package/dist/types/src/verification/parallelPool.d.ts +4 -0
  22. package/dist/types/src/verification/validationConcurrency.d.ts +11 -0
  23. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  24. package/package.json +2 -2
  25. package/dist/esm/src/chunk-T74RX3N2.js.map +0 -1
  26. package/dist/esm/src/chunk-YSXFCSVK.js.map +0 -1
  27. package/dist/types/test/client/ajv.spec.d.ts +0 -1
  28. package/dist/types/test/client/baseUrl.spec.d.ts +0 -1
  29. package/dist/types/test/client/methods.spec.d.ts +0 -18
  30. package/dist/types/test/eoa/eoa.spec.d.ts +0 -1
  31. package/dist/types/test/exit/ethUtils.spec.d.ts +0 -1
  32. package/dist/types/test/exit/exit.spec.d.ts +0 -1
  33. package/dist/types/test/exit/verificationHelpers.spec.d.ts +0 -1
  34. package/dist/types/test/fixtures.d.ts +0 -359
  35. package/dist/types/test/incentives/incentives.spec.d.ts +0 -1
  36. package/dist/types/test/splits/splits.spec.d.ts +0 -1
  37. package/dist/types/test/verification/parallelPool.spec.d.ts +0 -1
@@ -98,7 +98,7 @@ import { v4 as uuidv4 } from "uuid";
98
98
  // package.json
99
99
  var package_default = {
100
100
  name: "@obolnetwork/obol-sdk",
101
- version: "2.12.2",
101
+ version: "2.12.4",
102
102
  description: "A package for creating Distributed Validators using the Obol API.",
103
103
  bugs: {
104
104
  url: "https://github.com/obolnetwork/obol-sdk/issues"
@@ -113,7 +113,7 @@ var package_default = {
113
113
  "build:clean": "rm -rf ./dist",
114
114
  build: "npm-run-all build:clean build:tsup",
115
115
  "build:tsup": "tsup && tsc -b ./tsconfig.types.json",
116
- test: "NODE_OPTIONS=--experimental-vm-modules jest test/**/**.spec.ts --testPathIgnorePatterns=test/sdk-package/",
116
+ test: "NODE_OPTIONS=--experimental-vm-modules OBOL_SDK_MAX_CONCURRENT_LOCK_VALIDATIONS=0 jest test/**/**.spec.ts --testPathIgnorePatterns=test/sdk-package/",
117
117
  "generate-typedoc": "typedoc",
118
118
  "npm:publish": "npm publish --tag latest",
119
119
  "npm:publish:next": "npm publish --tag next",
@@ -555,7 +555,8 @@ var InvalidBaseUrlError = class _InvalidBaseUrlError extends Error {
555
555
  };
556
556
  var ClusterLockValidationTimeoutError = class _ClusterLockValidationTimeoutError extends Error {
557
557
  /**
558
- * @param timeoutMs - Same value as SDK whole-lock validation worker timeout.
558
+ * @param timeoutMs - Worker deadline that was exceeded (`VALIDATION_WORKER_TIMEOUT_MS`
559
+ * for the whole-lock worker, `WORKER_TIMEOUT_MS` for per-chunk BLS workers).
559
560
  */
560
561
  constructor(timeoutMs) {
561
562
  super(
@@ -566,6 +567,16 @@ var ClusterLockValidationTimeoutError = class _ClusterLockValidationTimeoutError
566
567
  Object.setPrototypeOf(this, _ClusterLockValidationTimeoutError.prototype);
567
568
  }
568
569
  };
570
+ var ClusterLockValidationBusyError = class _ClusterLockValidationBusyError extends Error {
571
+ constructor(maxConcurrent) {
572
+ super(
573
+ `Too many cluster lock validations in progress (limit: ${maxConcurrent}). Retry later.`
574
+ );
575
+ this.maxConcurrent = maxConcurrent;
576
+ this.name = "ClusterLockValidationBusyError";
577
+ Object.setPrototypeOf(this, _ClusterLockValidationBusyError.prototype);
578
+ }
579
+ };
569
580
 
570
581
  // src/base.ts
571
582
  var ALLOWED_OBOL_API_BASE_URLS = [
@@ -5277,6 +5288,9 @@ var MIN_KEYS_PER_WORKER_AGG = 100;
5277
5288
  var MIN_VALIDATORS_FOR_VALIDATION_WORKER = 50;
5278
5289
  var VALIDATION_WORKER_TIMEOUT_MS = 12e4;
5279
5290
  var WORKER_TIMEOUT_MS = 6e4;
5291
+ function isValidationTimeoutReply(msg) {
5292
+ return typeof msg === "object" && msg !== null && "validationTimeoutMs" in msg && typeof msg.validationTimeoutMs === "number";
5293
+ }
5280
5294
  var MAX_CONCURRENT_WORKERS_CAP = 8;
5281
5295
  function maxConcurrentWorkers(numWorkers) {
5282
5296
  return Math.min(numWorkers, MAX_CONCURRENT_WORKERS_CAP);
@@ -5373,7 +5387,7 @@ function verifySharesSync(shares, distributedKeys, threshold) {
5373
5387
  }
5374
5388
  function runWorkerAggregatePubkeys(wt, workerFile, data) {
5375
5389
  return __async(this, null, function* () {
5376
- return yield new Promise((resolve) => {
5390
+ return yield new Promise((resolve, reject) => {
5377
5391
  let settled = false;
5378
5392
  const worker = new wt.Worker(workerFile, { workerData: data });
5379
5393
  const finish = (result) => {
@@ -5384,7 +5398,11 @@ function runWorkerAggregatePubkeys(wt, workerFile, data) {
5384
5398
  resolve(result);
5385
5399
  };
5386
5400
  const timer = setTimeout(() => {
5387
- finish(null);
5401
+ if (settled) return;
5402
+ settled = true;
5403
+ clearTimeout(timer);
5404
+ worker.terminate();
5405
+ reject(new ClusterLockValidationTimeoutError(WORKER_TIMEOUT_MS));
5388
5406
  }, WORKER_TIMEOUT_MS);
5389
5407
  worker.once("message", (msg) => {
5390
5408
  finish(msg instanceof Uint8Array ? msg : null);
@@ -5400,7 +5418,7 @@ function runWorkerAggregatePubkeys(wt, workerFile, data) {
5400
5418
  }
5401
5419
  function runWorker(wt, workerFile, data) {
5402
5420
  return __async(this, null, function* () {
5403
- return yield new Promise((resolve) => {
5421
+ return yield new Promise((resolve, reject) => {
5404
5422
  let settled = false;
5405
5423
  const worker = new wt.Worker(workerFile, { workerData: data });
5406
5424
  const finish = (result) => {
@@ -5411,7 +5429,11 @@ function runWorker(wt, workerFile, data) {
5411
5429
  resolve(result);
5412
5430
  };
5413
5431
  const timer = setTimeout(() => {
5414
- finish(false);
5432
+ if (settled) return;
5433
+ settled = true;
5434
+ clearTimeout(timer);
5435
+ worker.terminate();
5436
+ reject(new ClusterLockValidationTimeoutError(WORKER_TIMEOUT_MS));
5415
5437
  }, WORKER_TIMEOUT_MS);
5416
5438
  worker.once("message", (msg) => {
5417
5439
  finish(msg === true);
@@ -5572,6 +5594,14 @@ function validateClusterLockInWorker(lock, safeRpcUrl) {
5572
5594
  resolve(result);
5573
5595
  };
5574
5596
  worker.once("message", (msg) => {
5597
+ if (isValidationTimeoutReply(msg)) {
5598
+ if (settled) return;
5599
+ settled = true;
5600
+ clearTimeout(timer);
5601
+ worker.terminate();
5602
+ reject(new ClusterLockValidationTimeoutError(msg.validationTimeoutMs));
5603
+ return;
5604
+ }
5575
5605
  finish(msg === true);
5576
5606
  });
5577
5607
  worker.once("error", () => {
@@ -16196,6 +16226,9 @@ var isValidClusterLock = (clusterLock, safeRpcUrl) => __async(null, null, functi
16196
16226
  }
16197
16227
  return true;
16198
16228
  } catch (err) {
16229
+ if (err instanceof ClusterLockValidationTimeoutError) {
16230
+ throw err;
16231
+ }
16199
16232
  return false;
16200
16233
  }
16201
16234
  });
@@ -21136,15 +21169,40 @@ var EOA = class {
21136
21169
  }
21137
21170
  };
21138
21171
 
21172
+ // src/verification/validationConcurrency.ts
21173
+ function getMaxConcurrentLockValidations() {
21174
+ const raw = define_process_env_default.OBOL_SDK_MAX_CONCURRENT_LOCK_VALIDATIONS;
21175
+ if (raw === "0") return 0;
21176
+ if (raw !== void 0 && raw !== "") {
21177
+ const n = Number.parseInt(raw, 10);
21178
+ if (Number.isFinite(n) && n > 0) return n;
21179
+ }
21180
+ return 2;
21181
+ }
21182
+ var activeValidations = 0;
21183
+ function withLockValidationConcurrency(fn) {
21184
+ return __async(this, null, function* () {
21185
+ const max = getMaxConcurrentLockValidations();
21186
+ if (max === 0) return yield fn();
21187
+ if (activeValidations >= max) {
21188
+ throw new ClusterLockValidationBusyError(max);
21189
+ }
21190
+ activeValidations++;
21191
+ try {
21192
+ return yield fn();
21193
+ } finally {
21194
+ activeValidations--;
21195
+ }
21196
+ });
21197
+ }
21198
+
21139
21199
  // src/services.ts
21140
21200
  var validateClusterLock = (lock, safeRpcUrl) => __async(null, null, function* () {
21141
- try {
21201
+ return yield withLockValidationConcurrency(() => __async(null, null, function* () {
21142
21202
  const inWorker = yield validateClusterLockInWorker(lock, safeRpcUrl);
21143
21203
  if (inWorker !== null) return inWorker;
21144
21204
  return yield isValidClusterLock(lock, safeRpcUrl);
21145
- } catch (err) {
21146
- throw err;
21147
- }
21205
+ }));
21148
21206
  });
21149
21207
 
21150
21208
  // src/index.ts
@@ -21742,6 +21800,7 @@ export {
21742
21800
  CONFIG_VERSION,
21743
21801
  CONFLICT_ERROR_MSG,
21744
21802
  Client,
21803
+ ClusterLockValidationBusyError,
21745
21804
  ClusterLockValidationTimeoutError,
21746
21805
  ConflictError,
21747
21806
  CreatorConfigHashSigningTypes,