@zkproofport-app/sdk 0.5.0-beta.8 → 0.5.0-beta.9

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.js CHANGED
@@ -43,6 +43,7 @@ const VERIFICATION_CHAINS = {
43
43
  oidc_domain_attestation: 8453,
44
44
  giwa_attestation: 91342,
45
45
  dojang_playground: 91342,
46
+ human_passport_score: 8453,
46
47
  },
47
48
  staging: {
48
49
  coinbase_attestation: 84532,
@@ -50,6 +51,7 @@ const VERIFICATION_CHAINS = {
50
51
  oidc_domain_attestation: 84532,
51
52
  giwa_attestation: 91342,
52
53
  dojang_playground: 91342,
54
+ human_passport_score: 84532,
53
55
  },
54
56
  local: {
55
57
  coinbase_attestation: 84532,
@@ -57,6 +59,7 @@ const VERIFICATION_CHAINS = {
57
59
  oidc_domain_attestation: 84532,
58
60
  giwa_attestation: 91342,
59
61
  dojang_playground: 91342,
62
+ human_passport_score: 84532,
60
63
  },
61
64
  };
62
65
  /**
@@ -158,6 +161,14 @@ const CIRCUIT_METADATA = {
158
161
  publicInputsCount: 160,
159
162
  publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'scope', 'nullifier'],
160
163
  },
164
+ // human-passport-score/src/main.nr: GIWA's six `pub [u8; 32]`, then
165
+ // min_score (u32, score x 10^4), scorer_id and now (u64) = 195 fields.
166
+ human_passport_score: {
167
+ name: 'Human Passport',
168
+ description: 'Prove a Human Passport score at or above a threshold, optionally authorizing one EIP-712 action',
169
+ publicInputsCount: 195,
170
+ publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'signer_list_merkle_root', 'scope', 'nullifier', 'min_score', 'scorer_id', 'now'],
171
+ },
161
172
  };
162
173
  /**
163
174
  * Default proof request expiration time in milliseconds.
@@ -654,6 +665,21 @@ function validateProofRequest(request) {
654
665
  return { valid: false, error: 'isIncluded is required and must be a boolean' };
655
666
  }
656
667
  }
668
+ else if (request.circuit === 'human_passport_score') {
669
+ const inputs = request.inputs;
670
+ if (inputs.userAddress && !/^0x[a-fA-F0-9]{40}$/.test(inputs.userAddress)) {
671
+ return { valid: false, error: 'Invalid userAddress format' };
672
+ }
673
+ if (!inputs.scope || typeof inputs.scope !== 'string' || inputs.scope.trim() === '') {
674
+ return { valid: false, error: 'scope is required and must be a non-empty string' };
675
+ }
676
+ try {
677
+ circuits.humanPassportScoreUnits(inputs.minScore);
678
+ }
679
+ catch (error) {
680
+ return { valid: false, error: error instanceof Error ? error.message : String(error) };
681
+ }
682
+ }
657
683
  else if (request.circuit === 'oidc_domain_attestation') {
658
684
  const inputs = request.inputs;
659
685
  if (!inputs.domain || typeof inputs.domain !== 'string' || inputs.domain.trim() === '') {
@@ -1075,7 +1101,7 @@ async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
1075
1101
  // their trust anchor as a public input the prover chooses. For OIDC that is
1076
1102
  // the RSA key -- see core's oidcProviderKeys. Checked here so a dApp that
1077
1103
  // verifies off-chain gets the same answer as one that verifies on-chain.
1078
- const issuer = await core.checkProofIssuer(circuit, publicInputs, { request: options.request, countryCondition: options.countryCondition });
1104
+ const issuer = await core.checkProofIssuer(circuit, publicInputs, { request: options.request, countryCondition: options.countryCondition, minScore: options.minScore });
1079
1105
  if (!issuer.ok) {
1080
1106
  return { valid: false, error: issuer.error };
1081
1107
  }
@@ -1241,6 +1267,12 @@ class ProofportSDK {
1241
1267
  * them. Bounded like {@link relayRequests}.
1242
1268
  */
1243
1269
  this.countryRequests = new Map();
1270
+ /**
1271
+ * requestId -> the score threshold of the Human Passport relay requests this
1272
+ * instance created, so verifyResponse* can hold the proof's min_score to it.
1273
+ * Bounded like {@link relayRequests}.
1274
+ */
1275
+ this.passportRequests = new Map();
1244
1276
  this.signer = null;
1245
1277
  this.socket = null;
1246
1278
  /**
@@ -1433,6 +1465,16 @@ class ProofportSDK {
1433
1465
  switch (builder) {
1434
1466
  case 'country':
1435
1467
  return this.createCoinbaseCountryRequest(inputs, options);
1468
+ case 'passport': {
1469
+ const minScore = inputs.minScore;
1470
+ try {
1471
+ circuits.humanPassportScoreUnits(minScore);
1472
+ }
1473
+ catch (error) {
1474
+ throw new Error(`${error instanceof Error ? error.message : String(error)} (circuit: ${circuit})`);
1475
+ }
1476
+ return this.createScopedRequest(circuit, inputs, options);
1477
+ }
1436
1478
  case 'scoped':
1437
1479
  return this.createScopedRequest(circuit, inputs, options);
1438
1480
  }
@@ -1782,6 +1824,7 @@ class ProofportSDK {
1782
1824
  request: options.request,
1783
1825
  signerVariant: options.signerVariant,
1784
1826
  countryCondition: options.countryCondition,
1827
+ minScore: options.minScore,
1785
1828
  });
1786
1829
  }
1787
1830
  /**
@@ -1847,6 +1890,42 @@ class ProofportSDK {
1847
1890
  'isIncluded } } -- the list and direction of the request you created.',
1848
1891
  };
1849
1892
  }
1893
+ /**
1894
+ * The score threshold a `human_passport_score` response must carry: the one
1895
+ * the caller passed, else the relay request this instance created under the
1896
+ * response's requestId, else the deep-link request still pending under it.
1897
+ * `{ error }` when there is none: the proof's threshold is the prover's
1898
+ * choice, so a response this SDK cannot place is refused rather than
1899
+ * accepted for whatever threshold it carries.
1900
+ */
1901
+ passportMinScoreFor(response, explicit) {
1902
+ if (explicit !== undefined)
1903
+ return { minScore: explicit };
1904
+ const remembered = this.passportRequests.get(response.requestId);
1905
+ if (remembered !== undefined)
1906
+ return { minScore: remembered };
1907
+ const pending = this.pendingRequests.get(response.requestId);
1908
+ const inputs = pending?.circuit === 'human_passport_score' ? pending.inputs : undefined;
1909
+ if (inputs && typeof inputs.minScore === 'number')
1910
+ return { minScore: inputs.minScore };
1911
+ return {
1912
+ error: `No Human Passport request ${JSON.stringify(response.requestId)} was created by this SDK instance, so the ` +
1913
+ "proof's score threshold cannot be checked against what was asked. Pass { minScore } -- the threshold of " +
1914
+ 'the request you created.',
1915
+ };
1916
+ }
1917
+ /** @internal Remember a Human Passport relay request's threshold for verifyResponse*. */
1918
+ rememberPassportRequest(requestId, inputs) {
1919
+ const minScore = inputs?.minScore;
1920
+ if (typeof requestId !== 'string' || typeof minScore !== 'number')
1921
+ return;
1922
+ this.passportRequests.delete(requestId);
1923
+ this.passportRequests.set(requestId, minScore);
1924
+ while (this.passportRequests.size > ProofportSDK.MAX_REMEMBERED_RELAY_REQUESTS) {
1925
+ const oldest = this.passportRequests.keys().next().value;
1926
+ this.passportRequests.delete(oldest);
1927
+ }
1928
+ }
1850
1929
  /** @internal Remember a Coinbase Country relay request's list and direction for verifyResponse*. */
1851
1930
  rememberCountryRequest(requestId, inputs) {
1852
1931
  const i = inputs;
@@ -1935,6 +2014,13 @@ class ProofportSDK {
1935
2014
  return { valid: false, error: found.error };
1936
2015
  countryCondition = found.condition;
1937
2016
  }
2017
+ let minScore;
2018
+ if (response.circuit === 'human_passport_score') {
2019
+ const found = this.passportMinScoreFor(response, options.minScore);
2020
+ if ('error' in found)
2021
+ return { valid: false, error: found.error };
2022
+ minScore = found.minScore;
2023
+ }
1938
2024
  const parsedProof = core.parseProofForOnChain(response.proof, response.publicInputs, response.publicInputs.length);
1939
2025
  // The response's verifierAddress and chainId are a claim to check, never
1940
2026
  // the contract to call: whoever wrote the response would otherwise pick
@@ -1943,7 +2029,7 @@ class ProofportSDK {
1943
2029
  return core.verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, this.verifierTarget(response.circuit), {
1944
2030
  verifierAddress: response.verifierAddress,
1945
2031
  chainId: response.chainId,
1946
- }, { request, signerVariant: response.signerVariant, countryCondition });
2032
+ }, { request, signerVariant: response.signerVariant, countryCondition, minScore });
1947
2033
  }
1948
2034
  /**
1949
2035
  * Verifies a proof response off-chain, against the circuit's verification key.
@@ -1987,7 +2073,14 @@ class ProofportSDK {
1987
2073
  return { valid: false, error: found.error };
1988
2074
  countryCondition = found.condition;
1989
2075
  }
1990
- return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request, countryCondition, signerVariant: response.signerVariant });
2076
+ let minScore;
2077
+ if (response.circuit === 'human_passport_score') {
2078
+ const found = this.passportMinScoreFor(response, options?.minScore);
2079
+ if ('error' in found)
2080
+ return { valid: false, error: found.error };
2081
+ minScore = found.minScore;
2082
+ }
2083
+ return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request, countryCondition, minScore, signerVariant: response.signerVariant });
1991
2084
  }
1992
2085
  // ============ Utility Methods ============
1993
2086
  /**
@@ -2365,6 +2458,15 @@ class ProofportSDK {
2365
2458
  }
2366
2459
  }
2367
2460
  }
2461
+ // A Human Passport threshold the circuit cannot carry is refused here too.
2462
+ if (circuit === 'human_passport_score') {
2463
+ try {
2464
+ circuits.humanPassportScoreUnits(inputs.minScore);
2465
+ }
2466
+ catch (error) {
2467
+ throw new Error(`${error instanceof Error ? error.message : String(error)} (circuit: ${circuit})`);
2468
+ }
2469
+ }
2368
2470
  // A Coinbase Country list the circuit would refuse is refused here, before a
2369
2471
  // challenge is burned, as createProofRequest does.
2370
2472
  if (circuit === 'coinbase_country_attestation') {
@@ -2432,6 +2534,8 @@ class ProofportSDK {
2432
2534
  this.rememberRelayRequest(created.requestId, scope);
2433
2535
  if (circuit === 'coinbase_country_attestation')
2434
2536
  this.rememberCountryRequest(created.requestId, inputs);
2537
+ if (circuit === 'human_passport_score')
2538
+ this.rememberPassportRequest(created.requestId, inputs);
2435
2539
  return created;
2436
2540
  }
2437
2541
  /**
@@ -2728,6 +2832,8 @@ ProofportSDK.REQUEST_BUILDERS = {
2728
2832
  oidc_domain_attestation: 'scoped',
2729
2833
  giwa_attestation: 'scoped',
2730
2834
  dojang_playground: 'scoped',
2835
+ // Scoped, plus the score threshold the proof must carry.
2836
+ human_passport_score: 'passport',
2731
2837
  };
2732
2838
 
2733
2839
  Object.defineProperty(exports, "COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT", {
@@ -2742,6 +2848,14 @@ Object.defineProperty(exports, "COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT", {
2742
2848
  enumerable: true,
2743
2849
  get: function () { return core.COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT; }
2744
2850
  });
2851
+ Object.defineProperty(exports, "HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_COUNT", {
2852
+ enumerable: true,
2853
+ get: function () { return core.HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_COUNT; }
2854
+ });
2855
+ Object.defineProperty(exports, "HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_LAYOUT", {
2856
+ enumerable: true,
2857
+ get: function () { return core.HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_LAYOUT; }
2858
+ });
2745
2859
  Object.defineProperty(exports, "OIDC_ALLOWED_AUDIENCES", {
2746
2860
  enumerable: true,
2747
2861
  get: function () { return core.OIDC_ALLOWED_AUDIENCES; }
@@ -2838,6 +2952,22 @@ Object.defineProperty(exports, "EXPERIMENTAL_CIRCUIT_IDS", {
2838
2952
  enumerable: true,
2839
2953
  get: function () { return circuits.EXPERIMENTAL_CIRCUIT_IDS; }
2840
2954
  });
2955
+ Object.defineProperty(exports, "HUMAN_PASSPORT_ISSUER", {
2956
+ enumerable: true,
2957
+ get: function () { return circuits.HUMAN_PASSPORT_ISSUER; }
2958
+ });
2959
+ Object.defineProperty(exports, "HUMAN_PASSPORT_ISSUER_ROOT", {
2960
+ enumerable: true,
2961
+ get: function () { return circuits.HUMAN_PASSPORT_ISSUER_ROOT; }
2962
+ });
2963
+ Object.defineProperty(exports, "HUMAN_PASSPORT_SCORER_ID", {
2964
+ enumerable: true,
2965
+ get: function () { return circuits.HUMAN_PASSPORT_SCORER_ID; }
2966
+ });
2967
+ Object.defineProperty(exports, "HUMAN_PASSPORT_SCORE_SCHEMA", {
2968
+ enumerable: true,
2969
+ get: function () { return circuits.HUMAN_PASSPORT_SCORE_SCHEMA; }
2970
+ });
2841
2971
  Object.defineProperty(exports, "PLANNED_CIRCUIT_IDS", {
2842
2972
  enumerable: true,
2843
2973
  get: function () { return circuits.PLANNED_CIRCUIT_IDS; }
@@ -2866,6 +2996,10 @@ Object.defineProperty(exports, "getCircuitSupportStatus", {
2866
2996
  enumerable: true,
2867
2997
  get: function () { return circuits.getCircuitSupportStatus; }
2868
2998
  });
2999
+ Object.defineProperty(exports, "humanPassportScoreUnits", {
3000
+ enumerable: true,
3001
+ get: function () { return circuits.humanPassportScoreUnits; }
3002
+ });
2869
3003
  Object.defineProperty(exports, "isCircuitId", {
2870
3004
  enumerable: true,
2871
3005
  get: function () { return circuits.isCircuitId; }