@zkproofport-app/sdk 0.5.0-beta.0 → 0.5.0-beta.2
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 +22 -15
- package/dist/ProofportSDK.d.ts +29 -8
- package/dist/constants.d.ts +43 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +177 -39
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +183 -37
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +177 -39
- package/dist/index.mjs.map +1 -1
- package/dist/offChainVerifier.d.ts +4 -0
- package/dist/types.d.ts +8 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25,6 +25,49 @@ const RELAY_URLS = {
|
|
|
25
25
|
staging: 'https://stg-relay.zkproofport.app',
|
|
26
26
|
local: 'http://localhost:4001',
|
|
27
27
|
};
|
|
28
|
+
/**
|
|
29
|
+
* The chain each circuit is verified on, per environment. Complete: a circuit
|
|
30
|
+
* added to the SDK is a compile error here until somebody names its chain.
|
|
31
|
+
*
|
|
32
|
+
* Mirrors the mobile app's `CIRCUIT_NETWORKS` (proofport-app
|
|
33
|
+
* src/config/contracts.ts), because a proof is checked where the app said its
|
|
34
|
+
* verifier is: Base for the Coinbase and OIDC circuits, GIWA Sepolia for GIWA
|
|
35
|
+
* and Dojang (testnet-only), Base Sepolia for Korea Mobile ID (testnet-only).
|
|
36
|
+
* The ADDRESS on that chain always comes from core's pinned table, never from
|
|
37
|
+
* a proof response.
|
|
38
|
+
*/
|
|
39
|
+
const VERIFICATION_CHAINS = {
|
|
40
|
+
production: {
|
|
41
|
+
coinbase_attestation: 8453,
|
|
42
|
+
coinbase_country_attestation: 8453,
|
|
43
|
+
oidc_domain_attestation: 8453,
|
|
44
|
+
giwa_attestation: 91342,
|
|
45
|
+
dojang_playground: 91342,
|
|
46
|
+
mdl_kr_ownership: 84532,
|
|
47
|
+
mdl_kr_age: 84532,
|
|
48
|
+
mdl_kr_region: 84532,
|
|
49
|
+
},
|
|
50
|
+
staging: {
|
|
51
|
+
coinbase_attestation: 84532,
|
|
52
|
+
coinbase_country_attestation: 84532,
|
|
53
|
+
oidc_domain_attestation: 84532,
|
|
54
|
+
giwa_attestation: 91342,
|
|
55
|
+
dojang_playground: 91342,
|
|
56
|
+
mdl_kr_ownership: 84532,
|
|
57
|
+
mdl_kr_age: 84532,
|
|
58
|
+
mdl_kr_region: 84532,
|
|
59
|
+
},
|
|
60
|
+
local: {
|
|
61
|
+
coinbase_attestation: 84532,
|
|
62
|
+
coinbase_country_attestation: 84532,
|
|
63
|
+
oidc_domain_attestation: 84532,
|
|
64
|
+
giwa_attestation: 91342,
|
|
65
|
+
dojang_playground: 91342,
|
|
66
|
+
mdl_kr_ownership: 84532,
|
|
67
|
+
mdl_kr_age: 84532,
|
|
68
|
+
mdl_kr_region: 84532,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
28
71
|
/**
|
|
29
72
|
* Default deep link URL scheme for ZKProofport mobile app.
|
|
30
73
|
* Used to construct deep link URLs that open the mobile app.
|
|
@@ -1098,6 +1141,10 @@ async function fetchVerificationKey(circuit, timeoutMs) {
|
|
|
1098
1141
|
* Needs no setup from the caller: the verifier ships with this SDK and is
|
|
1099
1142
|
* loaded on first use.
|
|
1100
1143
|
*
|
|
1144
|
+
* For `oidc_domain_attestation` it first checks the proof's RSA key against the
|
|
1145
|
+
* provider's published JWKS (core's `checkOidcProviderKey`); a key the provider
|
|
1146
|
+
* does not publish, or a JWKS that cannot be fetched, is `{ valid: false }`.
|
|
1147
|
+
*
|
|
1101
1148
|
* @param circuit - Canonical circuit identifier
|
|
1102
1149
|
* @param proof - Proof bytes as hex, WITHOUT public inputs (as the relay sends it)
|
|
1103
1150
|
* @param publicInputs - Public inputs as hex strings, in circuit order
|
|
@@ -1116,6 +1163,18 @@ async function fetchVerificationKey(circuit, timeoutMs) {
|
|
|
1116
1163
|
*/
|
|
1117
1164
|
async function verifyProofOffChain(circuit, proof, publicInputs, options = {}) {
|
|
1118
1165
|
const timeoutMs = options.timeoutMs ?? 30000;
|
|
1166
|
+
if (!circuits.isCircuitId(circuit)) {
|
|
1167
|
+
return { valid: false, error: `Unknown circuit '${circuit}'. Known: ${circuits.ALL_CIRCUIT_IDS.join(', ')}.` };
|
|
1168
|
+
}
|
|
1169
|
+
// Before Barretenberg, and for the same reason as on-chain: a proof can be
|
|
1170
|
+
// mathematically valid and still mean nothing, because some circuits take
|
|
1171
|
+
// their trust anchor as a public input the prover chooses. For OIDC that is
|
|
1172
|
+
// the RSA key -- see core's oidcProviderKeys. Checked here so a dApp that
|
|
1173
|
+
// verifies off-chain gets the same answer as one that verifies on-chain.
|
|
1174
|
+
const issuer = await core.checkProofIssuer(circuit, publicInputs);
|
|
1175
|
+
if (!issuer.ok) {
|
|
1176
|
+
return { valid: false, error: issuer.error };
|
|
1177
|
+
}
|
|
1119
1178
|
// A REQUIRED dependency, loaded lazily.
|
|
1120
1179
|
//
|
|
1121
1180
|
// It was briefly an optional peer dependency, on the reasoning that the WASM
|
|
@@ -1256,22 +1315,32 @@ class ProofportSDK {
|
|
|
1256
1315
|
this.pendingRequests = new Map();
|
|
1257
1316
|
this.signer = null;
|
|
1258
1317
|
this.socket = null;
|
|
1318
|
+
/**
|
|
1319
|
+
* Set by {@link ProofportSDK.create} from its environment preset. It decides
|
|
1320
|
+
* which chain a proof is verified on when the dApp configured no verifier
|
|
1321
|
+
* for the circuit; a custom-config SDK has none and must configure one.
|
|
1322
|
+
*/
|
|
1323
|
+
this.environment = null;
|
|
1259
1324
|
this.config = {
|
|
1260
1325
|
scheme: config.scheme || DEFAULT_SCHEME,
|
|
1261
1326
|
verifiers: config.verifiers || {},
|
|
1262
1327
|
};
|
|
1263
1328
|
this.relayUrl = config.relayUrl || '';
|
|
1329
|
+
if (config.environment !== undefined) {
|
|
1330
|
+
if (!Object.prototype.hasOwnProperty.call(VERIFICATION_CHAINS, config.environment)) {
|
|
1331
|
+
throw new Error(`Unknown environment '${config.environment}'. Known: ${Object.keys(VERIFICATION_CHAINS).join(', ')}.`);
|
|
1332
|
+
}
|
|
1333
|
+
this.environment = config.environment;
|
|
1334
|
+
}
|
|
1264
1335
|
}
|
|
1265
1336
|
// ============ Request Creation ============
|
|
1266
1337
|
/**
|
|
1267
1338
|
* @internal
|
|
1268
|
-
* Creates a
|
|
1339
|
+
* Creates a proof request for a circuit whose dapp-side input is a scope
|
|
1340
|
+
* (Coinbase KYC, OIDC domain, GIWA, Dojang), keeping that circuit's id.
|
|
1269
1341
|
*
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
* while maintaining privacy through zero-knowledge proofs.
|
|
1273
|
-
*
|
|
1274
|
-
* @param inputs - Circuit inputs for Coinbase KYC
|
|
1342
|
+
* @param circuit - The circuit requested; it is the request's circuit
|
|
1343
|
+
* @param inputs - Circuit inputs; `scope` is required (and `domain` for OIDC)
|
|
1275
1344
|
* @param inputs.scope - Application-specific scope (e.g., domain name)
|
|
1276
1345
|
* @param options - Request configuration options
|
|
1277
1346
|
|
|
@@ -1286,7 +1355,7 @@ class ProofportSDK {
|
|
|
1286
1355
|
*
|
|
1287
1356
|
* @example
|
|
1288
1357
|
* ```typescript
|
|
1289
|
-
* const request = sdk.
|
|
1358
|
+
* const request = sdk.createScopedRequest('coinbase_attestation', {
|
|
1290
1359
|
* scope: 'myapp.com'
|
|
1291
1360
|
* }, {
|
|
1292
1361
|
* dappName: 'My DApp',
|
|
@@ -1296,13 +1365,34 @@ class ProofportSDK {
|
|
|
1296
1365
|
* const deepLink = sdk.getDeepLinkUrl(request);
|
|
1297
1366
|
* ```
|
|
1298
1367
|
*/
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1368
|
+
createScopedRequest(circuit, inputs, options = {}) {
|
|
1369
|
+
const scope = inputs.scope;
|
|
1370
|
+
if (typeof scope !== 'string' || scope.trim() === '') {
|
|
1371
|
+
throw new Error(`scope is required for ${circuit} circuit`);
|
|
1372
|
+
}
|
|
1373
|
+
if (circuit === 'oidc_domain_attestation') {
|
|
1374
|
+
const domain = inputs.domain;
|
|
1375
|
+
if (typeof domain !== 'string' || domain.trim() === '') {
|
|
1376
|
+
throw new Error('domain is required for oidc_domain_attestation circuit');
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
const action = inputs.action;
|
|
1380
|
+
const binding = circuits.circuitActionBinding(circuit);
|
|
1381
|
+
if (binding === 'none' && action !== undefined) {
|
|
1382
|
+
throw new Error(`${circuit} has no action inputs, so an action sent with it would not be proved.`);
|
|
1383
|
+
}
|
|
1384
|
+
if (binding === 'required' || (binding === 'optional' && action !== undefined)) {
|
|
1385
|
+
const actionError = typedAction.validateTypedAction(action);
|
|
1386
|
+
if (actionError)
|
|
1387
|
+
throw new Error(`${actionError} (circuit: ${circuit})`);
|
|
1302
1388
|
}
|
|
1303
1389
|
const request = {
|
|
1304
1390
|
requestId: generateRequestId(),
|
|
1305
|
-
circuit
|
|
1391
|
+
// The circuit asked for, always. This used to be the literal
|
|
1392
|
+
// 'coinbase_attestation', and every circuit that was not country or mDL
|
|
1393
|
+
// was routed here -- a GIWA, Dojang or OIDC request silently became a
|
|
1394
|
+
// Coinbase KYC request.
|
|
1395
|
+
circuit,
|
|
1306
1396
|
inputs,
|
|
1307
1397
|
message: options.message,
|
|
1308
1398
|
dappName: options.dappName,
|
|
@@ -1399,16 +1489,17 @@ class ProofportSDK {
|
|
|
1399
1489
|
* ```
|
|
1400
1490
|
*/
|
|
1401
1491
|
createProofRequest(circuit, inputs, options = {}) {
|
|
1402
|
-
if (circuit
|
|
1403
|
-
|
|
1492
|
+
if (!circuits.isCircuitId(circuit)) {
|
|
1493
|
+
throw new Error(`Unknown circuit '${circuit}'. Known: ${circuits.ALL_CIRCUIT_IDS.join(', ')}.`);
|
|
1404
1494
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1495
|
+
const builder = ProofportSDK.REQUEST_BUILDERS[circuit];
|
|
1496
|
+
switch (builder) {
|
|
1497
|
+
case 'country':
|
|
1498
|
+
return this.createCoinbaseCountryRequest(inputs, options);
|
|
1499
|
+
case 'mdl':
|
|
1500
|
+
return this.createMdlKrRequest(circuit, inputs, options);
|
|
1501
|
+
case 'scoped':
|
|
1502
|
+
return this.createScopedRequest(circuit, inputs, options);
|
|
1412
1503
|
}
|
|
1413
1504
|
}
|
|
1414
1505
|
/**
|
|
@@ -1785,8 +1876,24 @@ class ProofportSDK {
|
|
|
1785
1876
|
*/
|
|
1786
1877
|
async verifyOnChain(circuit, proof, publicInputs, providerOrSigner) {
|
|
1787
1878
|
const parsedProof = core.parseProofForOnChain(proof, publicInputs, publicInputs.length);
|
|
1788
|
-
|
|
1789
|
-
|
|
1879
|
+
return core.verifyProofOnChain(circuit, parsedProof, providerOrSigner, this.verifierTarget(circuit));
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* The verifier for a circuit: the one the dApp configured, otherwise the
|
|
1883
|
+
* pinned deployment on the chain this SDK's environment verifies that
|
|
1884
|
+
* circuit on. `undefined` when neither exists, which core reports as an
|
|
1885
|
+
* error. Never anything a proof response said.
|
|
1886
|
+
*/
|
|
1887
|
+
verifierTarget(circuit) {
|
|
1888
|
+
const configured = this.config.verifiers[circuit];
|
|
1889
|
+
if (configured)
|
|
1890
|
+
return configured;
|
|
1891
|
+
if (this.environment === null)
|
|
1892
|
+
return undefined;
|
|
1893
|
+
const chains = VERIFICATION_CHAINS[this.environment];
|
|
1894
|
+
if (!Object.prototype.hasOwnProperty.call(chains, circuit))
|
|
1895
|
+
return undefined;
|
|
1896
|
+
return { chainId: chains[circuit] };
|
|
1790
1897
|
}
|
|
1791
1898
|
/**
|
|
1792
1899
|
* Verifies a proof response on-chain using the deployed verifier contract.
|
|
@@ -1827,12 +1934,14 @@ class ProofportSDK {
|
|
|
1827
1934
|
return { valid: false, error: 'Invalid or incomplete response' };
|
|
1828
1935
|
}
|
|
1829
1936
|
const parsedProof = core.parseProofForOnChain(response.proof, response.publicInputs, response.publicInputs.length);
|
|
1830
|
-
|
|
1831
|
-
|
|
1937
|
+
// The response's verifierAddress and chainId are a claim to check, never
|
|
1938
|
+
// the contract to call: whoever wrote the response would otherwise pick
|
|
1939
|
+
// the judge. A claim that differs from the pinned or configured verifier
|
|
1940
|
+
// is refused.
|
|
1941
|
+
return core.verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, this.verifierTarget(response.circuit), {
|
|
1832
1942
|
verifierAddress: response.verifierAddress,
|
|
1833
1943
|
chainId: response.chainId,
|
|
1834
|
-
};
|
|
1835
|
-
return core.verifyProofOnChain(response.circuit, parsedProof, providerOrSigner, customVerifier, responseVerifier);
|
|
1944
|
+
});
|
|
1836
1945
|
}
|
|
1837
1946
|
/**
|
|
1838
1947
|
* Verifies a proof response off-chain, against the circuit's verification key.
|
|
@@ -1883,8 +1992,17 @@ class ProofportSDK {
|
|
|
1883
1992
|
* ```
|
|
1884
1993
|
*/
|
|
1885
1994
|
getVerifierAddress(circuit) {
|
|
1886
|
-
|
|
1887
|
-
|
|
1995
|
+
return this.requireVerifier(circuit).address;
|
|
1996
|
+
}
|
|
1997
|
+
/** The configured or pinned verifier, or an error saying why there is none. */
|
|
1998
|
+
requireVerifier(circuit) {
|
|
1999
|
+
const target = this.verifierTarget(circuit);
|
|
2000
|
+
if (!target) {
|
|
2001
|
+
throw new Error(`No verifier configured for circuit '${circuit}'. Configure one in the SDK's verifiers option, or create the SDK with ProofportSDK.create() to use the pinned deployment.`);
|
|
2002
|
+
}
|
|
2003
|
+
if ('address' in target)
|
|
2004
|
+
return { address: target.address, chainId: target.chainId };
|
|
2005
|
+
return { address: core.getPinnedVerifier(circuit, target.chainId).address, chainId: target.chainId };
|
|
1888
2006
|
}
|
|
1889
2007
|
/**
|
|
1890
2008
|
* Gets the blockchain chain ID where the verifier contract is deployed.
|
|
@@ -1904,8 +2022,7 @@ class ProofportSDK {
|
|
|
1904
2022
|
* ```
|
|
1905
2023
|
*/
|
|
1906
2024
|
getVerifierChainId(circuit) {
|
|
1907
|
-
|
|
1908
|
-
return core.getVerifierChainId(circuit, customVerifier);
|
|
2025
|
+
return this.requireVerifier(circuit).chainId;
|
|
1909
2026
|
}
|
|
1910
2027
|
/**
|
|
1911
2028
|
* Gets metadata for a specific circuit type.
|
|
@@ -2052,17 +2169,20 @@ class ProofportSDK {
|
|
|
2052
2169
|
*/
|
|
2053
2170
|
static create(envOrConfig) {
|
|
2054
2171
|
if (typeof envOrConfig === 'undefined') {
|
|
2055
|
-
return
|
|
2172
|
+
return ProofportSDK.forEnvironment('production');
|
|
2056
2173
|
}
|
|
2057
2174
|
if (typeof envOrConfig === 'string') {
|
|
2058
|
-
|
|
2059
|
-
if (!relayUrl) {
|
|
2060
|
-
throw new Error(`Unknown environment: ${envOrConfig}. Use 'production', 'staging', or 'local'.`);
|
|
2061
|
-
}
|
|
2062
|
-
return new ProofportSDK({ relayUrl });
|
|
2175
|
+
return ProofportSDK.forEnvironment(envOrConfig);
|
|
2063
2176
|
}
|
|
2064
2177
|
return new ProofportSDK(envOrConfig);
|
|
2065
2178
|
}
|
|
2179
|
+
/** @internal An SDK on an environment preset's relay, verifying on that environment's chains. */
|
|
2180
|
+
static forEnvironment(env) {
|
|
2181
|
+
if (!Object.prototype.hasOwnProperty.call(RELAY_URLS, env)) {
|
|
2182
|
+
throw new Error(`Unknown environment: ${env}. Use 'production', 'staging', or 'local'.`);
|
|
2183
|
+
}
|
|
2184
|
+
return new ProofportSDK({ relayUrl: RELAY_URLS[env], environment: env });
|
|
2185
|
+
}
|
|
2066
2186
|
/**
|
|
2067
2187
|
* Detects if the code is running on a mobile device.
|
|
2068
2188
|
*
|
|
@@ -2196,7 +2316,10 @@ class ProofportSDK {
|
|
|
2196
2316
|
// calling createRelayRequest() for it with no signer got no local error and
|
|
2197
2317
|
// a relay 401 two round trips later.
|
|
2198
2318
|
static needsWalletSignature(circuit) {
|
|
2199
|
-
|
|
2319
|
+
if (!circuits.isCircuitId(circuit)) {
|
|
2320
|
+
throw new Error(`Unknown circuit '${circuit}'. Expected: ${circuits.ALL_CIRCUIT_IDS.join(', ')}`);
|
|
2321
|
+
}
|
|
2322
|
+
return circuits.CIRCUIT_NEEDS_WALLET_SIGNATURE[circuit];
|
|
2200
2323
|
}
|
|
2201
2324
|
async createRelayRequest(circuit, inputs, options = {}) {
|
|
2202
2325
|
if (!this.relayUrl) {
|
|
@@ -2570,6 +2693,21 @@ class ProofportSDK {
|
|
|
2570
2693
|
return core.extractDomainFromPublicInputs(publicInputs, circuit);
|
|
2571
2694
|
}
|
|
2572
2695
|
}
|
|
2696
|
+
/**
|
|
2697
|
+
* How each circuit's request is built and checked. Keyed by circuit id and
|
|
2698
|
+
* exhaustive over it, so a new circuit is a compile error here instead of
|
|
2699
|
+
* falling through to another circuit's builder.
|
|
2700
|
+
*/
|
|
2701
|
+
ProofportSDK.REQUEST_BUILDERS = {
|
|
2702
|
+
coinbase_attestation: 'scoped',
|
|
2703
|
+
coinbase_country_attestation: 'country',
|
|
2704
|
+
oidc_domain_attestation: 'scoped',
|
|
2705
|
+
giwa_attestation: 'scoped',
|
|
2706
|
+
dojang_playground: 'scoped',
|
|
2707
|
+
mdl_kr_ownership: 'mdl',
|
|
2708
|
+
mdl_kr_age: 'mdl',
|
|
2709
|
+
mdl_kr_region: 'mdl',
|
|
2710
|
+
};
|
|
2573
2711
|
|
|
2574
2712
|
Object.defineProperty(exports, "COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT", {
|
|
2575
2713
|
enumerable: true,
|
|
@@ -2587,6 +2725,10 @@ Object.defineProperty(exports, "OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT", {
|
|
|
2587
2725
|
enumerable: true,
|
|
2588
2726
|
get: function () { return core.OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT; }
|
|
2589
2727
|
});
|
|
2728
|
+
Object.defineProperty(exports, "PINNED_VERIFIERS", {
|
|
2729
|
+
enumerable: true,
|
|
2730
|
+
get: function () { return core.PINNED_VERIFIERS; }
|
|
2731
|
+
});
|
|
2590
2732
|
Object.defineProperty(exports, "extractDomainFromPublicInputs", {
|
|
2591
2733
|
enumerable: true,
|
|
2592
2734
|
get: function () { return core.extractDomainFromPublicInputs; }
|
|
@@ -2599,6 +2741,10 @@ Object.defineProperty(exports, "extractScopeFromPublicInputs", {
|
|
|
2599
2741
|
enumerable: true,
|
|
2600
2742
|
get: function () { return core.extractScopeFromPublicInputs; }
|
|
2601
2743
|
});
|
|
2744
|
+
Object.defineProperty(exports, "getPinnedVerifier", {
|
|
2745
|
+
enumerable: true,
|
|
2746
|
+
get: function () { return core.getPinnedVerifier; }
|
|
2747
|
+
});
|
|
2602
2748
|
Object.defineProperty(exports, "ALL_CIRCUIT_IDS", {
|
|
2603
2749
|
enumerable: true,
|
|
2604
2750
|
get: function () { return circuits.ALL_CIRCUIT_IDS; }
|