@zkproofport-app/sdk 0.2.2 → 0.2.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.
package/dist/index.js CHANGED
@@ -72,6 +72,12 @@ const CIRCUIT_METADATA = {
72
72
  publicInputsCount: 14,
73
73
  publicInputNames: ['signal_hash', 'signer_list_merkle_root', 'country_list', 'country_list_length', 'is_included'],
74
74
  },
75
+ oidc_domain_attestation: {
76
+ name: 'OIDC Domain',
77
+ description: 'Prove email domain affiliation via OIDC JWT',
78
+ publicInputsCount: 420,
79
+ publicInputNames: ['pubkey_modulus_limbs', 'domain', 'scope', 'nullifier'],
80
+ },
75
81
  };
76
82
  /**
77
83
  * Standard verifier contract ABI shared across all Barretenberg-generated verifiers.
@@ -203,6 +209,34 @@ const COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT = {
203
209
  NULLIFIER_START: 118,
204
210
  NULLIFIER_END: 149,
205
211
  };
212
+ /**
213
+ * OIDC Domain Attestation circuit public input layout (byte offsets).
214
+ * Defines the byte positions of each field in the flattened public inputs array.
215
+ *
216
+ * Public inputs are packed as individual field elements (one byte per element):
217
+ * - pubkey_modulus_limbs: 18 x u128 = 18 x 16 bytes = 288 bytes → fields 0–287
218
+ * - domain (BoundedVec<u8, 64>): 4-byte length (u32) + 64-byte storage = 68 fields → fields 288–355
219
+ * - scope: 32 bytes → fields 356–387
220
+ * - nullifier: 32 bytes → fields 388–419
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const scope = publicInputs.slice(
225
+ * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_START,
226
+ * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_END + 1
227
+ * );
228
+ * ```
229
+ */
230
+ const OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT = {
231
+ PUBKEY_MODULUS_START: 0,
232
+ PUBKEY_MODULUS_END: 287,
233
+ DOMAIN_START: 288,
234
+ DOMAIN_END: 355,
235
+ SCOPE_START: 356,
236
+ SCOPE_END: 387,
237
+ NULLIFIER_START: 388,
238
+ NULLIFIER_END: 419,
239
+ };
206
240
 
207
241
  /**
208
242
  * Deep Link utilities for ZKProofport SDK
@@ -455,7 +489,7 @@ function validateProofRequest(request) {
455
489
  if (!request.circuit) {
456
490
  return { valid: false, error: 'Missing circuit type' };
457
491
  }
458
- if (!['coinbase_attestation', 'coinbase_country_attestation'].includes(request.circuit)) {
492
+ if (!['coinbase_attestation', 'coinbase_country_attestation', 'oidc_domain_attestation'].includes(request.circuit)) {
459
493
  return { valid: false, error: `Invalid circuit type: ${request.circuit}` };
460
494
  }
461
495
  if (!request.callbackUrl) {
@@ -485,6 +519,18 @@ function validateProofRequest(request) {
485
519
  return { valid: false, error: 'isIncluded is required and must be a boolean' };
486
520
  }
487
521
  }
522
+ else if (request.circuit === 'oidc_domain_attestation') {
523
+ const inputs = request.inputs;
524
+ if (!inputs.domain || typeof inputs.domain !== 'string' || inputs.domain.trim() === '') {
525
+ return { valid: false, error: 'domain is required and must be a non-empty string' };
526
+ }
527
+ if (!inputs.scope || typeof inputs.scope !== 'string' || inputs.scope.trim() === '') {
528
+ return { valid: false, error: 'scope is required and must be a non-empty string' };
529
+ }
530
+ if (inputs.provider !== undefined && (typeof inputs.provider !== 'string' || inputs.provider.trim() === '')) {
531
+ return { valid: false, error: 'provider must be a non-empty string when specified' };
532
+ }
533
+ }
488
534
  // Check expiry
489
535
  if (request.expiresAt && Date.now() > request.expiresAt) {
490
536
  return { valid: false, error: 'Request has expired' };
@@ -919,6 +965,10 @@ function extractScopeFromPublicInputs(publicInputsHex, circuit) {
919
965
  start = 86;
920
966
  end = 117;
921
967
  }
968
+ else if (circuit === 'oidc_domain_attestation') {
969
+ start = 356;
970
+ end = 387;
971
+ }
922
972
  else {
923
973
  start = 64;
924
974
  end = 95;
@@ -952,6 +1002,10 @@ function extractNullifierFromPublicInputs(publicInputsHex, circuit) {
952
1002
  start = 118;
953
1003
  end = 149;
954
1004
  }
1005
+ else if (circuit === 'oidc_domain_attestation') {
1006
+ start = 388;
1007
+ end = 419;
1008
+ }
955
1009
  else {
956
1010
  start = 96;
957
1011
  end = 127;
@@ -1843,53 +1897,26 @@ class ProofportSDK {
1843
1897
  }
1844
1898
  return await response.json();
1845
1899
  }
1846
- /**
1847
- * Creates a proof request through the relay server.
1848
- *
1849
- * This is the recommended way to create proof requests. The relay server:
1850
- * - Issues a server-side requestId (validated by the mobile app)
1851
- * - Tracks request status in Redis
1852
- * - Builds the deep link with relay callback URL
1853
- * - Stores inputs hash for deep link integrity verification
1854
- *
1855
- * @param circuit - Circuit type identifier
1856
- * @param inputs - Circuit-specific inputs
1857
- * @param options - Request options (message, dappName, dappIcon, nonce)
1858
- * @returns Promise resolving to RelayProofRequest with requestId, deepLink, pollUrl
1859
- * @throws Error if signer not set or relay request fails
1860
- *
1861
- * @example
1862
- * ```typescript
1863
- * const sdk = ProofportSDK.create();
1864
- * sdk.setSigner(signer);
1865
- *
1866
- * const relay = await sdk.createRelayRequest('coinbase_attestation', {
1867
- * scope: 'myapp.com'
1868
- * }, { dappName: 'My DApp' });
1869
- *
1870
- * // Generate QR code from relay deep link
1871
- * const qr = await sdk.generateQRCode(relay.deepLink);
1872
- *
1873
- * // Wait for proof (WebSocket primary, polling fallback)
1874
- * const result = await sdk.waitForProof(relay.requestId);
1875
- * ```
1876
- */
1877
1900
  async createRelayRequest(circuit, inputs, options = {}) {
1878
- if (!this.signer) {
1879
- throw new Error('Signer not set. Call setSigner() first.');
1880
- }
1881
1901
  if (!this.relayUrl) {
1882
1902
  throw new Error('relayUrl is required. Set it in ProofportSDK config.');
1883
1903
  }
1884
- // Get challenge from relay and sign it
1885
- const { challenge } = await this.getChallenge();
1886
- const signature = await this.signer.signMessage(challenge);
1904
+ const needsSignature = ProofportSDK.WALLET_SIGNATURE_CIRCUITS.includes(circuit);
1905
+ if (needsSignature && !this.signer) {
1906
+ throw new Error('Signer not set. Call setSigner() first. Wallet signature is required for this circuit.');
1907
+ }
1908
+ // Get challenge + requestId from relay
1909
+ const { requestId, challenge } = await this.getChallenge();
1887
1910
  const body = {
1911
+ requestId,
1888
1912
  circuitId: circuit,
1889
1913
  inputs,
1890
1914
  challenge,
1891
- signature,
1892
1915
  };
1916
+ // Sign challenge for circuits that require wallet signature
1917
+ if (needsSignature && this.signer) {
1918
+ body.signature = await this.signer.signMessage(challenge);
1919
+ }
1893
1920
  if (options.message)
1894
1921
  body.message = options.message;
1895
1922
  if (options.dappName)
@@ -2166,9 +2193,46 @@ class ProofportSDK {
2166
2193
  return extractNullifierFromPublicInputs(publicInputs, circuit);
2167
2194
  }
2168
2195
  }
2196
+ /**
2197
+ * Creates a proof request through the relay server.
2198
+ *
2199
+ * This is the recommended way to create proof requests. The relay server:
2200
+ * - Issues a server-side requestId (validated by the mobile app)
2201
+ * - Tracks request status in Redis
2202
+ * - Builds the deep link with relay callback URL
2203
+ * - Stores inputs hash for deep link integrity verification
2204
+ *
2205
+ * @param circuit - Circuit type identifier
2206
+ * @param inputs - Circuit-specific inputs
2207
+ * @param options - Request options (message, dappName, dappIcon, nonce)
2208
+ * @returns Promise resolving to RelayProofRequest with requestId, deepLink, pollUrl
2209
+ * @throws Error if signer not set or relay request fails
2210
+ *
2211
+ * @example
2212
+ * ```typescript
2213
+ * const sdk = ProofportSDK.create();
2214
+ * sdk.setSigner(signer);
2215
+ *
2216
+ * const relay = await sdk.createRelayRequest('coinbase_attestation', {
2217
+ * scope: 'myapp.com'
2218
+ * }, { dappName: 'My DApp' });
2219
+ *
2220
+ * // Generate QR code from relay deep link
2221
+ * const qr = await sdk.generateQRCode(relay.deepLink);
2222
+ *
2223
+ * // Wait for proof (WebSocket primary, polling fallback)
2224
+ * const result = await sdk.waitForProof(relay.requestId);
2225
+ * ```
2226
+ */
2227
+ // Circuits that require wallet signature (used as circuit input)
2228
+ ProofportSDK.WALLET_SIGNATURE_CIRCUITS = [
2229
+ 'coinbase_attestation',
2230
+ 'coinbase_country_attestation',
2231
+ ];
2169
2232
 
2170
2233
  exports.COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT = COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT;
2171
2234
  exports.COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT = COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT;
2235
+ exports.OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT = OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT;
2172
2236
  exports.ProofportSDK = ProofportSDK;
2173
2237
  exports.default = ProofportSDK;
2174
2238
  exports.extractNullifierFromPublicInputs = extractNullifierFromPublicInputs;