@obolnetwork/obol-sdk 2.12.1 → 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 (38) hide show
  1. package/README.md +6 -4
  2. package/dist/browser/src/index.js +146 -62
  3. package/dist/browser/src/index.js.map +1 -1
  4. package/dist/cjs/src/index.js +149 -62
  5. package/dist/cjs/src/index.js.map +1 -1
  6. package/dist/cjs/src/verification/clusterLockValidationWorker.js +39 -10
  7. package/dist/cjs/src/verification/clusterLockValidationWorker.js.map +1 -1
  8. package/dist/cjs/src/verification/parallelPool.js +33 -14
  9. package/dist/cjs/src/verification/parallelPool.js.map +1 -1
  10. package/dist/esm/src/{chunk-RYTIXFRX.js → chunk-FGMJVLIN.js} +53 -15
  11. package/dist/esm/src/chunk-FGMJVLIN.js.map +1 -0
  12. package/dist/esm/src/{chunk-5ASVONSJ.js → chunk-YZWJJHPO.js} +9 -7
  13. package/dist/esm/src/chunk-YZWJJHPO.js.map +1 -0
  14. package/dist/esm/src/index.js +56 -7
  15. package/dist/esm/src/index.js.map +1 -1
  16. package/dist/esm/src/verification/clusterLockValidationWorker.js +9 -3
  17. package/dist/esm/src/verification/clusterLockValidationWorker.js.map +1 -1
  18. package/dist/esm/src/verification/parallelPool.js +1 -1
  19. package/dist/types/src/base.d.ts +5 -3
  20. package/dist/types/src/errors.d.ts +22 -4
  21. package/dist/types/src/index.d.ts +5 -6
  22. package/dist/types/src/services.d.ts +6 -3
  23. package/dist/types/src/verification/parallelPool.d.ts +4 -0
  24. package/dist/types/src/verification/validationConcurrency.d.ts +11 -0
  25. package/dist/types/tsconfig.types.tsbuildinfo +1 -1
  26. package/package.json +3 -3
  27. package/dist/esm/src/chunk-5ASVONSJ.js.map +0 -1
  28. package/dist/esm/src/chunk-RYTIXFRX.js.map +0 -1
  29. package/dist/types/test/client/ajv.spec.d.ts +0 -1
  30. package/dist/types/test/client/methods.spec.d.ts +0 -18
  31. package/dist/types/test/eoa/eoa.spec.d.ts +0 -1
  32. package/dist/types/test/exit/ethUtils.spec.d.ts +0 -1
  33. package/dist/types/test/exit/exit.spec.d.ts +0 -1
  34. package/dist/types/test/exit/verificationHelpers.spec.d.ts +0 -1
  35. package/dist/types/test/fixtures.d.ts +0 -359
  36. package/dist/types/test/incentives/incentives.spec.d.ts +0 -1
  37. package/dist/types/test/splits/splits.spec.d.ts +0 -1
  38. package/dist/types/test/verification/parallelPool.spec.d.ts +0 -1
@@ -108,12 +108,14 @@ var __yieldStar = (value) => {
108
108
  // src/index.ts
109
109
  var index_exports = {};
110
110
  __export(index_exports, {
111
+ ALLOWED_OBOL_API_BASE_URLS: () => ALLOWED_OBOL_API_BASE_URLS,
111
112
  AVAILABLE_SPLITTER_CHAINS: () => AVAILABLE_SPLITTER_CHAINS,
112
113
  CAPELLA_FORK_MAPPING: () => CAPELLA_FORK_MAPPING,
113
114
  CHAIN_CONFIGURATION: () => CHAIN_CONFIGURATION,
114
115
  CONFIG_VERSION: () => CONFIG_VERSION,
115
116
  CONFLICT_ERROR_MSG: () => CONFLICT_ERROR_MSG,
116
117
  Client: () => Client,
118
+ ClusterLockValidationBusyError: () => ClusterLockValidationBusyError,
117
119
  ClusterLockValidationTimeoutError: () => ClusterLockValidationTimeoutError,
118
120
  ConflictError: () => ConflictError,
119
121
  CreatorConfigHashSigningTypes: () => CreatorConfigHashSigningTypes,
@@ -140,6 +142,7 @@ __export(index_exports, {
140
142
  FORK_NAMES: () => FORK_NAMES,
141
143
  GENESIS_VALIDATOR_ROOT: () => GENESIS_VALIDATOR_ROOT,
142
144
  Incentives: () => Incentives,
145
+ InvalidBaseUrlError: () => InvalidBaseUrlError,
143
146
  OBOL_SDK_EMAIL: () => OBOL_SDK_EMAIL,
144
147
  ObolSplits: () => ObolSplits,
145
148
  OperatorConfigHashSigningTypes: () => OperatorConfigHashSigningTypes,
@@ -183,7 +186,7 @@ var import_uuid = require("uuid");
183
186
  // package.json
184
187
  var package_default = {
185
188
  name: "@obolnetwork/obol-sdk",
186
- version: "2.12.1",
189
+ version: "2.12.4",
187
190
  description: "A package for creating Distributed Validators using the Obol API.",
188
191
  bugs: {
189
192
  url: "https://github.com/obolnetwork/obol-sdk/issues"
@@ -198,7 +201,7 @@ var package_default = {
198
201
  "build:clean": "rm -rf ./dist",
199
202
  build: "npm-run-all build:clean build:tsup",
200
203
  "build:tsup": "tsup && tsc -b ./tsconfig.types.json",
201
- test: "NODE_OPTIONS=--experimental-vm-modules jest test/**/**.spec.ts --testPathIgnorePatterns=test/sdk-package/",
204
+ test: "NODE_OPTIONS=--experimental-vm-modules OBOL_SDK_MAX_CONCURRENT_LOCK_VALIDATIONS=0 jest test/**/**.spec.ts --testPathIgnorePatterns=test/sdk-package/",
202
205
  "generate-typedoc": "typedoc",
203
206
  "npm:publish": "npm publish --tag latest",
204
207
  "npm:publish:next": "npm publish --tag next",
@@ -261,7 +264,6 @@ var package_default = {
261
264
  "ajv-formats": "3.0.1",
262
265
  "ajv-keywords": "5.1.0",
263
266
  "cross-fetch": "4.1.0",
264
- dotenv: "17.4.2",
265
267
  elliptic: "6.6.1",
266
268
  ethers: "6.16.0",
267
269
  semver: "7.7.4",
@@ -274,6 +276,7 @@ var package_default = {
274
276
  "@types/node": "24.12.2",
275
277
  "@types/semver": "7.7.1",
276
278
  "@types/uuid": "9.0.8",
279
+ dotenv: "17.4.2",
277
280
  "@typescript-eslint/eslint-plugin": "6.21.0",
278
281
  "@typescript-eslint/parser": "6.21.0",
279
282
  eslint: "8.57.1",
@@ -401,8 +404,6 @@ var MAINNET_SPLIT_V2_FACTORY_BYTECODE = "0x6080604090808252600480361015610015575
401
404
  var HOODI_SPLIT_V2_FACTORY_BYTECODE = "0x6080604090808252600480361015610015575f80fd5b5f3560e01c9182632556fa391461043c5750816380ebf0ab146102be5781639e317f121461027a578163cd6bc1211461023f578163e9889edd1461016d578163f79918b0146100de575063fc6119b11461006d575f80fd5b346100da575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100da576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000f9c25250523df26343222fc46de932355b850c97168152f35b5f80fd5b82346100da577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc916080833601126100da5780359267ffffffffffffffff84116100da5760809084360301126100da5761016573ffffffffffffffffffffffffffffffffffffffff916020946101526105e7565b61015a61060a565b91606435930161090f565b915191168152f35b82346100da5760209073ffffffffffffffffffffffffffffffffffffffff6101656101a061019a3661062d565b91610b37565b309061023a7f000000000000000000000000f9c25250523df26343222fc46de932355b850c9790604051916c5af43d3d93803e605757fd5bf36051526044526f593da1005b3d3d3d3d363d3d37363d736030527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6020527060593d8160093d39f336602c57343d527f5f526071600f20916040525f606052565b610b7a565b82346100da576102546101a061019a3661062d565b803b151573ffffffffffffffffffffffffffffffffffffffff8351921682526020820152f35b82346100da5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126100da57602091355f525f8252805f20549051908152f35b82346100da577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9181833601126100da5780359267ffffffffffffffff84116100da5760809084360301126100da5761016561039c73ffffffffffffffffffffffffffffffffffffffff9261034a6103766103376105e7565b875192839160209a8b84019601866107c7565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282610858565b519020805f525f8652845f205490855191878301528682526103978261083c565b6108c2565b848151910120309061023a7f000000000000000000000000f9c25250523df26343222fc46de932355b850c9790604051916c5af43d3d93803e605757fd5bf36051526044526f593da1005b3d3d3d3d363d3d37363d736030527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6020527060593d8160093d39f336602c57343d527f5f526071600f20916040525f606052565b9083346100da577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6060813601126100da5782359067ffffffffffffffff82116100da5760809082850192360301126100da576104976105e7565b6105286104a261060a565b6104e4602097888101906104bb8161034a888a866107c7565b519020805f525f8952865f20908154916001830190558751918a8301528982526103978261083c565b73ffffffffffffffffffffffffffffffffffffffff9281898593519101207f000000000000000000000000f9c25250523df26343222fc46de932355b850c97610aae565b1695863b156100da575f858592610569895194859384937fbaa7fda400000000000000000000000000000000000000000000000000000000855284016107c7565b0381838b5af180156105dd57928795927fb3ec24e9259e438f9917b49f27c0dd89a11b7626cb63e6fc977863c0b26a681b95926105ba956105ce575b508188519586956060875260608701906106f5565b93168a85015216868301520390a251908152f35b6105d7906107fb565b8a6105a5565b86513d5f823e3d90fd5b6024359073ffffffffffffffffffffffffffffffffffffffff821682036100da57565b6044359073ffffffffffffffffffffffffffffffffffffffff821682036100da57565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc906060828201126100da576004359167ffffffffffffffff83116100da57826080920301126100da576004019060243573ffffffffffffffffffffffffffffffffffffffff811681036100da579060443590565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1823603018112156100da57016020813591019167ffffffffffffffff82116100da578160051b360383136100da57565b6080820161070382806106a2565b608085529182905260a08401915f905b80821061078f5750505061072a60208301836106a2565b909284830360208601528183527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82116100da5760609160051b8094602085013760408101356040860152013561ffff81168091036100da5760606020940152010190565b90919283359073ffffffffffffffffffffffffffffffffffffffff82168092036100da57600191815260208091019401920190610713565b9073ffffffffffffffffffffffffffffffffffffffff6107f46020929594956040855260408501906106f5565b9416910152565b67ffffffffffffffff811161080f57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040810190811067ffffffffffffffff82111761080f57604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761080f57604052565b908151915f5b8381106108af575050015f815290565b806020809284010151818501520161089f565b61090d909291926108e160405194859260208401526040830190610899565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101845283610858565b565b93929161091d838387610b37565b7f000000000000000000000000f9c25250523df26343222fc46de932355b850c976109bb308361023a8490604051916c5af43d3d93803e605757fd5bf36051526044526f593da1005b3d3d3d3d363d3d37363d736030527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6020527060593d8160093d39f336602c57343d527f5f526071600f20916040525f606052565b803b610aa55750906109cc91610aae565b9473ffffffffffffffffffffffffffffffffffffffff9283871694853b156100da57604051947fbaa7fda40000000000000000000000000000000000000000000000000000000086525f8680610a268688600484016107c7565b0381838b5af1948515610a9a577fc4cec5a1846f5c98dc275670618bfecffec4da2e7cba63760ef46f38c75d236e96610a7496610a8b575b50816040519687966080885260808801906106f5565b9416602086015216604084015260608301520390a2565b610a94906107fb565b5f610a5e565b6040513d5f823e3d90fd5b96505050505050565b9190604051926c5af43d3d93803e605757fd5bf36051526044526f593da1005b3d3d3d3d363d3d37363d736030527f9e4ac34f21c619cefc926c8bd93b54bf5a39c7ab2127a895af1cc0691d7e3dff6020527060593d8160093d39f336602c57343d527f5f526071600f5ff5916040525f6060528115610b2a57565b63301164255f526004601cfd5b6040519291610b4f9184916108e191602084016107c7565b610b7460206040518093610b668383018097610899565b908152038084520182610858565b51902090565b91909160ff5f5360355260601b60015260155260555f20905f60355256fea2646970667358221220edd55753c55f257991df670fc562cdf54adb62d710125933fc4a0a7afddbc02564736f6c63430008170033";
402
405
 
403
406
  // src/constants.ts
404
- var dotenv = __toESM(require("dotenv"));
405
- dotenv.config();
406
407
  var CONFLICT_ERROR_MSG = "Conflict";
407
408
  var EIP712_DOMAIN_NAME = "Obol";
408
409
  var EIP712_DOMAIN_VERSION = "1";
@@ -611,40 +612,6 @@ var CAPELLA_FORK_MAPPING = {
611
612
  // Hoodi
612
613
  };
613
614
 
614
- // src/base.ts
615
- var Base = class {
616
- constructor({
617
- baseUrl = DEFAULT_BASE_URL,
618
- chainId = DEFAULT_CHAIN_ID
619
- }) {
620
- this.baseUrl = baseUrl;
621
- this.chainId = chainId;
622
- this.fork_version = FORK_MAPPING[this.chainId];
623
- }
624
- request(endpoint, options) {
625
- return __async(this, null, function* () {
626
- const url = `${this.baseUrl}${endpoint}`;
627
- const config2 = __spreadProps(__spreadValues({}, options), {
628
- headers: __spreadValues({
629
- "Content-Type": "application/json",
630
- "User-Agent": `Obol-SDK/${SDK_VERSION}`
631
- }, options == null ? void 0 : options.headers)
632
- });
633
- try {
634
- const response = yield fetch(url, config2);
635
- if (response.ok) {
636
- return yield response.json();
637
- } else {
638
- const errorResponse = yield response.json();
639
- throw errorResponse;
640
- }
641
- } catch (e) {
642
- throw e;
643
- }
644
- });
645
- }
646
- };
647
-
648
615
  // src/errors.ts
649
616
  var ConflictError = class _ConflictError extends Error {
650
617
  constructor() {
@@ -667,9 +634,17 @@ var UnsupportedChainError = class _UnsupportedChainError extends Error {
667
634
  Object.setPrototypeOf(this, _UnsupportedChainError.prototype);
668
635
  }
669
636
  };
637
+ var InvalidBaseUrlError = class _InvalidBaseUrlError extends Error {
638
+ constructor(message2) {
639
+ super(message2);
640
+ this.name = "InvalidBaseUrlError";
641
+ Object.setPrototypeOf(this, _InvalidBaseUrlError.prototype);
642
+ }
643
+ };
670
644
  var ClusterLockValidationTimeoutError = class _ClusterLockValidationTimeoutError extends Error {
671
645
  /**
672
- * @param timeoutMs - Same value as SDK whole-lock validation worker timeout.
646
+ * @param timeoutMs - Worker deadline that was exceeded (`VALIDATION_WORKER_TIMEOUT_MS`
647
+ * for the whole-lock worker, `WORKER_TIMEOUT_MS` for per-chunk BLS workers).
673
648
  */
674
649
  constructor(timeoutMs) {
675
650
  super(
@@ -680,6 +655,68 @@ var ClusterLockValidationTimeoutError = class _ClusterLockValidationTimeoutError
680
655
  Object.setPrototypeOf(this, _ClusterLockValidationTimeoutError.prototype);
681
656
  }
682
657
  };
658
+ var ClusterLockValidationBusyError = class _ClusterLockValidationBusyError extends Error {
659
+ constructor(maxConcurrent) {
660
+ super(
661
+ `Too many cluster lock validations in progress (limit: ${maxConcurrent}). Retry later.`
662
+ );
663
+ this.maxConcurrent = maxConcurrent;
664
+ this.name = "ClusterLockValidationBusyError";
665
+ Object.setPrototypeOf(this, _ClusterLockValidationBusyError.prototype);
666
+ }
667
+ };
668
+
669
+ // src/base.ts
670
+ var ALLOWED_OBOL_API_BASE_URLS = [
671
+ DEFAULT_BASE_URL,
672
+ "https://obol-api-nonprod-dev.dev.obol.tech",
673
+ "https://obol-api-nonprod-qa.dev.obol.tech"
674
+ ];
675
+ var ALLOWED_BASE_URLS = new Set(ALLOWED_OBOL_API_BASE_URLS);
676
+ function assertAllowedBaseUrl(baseUrl) {
677
+ let candidate = baseUrl.trim();
678
+ while (candidate.endsWith("/")) {
679
+ candidate = candidate.slice(0, -1);
680
+ }
681
+ if (!ALLOWED_BASE_URLS.has(candidate)) {
682
+ throw new InvalidBaseUrlError(
683
+ `baseUrl must be one of: ${ALLOWED_OBOL_API_BASE_URLS.join(", ")}`
684
+ );
685
+ }
686
+ return candidate;
687
+ }
688
+ var Base = class {
689
+ constructor({
690
+ baseUrl = DEFAULT_BASE_URL,
691
+ chainId = DEFAULT_CHAIN_ID
692
+ }) {
693
+ this.baseUrl = assertAllowedBaseUrl(baseUrl);
694
+ this.chainId = chainId;
695
+ this.fork_version = FORK_MAPPING[this.chainId];
696
+ }
697
+ request(endpoint, options) {
698
+ return __async(this, null, function* () {
699
+ const url = `${this.baseUrl}${endpoint}`;
700
+ const config = __spreadProps(__spreadValues({}, options), {
701
+ headers: __spreadValues({
702
+ "Content-Type": "application/json",
703
+ "User-Agent": `Obol-SDK/${SDK_VERSION}`
704
+ }, options == null ? void 0 : options.headers)
705
+ });
706
+ try {
707
+ const response = yield fetch(url, config);
708
+ if (response.ok) {
709
+ return yield response.json();
710
+ } else {
711
+ const errorResponse = yield response.json();
712
+ throw errorResponse;
713
+ }
714
+ } catch (e) {
715
+ throw e;
716
+ }
717
+ });
718
+ }
719
+ };
683
720
 
684
721
  // src/verification/common.ts
685
722
  var import_ssz7 = require("@chainsafe/ssz");
@@ -5055,6 +5092,9 @@ var MIN_KEYS_PER_WORKER_AGG = 100;
5055
5092
  var MIN_VALIDATORS_FOR_VALIDATION_WORKER = 50;
5056
5093
  var VALIDATION_WORKER_TIMEOUT_MS = 12e4;
5057
5094
  var WORKER_TIMEOUT_MS = 6e4;
5095
+ function isValidationTimeoutReply(msg) {
5096
+ return typeof msg === "object" && msg !== null && "validationTimeoutMs" in msg && typeof msg.validationTimeoutMs === "number";
5097
+ }
5058
5098
  var MAX_CONCURRENT_WORKERS_CAP = 8;
5059
5099
  function maxConcurrentWorkers(numWorkers) {
5060
5100
  return Math.min(numWorkers, MAX_CONCURRENT_WORKERS_CAP);
@@ -5151,7 +5191,7 @@ function verifySharesSync(shares, distributedKeys, threshold) {
5151
5191
  }
5152
5192
  function runWorkerAggregatePubkeys(wt, workerFile, data) {
5153
5193
  return __async(this, null, function* () {
5154
- return yield new Promise((resolve) => {
5194
+ return yield new Promise((resolve, reject) => {
5155
5195
  let settled = false;
5156
5196
  const worker = new wt.Worker(workerFile, { workerData: data });
5157
5197
  const finish = (result) => {
@@ -5162,7 +5202,11 @@ function runWorkerAggregatePubkeys(wt, workerFile, data) {
5162
5202
  resolve(result);
5163
5203
  };
5164
5204
  const timer = setTimeout(() => {
5165
- finish(null);
5205
+ if (settled) return;
5206
+ settled = true;
5207
+ clearTimeout(timer);
5208
+ worker.terminate();
5209
+ reject(new ClusterLockValidationTimeoutError(WORKER_TIMEOUT_MS));
5166
5210
  }, WORKER_TIMEOUT_MS);
5167
5211
  worker.once("message", (msg) => {
5168
5212
  finish(msg instanceof Uint8Array ? msg : null);
@@ -5178,7 +5222,7 @@ function runWorkerAggregatePubkeys(wt, workerFile, data) {
5178
5222
  }
5179
5223
  function runWorker(wt, workerFile, data) {
5180
5224
  return __async(this, null, function* () {
5181
- return yield new Promise((resolve) => {
5225
+ return yield new Promise((resolve, reject) => {
5182
5226
  let settled = false;
5183
5227
  const worker = new wt.Worker(workerFile, { workerData: data });
5184
5228
  const finish = (result) => {
@@ -5189,7 +5233,11 @@ function runWorker(wt, workerFile, data) {
5189
5233
  resolve(result);
5190
5234
  };
5191
5235
  const timer = setTimeout(() => {
5192
- finish(false);
5236
+ if (settled) return;
5237
+ settled = true;
5238
+ clearTimeout(timer);
5239
+ worker.terminate();
5240
+ reject(new ClusterLockValidationTimeoutError(WORKER_TIMEOUT_MS));
5193
5241
  }, WORKER_TIMEOUT_MS);
5194
5242
  worker.once("message", (msg) => {
5195
5243
  finish(msg === true);
@@ -5333,15 +5381,7 @@ function validateClusterLockInWorker(lock, safeRpcUrl) {
5333
5381
  const worker = new wt.Worker(workerFile, {
5334
5382
  workerData: { lock, safeRpcUrl }
5335
5383
  });
5336
- let timer;
5337
- const finish = (result) => {
5338
- if (settled) return;
5339
- settled = true;
5340
- clearTimeout(timer);
5341
- worker.terminate();
5342
- resolve(result);
5343
- };
5344
- timer = setTimeout(() => {
5384
+ const timer = setTimeout(() => {
5345
5385
  if (settled) return;
5346
5386
  settled = true;
5347
5387
  clearTimeout(timer);
@@ -5350,7 +5390,22 @@ function validateClusterLockInWorker(lock, safeRpcUrl) {
5350
5390
  new ClusterLockValidationTimeoutError(VALIDATION_WORKER_TIMEOUT_MS)
5351
5391
  );
5352
5392
  }, VALIDATION_WORKER_TIMEOUT_MS);
5393
+ const finish = (result) => {
5394
+ if (settled) return;
5395
+ settled = true;
5396
+ clearTimeout(timer);
5397
+ worker.terminate();
5398
+ resolve(result);
5399
+ };
5353
5400
  worker.once("message", (msg) => {
5401
+ if (isValidationTimeoutReply(msg)) {
5402
+ if (settled) return;
5403
+ settled = true;
5404
+ clearTimeout(timer);
5405
+ worker.terminate();
5406
+ reject(new ClusterLockValidationTimeoutError(msg.validationTimeoutMs));
5407
+ return;
5408
+ }
5354
5409
  finish(msg === true);
5355
5410
  });
5356
5411
  worker.once("error", () => {
@@ -14910,6 +14965,9 @@ var isValidClusterLock = (clusterLock, safeRpcUrl) => __async(null, null, functi
14910
14965
  }
14911
14966
  return true;
14912
14967
  } catch (err) {
14968
+ if (err instanceof ClusterLockValidationTimeoutError) {
14969
+ throw err;
14970
+ }
14913
14971
  return false;
14914
14972
  }
14915
14973
  });
@@ -18262,11 +18320,11 @@ var encodeCreateSplitV2DeterministicTxData = (splitParams, splitOwnerAddress, sa
18262
18320
  );
18263
18321
  };
18264
18322
  var getChainConfig = (chainId) => {
18265
- const config2 = CHAIN_CONFIGURATION[chainId];
18266
- if (!config2) {
18323
+ const config = CHAIN_CONFIGURATION[chainId];
18324
+ if (!config) {
18267
18325
  throw new Error(`Chain configuration not found for chain ID ${chainId}`);
18268
18326
  }
18269
- return config2;
18327
+ return config;
18270
18328
  };
18271
18329
  var requestWithdrawalFromOVM = (_0) => __async(null, [_0], function* ({
18272
18330
  ovmAddress,
@@ -19838,15 +19896,40 @@ var EOA = class {
19838
19896
  }
19839
19897
  };
19840
19898
 
19899
+ // src/verification/validationConcurrency.ts
19900
+ function getMaxConcurrentLockValidations() {
19901
+ const raw = process.env.OBOL_SDK_MAX_CONCURRENT_LOCK_VALIDATIONS;
19902
+ if (raw === "0") return 0;
19903
+ if (raw !== void 0 && raw !== "") {
19904
+ const n = Number.parseInt(raw, 10);
19905
+ if (Number.isFinite(n) && n > 0) return n;
19906
+ }
19907
+ return 2;
19908
+ }
19909
+ var activeValidations = 0;
19910
+ function withLockValidationConcurrency(fn) {
19911
+ return __async(this, null, function* () {
19912
+ const max = getMaxConcurrentLockValidations();
19913
+ if (max === 0) return yield fn();
19914
+ if (activeValidations >= max) {
19915
+ throw new ClusterLockValidationBusyError(max);
19916
+ }
19917
+ activeValidations++;
19918
+ try {
19919
+ return yield fn();
19920
+ } finally {
19921
+ activeValidations--;
19922
+ }
19923
+ });
19924
+ }
19925
+
19841
19926
  // src/services.ts
19842
19927
  var validateClusterLock = (lock, safeRpcUrl) => __async(null, null, function* () {
19843
- try {
19928
+ return yield withLockValidationConcurrency(() => __async(null, null, function* () {
19844
19929
  const inWorker = yield validateClusterLockInWorker(lock, safeRpcUrl);
19845
19930
  if (inWorker !== null) return inWorker;
19846
19931
  return yield isValidClusterLock(lock, safeRpcUrl);
19847
- } catch (err) {
19848
- throw err;
19849
- }
19932
+ }));
19850
19933
  });
19851
19934
 
19852
19935
  // src/index.ts
@@ -19856,6 +19939,7 @@ var Client = class extends Base {
19856
19939
  *
19857
19940
  * @param config - Client configuration object.
19858
19941
  * @param config.baseUrl - Obol API base URL. Defaults to `https://api.obol.tech`.
19942
+ * Must match one of {@link ALLOWED_OBOL_API_BASE_URLS} (API paths use `/v1/...` separately).
19859
19943
  * @param config.chainId - Target chain ID. Defaults to `560048` (Hoodi).
19860
19944
  * Supported: 1 (Mainnet), 560048 (Hoodi), 100 (Gnosis), 11155111 (Sepolia).
19861
19945
  * @param signer - An ethers `Wallet` or `JsonRpcSigner`. Required for any
@@ -19873,8 +19957,8 @@ var Client = class extends Base {
19873
19957
  * const client = new Client({ chainId: 560048 }, signer);
19874
19958
  * ```
19875
19959
  */
19876
- constructor(config2, signer, provider) {
19877
- super(config2);
19960
+ constructor(config, signer, provider) {
19961
+ super(config);
19878
19962
  this.signer = signer;
19879
19963
  this.provider = provider != null ? provider : signer && "provider" in signer ? signer.provider : void 0;
19880
19964
  this.incentives = new Incentives(
@@ -20437,12 +20521,14 @@ var Client = class extends Base {
20437
20521
  };
20438
20522
  // Annotate the CommonJS export names for ESM import in node:
20439
20523
  0 && (module.exports = {
20524
+ ALLOWED_OBOL_API_BASE_URLS,
20440
20525
  AVAILABLE_SPLITTER_CHAINS,
20441
20526
  CAPELLA_FORK_MAPPING,
20442
20527
  CHAIN_CONFIGURATION,
20443
20528
  CONFIG_VERSION,
20444
20529
  CONFLICT_ERROR_MSG,
20445
20530
  Client,
20531
+ ClusterLockValidationBusyError,
20446
20532
  ClusterLockValidationTimeoutError,
20447
20533
  ConflictError,
20448
20534
  CreatorConfigHashSigningTypes,
@@ -20469,6 +20555,7 @@ var Client = class extends Base {
20469
20555
  FORK_NAMES,
20470
20556
  GENESIS_VALIDATOR_ROOT,
20471
20557
  Incentives,
20558
+ InvalidBaseUrlError,
20472
20559
  OBOL_SDK_EMAIL,
20473
20560
  ObolSplits,
20474
20561
  OperatorConfigHashSigningTypes,