@zkproofport-app/sdk 0.5.0-beta.3 → 0.5.0-beta.5

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.
package/dist/index.esm.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { checkProofIssuer, parseProofForOnChain, verifyProofOnChain, getPinnedVerifier, extractScopeFromPublicInputs, extractNullifierFromPublicInputs, extractDomainFromPublicInputs } from '@zkproofport-app/core';
2
- export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, MDL_KR_PUBLIC_INPUT_LAYOUT, OIDC_ALLOWED_AUDIENCES, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, OIDC_NONCE_DOMAIN, OIDC_NOW_MAX_AGE_SECONDS, OIDC_NOW_MAX_FUTURE_SECONDS, OIDC_V1_PUBLIC_INPUT_COUNT, OIDC_V2_PUBLIC_INPUT_COUNT, PINNED_VERIFIERS, checkOidcPolicy, deriveOidcNonceBinding, extractDomainFromPublicInputs, extractNullifierFromPublicInputs, extractScopeFromPublicInputs, getPinnedVerifier, oidcAudienceHash } from '@zkproofport-app/core';
3
- import { isCircuitId, ALL_CIRCUIT_IDS, circuitActionBinding, CIRCUIT_VK_PATHS, CIRCUIT_NEEDS_WALLET_SIGNATURE } from '@zkproofport-app/core/circuits';
4
- export { ALL_CIRCUIT_IDS, CIRCUIT_ACTION_BINDING, CIRCUIT_IDS, CIRCUIT_SUPPORT_STATUS, CIRCUIT_VK_PATHS, EXPERIMENTAL_CIRCUIT_IDS, PLANNED_CIRCUIT_IDS, SUPPORTED_CIRCUIT_IDS, circuitActionBinding, getCircuitSupportStatus, isCircuitId, isSupportedCircuitId } from '@zkproofport-app/core/circuits';
2
+ export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, OIDC_ALLOWED_AUDIENCES, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, OIDC_NONCE_DOMAIN, OIDC_NOW_MAX_AGE_SECONDS, OIDC_NOW_MAX_FUTURE_SECONDS, OIDC_V1_PUBLIC_INPUT_COUNT, OIDC_V2_PUBLIC_INPUT_COUNT, PINNED_VARIANT_VERIFIERS, PINNED_VERIFIERS, checkOidcPolicy, deriveOidcNonceBinding, extractDomainFromPublicInputs, extractNullifierFromPublicInputs, extractScopeFromPublicInputs, getPinnedVariantVerifier, getPinnedVerifier, oidcAudienceHash } from '@zkproofport-app/core';
3
+ import { isCircuitId, ALL_CIRCUIT_IDS, circuitActionBinding, resolveSignerVariant, getCircuitPackage, CIRCUIT_NEEDS_WALLET_SIGNATURE } from '@zkproofport-app/core/circuits';
4
+ export { ALL_CIRCUIT_IDS, CIRCUIT_ACTION_BINDING, CIRCUIT_IDS, CIRCUIT_PACKAGES, CIRCUIT_SUPPORT_STATUS, CIRCUIT_VK_PATHS, EXPERIMENTAL_CIRCUIT_IDS, PLANNED_CIRCUIT_IDS, SIGNER_VARIANTS, SUPPORTED_CIRCUIT_IDS, circuitActionBinding, evmProofByteLength, getCircuitPackage, getCircuitSupportStatus, isCircuitId, isSignerVariant, isSupportedCircuitId, resolveSignerVariant, signerVariantsOf } from '@zkproofport-app/core/circuits';
5
5
  import { validateTypedAction } from '@zkproofport-app/core/typedAction';
6
6
  export { parseTypedAction, validateTypedAction } from '@zkproofport-app/core/typedAction';
7
7
 
@@ -30,7 +30,7 @@ const RELAY_URLS = {
30
30
  * Mirrors the mobile app's `CIRCUIT_NETWORKS` (proofport-app
31
31
  * src/config/contracts.ts), because a proof is checked where the app said its
32
32
  * verifier is: Base for the Coinbase and OIDC circuits, GIWA Sepolia for GIWA
33
- * and Dojang (testnet-only), Base Sepolia for Korea Mobile ID (testnet-only).
33
+ * and Dojang (testnet-only).
34
34
  * The ADDRESS on that chain always comes from core's pinned table, never from
35
35
  * a proof response.
36
36
  */
@@ -41,9 +41,6 @@ const VERIFICATION_CHAINS = {
41
41
  oidc_domain_attestation: 8453,
42
42
  giwa_attestation: 91342,
43
43
  dojang_playground: 91342,
44
- mdl_kr_ownership: 84532,
45
- mdl_kr_age: 84532,
46
- mdl_kr_region: 84532,
47
44
  },
48
45
  staging: {
49
46
  coinbase_attestation: 84532,
@@ -51,9 +48,6 @@ const VERIFICATION_CHAINS = {
51
48
  oidc_domain_attestation: 84532,
52
49
  giwa_attestation: 91342,
53
50
  dojang_playground: 91342,
54
- mdl_kr_ownership: 84532,
55
- mdl_kr_age: 84532,
56
- mdl_kr_region: 84532,
57
51
  },
58
52
  local: {
59
53
  coinbase_attestation: 84532,
@@ -61,9 +55,6 @@ const VERIFICATION_CHAINS = {
61
55
  oidc_domain_attestation: 84532,
62
56
  giwa_attestation: 91342,
63
57
  dojang_playground: 91342,
64
- mdl_kr_ownership: 84532,
65
- mdl_kr_age: 84532,
66
- mdl_kr_region: 84532,
67
58
  },
68
59
  };
69
60
  /**
@@ -99,19 +90,20 @@ const DEEP_LINK_HOSTS = {
99
90
  * ```typescript
100
91
  * const metadata = CIRCUIT_METADATA['coinbase_attestation'];
101
92
  * console.log(metadata.name); // "Coinbase KYC"
102
- * console.log(metadata.publicInputsCount); // 128
93
+ * console.log(metadata.publicInputsCount); // 193
103
94
  * ```
104
95
  */
105
96
  const CIRCUIT_METADATA = {
106
97
  coinbase_attestation: {
107
98
  name: 'Coinbase KYC',
108
- description: 'Prove Coinbase identity verification',
109
- // 4 x `pub [u8; 32]` in coinbase-attestation/src/main.nr, flattened to
110
- // bytes: signal_hash, signer_list_merkle_root, scope, nullifier.
111
- // Read 2 here until 2026-09-04, which was wrong under any reading —
112
- // the circuit has never had two public inputs, logical or flattened.
113
- publicInputsCount: 128,
114
- publicInputNames: ['signal_hash', 'signer_list_merkle_root'],
99
+ description: 'Prove Coinbase identity verification, optionally authorizing one EIP-712 action',
100
+ // Coinbase KYC v2 (coinbase-attestation-v2/src/main.nr): GIWA's six
101
+ // `pub [u8; 32]` in its order, then `attested_at: pub u64` = 193 fields.
102
+ // signal_hash 0-31, domain_separator 32-63, action_hash 64-95,
103
+ // signer_list_merkle_root 96-127, scope 128-159, nullifier 160-191,
104
+ // attested_at 192. v1's 128 fields are refused on every verify path.
105
+ publicInputsCount: 193,
106
+ publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'signer_list_merkle_root', 'scope', 'nullifier', 'attested_at'],
115
107
  },
116
108
  coinbase_country_attestation: {
117
109
  name: 'Coinbase Country',
@@ -160,27 +152,6 @@ const CIRCUIT_METADATA = {
160
152
  publicInputsCount: 160,
161
153
  publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'scope', 'nullifier'],
162
154
  },
163
- // Korea Mobile ID (mDL) circuits. Planned — not officially supported yet.
164
- // Counts are byte-flattened field totals from the compiled circuit ABIs:
165
- // [u8; 32] arrays contribute 32 inputs each.
166
- mdl_kr_ownership: {
167
- name: 'Korea Mobile ID — Ownership',
168
- description: "Prove valid Korean mobile driver's license ownership with selective disclosure",
169
- publicInputsCount: 97,
170
- publicInputNames: ['scope', 'nullifier_value', 'disclose_flags', 'owner_commit'],
171
- },
172
- mdl_kr_age: {
173
- name: 'Korea Mobile ID — Age',
174
- description: "Prove minimum age from Korean mobile driver's license without revealing birth date",
175
- publicInputsCount: 66,
176
- publicInputNames: ['scope', 'nullifier_value', 'age_threshold', 'current_year'],
177
- },
178
- mdl_kr_region: {
179
- name: 'Korea Mobile ID — Region',
180
- description: "Prove si/do residency from Korean mobile driver's license without revealing address",
181
- publicInputsCount: 96,
182
- publicInputNames: ['scope', 'nullifier_value', 'region_code'],
183
- },
184
155
  };
185
156
  /**
186
157
  * Default proof request expiration time in milliseconds.
@@ -424,6 +395,12 @@ function parseProofResponseUrl(url) {
424
395
  if (timestamp) {
425
396
  response.timestamp = parseInt(timestamp, 10);
426
397
  }
398
+ // Kept as sent, even when unknown: verification refuses it by name,
399
+ // which says more than a callback that fails to parse.
400
+ const signerVariant = urlObj.searchParams.get('signerVariant');
401
+ if (signerVariant !== null) {
402
+ response.signerVariant = signerVariant;
403
+ }
427
404
  }
428
405
  else if (status === 'error') {
429
406
  response.error = urlObj.searchParams.get('error') || undefined;
@@ -455,94 +432,6 @@ function parseProofResponseUrl(url) {
455
432
  function isProofportDeepLink(url, scheme = DEFAULT_SCHEME) {
456
433
  return url.toLowerCase().startsWith(`${scheme.toLowerCase()}://`);
457
434
  }
458
- /**
459
- * @internal
460
- * Validates a proof request for completeness and correctness.
461
- *
462
- * Performs comprehensive validation including:
463
- * - Required fields (requestId, circuit, callbackUrl)
464
- * - Circuit type validity (must be a supported circuit)
465
- * - Circuit-specific input validation (e.g., userAddress format, countryList structure)
466
- * - Expiration check (if expiresAt is provided)
467
- *
468
- * Note: userAddress is optional for both circuits - the mobile app will prompt
469
- * for wallet connection if not provided.
470
- *
471
- * @param request - Proof request to validate
472
- * @returns Validation result with `valid` flag and optional `error` message
473
- */
474
- /**
475
- * Validates a free-text mDL input (scope / targetRegion).
476
- * Rejects empty or whitespace-only values, control characters (which break
477
- * deep-link query encoding and downstream logging), and values over 256 chars
478
- * (server-side length cap mirror). UTF-8 text such as Korean region names is
479
- * allowed.
480
- *
481
- * @returns Error message string, or null when valid.
482
- */
483
- function validateMdlTextInput(value, fieldName) {
484
- if (typeof value !== 'string' || value.trim() === '') {
485
- return `${fieldName} is required and must be a non-empty string`;
486
- }
487
- if (value.length > 256) {
488
- return `${fieldName} must be 256 characters or fewer`;
489
- }
490
- // eslint-disable-next-line no-control-regex
491
- if (/[\u0000-\u001F\u007F]/.test(value)) {
492
- return `${fieldName} must not contain control characters`;
493
- }
494
- return null;
495
- }
496
- /**
497
- * Validates dapp-supplied inputs for the Korea Mobile ID (mDL) circuits.
498
- * Shared by deep-link request validation and relay request creation so the
499
- * same guards apply on every request path.
500
- *
501
- * Rules:
502
- * - `scope` — required non-empty string, ≤256 chars, no control characters
503
- * - `mdl_kr_ownership.discloseFlags` — optional integer 0–15 (0x0F bitmask)
504
- * - `mdl_kr_age.ageThreshold` — required integer 1–150
505
- * - `mdl_kr_region.targetRegion` — required non-empty string (Korean si/do),
506
- * ≤256 chars, no control characters
507
- *
508
- * @param circuit - One of the three mDL circuit identifiers
509
- * @param inputs - Dapp-supplied circuit inputs
510
- * @returns Error message string, or null when the inputs are valid
511
- */
512
- function validateMdlInputs(circuit, inputs) {
513
- const scopeError = validateMdlTextInput(inputs.scope, 'scope');
514
- if (scopeError) {
515
- return scopeError;
516
- }
517
- if (circuit === 'mdl_kr_ownership') {
518
- const { discloseFlags } = inputs;
519
- if (discloseFlags !== undefined) {
520
- if (typeof discloseFlags !== 'number' ||
521
- !Number.isInteger(discloseFlags) ||
522
- discloseFlags < 0 ||
523
- discloseFlags > 0x0f) {
524
- return 'discloseFlags must be an integer between 0 and 15';
525
- }
526
- }
527
- }
528
- else if (circuit === 'mdl_kr_age') {
529
- const { ageThreshold } = inputs;
530
- if (typeof ageThreshold !== 'number' ||
531
- !Number.isInteger(ageThreshold) ||
532
- ageThreshold < 1 ||
533
- ageThreshold > 150) {
534
- return 'ageThreshold is required and must be an integer between 1 and 150';
535
- }
536
- }
537
- else {
538
- const { targetRegion } = inputs;
539
- const regionError = validateMdlTextInput(targetRegion, 'targetRegion');
540
- if (regionError) {
541
- return regionError;
542
- }
543
- }
544
- return null;
545
- }
546
435
  /**
547
436
  * Longest accepted `returnScheme` value.
548
437
  * Kept in sync with proofport-relay `src/returnScheme.ts`.
@@ -702,6 +591,22 @@ function detectReturnScheme(userAgent) {
702
591
  }
703
592
  return undefined;
704
593
  }
594
+ /**
595
+ * @internal
596
+ * Validates a proof request for completeness and correctness.
597
+ *
598
+ * Performs comprehensive validation including:
599
+ * - Required fields (requestId, circuit, callbackUrl)
600
+ * - Circuit type validity (must be a supported circuit)
601
+ * - Circuit-specific input validation (e.g., userAddress format, countryList structure)
602
+ * - Expiration check (if expiresAt is provided)
603
+ *
604
+ * Note: userAddress is optional for both circuits - the mobile app will prompt
605
+ * for wallet connection if not provided.
606
+ *
607
+ * @param request - Proof request to validate
608
+ * @returns Validation result with `valid` flag and optional `error` message
609
+ */
705
610
  function validateProofRequest(request) {
706
611
  if (!request.requestId) {
707
612
  return { valid: false, error: 'Missing requestId' };
@@ -757,14 +662,6 @@ function validateProofRequest(request) {
757
662
  return { valid: false, error: 'provider must be a non-empty string when specified' };
758
663
  }
759
664
  }
760
- else if (request.circuit === 'mdl_kr_ownership' ||
761
- request.circuit === 'mdl_kr_age' ||
762
- request.circuit === 'mdl_kr_region') {
763
- const mdlError = validateMdlInputs(request.circuit, request.inputs);
764
- if (mdlError) {
765
- return { valid: false, error: mdlError };
766
- }
767
- }
768
665
  // The action, decided by the circuit's own entry rather than by naming a
769
666
  // circuit here, so every action-capable circuit is checked the same way.
770
667
  {
@@ -3868,7 +3765,7 @@ function estimateQRDataSize(requestOrUrl, scheme = DEFAULT_SCHEME) {
3868
3765
  * The version. `@aztec/bb.js` must be the WASM build of the same bb the
3869
3766
  * circuits are compiled with -- `BB_VERSION` in circuits/toolchain.env,
3870
3767
  * 4.2.0-aztecnr-rc.2 since the beta.19 toolchain. Versions are not
3871
- * interchangeable: on the Korea Mobile ID age circuit the 2025 nightly wrote
3768
+ * interchangeable: on one of our circuits the 2025 nightly wrote
3872
3769
  * a 16256-byte proof where bb 1.2.0 wrote 16224 for the identical circuit and
3873
3770
  * witness, with the SAME verification key, so the key cannot warn you. A
3874
3771
  * mismatch shows up only as verification failing.
@@ -3970,15 +3867,12 @@ function normalisePublicInputs(publicInputs) {
3970
3867
  *
3971
3868
  * @internal
3972
3869
  */
3973
- async function fetchVerificationKey(circuit, timeoutMs) {
3974
- const cached = vkCache.get(circuit);
3870
+ async function fetchVerificationKey(circuit, variant, timeoutMs) {
3871
+ const cacheKey = `${circuit}/${variant}`;
3872
+ const cached = vkCache.get(cacheKey);
3975
3873
  if (cached && Date.now() - cached.at < VK_CACHE_TTL_MS)
3976
3874
  return cached.vk;
3977
- const vkPath = CIRCUIT_VK_PATHS[circuit];
3978
- if (!vkPath) {
3979
- throw new Error(`No verification key path for circuit '${circuit}'. ` +
3980
- `Add it to CIRCUIT_VK_PATHS, or pass verificationKey directly.`);
3981
- }
3875
+ const vkPath = getCircuitPackage(circuit, variant).vkPath;
3982
3876
  const url = `${CIRCUITS_VK_BASE}/${vkPath}`;
3983
3877
  const controller = new AbortController();
3984
3878
  const timer = setTimeout(() => controller.abort(), timeoutMs);
@@ -3995,7 +3889,7 @@ async function fetchVerificationKey(circuit, timeoutMs) {
3995
3889
  throw new Error(`The verification key at ${url} is ${vk.length} bytes, far too small to be one. ` +
3996
3890
  `The path is probably wrong and something else was served.`);
3997
3891
  }
3998
- vkCache.set(circuit, { vk, at: Date.now() });
3892
+ vkCache.set(cacheKey, { vk, at: Date.now() });
3999
3893
  return vk;
4000
3894
  }
4001
3895
  finally {
@@ -4035,6 +3929,10 @@ async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
4035
3929
  if (!isCircuitId(circuit)) {
4036
3930
  return { valid: false, error: `Unknown circuit '${circuit}'. Known: ${ALL_CIRCUIT_IDS.join(', ')}.` };
4037
3931
  }
3932
+ const signer = resolveSignerVariant(circuit, options.signerVariant, proof);
3933
+ if ('error' in signer) {
3934
+ return { valid: false, error: signer.error };
3935
+ }
4038
3936
  // Before Barretenberg, and for the same reason as on-chain: a proof can be
4039
3937
  // mathematically valid and still mean nothing, because some circuits take
4040
3938
  // their trust anchor as a public input the prover chooses. For OIDC that is
@@ -4081,7 +3979,7 @@ async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
4081
3979
  // relay can deliver a short value (`0x01`), and the check below must see
4082
3980
  // exactly what the circuit committed to.
4083
3981
  const fields = normalisePublicInputs(publicInputs);
4084
- const vk = options.verificationKey ?? (await fetchVerificationKey(circuit, timeoutMs));
3982
+ const vk = options.verificationKey ?? (await fetchVerificationKey(circuit, signer.variant, timeoutMs));
4085
3983
  const barretenberg = await bb.Barretenberg.new({ threads: 1 });
4086
3984
  api = barretenberg;
4087
3985
  const verifier = new bb.UltraHonkVerifierBackend(barretenberg);
@@ -4115,6 +4013,17 @@ const RELAY_TERMINAL_STATUSES = ['completed', 'error', 'failed', 'cancelled', 'e
4115
4013
  function isTerminalRelayStatus(status) {
4116
4014
  return RELAY_TERMINAL_STATUSES.includes(status);
4117
4015
  }
4016
+ /**
4017
+ * How long `waitForProof()` / `waitForResult()` wait when the caller passes no
4018
+ * `timeoutMs`: 600 000 ms (10 min).
4019
+ *
4020
+ * The relay answers `expired` itself at 540 s, so with this default a dApp
4021
+ * always gets a terminal status to branch on rather than its own timeout. A
4022
+ * heavy proof on an older phone takes a few minutes after the user confirms;
4023
+ * the earlier 300 000 ms default could fire while such a proof was still being
4024
+ * made.
4025
+ */
4026
+ const DEFAULT_RELAY_WAIT_MS = 600000;
4118
4027
 
4119
4028
  /**
4120
4029
  * Proofport SDK - Main class
@@ -4265,7 +4174,7 @@ class ProofportSDK {
4265
4174
  const request = {
4266
4175
  requestId: generateRequestId(),
4267
4176
  // The circuit asked for, always. This used to be the literal
4268
- // 'coinbase_attestation', and every circuit that was not country or mDL
4177
+ // 'coinbase_attestation', and every circuit that was not country
4269
4178
  // was routed here -- a GIWA, Dojang or OIDC request silently became a
4270
4179
  // Coinbase KYC request.
4271
4180
  circuit,
@@ -4372,45 +4281,10 @@ class ProofportSDK {
4372
4281
  switch (builder) {
4373
4282
  case 'country':
4374
4283
  return this.createCoinbaseCountryRequest(inputs, options);
4375
- case 'mdl':
4376
- return this.createMdlKrRequest(circuit, inputs, options);
4377
4284
  case 'scoped':
4378
4285
  return this.createScopedRequest(circuit, inputs, options);
4379
4286
  }
4380
4287
  }
4381
- /**
4382
- * @internal
4383
- * Creates a Korea Mobile ID (mDL) proof request for any of the three
4384
- * mDL predicate circuits (ownership / age / region).
4385
- *
4386
- * The mobile app collects the license data on-device; the dapp only
4387
- * supplies the predicate parameters validated here. No wallet signature
4388
- * is required for mDL circuits.
4389
- *
4390
- * @param circuit - 'mdl_kr_ownership' | 'mdl_kr_age' | 'mdl_kr_region'
4391
- * @param inputs - Predicate inputs (see MdlKr*Inputs types)
4392
- * @param options - Request configuration options
4393
- *
4394
- * @throws Error if the predicate inputs fail validation
4395
- */
4396
- createMdlKrRequest(circuit, inputs, options = {}) {
4397
- const mdlError = validateMdlInputs(circuit, inputs);
4398
- if (mdlError) {
4399
- throw new Error(`${mdlError} (circuit: ${circuit})`);
4400
- }
4401
- const request = {
4402
- requestId: generateRequestId(),
4403
- circuit,
4404
- inputs,
4405
- message: options.message,
4406
- dappName: options.dappName,
4407
- dappIcon: options.dappIcon,
4408
- createdAt: Date.now(),
4409
- expiresAt: Date.now() + (options.expiresInMs || DEFAULT_REQUEST_EXPIRY_MS),
4410
- };
4411
- this.pendingRequests.set(request.requestId, request);
4412
- return request;
4413
- }
4414
4288
  // ============ Deep Link Generation ============
4415
4289
  /**
4416
4290
  * @internal
@@ -4754,6 +4628,7 @@ class ProofportSDK {
4754
4628
  const parsedProof = parseProofForOnChain(proof, publicInputs, publicInputs.length);
4755
4629
  return verifyProofOnChain(circuit, parsedProof, providerOrSigner, this.verifierTarget(circuit), undefined, {
4756
4630
  request: options.request,
4631
+ signerVariant: options.signerVariant,
4757
4632
  });
4758
4633
  }
4759
4634
  /**
@@ -4867,7 +4742,7 @@ class ProofportSDK {
4867
4742
  return verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, this.verifierTarget(response.circuit), {
4868
4743
  verifierAddress: response.verifierAddress,
4869
4744
  chainId: response.chainId,
4870
- }, { request });
4745
+ }, { request, signerVariant: response.signerVariant });
4871
4746
  }
4872
4747
  /**
4873
4748
  * Verifies a proof response off-chain, against the circuit's verification key.
@@ -4904,7 +4779,7 @@ class ProofportSDK {
4904
4779
  return { valid: false, error: found.error };
4905
4780
  request = found.request;
4906
4781
  }
4907
- return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request });
4782
+ return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request, signerVariant: response.signerVariant });
4908
4783
  }
4909
4784
  // ============ Utility Methods ============
4910
4785
  /**
@@ -5262,14 +5137,6 @@ class ProofportSDK {
5262
5137
  if (needsSignature && !this.signer) {
5263
5138
  throw new Error('Signer not set. Call setSigner() first. Wallet signature is required for this circuit.');
5264
5139
  }
5265
- // mDL circuits: validate predicate inputs client-side before hitting the
5266
- // relay, so a bad ageThreshold / targetRegion fails fast with a clear error.
5267
- if (circuit === 'mdl_kr_ownership' || circuit === 'mdl_kr_age' || circuit === 'mdl_kr_region') {
5268
- const mdlError = validateMdlInputs(circuit, inputs);
5269
- if (mdlError) {
5270
- throw new Error(`${mdlError} (circuit: ${circuit})`);
5271
- }
5272
- }
5273
5140
  // The action, per the circuit's entry in CIRCUIT_ACTION_BINDING. Checked
5274
5141
  // here, before a challenge is burned, because the alternative is a refusal
5275
5142
  // from inside the mobile app -- a screen the dapp developer never sees,
@@ -5385,14 +5252,14 @@ class ProofportSDK {
5385
5252
  * @param requestId - The relay-issued request ID
5386
5253
  * @param options - Polling options
5387
5254
  * @param options.intervalMs - Polling interval in milliseconds (default: 2000)
5388
- * @param options.timeoutMs - Maximum polling time in milliseconds (default: 300000 = 5 min)
5255
+ * @param options.timeoutMs - Maximum polling time in milliseconds (default: 600000 = 10 min, `DEFAULT_RELAY_WAIT_MS`)
5389
5256
  * @param options.onStatusChange - Callback when status changes
5390
5257
  * @returns Promise resolving to final RelayProofResult
5391
5258
  * @throws Error if timeout or relay error
5392
5259
  */
5393
5260
  async waitForResult(requestId, options = {}) {
5394
5261
  const interval = options.intervalMs || 2000;
5395
- const timeout = options.timeoutMs || 300000;
5262
+ const timeout = options.timeoutMs || DEFAULT_RELAY_WAIT_MS;
5396
5263
  const startTime = Date.now();
5397
5264
  let lastStatus = '';
5398
5265
  while (Date.now() - startTime < timeout) {
@@ -5504,12 +5371,12 @@ class ProofportSDK {
5504
5371
  *
5505
5372
  * @param requestId - The relay-issued request ID
5506
5373
  * @param options - Configuration options
5507
- * @param options.timeoutMs - Maximum wait time in ms (default: 300000 = 5 min)
5374
+ * @param options.timeoutMs - Maximum wait time in ms (default: 600000 = 10 min, `DEFAULT_RELAY_WAIT_MS`)
5508
5375
  * @param options.onStatusChange - Callback for status updates
5509
5376
  * @returns Promise resolving to final RelayProofResult
5510
5377
  */
5511
5378
  async waitForProof(requestId, options = {}) {
5512
- const timeout = options.timeoutMs || 300000;
5379
+ const timeout = options.timeoutMs || DEFAULT_RELAY_WAIT_MS;
5513
5380
  // Try Socket.IO first
5514
5381
  if (this.relayUrl) {
5515
5382
  try {
@@ -5641,10 +5508,7 @@ ProofportSDK.REQUEST_BUILDERS = {
5641
5508
  oidc_domain_attestation: 'scoped',
5642
5509
  giwa_attestation: 'scoped',
5643
5510
  dojang_playground: 'scoped',
5644
- mdl_kr_ownership: 'mdl',
5645
- mdl_kr_age: 'mdl',
5646
- mdl_kr_region: 'mdl',
5647
5511
  };
5648
5512
 
5649
- export { ProofportSDK, RELAY_TERMINAL_STATUSES, ProofportSDK as default, isTerminalRelayStatus, verifyProofOffChain };
5513
+ export { DEFAULT_RELAY_WAIT_MS, ProofportSDK, RELAY_TERMINAL_STATUSES, ProofportSDK as default, isTerminalRelayStatus, verifyProofOffChain };
5650
5514
  //# sourceMappingURL=index.esm.js.map