@zkproofport-app/sdk 0.4.3 → 0.5.0-beta.0

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.
@@ -1,236 +1 @@
1
- /**
2
- * Canonical ZKProofport circuit identifiers.
3
- *
4
- * This module is the single source of truth for circuit IDs. Every other layer
5
- * — the mobile app, the demo, the relay, server-side provers — reads its list
6
- * from here instead of keeping a private copy that silently drifts.
7
- *
8
- * It has **no imports and no dependencies**, so it can be pulled in on its own:
9
- *
10
- * ```typescript
11
- * import { CIRCUIT_IDS, isCircuitId } from '@zkproofport-app/sdk/circuits';
12
- * ```
13
- *
14
- * The same names are also re-exported from the package root
15
- * (`@zkproofport-app/sdk`) for callers that already import the SDK.
16
- *
17
- * ## Identifiers are canonical and case-sensitive
18
- *
19
- * Each ID is the circuit's `name` in its `Nargo.toml`, verbatim. The format is
20
- * lowercase with underscores. Hyphenated spellings (`coinbase-kyc`,
21
- * `mdl-kr-age`) are directory or UI route names in other repositories — they
22
- * are **not** circuit IDs, and passing one produces a nullifier mismatch or a
23
- * failed on-chain lookup rather than a clear error.
24
- */
25
- /**
26
- * Whether a circuit is officially supported today or still on the roadmap.
27
- *
28
- * - `supported` — generally available. Safe to build a product on.
29
- * - `planned` — the identifier is reserved and the circuit exists, but it is
30
- * not officially supported yet. Availability, inputs and public-input layout
31
- * may change without a major version bump.
32
- */
33
- export type CircuitSupportStatus = 'supported' | 'experimental' | 'planned';
34
- /**
35
- * Canonical circuit identifiers, keyed by a stable constant name.
36
- *
37
- * Prefer these constants over string literals so a rename is a compile error
38
- * rather than a runtime surprise.
39
- *
40
- * @example
41
- * ```typescript
42
- * import { CIRCUIT_IDS } from '@zkproofport-app/sdk/circuits';
43
- *
44
- * const relay = await sdk.createRelayRequest(CIRCUIT_IDS.COINBASE_ATTESTATION, {
45
- * scope: 'myapp.com',
46
- * });
47
- * ```
48
- */
49
- export declare const CIRCUIT_IDS: Readonly<{
50
- /** Coinbase KYC attestation. Officially supported. */
51
- readonly COINBASE_ATTESTATION: "coinbase_attestation";
52
- /** Coinbase country attestation (inclusion / exclusion). Officially supported. */
53
- readonly COINBASE_COUNTRY_ATTESTATION: "coinbase_country_attestation";
54
- /** OIDC email-domain attestation. Officially supported. */
55
- readonly OIDC_DOMAIN_ATTESTATION: "oidc_domain_attestation";
56
- /** GIWA attestation. Planned — not officially supported yet. */
57
- readonly GIWA_ATTESTATION: "giwa_attestation";
58
- /** Dojang Playground on GIWA Sepolia. Experimental — testnet only. */
59
- readonly DOJANG_PLAYGROUND: "dojang_playground";
60
- /** Korea Mobile ID ownership. Planned — not officially supported yet. */
61
- readonly MDL_KR_OWNERSHIP: "mdl_kr_ownership";
62
- /** Korea Mobile ID age threshold. Planned — not officially supported yet. */
63
- readonly MDL_KR_AGE: "mdl_kr_age";
64
- /** Korea Mobile ID si/do region. Planned — not officially supported yet. */
65
- readonly MDL_KR_REGION: "mdl_kr_region";
66
- }>;
67
- /**
68
- * Union of every canonical circuit identifier.
69
- *
70
- * `CircuitType` (exported from the package root) is an alias of this type — the
71
- * two names refer to the same union, and this module is where it is defined.
72
- */
73
- export type CircuitId = (typeof CIRCUIT_IDS)[keyof typeof CIRCUIT_IDS];
74
- /**
75
- * Support status for every circuit.
76
- *
77
- * The record is exhaustive over {@link CircuitId}: adding an identifier without
78
- * giving it a status is a compile error, so this list cannot drift from
79
- * {@link CIRCUIT_IDS}.
80
- *
81
- * @example
82
- * ```typescript
83
- * import { CIRCUIT_SUPPORT_STATUS } from '@zkproofport-app/sdk/circuits';
84
- *
85
- * CIRCUIT_SUPPORT_STATUS.coinbase_attestation; // 'supported'
86
- * CIRCUIT_SUPPORT_STATUS.mdl_kr_age; // 'planned'
87
- * ```
88
- */
89
- export declare const CIRCUIT_SUPPORT_STATUS: Readonly<Record<CircuitId, CircuitSupportStatus>>;
90
- /**
91
- * Where each circuit's verification key FILE lives inside the
92
- * `zkproofport/circuits` repository, relative to its root.
93
- *
94
- * Off-chain verification needs the verification key and nothing else — no
95
- * circuit bytecode, no witness. The key is public by nature: it is what anyone
96
- * checking a proof must already have, and the Solidity verifiers deployed
97
- * on-chain embed the same key.
98
- *
99
- * NOTE THE TRAILING `/vk` TWICE. In that repository `target/vk` is a DIRECTORY
100
- * holding `vk`, `vk_hash` and `SHA256SUMS`; the key itself is `target/vk/vk`.
101
- * These paths were first copied here from the mobile app, which keeps the
102
- * directory and the filename as two fields and joins them — so taking only the
103
- * directory produced a URL that answers 404, and the first browser to try
104
- * off-chain verification said "Could not fetch the verification key (HTTP 404)".
105
- *
106
- * Exhaustive over {@link CircuitId} on purpose. A new circuit whose key path is
107
- * not listed here fails to compile rather than failing at verification time,
108
- * where the only symptom would be a proof that cannot be checked.
109
- */
110
- export declare const CIRCUIT_VK_PATHS: Readonly<Record<CircuitId, string>>;
111
- /**
112
- * Every canonical circuit identifier, in declaration order.
113
- *
114
- * Includes circuits that are still `planned`. Use {@link SUPPORTED_CIRCUIT_IDS}
115
- * when you only want the ones that are officially supported today.
116
- */
117
- export declare const ALL_CIRCUIT_IDS: readonly CircuitId[];
118
- /**
119
- * Circuits that are officially supported today: the two Coinbase circuits and
120
- * OIDC domain attestation.
121
- *
122
- * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
123
- */
124
- export declare const SUPPORTED_CIRCUIT_IDS: readonly CircuitId[];
125
- /**
126
- * Circuits whose identifiers are reserved but which are not officially
127
- * supported yet: GIWA attestation and the three Korea Mobile ID circuits.
128
- *
129
- * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
130
- */
131
- /**
132
- * Circuits you can prove today, on a testnet, with everything subject to change.
133
- *
134
- * `giwa_attestation` is in this state. Calling it `planned` would be wrong —
135
- * the circuit compiles, the verifier is deployed and a proof verifies against
136
- * it — and calling it `supported` would be worse, because the only deployment
137
- * is a testnet (GIWA Sepolia). Neither existing word was true, so the honest
138
- * move was a third word rather than picking the closer lie.
139
- */
140
- export declare const EXPERIMENTAL_CIRCUIT_IDS: readonly CircuitId[];
141
- export declare const PLANNED_CIRCUIT_IDS: readonly CircuitId[];
142
- /**
143
- * Narrows an unknown value to a canonical circuit identifier.
144
- *
145
- * Returns `false` for hyphenated route names such as `'coinbase-kyc'`, which
146
- * are not circuit IDs.
147
- *
148
- * @example
149
- * ```typescript
150
- * isCircuitId('coinbase_attestation'); // true
151
- * isCircuitId('coinbase-kyc'); // false
152
- * ```
153
- */
154
- export declare function isCircuitId(value: unknown): value is CircuitId;
155
- /**
156
- * Narrows an unknown value to a circuit identifier that is officially supported
157
- * today. Planned circuits return `false`.
158
- *
159
- * @example
160
- * ```typescript
161
- * isSupportedCircuitId('oidc_domain_attestation'); // true
162
- * isSupportedCircuitId('mdl_kr_age'); // false — planned
163
- * ```
164
- */
165
- export declare function isSupportedCircuitId(value: unknown): value is CircuitId;
166
- /**
167
- * Returns the support status of a circuit.
168
- *
169
- * @param circuit - A canonical circuit identifier.
170
- * @throws Error when the value is not a canonical circuit identifier.
171
- *
172
- * @example
173
- * ```typescript
174
- * getCircuitSupportStatus('giwa_attestation'); // 'planned'
175
- * ```
176
- */
177
- export declare function getCircuitSupportStatus(circuit: CircuitId): CircuitSupportStatus;
178
- /**
179
- * Whether a circuit's relay request must carry a wallet signature.
180
- *
181
- * The SDK checks this to fail fast — "Signer not set" locally beats a 401 from
182
- * the relay two round trips later, with nothing saying which circuit needed
183
- * what. The relay declares its OWN copy on purpose and does not import this
184
- * one: it is a security boundary, and an auth policy that a published package
185
- * can change is not a policy. A test in the relay asserts the two agree.
186
- *
187
- * `satisfies` and not an annotation, so a circuit added above is a compile
188
- * error here until somebody decides which it is.
189
- */
190
- /**
191
- * Whether a circuit's proof can bind an EIP-712 action, and whether it must.
192
- *
193
- * ONE TABLE, because the answer was becoming a chain of `circuit === '...'`
194
- * tests. It was asked in the deep-link validator and again in
195
- * `createRelayRequest`, both spelling out one circuit id, and a second
196
- * action-capable circuit would have made each of them a two-branch chain that
197
- * ends on whatever the last test happens to be.
198
- *
199
- * 'required' the circuit proves nothing without an action -- the wallet
200
- * signs the typed data and there is no other message.
201
- * 'optional' the circuit signs the action when one is supplied and
202
- * personal_signs its signal hash when one is not. The circuit
203
- * itself branches; see giwa-attestation/src/main.nr.
204
- * 'none' the circuit has no action inputs. An action sent anyway is a
205
- * caller misunderstanding, and is refused rather than dropped:
206
- * silently ignoring it would let a dapp believe a proof
207
- * authorized something it never mentioned.
208
- */
209
- export type CircuitActionBinding = 'none' | 'required' | 'optional';
210
- export declare const CIRCUIT_ACTION_BINDING: {
211
- coinbase_attestation: "none";
212
- coinbase_country_attestation: "none";
213
- oidc_domain_attestation: "none";
214
- giwa_attestation: "optional";
215
- dojang_playground: "optional";
216
- mdl_kr_ownership: "none";
217
- mdl_kr_age: "none";
218
- mdl_kr_region: "none";
219
- };
220
- /**
221
- * How this circuit treats an action, or an error naming the id that is not one.
222
- *
223
- * No default: a circuit nobody has classified must not inherit 'none', which
224
- * would silently drop an action a dapp meant to bind.
225
- */
226
- export declare function circuitActionBinding(circuit: string): CircuitActionBinding;
227
- export declare const CIRCUIT_NEEDS_WALLET_SIGNATURE: {
228
- coinbase_attestation: true;
229
- coinbase_country_attestation: true;
230
- oidc_domain_attestation: false;
231
- mdl_kr_ownership: false;
232
- mdl_kr_age: false;
233
- mdl_kr_region: false;
234
- giwa_attestation: true;
235
- dojang_playground: true;
236
- };
1
+ export * from '@zkproofport-app/core/circuits';
@@ -1,251 +1,2 @@
1
- /**
2
- * Canonical ZKProofport circuit identifiers.
3
- *
4
- * This module is the single source of truth for circuit IDs. Every other layer
5
- * — the mobile app, the demo, the relay, server-side provers — reads its list
6
- * from here instead of keeping a private copy that silently drifts.
7
- *
8
- * It has **no imports and no dependencies**, so it can be pulled in on its own:
9
- *
10
- * ```typescript
11
- * import { CIRCUIT_IDS, isCircuitId } from '@zkproofport-app/sdk/circuits';
12
- * ```
13
- *
14
- * The same names are also re-exported from the package root
15
- * (`@zkproofport-app/sdk`) for callers that already import the SDK.
16
- *
17
- * ## Identifiers are canonical and case-sensitive
18
- *
19
- * Each ID is the circuit's `name` in its `Nargo.toml`, verbatim. The format is
20
- * lowercase with underscores. Hyphenated spellings (`coinbase-kyc`,
21
- * `mdl-kr-age`) are directory or UI route names in other repositories — they
22
- * are **not** circuit IDs, and passing one produces a nullifier mismatch or a
23
- * failed on-chain lookup rather than a clear error.
24
- */
25
- /**
26
- * Canonical circuit identifiers, keyed by a stable constant name.
27
- *
28
- * Prefer these constants over string literals so a rename is a compile error
29
- * rather than a runtime surprise.
30
- *
31
- * @example
32
- * ```typescript
33
- * import { CIRCUIT_IDS } from '@zkproofport-app/sdk/circuits';
34
- *
35
- * const relay = await sdk.createRelayRequest(CIRCUIT_IDS.COINBASE_ATTESTATION, {
36
- * scope: 'myapp.com',
37
- * });
38
- * ```
39
- */
40
- const CIRCUIT_IDS = Object.freeze({
41
- /** Coinbase KYC attestation. Officially supported. */
42
- COINBASE_ATTESTATION: 'coinbase_attestation',
43
- /** Coinbase country attestation (inclusion / exclusion). Officially supported. */
44
- COINBASE_COUNTRY_ATTESTATION: 'coinbase_country_attestation',
45
- /** OIDC email-domain attestation. Officially supported. */
46
- OIDC_DOMAIN_ATTESTATION: 'oidc_domain_attestation',
47
- /** GIWA attestation. Planned — not officially supported yet. */
48
- GIWA_ATTESTATION: 'giwa_attestation',
49
- /** Dojang Playground on GIWA Sepolia. Experimental — testnet only. */
50
- DOJANG_PLAYGROUND: 'dojang_playground',
51
- /** Korea Mobile ID ownership. Planned — not officially supported yet. */
52
- MDL_KR_OWNERSHIP: 'mdl_kr_ownership',
53
- /** Korea Mobile ID age threshold. Planned — not officially supported yet. */
54
- MDL_KR_AGE: 'mdl_kr_age',
55
- /** Korea Mobile ID si/do region. Planned — not officially supported yet. */
56
- MDL_KR_REGION: 'mdl_kr_region',
57
- });
58
- /**
59
- * Support status for every circuit.
60
- *
61
- * The record is exhaustive over {@link CircuitId}: adding an identifier without
62
- * giving it a status is a compile error, so this list cannot drift from
63
- * {@link CIRCUIT_IDS}.
64
- *
65
- * @example
66
- * ```typescript
67
- * import { CIRCUIT_SUPPORT_STATUS } from '@zkproofport-app/sdk/circuits';
68
- *
69
- * CIRCUIT_SUPPORT_STATUS.coinbase_attestation; // 'supported'
70
- * CIRCUIT_SUPPORT_STATUS.mdl_kr_age; // 'planned'
71
- * ```
72
- */
73
- const CIRCUIT_SUPPORT_STATUS = Object.freeze({
74
- coinbase_attestation: 'supported',
75
- coinbase_country_attestation: 'supported',
76
- oidc_domain_attestation: 'supported',
77
- // Experimental, not planned: the circuit is built, its verifier is
78
- // deployed on GIWA Sepolia and the demo requests it. What keeps it out of
79
- // 'supported' is that it is testnet-only, so the app offers it behind
80
- // Developer Mode and reads its files from main rather than a release tag.
81
- giwa_attestation: 'experimental',
82
- // Same footing as GIWA: built, verifier deployed on GIWA Sepolia, a real
83
- // proof verifies there. Testnet only.
84
- dojang_playground: 'experimental',
85
- mdl_kr_ownership: 'planned',
86
- mdl_kr_age: 'planned',
87
- mdl_kr_region: 'planned',
88
- });
89
- /**
90
- * Where each circuit's verification key FILE lives inside the
91
- * `zkproofport/circuits` repository, relative to its root.
92
- *
93
- * Off-chain verification needs the verification key and nothing else — no
94
- * circuit bytecode, no witness. The key is public by nature: it is what anyone
95
- * checking a proof must already have, and the Solidity verifiers deployed
96
- * on-chain embed the same key.
97
- *
98
- * NOTE THE TRAILING `/vk` TWICE. In that repository `target/vk` is a DIRECTORY
99
- * holding `vk`, `vk_hash` and `SHA256SUMS`; the key itself is `target/vk/vk`.
100
- * These paths were first copied here from the mobile app, which keeps the
101
- * directory and the filename as two fields and joins them — so taking only the
102
- * directory produced a URL that answers 404, and the first browser to try
103
- * off-chain verification said "Could not fetch the verification key (HTTP 404)".
104
- *
105
- * Exhaustive over {@link CircuitId} on purpose. A new circuit whose key path is
106
- * not listed here fails to compile rather than failing at verification time,
107
- * where the only symptom would be a proof that cannot be checked.
108
- */
109
- const CIRCUIT_VK_PATHS = Object.freeze({
110
- coinbase_attestation: 'coinbase-attestation/target/vk/vk',
111
- coinbase_country_attestation: 'coinbase-country-attestation/target/vk/vk',
112
- oidc_domain_attestation: 'oidc-domain-attestation/target/vk/vk',
113
- giwa_attestation: 'giwa-attestation/target/vk/vk',
114
- dojang_playground: 'dojang-playground/target/vk/vk',
115
- mdl_kr_ownership: 'mdl/kr-ownership/target/vk/vk',
116
- mdl_kr_age: 'mdl/kr-age/target/vk/vk',
117
- mdl_kr_region: 'mdl/kr-region/target/vk/vk',
118
- });
119
- /**
120
- * Every canonical circuit identifier, in declaration order.
121
- *
122
- * Includes circuits that are still `planned`. Use {@link SUPPORTED_CIRCUIT_IDS}
123
- * when you only want the ones that are officially supported today.
124
- */
125
- const ALL_CIRCUIT_IDS = Object.freeze(Object.values(CIRCUIT_IDS));
126
- /**
127
- * Circuits that are officially supported today: the two Coinbase circuits and
128
- * OIDC domain attestation.
129
- *
130
- * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
131
- */
132
- const SUPPORTED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'supported'));
133
- /**
134
- * Circuits whose identifiers are reserved but which are not officially
135
- * supported yet: GIWA attestation and the three Korea Mobile ID circuits.
136
- *
137
- * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
138
- */
139
- /**
140
- * Circuits you can prove today, on a testnet, with everything subject to change.
141
- *
142
- * `giwa_attestation` is in this state. Calling it `planned` would be wrong —
143
- * the circuit compiles, the verifier is deployed and a proof verifies against
144
- * it — and calling it `supported` would be worse, because the only deployment
145
- * is a testnet (GIWA Sepolia). Neither existing word was true, so the honest
146
- * move was a third word rather than picking the closer lie.
147
- */
148
- const EXPERIMENTAL_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter(id => CIRCUIT_SUPPORT_STATUS[id] === 'experimental'));
149
- const PLANNED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'planned'));
150
- /**
151
- * Narrows an unknown value to a canonical circuit identifier.
152
- *
153
- * Returns `false` for hyphenated route names such as `'coinbase-kyc'`, which
154
- * are not circuit IDs.
155
- *
156
- * @example
157
- * ```typescript
158
- * isCircuitId('coinbase_attestation'); // true
159
- * isCircuitId('coinbase-kyc'); // false
160
- * ```
161
- */
162
- function isCircuitId(value) {
163
- return typeof value === 'string' && ALL_CIRCUIT_IDS.includes(value);
164
- }
165
- /**
166
- * Narrows an unknown value to a circuit identifier that is officially supported
167
- * today. Planned circuits return `false`.
168
- *
169
- * @example
170
- * ```typescript
171
- * isSupportedCircuitId('oidc_domain_attestation'); // true
172
- * isSupportedCircuitId('mdl_kr_age'); // false — planned
173
- * ```
174
- */
175
- function isSupportedCircuitId(value) {
176
- return isCircuitId(value) && CIRCUIT_SUPPORT_STATUS[value] === 'supported';
177
- }
178
- /**
179
- * Returns the support status of a circuit.
180
- *
181
- * @param circuit - A canonical circuit identifier.
182
- * @throws Error when the value is not a canonical circuit identifier.
183
- *
184
- * @example
185
- * ```typescript
186
- * getCircuitSupportStatus('giwa_attestation'); // 'planned'
187
- * ```
188
- */
189
- function getCircuitSupportStatus(circuit) {
190
- if (!isCircuitId(circuit)) {
191
- throw new Error(`Unknown circuit '${String(circuit)}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`);
192
- }
193
- return CIRCUIT_SUPPORT_STATUS[circuit];
194
- }
195
- const CIRCUIT_ACTION_BINDING = {
196
- coinbase_attestation: 'none',
197
- coinbase_country_attestation: 'none',
198
- // The signature lives inside the identity token; no wallet, no action.
199
- oidc_domain_attestation: 'none',
200
- // Branches in-circuit: with an action the wallet signs the typed data,
201
- // without one it personal_signs the request's signal hash.
202
- giwa_attestation: 'optional',
203
- // Same branch as GIWA; see dojang-playground/src/main.nr.
204
- dojang_playground: 'optional',
205
- mdl_kr_ownership: 'none',
206
- mdl_kr_age: 'none',
207
- mdl_kr_region: 'none',
208
- };
209
- /*
210
- * The union is declared above rather than derived from the table's values.
211
- *
212
- * Deriving it narrowed the type to whatever the table happens to hold today --
213
- * 'none' | 'optional' -- and TypeScript then called every `=== 'required'`
214
- * check impossible. The publish typecheck caught it; `rollup` and `vitest` did
215
- * not. 'required' is a state a circuit can legitimately be in (an EIP-712 path
216
- * and nothing else), so the union says so and the table is checked against it.
217
- */
218
- /**
219
- * How this circuit treats an action, or an error naming the id that is not one.
220
- *
221
- * No default: a circuit nobody has classified must not inherit 'none', which
222
- * would silently drop an action a dapp meant to bind.
223
- */
224
- function circuitActionBinding(circuit) {
225
- const binding = CIRCUIT_ACTION_BINDING[circuit];
226
- if (!binding) {
227
- throw new Error(`Unknown circuit '${circuit}'. Expected: ${ALL_CIRCUIT_IDS.join(', ')}`);
228
- }
229
- return binding;
230
- }
231
- const CIRCUIT_NEEDS_WALLET_SIGNATURE = {
232
- coinbase_attestation: true,
233
- coinbase_country_attestation: true,
234
- // The signature is inside the OIDC identity token, checked by the prover.
235
- oidc_domain_attestation: false,
236
- // Web2 (OmniOne CX) flows with no wallet binding at all.
237
- mdl_kr_ownership: false,
238
- mdl_kr_age: false,
239
- mdl_kr_region: false,
240
- // A GIWA-attested wallet signing an EIP-712 action (or its signal hash).
241
- // This read `false` while the circuit had always verified a wallet signature
242
- // -- it sat under the Web2 comment above and was never revisited. A request
243
- // for it would have reached the relay with no signer.
244
- giwa_attestation: true,
245
- // The wallet signs the request, and the same key must have signed its
246
- // Playground faucet transaction.
247
- dojang_playground: true,
248
- };
249
-
250
- export { ALL_CIRCUIT_IDS, CIRCUIT_ACTION_BINDING, CIRCUIT_IDS, CIRCUIT_NEEDS_WALLET_SIGNATURE, CIRCUIT_SUPPORT_STATUS, CIRCUIT_VK_PATHS, EXPERIMENTAL_CIRCUIT_IDS, PLANNED_CIRCUIT_IDS, SUPPORTED_CIRCUIT_IDS, circuitActionBinding, getCircuitSupportStatus, isCircuitId, isSupportedCircuitId };
1
+ export * from '@zkproofport-app/core/circuits';
251
2
  //# sourceMappingURL=circuits.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"circuits.esm.js","sources":["../src/circuits.ts"],"sourcesContent":["/**\n * Canonical ZKProofport circuit identifiers.\n *\n * This module is the single source of truth for circuit IDs. Every other layer\n * — the mobile app, the demo, the relay, server-side provers — reads its list\n * from here instead of keeping a private copy that silently drifts.\n *\n * It has **no imports and no dependencies**, so it can be pulled in on its own:\n *\n * ```typescript\n * import { CIRCUIT_IDS, isCircuitId } from '@zkproofport-app/sdk/circuits';\n * ```\n *\n * The same names are also re-exported from the package root\n * (`@zkproofport-app/sdk`) for callers that already import the SDK.\n *\n * ## Identifiers are canonical and case-sensitive\n *\n * Each ID is the circuit's `name` in its `Nargo.toml`, verbatim. The format is\n * lowercase with underscores. Hyphenated spellings (`coinbase-kyc`,\n * `mdl-kr-age`) are directory or UI route names in other repositories — they\n * are **not** circuit IDs, and passing one produces a nullifier mismatch or a\n * failed on-chain lookup rather than a clear error.\n */\n\n/**\n * Whether a circuit is officially supported today or still on the roadmap.\n *\n * - `supported` — generally available. Safe to build a product on.\n * - `planned` — the identifier is reserved and the circuit exists, but it is\n * not officially supported yet. Availability, inputs and public-input layout\n * may change without a major version bump.\n */\nexport type CircuitSupportStatus = 'supported' | 'experimental' | 'planned';\n\n/**\n * Canonical circuit identifiers, keyed by a stable constant name.\n *\n * Prefer these constants over string literals so a rename is a compile error\n * rather than a runtime surprise.\n *\n * @example\n * ```typescript\n * import { CIRCUIT_IDS } from '@zkproofport-app/sdk/circuits';\n *\n * const relay = await sdk.createRelayRequest(CIRCUIT_IDS.COINBASE_ATTESTATION, {\n * scope: 'myapp.com',\n * });\n * ```\n */\nexport const CIRCUIT_IDS = Object.freeze({\n /** Coinbase KYC attestation. Officially supported. */\n COINBASE_ATTESTATION: 'coinbase_attestation',\n /** Coinbase country attestation (inclusion / exclusion). Officially supported. */\n COINBASE_COUNTRY_ATTESTATION: 'coinbase_country_attestation',\n /** OIDC email-domain attestation. Officially supported. */\n OIDC_DOMAIN_ATTESTATION: 'oidc_domain_attestation',\n /** GIWA attestation. Planned — not officially supported yet. */\n GIWA_ATTESTATION: 'giwa_attestation',\n /** Dojang Playground on GIWA Sepolia. Experimental — testnet only. */\n DOJANG_PLAYGROUND: 'dojang_playground',\n /** Korea Mobile ID ownership. Planned — not officially supported yet. */\n MDL_KR_OWNERSHIP: 'mdl_kr_ownership',\n /** Korea Mobile ID age threshold. Planned — not officially supported yet. */\n MDL_KR_AGE: 'mdl_kr_age',\n /** Korea Mobile ID si/do region. Planned — not officially supported yet. */\n MDL_KR_REGION: 'mdl_kr_region',\n} as const);\n\n/**\n * Union of every canonical circuit identifier.\n *\n * `CircuitType` (exported from the package root) is an alias of this type — the\n * two names refer to the same union, and this module is where it is defined.\n */\nexport type CircuitId = (typeof CIRCUIT_IDS)[keyof typeof CIRCUIT_IDS];\n\n/**\n * Support status for every circuit.\n *\n * The record is exhaustive over {@link CircuitId}: adding an identifier without\n * giving it a status is a compile error, so this list cannot drift from\n * {@link CIRCUIT_IDS}.\n *\n * @example\n * ```typescript\n * import { CIRCUIT_SUPPORT_STATUS } from '@zkproofport-app/sdk/circuits';\n *\n * CIRCUIT_SUPPORT_STATUS.coinbase_attestation; // 'supported'\n * CIRCUIT_SUPPORT_STATUS.mdl_kr_age; // 'planned'\n * ```\n */\nexport const CIRCUIT_SUPPORT_STATUS: Readonly<Record<CircuitId, CircuitSupportStatus>> =\n Object.freeze({\n coinbase_attestation: 'supported',\n coinbase_country_attestation: 'supported',\n oidc_domain_attestation: 'supported',\n // Experimental, not planned: the circuit is built, its verifier is\n // deployed on GIWA Sepolia and the demo requests it. What keeps it out of\n // 'supported' is that it is testnet-only, so the app offers it behind\n // Developer Mode and reads its files from main rather than a release tag.\n giwa_attestation: 'experimental',\n // Same footing as GIWA: built, verifier deployed on GIWA Sepolia, a real\n // proof verifies there. Testnet only.\n dojang_playground: 'experimental',\n mdl_kr_ownership: 'planned',\n mdl_kr_age: 'planned',\n mdl_kr_region: 'planned',\n } as const);\n\n/**\n * Where each circuit's verification key FILE lives inside the\n * `zkproofport/circuits` repository, relative to its root.\n *\n * Off-chain verification needs the verification key and nothing else — no\n * circuit bytecode, no witness. The key is public by nature: it is what anyone\n * checking a proof must already have, and the Solidity verifiers deployed\n * on-chain embed the same key.\n *\n * NOTE THE TRAILING `/vk` TWICE. In that repository `target/vk` is a DIRECTORY\n * holding `vk`, `vk_hash` and `SHA256SUMS`; the key itself is `target/vk/vk`.\n * These paths were first copied here from the mobile app, which keeps the\n * directory and the filename as two fields and joins them — so taking only the\n * directory produced a URL that answers 404, and the first browser to try\n * off-chain verification said \"Could not fetch the verification key (HTTP 404)\".\n *\n * Exhaustive over {@link CircuitId} on purpose. A new circuit whose key path is\n * not listed here fails to compile rather than failing at verification time,\n * where the only symptom would be a proof that cannot be checked.\n */\nexport const CIRCUIT_VK_PATHS: Readonly<Record<CircuitId, string>> = Object.freeze({\n coinbase_attestation: 'coinbase-attestation/target/vk/vk',\n coinbase_country_attestation: 'coinbase-country-attestation/target/vk/vk',\n oidc_domain_attestation: 'oidc-domain-attestation/target/vk/vk',\n giwa_attestation: 'giwa-attestation/target/vk/vk',\n dojang_playground: 'dojang-playground/target/vk/vk',\n mdl_kr_ownership: 'mdl/kr-ownership/target/vk/vk',\n mdl_kr_age: 'mdl/kr-age/target/vk/vk',\n mdl_kr_region: 'mdl/kr-region/target/vk/vk',\n} as const);\n\n/**\n * Every canonical circuit identifier, in declaration order.\n *\n * Includes circuits that are still `planned`. Use {@link SUPPORTED_CIRCUIT_IDS}\n * when you only want the ones that are officially supported today.\n */\nexport const ALL_CIRCUIT_IDS: readonly CircuitId[] = Object.freeze(\n Object.values(CIRCUIT_IDS) as CircuitId[]\n);\n\n/**\n * Circuits that are officially supported today: the two Coinbase circuits and\n * OIDC domain attestation.\n *\n * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.\n */\nexport const SUPPORTED_CIRCUIT_IDS: readonly CircuitId[] = Object.freeze(\n ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'supported')\n);\n\n/**\n * Circuits whose identifiers are reserved but which are not officially\n * supported yet: GIWA attestation and the three Korea Mobile ID circuits.\n *\n * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.\n */\n/**\n * Circuits you can prove today, on a testnet, with everything subject to change.\n *\n * `giwa_attestation` is in this state. Calling it `planned` would be wrong —\n * the circuit compiles, the verifier is deployed and a proof verifies against\n * it — and calling it `supported` would be worse, because the only deployment\n * is a testnet (GIWA Sepolia). Neither existing word was true, so the honest\n * move was a third word rather than picking the closer lie.\n */\nexport const EXPERIMENTAL_CIRCUIT_IDS: readonly CircuitId[] = Object.freeze(\n ALL_CIRCUIT_IDS.filter(id => CIRCUIT_SUPPORT_STATUS[id] === 'experimental'),\n);\n\nexport const PLANNED_CIRCUIT_IDS: readonly CircuitId[] = Object.freeze(\n ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'planned')\n);\n\n/**\n * Narrows an unknown value to a canonical circuit identifier.\n *\n * Returns `false` for hyphenated route names such as `'coinbase-kyc'`, which\n * are not circuit IDs.\n *\n * @example\n * ```typescript\n * isCircuitId('coinbase_attestation'); // true\n * isCircuitId('coinbase-kyc'); // false\n * ```\n */\nexport function isCircuitId(value: unknown): value is CircuitId {\n return typeof value === 'string' && (ALL_CIRCUIT_IDS as readonly string[]).includes(value);\n}\n\n/**\n * Narrows an unknown value to a circuit identifier that is officially supported\n * today. Planned circuits return `false`.\n *\n * @example\n * ```typescript\n * isSupportedCircuitId('oidc_domain_attestation'); // true\n * isSupportedCircuitId('mdl_kr_age'); // false — planned\n * ```\n */\nexport function isSupportedCircuitId(value: unknown): value is CircuitId {\n return isCircuitId(value) && CIRCUIT_SUPPORT_STATUS[value] === 'supported';\n}\n\n/**\n * Returns the support status of a circuit.\n *\n * @param circuit - A canonical circuit identifier.\n * @throws Error when the value is not a canonical circuit identifier.\n *\n * @example\n * ```typescript\n * getCircuitSupportStatus('giwa_attestation'); // 'planned'\n * ```\n */\nexport function getCircuitSupportStatus(circuit: CircuitId): CircuitSupportStatus {\n if (!isCircuitId(circuit)) {\n throw new Error(\n `Unknown circuit '${String(circuit)}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`\n );\n }\n return CIRCUIT_SUPPORT_STATUS[circuit];\n}\n\n/**\n * Whether a circuit's relay request must carry a wallet signature.\n *\n * The SDK checks this to fail fast — \"Signer not set\" locally beats a 401 from\n * the relay two round trips later, with nothing saying which circuit needed\n * what. The relay declares its OWN copy on purpose and does not import this\n * one: it is a security boundary, and an auth policy that a published package\n * can change is not a policy. A test in the relay asserts the two agree.\n *\n * `satisfies` and not an annotation, so a circuit added above is a compile\n * error here until somebody decides which it is.\n */\n/**\n * Whether a circuit's proof can bind an EIP-712 action, and whether it must.\n *\n * ONE TABLE, because the answer was becoming a chain of `circuit === '...'`\n * tests. It was asked in the deep-link validator and again in\n * `createRelayRequest`, both spelling out one circuit id, and a second\n * action-capable circuit would have made each of them a two-branch chain that\n * ends on whatever the last test happens to be.\n *\n * 'required' the circuit proves nothing without an action -- the wallet\n * signs the typed data and there is no other message.\n * 'optional' the circuit signs the action when one is supplied and\n * personal_signs its signal hash when one is not. The circuit\n * itself branches; see giwa-attestation/src/main.nr.\n * 'none' the circuit has no action inputs. An action sent anyway is a\n * caller misunderstanding, and is refused rather than dropped:\n * silently ignoring it would let a dapp believe a proof\n * authorized something it never mentioned.\n */\nexport type CircuitActionBinding = 'none' | 'required' | 'optional';\n\nexport const CIRCUIT_ACTION_BINDING = {\n coinbase_attestation: 'none',\n coinbase_country_attestation: 'none',\n // The signature lives inside the identity token; no wallet, no action.\n oidc_domain_attestation: 'none',\n // Branches in-circuit: with an action the wallet signs the typed data,\n // without one it personal_signs the request's signal hash.\n giwa_attestation: 'optional',\n // Same branch as GIWA; see dojang-playground/src/main.nr.\n dojang_playground: 'optional',\n mdl_kr_ownership: 'none',\n mdl_kr_age: 'none',\n mdl_kr_region: 'none',\n} satisfies Record<CircuitId, CircuitActionBinding>;\n\n/*\n * The union is declared above rather than derived from the table's values.\n *\n * Deriving it narrowed the type to whatever the table happens to hold today --\n * 'none' | 'optional' -- and TypeScript then called every `=== 'required'`\n * check impossible. The publish typecheck caught it; `rollup` and `vitest` did\n * not. 'required' is a state a circuit can legitimately be in (an EIP-712 path\n * and nothing else), so the union says so and the table is checked against it.\n */\n\n/**\n * How this circuit treats an action, or an error naming the id that is not one.\n *\n * No default: a circuit nobody has classified must not inherit 'none', which\n * would silently drop an action a dapp meant to bind.\n */\nexport function circuitActionBinding(circuit: string): CircuitActionBinding {\n const binding = (CIRCUIT_ACTION_BINDING as Record<string, CircuitActionBinding | undefined>)[circuit];\n if (!binding) {\n throw new Error(\n `Unknown circuit '${circuit}'. Expected: ${ALL_CIRCUIT_IDS.join(', ')}`,\n );\n }\n return binding;\n}\n\nexport const CIRCUIT_NEEDS_WALLET_SIGNATURE = {\n coinbase_attestation: true,\n coinbase_country_attestation: true,\n // The signature is inside the OIDC identity token, checked by the prover.\n oidc_domain_attestation: false,\n // Web2 (OmniOne CX) flows with no wallet binding at all.\n mdl_kr_ownership: false,\n mdl_kr_age: false,\n mdl_kr_region: false,\n // A GIWA-attested wallet signing an EIP-712 action (or its signal hash).\n // This read `false` while the circuit had always verified a wallet signature\n // -- it sat under the Web2 comment above and was never revisited. A request\n // for it would have reached the relay with no signer.\n giwa_attestation: true,\n // The wallet signs the request, and the same key must have signed its\n // Playground faucet transaction.\n dojang_playground: true,\n} satisfies Record<CircuitId, boolean>;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"circuits.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}