@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/README.md +34 -1
- package/dist/ProofportSDK.d.ts +19 -0
- package/dist/constants.d.ts +4 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.esm.js +112 -6
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +137 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +112 -6
- package/dist/index.mjs.map +1 -1
- package/dist/offChainVerifier.d.ts +6 -0
- package/dist/types.d.ts +18 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@zkproofport-app/sdk)
|
|
4
4
|
[](./LICENSE)
|
|
5
5
|
|
|
6
|
-
TypeScript SDK for requesting zero-knowledge proofs from the [ZKProofport](https://zkproofport.com) mobile app and verifying them on-chain.
|
|
6
|
+
TypeScript SDK for requesting zero-knowledge proofs from the [ZKProofport](https://zkproofport.com) mobile app and verifying them on-chain. Four circuits are officially supported today — Coinbase KYC, Coinbase country attestation, OIDC email-domain attestation (Google, Microsoft 365), and Human Passport score. Two more prove today against a testnet deployment and are marked experimental: GIWA attestation and Dojang Playground. [Circuit Identifiers](#circuit-identifiers) has the full list and what each status means.
|
|
7
7
|
|
|
8
8
|
## How It Works
|
|
9
9
|
|
|
@@ -125,6 +125,7 @@ import { CIRCUIT_IDS, CIRCUIT_SUPPORT_STATUS } from '@zkproofport-app/sdk/circui
|
|
|
125
125
|
| `CIRCUIT_IDS.COINBASE_ATTESTATION` | `coinbase_attestation` | **Supported** |
|
|
126
126
|
| `CIRCUIT_IDS.COINBASE_COUNTRY_ATTESTATION` | `coinbase_country_attestation` | **Supported** |
|
|
127
127
|
| `CIRCUIT_IDS.OIDC_DOMAIN_ATTESTATION` | `oidc_domain_attestation` | **Supported** |
|
|
128
|
+
| `CIRCUIT_IDS.HUMAN_PASSPORT_SCORE` | `human_passport_score` | **Supported** |
|
|
128
129
|
| `CIRCUIT_IDS.GIWA_ATTESTATION` | `giwa_attestation` | _Experimental_ |
|
|
129
130
|
| `CIRCUIT_IDS.DOJANG_PLAYGROUND` | `dojang_playground` | _Experimental_ |
|
|
130
131
|
|
|
@@ -268,6 +269,38 @@ const relay = await sdk.createRelayRequest('oidc_domain_attestation', {
|
|
|
268
269
|
|
|
269
270
|
> When `provider` is set, the mobile app verifies the user's account is managed by the specified workspace provider (e.g., Google Workspace `hd` claim, Microsoft 365 `tid` claim). Without `provider`, only the email domain is verified.
|
|
270
271
|
|
|
272
|
+
### `human_passport_score`
|
|
273
|
+
|
|
274
|
+
Proves the wallet holds an unexpired [Human Passport](https://passport.human.tech) score at or above a threshold, without revealing the wallet or the exact score. The score is the one Human Passport attests on Base (scoreV2); the user creates it in Human Passport and records it on Base first. Requires a wallet signer, and can authorize one EIP-712 action like Coinbase KYC.
|
|
275
|
+
|
|
276
|
+
| Field | Type | Required | Description |
|
|
277
|
+
|-------|------|----------|-------------|
|
|
278
|
+
| `scope` | `string` | Yes | Application-specific identifier |
|
|
279
|
+
| `minScore` | `number` | Yes | Threshold in Passport points (`20` = 20.0; above 0, at most four decimals) |
|
|
280
|
+
| `action` | `TypedAction` | No | An EIP-712 action the wallet signs instead of the request's signal hash |
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
const relay = await sdk.createRelayRequest('human_passport_score', {
|
|
284
|
+
scope: 'myapp.com',
|
|
285
|
+
minScore: 20,
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Its nullifier is `keccak(keccak(wallet ++ keccak("human_passport_score")) ++ scope)`.
|
|
290
|
+
|
|
291
|
+
The threshold is a public input the prover chooses, so `verifyResponseOnChain`
|
|
292
|
+
and `verifyResponseOffChain` compare it with the request this SDK instance
|
|
293
|
+
created and refuse any other. A response the instance cannot place is refused;
|
|
294
|
+
pass the threshold explicitly in that case:
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
await sdk.verifyResponseOnChain(response, provider, { minScore: 20 });
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Every verify path also requires Human Passport's issuer root, its Base scorer
|
|
301
|
+
(`335`) and a proof time within 15 minutes behind and 5 minutes ahead of your
|
|
302
|
+
clock (`checkHumanPassportProof`).
|
|
303
|
+
|
|
271
304
|
## Experimental Circuits
|
|
272
305
|
|
|
273
306
|
### `giwa_attestation`
|
package/dist/ProofportSDK.d.ts
CHANGED
|
@@ -57,6 +57,12 @@ export declare class ProofportSDK {
|
|
|
57
57
|
* them. Bounded like {@link relayRequests}.
|
|
58
58
|
*/
|
|
59
59
|
private countryRequests;
|
|
60
|
+
/**
|
|
61
|
+
* requestId -> the score threshold of the Human Passport relay requests this
|
|
62
|
+
* instance created, so verifyResponse* can hold the proof's min_score to it.
|
|
63
|
+
* Bounded like {@link relayRequests}.
|
|
64
|
+
*/
|
|
65
|
+
private passportRequests;
|
|
60
66
|
private signer;
|
|
61
67
|
private relayUrl;
|
|
62
68
|
private socket;
|
|
@@ -501,6 +507,7 @@ export declare class ProofportSDK {
|
|
|
501
507
|
request?: OidcRequestContext;
|
|
502
508
|
signerVariant?: string;
|
|
503
509
|
countryCondition?: CountryCondition;
|
|
510
|
+
minScore?: number;
|
|
504
511
|
}): Promise<{
|
|
505
512
|
valid: boolean;
|
|
506
513
|
error?: string;
|
|
@@ -525,6 +532,17 @@ export declare class ProofportSDK {
|
|
|
525
532
|
* place is refused rather than accepted for whatever list it carries.
|
|
526
533
|
*/
|
|
527
534
|
private countryConditionFor;
|
|
535
|
+
/**
|
|
536
|
+
* The score threshold a `human_passport_score` response must carry: the one
|
|
537
|
+
* the caller passed, else the relay request this instance created under the
|
|
538
|
+
* response's requestId, else the deep-link request still pending under it.
|
|
539
|
+
* `{ error }` when there is none: the proof's threshold is the prover's
|
|
540
|
+
* choice, so a response this SDK cannot place is refused rather than
|
|
541
|
+
* accepted for whatever threshold it carries.
|
|
542
|
+
*/
|
|
543
|
+
private passportMinScoreFor;
|
|
544
|
+
/** @internal Remember a Human Passport relay request's threshold for verifyResponse*. */
|
|
545
|
+
private rememberPassportRequest;
|
|
528
546
|
/** @internal Remember a Coinbase Country relay request's list and direction for verifyResponse*. */
|
|
529
547
|
private rememberCountryRequest;
|
|
530
548
|
/**
|
|
@@ -578,6 +596,7 @@ export declare class ProofportSDK {
|
|
|
578
596
|
verifyResponseOnChain(response: ProofResponse, providerOrSigner?: any, options?: {
|
|
579
597
|
request?: OidcRequestContext;
|
|
580
598
|
countryCondition?: CountryCondition;
|
|
599
|
+
minScore?: number;
|
|
581
600
|
}): Promise<{
|
|
582
601
|
valid: boolean;
|
|
583
602
|
error?: string;
|
package/dist/constants.d.ts
CHANGED
|
@@ -31,6 +31,7 @@ export declare const VERIFICATION_CHAINS: {
|
|
|
31
31
|
readonly oidc_domain_attestation: 8453;
|
|
32
32
|
readonly giwa_attestation: 91342;
|
|
33
33
|
readonly dojang_playground: 91342;
|
|
34
|
+
readonly human_passport_score: 8453;
|
|
34
35
|
};
|
|
35
36
|
readonly staging: {
|
|
36
37
|
readonly coinbase_attestation: 84532;
|
|
@@ -38,6 +39,7 @@ export declare const VERIFICATION_CHAINS: {
|
|
|
38
39
|
readonly oidc_domain_attestation: 84532;
|
|
39
40
|
readonly giwa_attestation: 91342;
|
|
40
41
|
readonly dojang_playground: 91342;
|
|
42
|
+
readonly human_passport_score: 84532;
|
|
41
43
|
};
|
|
42
44
|
readonly local: {
|
|
43
45
|
readonly coinbase_attestation: 84532;
|
|
@@ -45,6 +47,7 @@ export declare const VERIFICATION_CHAINS: {
|
|
|
45
47
|
readonly oidc_domain_attestation: 84532;
|
|
46
48
|
readonly giwa_attestation: 91342;
|
|
47
49
|
readonly dojang_playground: 91342;
|
|
50
|
+
readonly human_passport_score: 84532;
|
|
48
51
|
};
|
|
49
52
|
};
|
|
50
53
|
/**
|
|
@@ -123,4 +126,4 @@ export declare const DEFAULT_REQUEST_EXPIRY_MS: number;
|
|
|
123
126
|
* ```
|
|
124
127
|
*/
|
|
125
128
|
export declare const MAX_QR_DATA_SIZE = 2953;
|
|
126
|
-
export { VERIFIER_ABI, RPC_ENDPOINTS, COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, } from '@zkproofport-app/core';
|
|
129
|
+
export { VERIFIER_ABI, RPC_ENDPOINTS, COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_LAYOUT, HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_COUNT, } from '@zkproofport-app/core';
|
package/dist/index.d.ts
CHANGED
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
*/
|
|
28
28
|
export { ProofportSDK, default } from './ProofportSDK';
|
|
29
29
|
export { extractScopeFromPublicInputs, extractNullifierFromPublicInputs, extractDomainFromPublicInputs, } from './verifier';
|
|
30
|
-
export { CIRCUIT_IDS, CIRCUIT_SUPPORT_STATUS, ALL_CIRCUIT_IDS, SUPPORTED_CIRCUIT_IDS, EXPERIMENTAL_CIRCUIT_IDS, PLANNED_CIRCUIT_IDS, isCircuitId, isSupportedCircuitId, getCircuitSupportStatus, CIRCUIT_VK_PATHS, CIRCUIT_PACKAGES, SIGNER_VARIANTS, isSignerVariant, signerVariantsOf, getCircuitPackage, resolveSignerVariant, evmProofByteLength, } from './circuits';
|
|
30
|
+
export { CIRCUIT_IDS, CIRCUIT_SUPPORT_STATUS, ALL_CIRCUIT_IDS, SUPPORTED_CIRCUIT_IDS, EXPERIMENTAL_CIRCUIT_IDS, PLANNED_CIRCUIT_IDS, isCircuitId, isSupportedCircuitId, getCircuitSupportStatus, CIRCUIT_VK_PATHS, CIRCUIT_PACKAGES, SIGNER_VARIANTS, isSignerVariant, signerVariantsOf, getCircuitPackage, resolveSignerVariant, HUMAN_PASSPORT_ISSUER, HUMAN_PASSPORT_ISSUER_ROOT, HUMAN_PASSPORT_SCORER_ID, HUMAN_PASSPORT_SCORE_SCHEMA, humanPassportScoreUnits, evmProofByteLength, } from './circuits';
|
|
31
31
|
export { verifyProofOffChain } from './offChainVerifier';
|
|
32
32
|
export type { OffChainVerifyResult, OffChainVerifyOptions, } from './offChainVerifier';
|
|
33
33
|
export { PINNED_VERIFIERS, PINNED_VARIANT_VERIFIERS, getPinnedVerifier, getPinnedVariantVerifier } from './verifier';
|
|
34
34
|
export type { PinnedVerifier } from './verifier';
|
|
35
35
|
export { checkOidcPolicy, deriveOidcNonceBinding, oidcAudienceHash, OIDC_ALLOWED_AUDIENCES, OIDC_NONCE_DOMAIN, OIDC_NOW_MAX_AGE_SECONDS, OIDC_NOW_MAX_FUTURE_SECONDS, OIDC_V1_PUBLIC_INPUT_COUNT, OIDC_V2_PUBLIC_INPUT_COUNT, } from './verifier';
|
|
36
36
|
export type { OidcRequestContext, OidcAudience, OidcNonceMode } from './verifier';
|
|
37
|
-
export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, } from './constants';
|
|
37
|
+
export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_LAYOUT, HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_COUNT, } from './constants';
|
|
38
38
|
export type { CircuitId, CircuitSupportStatus, SignerVariant, CircuitPackage } from './circuits';
|
|
39
39
|
export { CIRCUIT_ACTION_BINDING, circuitActionBinding, } from './circuits';
|
|
40
40
|
export type { CircuitActionBinding } from './circuits';
|
|
41
|
-
export type { CircuitType, ProofRequestStatus, CoinbaseKycInputs, ActionBoundInputs, GiwaAttestationInputs, DojangPlaygroundInputs, TypedAction, CoinbaseCountryInputs, OidcDomainInputs, CircuitInputs, ProofRequest, ProofResponse, QRCodeOptions, VerifierContract, ProofportConfig, ChallengeResponse, WalletSigner, RelayProofRequest, RelayProofResult, RelayProofStatus, RelayTerminalStatus, SDKEnvironment, } from './types';
|
|
41
|
+
export type { CircuitType, ProofRequestStatus, CoinbaseKycInputs, ActionBoundInputs, GiwaAttestationInputs, DojangPlaygroundInputs, TypedAction, CoinbaseCountryInputs, HumanPassportScoreInputs, OidcDomainInputs, CircuitInputs, ProofRequest, ProofResponse, QRCodeOptions, VerifierContract, ProofportConfig, ChallengeResponse, WalletSigner, RelayProofRequest, RelayProofResult, RelayProofStatus, RelayTerminalStatus, SDKEnvironment, } from './types';
|
|
42
42
|
export { RELAY_TERMINAL_STATUSES, isTerminalRelayStatus, DEFAULT_RELAY_WAIT_MS } from './relayStatus';
|
|
43
43
|
export { validateTypedAction, parseTypedAction } from './typedAction';
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { countryListError, checkProofIssuer, parseProofForOnChain, verifyProofOnChain, getPinnedVerifier, extractScopeFromPublicInputs, extractNullifierFromPublicInputs, extractDomainFromPublicInputs } from '@zkproofport-app/core';
|
|
2
|
-
export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, 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';
|
|
2
|
+
export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_COUNT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, HUMAN_PASSPORT_SCORE_PUBLIC_INPUT_COUNT, HUMAN_PASSPORT_SCORE_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, humanPassportScoreUnits, 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, HUMAN_PASSPORT_ISSUER, HUMAN_PASSPORT_ISSUER_ROOT, HUMAN_PASSPORT_SCORER_ID, HUMAN_PASSPORT_SCORE_SCHEMA, PLANNED_CIRCUIT_IDS, SIGNER_VARIANTS, SUPPORTED_CIRCUIT_IDS, circuitActionBinding, evmProofByteLength, getCircuitPackage, getCircuitSupportStatus, humanPassportScoreUnits, 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
|
|
|
@@ -41,6 +41,7 @@ const VERIFICATION_CHAINS = {
|
|
|
41
41
|
oidc_domain_attestation: 8453,
|
|
42
42
|
giwa_attestation: 91342,
|
|
43
43
|
dojang_playground: 91342,
|
|
44
|
+
human_passport_score: 8453,
|
|
44
45
|
},
|
|
45
46
|
staging: {
|
|
46
47
|
coinbase_attestation: 84532,
|
|
@@ -48,6 +49,7 @@ const VERIFICATION_CHAINS = {
|
|
|
48
49
|
oidc_domain_attestation: 84532,
|
|
49
50
|
giwa_attestation: 91342,
|
|
50
51
|
dojang_playground: 91342,
|
|
52
|
+
human_passport_score: 84532,
|
|
51
53
|
},
|
|
52
54
|
local: {
|
|
53
55
|
coinbase_attestation: 84532,
|
|
@@ -55,6 +57,7 @@ const VERIFICATION_CHAINS = {
|
|
|
55
57
|
oidc_domain_attestation: 84532,
|
|
56
58
|
giwa_attestation: 91342,
|
|
57
59
|
dojang_playground: 91342,
|
|
60
|
+
human_passport_score: 84532,
|
|
58
61
|
},
|
|
59
62
|
};
|
|
60
63
|
/**
|
|
@@ -156,6 +159,14 @@ const CIRCUIT_METADATA = {
|
|
|
156
159
|
publicInputsCount: 160,
|
|
157
160
|
publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'scope', 'nullifier'],
|
|
158
161
|
},
|
|
162
|
+
// human-passport-score/src/main.nr: GIWA's six `pub [u8; 32]`, then
|
|
163
|
+
// min_score (u32, score x 10^4), scorer_id and now (u64) = 195 fields.
|
|
164
|
+
human_passport_score: {
|
|
165
|
+
name: 'Human Passport',
|
|
166
|
+
description: 'Prove a Human Passport score at or above a threshold, optionally authorizing one EIP-712 action',
|
|
167
|
+
publicInputsCount: 195,
|
|
168
|
+
publicInputNames: ['signal_hash', 'domain_separator', 'action_hash', 'signer_list_merkle_root', 'scope', 'nullifier', 'min_score', 'scorer_id', 'now'],
|
|
169
|
+
},
|
|
159
170
|
};
|
|
160
171
|
/**
|
|
161
172
|
* Default proof request expiration time in milliseconds.
|
|
@@ -652,6 +663,21 @@ function validateProofRequest(request) {
|
|
|
652
663
|
return { valid: false, error: 'isIncluded is required and must be a boolean' };
|
|
653
664
|
}
|
|
654
665
|
}
|
|
666
|
+
else if (request.circuit === 'human_passport_score') {
|
|
667
|
+
const inputs = request.inputs;
|
|
668
|
+
if (inputs.userAddress && !/^0x[a-fA-F0-9]{40}$/.test(inputs.userAddress)) {
|
|
669
|
+
return { valid: false, error: 'Invalid userAddress format' };
|
|
670
|
+
}
|
|
671
|
+
if (!inputs.scope || typeof inputs.scope !== 'string' || inputs.scope.trim() === '') {
|
|
672
|
+
return { valid: false, error: 'scope is required and must be a non-empty string' };
|
|
673
|
+
}
|
|
674
|
+
try {
|
|
675
|
+
humanPassportScoreUnits(inputs.minScore);
|
|
676
|
+
}
|
|
677
|
+
catch (error) {
|
|
678
|
+
return { valid: false, error: error instanceof Error ? error.message : String(error) };
|
|
679
|
+
}
|
|
680
|
+
}
|
|
655
681
|
else if (request.circuit === 'oidc_domain_attestation') {
|
|
656
682
|
const inputs = request.inputs;
|
|
657
683
|
if (!inputs.domain || typeof inputs.domain !== 'string' || inputs.domain.trim() === '') {
|
|
@@ -3940,7 +3966,7 @@ async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
|
|
|
3940
3966
|
// their trust anchor as a public input the prover chooses. For OIDC that is
|
|
3941
3967
|
// the RSA key -- see core's oidcProviderKeys. Checked here so a dApp that
|
|
3942
3968
|
// verifies off-chain gets the same answer as one that verifies on-chain.
|
|
3943
|
-
const issuer = await checkProofIssuer(circuit, publicInputs, { request: options.request, countryCondition: options.countryCondition });
|
|
3969
|
+
const issuer = await checkProofIssuer(circuit, publicInputs, { request: options.request, countryCondition: options.countryCondition, minScore: options.minScore });
|
|
3944
3970
|
if (!issuer.ok) {
|
|
3945
3971
|
return { valid: false, error: issuer.error };
|
|
3946
3972
|
}
|
|
@@ -4106,6 +4132,12 @@ class ProofportSDK {
|
|
|
4106
4132
|
* them. Bounded like {@link relayRequests}.
|
|
4107
4133
|
*/
|
|
4108
4134
|
this.countryRequests = new Map();
|
|
4135
|
+
/**
|
|
4136
|
+
* requestId -> the score threshold of the Human Passport relay requests this
|
|
4137
|
+
* instance created, so verifyResponse* can hold the proof's min_score to it.
|
|
4138
|
+
* Bounded like {@link relayRequests}.
|
|
4139
|
+
*/
|
|
4140
|
+
this.passportRequests = new Map();
|
|
4109
4141
|
this.signer = null;
|
|
4110
4142
|
this.socket = null;
|
|
4111
4143
|
/**
|
|
@@ -4298,6 +4330,16 @@ class ProofportSDK {
|
|
|
4298
4330
|
switch (builder) {
|
|
4299
4331
|
case 'country':
|
|
4300
4332
|
return this.createCoinbaseCountryRequest(inputs, options);
|
|
4333
|
+
case 'passport': {
|
|
4334
|
+
const minScore = inputs.minScore;
|
|
4335
|
+
try {
|
|
4336
|
+
humanPassportScoreUnits(minScore);
|
|
4337
|
+
}
|
|
4338
|
+
catch (error) {
|
|
4339
|
+
throw new Error(`${error instanceof Error ? error.message : String(error)} (circuit: ${circuit})`);
|
|
4340
|
+
}
|
|
4341
|
+
return this.createScopedRequest(circuit, inputs, options);
|
|
4342
|
+
}
|
|
4301
4343
|
case 'scoped':
|
|
4302
4344
|
return this.createScopedRequest(circuit, inputs, options);
|
|
4303
4345
|
}
|
|
@@ -4647,6 +4689,7 @@ class ProofportSDK {
|
|
|
4647
4689
|
request: options.request,
|
|
4648
4690
|
signerVariant: options.signerVariant,
|
|
4649
4691
|
countryCondition: options.countryCondition,
|
|
4692
|
+
minScore: options.minScore,
|
|
4650
4693
|
});
|
|
4651
4694
|
}
|
|
4652
4695
|
/**
|
|
@@ -4712,6 +4755,42 @@ class ProofportSDK {
|
|
|
4712
4755
|
'isIncluded } } -- the list and direction of the request you created.',
|
|
4713
4756
|
};
|
|
4714
4757
|
}
|
|
4758
|
+
/**
|
|
4759
|
+
* The score threshold a `human_passport_score` response must carry: the one
|
|
4760
|
+
* the caller passed, else the relay request this instance created under the
|
|
4761
|
+
* response's requestId, else the deep-link request still pending under it.
|
|
4762
|
+
* `{ error }` when there is none: the proof's threshold is the prover's
|
|
4763
|
+
* choice, so a response this SDK cannot place is refused rather than
|
|
4764
|
+
* accepted for whatever threshold it carries.
|
|
4765
|
+
*/
|
|
4766
|
+
passportMinScoreFor(response, explicit) {
|
|
4767
|
+
if (explicit !== undefined)
|
|
4768
|
+
return { minScore: explicit };
|
|
4769
|
+
const remembered = this.passportRequests.get(response.requestId);
|
|
4770
|
+
if (remembered !== undefined)
|
|
4771
|
+
return { minScore: remembered };
|
|
4772
|
+
const pending = this.pendingRequests.get(response.requestId);
|
|
4773
|
+
const inputs = pending?.circuit === 'human_passport_score' ? pending.inputs : undefined;
|
|
4774
|
+
if (inputs && typeof inputs.minScore === 'number')
|
|
4775
|
+
return { minScore: inputs.minScore };
|
|
4776
|
+
return {
|
|
4777
|
+
error: `No Human Passport request ${JSON.stringify(response.requestId)} was created by this SDK instance, so the ` +
|
|
4778
|
+
"proof's score threshold cannot be checked against what was asked. Pass { minScore } -- the threshold of " +
|
|
4779
|
+
'the request you created.',
|
|
4780
|
+
};
|
|
4781
|
+
}
|
|
4782
|
+
/** @internal Remember a Human Passport relay request's threshold for verifyResponse*. */
|
|
4783
|
+
rememberPassportRequest(requestId, inputs) {
|
|
4784
|
+
const minScore = inputs?.minScore;
|
|
4785
|
+
if (typeof requestId !== 'string' || typeof minScore !== 'number')
|
|
4786
|
+
return;
|
|
4787
|
+
this.passportRequests.delete(requestId);
|
|
4788
|
+
this.passportRequests.set(requestId, minScore);
|
|
4789
|
+
while (this.passportRequests.size > ProofportSDK.MAX_REMEMBERED_RELAY_REQUESTS) {
|
|
4790
|
+
const oldest = this.passportRequests.keys().next().value;
|
|
4791
|
+
this.passportRequests.delete(oldest);
|
|
4792
|
+
}
|
|
4793
|
+
}
|
|
4715
4794
|
/** @internal Remember a Coinbase Country relay request's list and direction for verifyResponse*. */
|
|
4716
4795
|
rememberCountryRequest(requestId, inputs) {
|
|
4717
4796
|
const i = inputs;
|
|
@@ -4800,6 +4879,13 @@ class ProofportSDK {
|
|
|
4800
4879
|
return { valid: false, error: found.error };
|
|
4801
4880
|
countryCondition = found.condition;
|
|
4802
4881
|
}
|
|
4882
|
+
let minScore;
|
|
4883
|
+
if (response.circuit === 'human_passport_score') {
|
|
4884
|
+
const found = this.passportMinScoreFor(response, options.minScore);
|
|
4885
|
+
if ('error' in found)
|
|
4886
|
+
return { valid: false, error: found.error };
|
|
4887
|
+
minScore = found.minScore;
|
|
4888
|
+
}
|
|
4803
4889
|
const parsedProof = parseProofForOnChain(response.proof, response.publicInputs, response.publicInputs.length);
|
|
4804
4890
|
// The response's verifierAddress and chainId are a claim to check, never
|
|
4805
4891
|
// the contract to call: whoever wrote the response would otherwise pick
|
|
@@ -4808,7 +4894,7 @@ class ProofportSDK {
|
|
|
4808
4894
|
return verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, this.verifierTarget(response.circuit), {
|
|
4809
4895
|
verifierAddress: response.verifierAddress,
|
|
4810
4896
|
chainId: response.chainId,
|
|
4811
|
-
}, { request, signerVariant: response.signerVariant, countryCondition });
|
|
4897
|
+
}, { request, signerVariant: response.signerVariant, countryCondition, minScore });
|
|
4812
4898
|
}
|
|
4813
4899
|
/**
|
|
4814
4900
|
* Verifies a proof response off-chain, against the circuit's verification key.
|
|
@@ -4852,7 +4938,14 @@ class ProofportSDK {
|
|
|
4852
4938
|
return { valid: false, error: found.error };
|
|
4853
4939
|
countryCondition = found.condition;
|
|
4854
4940
|
}
|
|
4855
|
-
|
|
4941
|
+
let minScore;
|
|
4942
|
+
if (response.circuit === 'human_passport_score') {
|
|
4943
|
+
const found = this.passportMinScoreFor(response, options?.minScore);
|
|
4944
|
+
if ('error' in found)
|
|
4945
|
+
return { valid: false, error: found.error };
|
|
4946
|
+
minScore = found.minScore;
|
|
4947
|
+
}
|
|
4948
|
+
return verifyProofOffChain(response.circuit, response.proof, response.publicInputs, { ...options, request, countryCondition, minScore, signerVariant: response.signerVariant });
|
|
4856
4949
|
}
|
|
4857
4950
|
// ============ Utility Methods ============
|
|
4858
4951
|
/**
|
|
@@ -5230,6 +5323,15 @@ class ProofportSDK {
|
|
|
5230
5323
|
}
|
|
5231
5324
|
}
|
|
5232
5325
|
}
|
|
5326
|
+
// A Human Passport threshold the circuit cannot carry is refused here too.
|
|
5327
|
+
if (circuit === 'human_passport_score') {
|
|
5328
|
+
try {
|
|
5329
|
+
humanPassportScoreUnits(inputs.minScore);
|
|
5330
|
+
}
|
|
5331
|
+
catch (error) {
|
|
5332
|
+
throw new Error(`${error instanceof Error ? error.message : String(error)} (circuit: ${circuit})`);
|
|
5333
|
+
}
|
|
5334
|
+
}
|
|
5233
5335
|
// A Coinbase Country list the circuit would refuse is refused here, before a
|
|
5234
5336
|
// challenge is burned, as createProofRequest does.
|
|
5235
5337
|
if (circuit === 'coinbase_country_attestation') {
|
|
@@ -5297,6 +5399,8 @@ class ProofportSDK {
|
|
|
5297
5399
|
this.rememberRelayRequest(created.requestId, scope);
|
|
5298
5400
|
if (circuit === 'coinbase_country_attestation')
|
|
5299
5401
|
this.rememberCountryRequest(created.requestId, inputs);
|
|
5402
|
+
if (circuit === 'human_passport_score')
|
|
5403
|
+
this.rememberPassportRequest(created.requestId, inputs);
|
|
5300
5404
|
return created;
|
|
5301
5405
|
}
|
|
5302
5406
|
/**
|
|
@@ -5593,6 +5697,8 @@ ProofportSDK.REQUEST_BUILDERS = {
|
|
|
5593
5697
|
oidc_domain_attestation: 'scoped',
|
|
5594
5698
|
giwa_attestation: 'scoped',
|
|
5595
5699
|
dojang_playground: 'scoped',
|
|
5700
|
+
// Scoped, plus the score threshold the proof must carry.
|
|
5701
|
+
human_passport_score: 'passport',
|
|
5596
5702
|
};
|
|
5597
5703
|
|
|
5598
5704
|
export { DEFAULT_RELAY_WAIT_MS, ProofportSDK, RELAY_TERMINAL_STATUSES, ProofportSDK as default, isTerminalRelayStatus, verifyProofOffChain };
|