@zkproofport-app/sdk 0.2.10 → 0.2.12

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.
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Canonical ZKProofport circuit identifiers.
5
+ *
6
+ * This module is the single source of truth for circuit IDs. Every other layer
7
+ * — the mobile app, the demo, the relay, server-side provers — reads its list
8
+ * from here instead of keeping a private copy that silently drifts.
9
+ *
10
+ * It has **no imports and no dependencies**, so it can be pulled in on its own:
11
+ *
12
+ * ```typescript
13
+ * import { CIRCUIT_IDS, isCircuitId } from '@zkproofport-app/sdk/circuits';
14
+ * ```
15
+ *
16
+ * The same names are also re-exported from the package root
17
+ * (`@zkproofport-app/sdk`) for callers that already import the SDK.
18
+ *
19
+ * ## Identifiers are canonical and case-sensitive
20
+ *
21
+ * Each ID is the circuit's `name` in its `Nargo.toml`, verbatim. The format is
22
+ * lowercase with underscores. Hyphenated spellings (`coinbase-kyc`,
23
+ * `mdl-kr-age`) are directory or UI route names in other repositories — they
24
+ * are **not** circuit IDs, and passing one produces a nullifier mismatch or a
25
+ * failed on-chain lookup rather than a clear error.
26
+ */
27
+ /**
28
+ * Canonical circuit identifiers, keyed by a stable constant name.
29
+ *
30
+ * Prefer these constants over string literals so a rename is a compile error
31
+ * rather than a runtime surprise.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * import { CIRCUIT_IDS } from '@zkproofport-app/sdk/circuits';
36
+ *
37
+ * const relay = await sdk.createRelayRequest(CIRCUIT_IDS.COINBASE_ATTESTATION, {
38
+ * scope: 'myapp.com',
39
+ * });
40
+ * ```
41
+ */
42
+ const CIRCUIT_IDS = Object.freeze({
43
+ /** Coinbase KYC attestation. Officially supported. */
44
+ COINBASE_ATTESTATION: 'coinbase_attestation',
45
+ /** Coinbase country attestation (inclusion / exclusion). Officially supported. */
46
+ COINBASE_COUNTRY_ATTESTATION: 'coinbase_country_attestation',
47
+ /** OIDC email-domain attestation. Officially supported. */
48
+ OIDC_DOMAIN_ATTESTATION: 'oidc_domain_attestation',
49
+ /** GIWA attestation. Planned — not officially supported yet. */
50
+ GIWA_ATTESTATION: 'giwa_attestation',
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
+ giwa_attestation: 'planned',
78
+ mdl_kr_ownership: 'planned',
79
+ mdl_kr_age: 'planned',
80
+ mdl_kr_region: 'planned',
81
+ });
82
+ /**
83
+ * Every canonical circuit identifier, in declaration order.
84
+ *
85
+ * Includes circuits that are still `planned`. Use {@link SUPPORTED_CIRCUIT_IDS}
86
+ * when you only want the ones that are officially supported today.
87
+ */
88
+ const ALL_CIRCUIT_IDS = Object.freeze(Object.values(CIRCUIT_IDS));
89
+ /**
90
+ * Circuits that are officially supported today: the two Coinbase circuits and
91
+ * OIDC domain attestation.
92
+ *
93
+ * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
94
+ */
95
+ const SUPPORTED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'supported'));
96
+ /**
97
+ * Circuits whose identifiers are reserved but which are not officially
98
+ * supported yet: GIWA attestation and the three Korea Mobile ID circuits.
99
+ *
100
+ * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
101
+ */
102
+ const PLANNED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'planned'));
103
+ /**
104
+ * Narrows an unknown value to a canonical circuit identifier.
105
+ *
106
+ * Returns `false` for hyphenated route names such as `'coinbase-kyc'`, which
107
+ * are not circuit IDs.
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * isCircuitId('coinbase_attestation'); // true
112
+ * isCircuitId('coinbase-kyc'); // false
113
+ * ```
114
+ */
115
+ function isCircuitId(value) {
116
+ return typeof value === 'string' && ALL_CIRCUIT_IDS.includes(value);
117
+ }
118
+ /**
119
+ * Narrows an unknown value to a circuit identifier that is officially supported
120
+ * today. Planned circuits return `false`.
121
+ *
122
+ * @example
123
+ * ```typescript
124
+ * isSupportedCircuitId('oidc_domain_attestation'); // true
125
+ * isSupportedCircuitId('mdl_kr_age'); // false — planned
126
+ * ```
127
+ */
128
+ function isSupportedCircuitId(value) {
129
+ return isCircuitId(value) && CIRCUIT_SUPPORT_STATUS[value] === 'supported';
130
+ }
131
+ /**
132
+ * Returns the support status of a circuit.
133
+ *
134
+ * @param circuit - A canonical circuit identifier.
135
+ * @throws Error when the value is not a canonical circuit identifier.
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * getCircuitSupportStatus('giwa_attestation'); // 'planned'
140
+ * ```
141
+ */
142
+ function getCircuitSupportStatus(circuit) {
143
+ if (!isCircuitId(circuit)) {
144
+ throw new Error(`Unknown circuit '${String(circuit)}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`);
145
+ }
146
+ return CIRCUIT_SUPPORT_STATUS[circuit];
147
+ }
148
+
149
+ exports.ALL_CIRCUIT_IDS = ALL_CIRCUIT_IDS;
150
+ exports.CIRCUIT_IDS = CIRCUIT_IDS;
151
+ exports.CIRCUIT_SUPPORT_STATUS = CIRCUIT_SUPPORT_STATUS;
152
+ exports.PLANNED_CIRCUIT_IDS = PLANNED_CIRCUIT_IDS;
153
+ exports.SUPPORTED_CIRCUIT_IDS = SUPPORTED_CIRCUIT_IDS;
154
+ exports.getCircuitSupportStatus = getCircuitSupportStatus;
155
+ exports.isCircuitId = isCircuitId;
156
+ exports.isSupportedCircuitId = isSupportedCircuitId;
157
+ //# sourceMappingURL=circuits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuits.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' | '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 /** 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 giwa_attestation: 'planned',\n mdl_kr_ownership: 'planned',\n mdl_kr_age: 'planned',\n mdl_kr_region: 'planned',\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 */\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"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;AAYH;;;;;;;;;;;;;;AAcG;AACI,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;;AAEvC,IAAA,oBAAoB,EAAE,sBAAsB;;AAE5C,IAAA,4BAA4B,EAAE,8BAA8B;;AAE5D,IAAA,uBAAuB,EAAE,yBAAyB;;AAElD,IAAA,gBAAgB,EAAE,kBAAkB;;AAEpC,IAAA,gBAAgB,EAAE,kBAAkB;;AAEpC,IAAA,UAAU,EAAE,YAAY;;AAExB,IAAA,aAAa,EAAE,eAAe;AACtB,CAAA;AAUV;;;;;;;;;;;;;;AAcG;AACI,MAAM,sBAAsB,GACjC,MAAM,CAAC,MAAM,CAAC;AACZ,IAAA,oBAAoB,EAAE,WAAW;AACjC,IAAA,4BAA4B,EAAE,WAAW;AACzC,IAAA,uBAAuB,EAAE,WAAW;AACpC,IAAA,gBAAgB,EAAE,SAAS;AAC3B,IAAA,gBAAgB,EAAE,SAAS;AAC3B,IAAA,UAAU,EAAE,SAAS;AACrB,IAAA,aAAa,EAAE,SAAS;AAChB,CAAA;AAEZ;;;;;AAKG;AACI,MAAM,eAAe,GAAyB,MAAM,CAAC,MAAM,CAChE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAgB;AAG3C;;;;;AAKG;AACI,MAAM,qBAAqB,GAAyB,MAAM,CAAC,MAAM,CACtE,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,sBAAsB,CAAC,EAAE,CAAC,KAAK,WAAW,CAAC;AAG5E;;;;;AAKG;AACI,MAAM,mBAAmB,GAAyB,MAAM,CAAC,MAAM,CACpE,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,sBAAsB,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC;AAG1E;;;;;;;;;;;AAWG;AACG,SAAU,WAAW,CAAC,KAAc,EAAA;IACxC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,eAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC5F;AAEA;;;;;;;;;AASG;AACG,SAAU,oBAAoB,CAAC,KAAc,EAAA;IACjD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,KAAK,WAAW;AAC5E;AAEA;;;;;;;;;;AAUG;AACG,SAAU,uBAAuB,CAAC,OAAkB,EAAA;AACxD,IAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE;AACzB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,iBAAA,EAAoB,MAAM,CAAC,OAAO,CAAC,CAAA,oBAAA,EAAuB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAE,CACvF;IACH;AACA,IAAA,OAAO,sBAAsB,CAAC,OAAO,CAAC;AACxC;;;;;;;;;;;"}
@@ -0,0 +1,148 @@
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
+ /** Korea Mobile ID ownership. Planned — not officially supported yet. */
50
+ MDL_KR_OWNERSHIP: 'mdl_kr_ownership',
51
+ /** Korea Mobile ID age threshold. Planned — not officially supported yet. */
52
+ MDL_KR_AGE: 'mdl_kr_age',
53
+ /** Korea Mobile ID si/do region. Planned — not officially supported yet. */
54
+ MDL_KR_REGION: 'mdl_kr_region',
55
+ });
56
+ /**
57
+ * Support status for every circuit.
58
+ *
59
+ * The record is exhaustive over {@link CircuitId}: adding an identifier without
60
+ * giving it a status is a compile error, so this list cannot drift from
61
+ * {@link CIRCUIT_IDS}.
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * import { CIRCUIT_SUPPORT_STATUS } from '@zkproofport-app/sdk/circuits';
66
+ *
67
+ * CIRCUIT_SUPPORT_STATUS.coinbase_attestation; // 'supported'
68
+ * CIRCUIT_SUPPORT_STATUS.mdl_kr_age; // 'planned'
69
+ * ```
70
+ */
71
+ const CIRCUIT_SUPPORT_STATUS = Object.freeze({
72
+ coinbase_attestation: 'supported',
73
+ coinbase_country_attestation: 'supported',
74
+ oidc_domain_attestation: 'supported',
75
+ giwa_attestation: 'planned',
76
+ mdl_kr_ownership: 'planned',
77
+ mdl_kr_age: 'planned',
78
+ mdl_kr_region: 'planned',
79
+ });
80
+ /**
81
+ * Every canonical circuit identifier, in declaration order.
82
+ *
83
+ * Includes circuits that are still `planned`. Use {@link SUPPORTED_CIRCUIT_IDS}
84
+ * when you only want the ones that are officially supported today.
85
+ */
86
+ const ALL_CIRCUIT_IDS = Object.freeze(Object.values(CIRCUIT_IDS));
87
+ /**
88
+ * Circuits that are officially supported today: the two Coinbase circuits and
89
+ * OIDC domain attestation.
90
+ *
91
+ * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
92
+ */
93
+ const SUPPORTED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'supported'));
94
+ /**
95
+ * Circuits whose identifiers are reserved but which are not officially
96
+ * supported yet: GIWA attestation and the three Korea Mobile ID circuits.
97
+ *
98
+ * Derived from {@link CIRCUIT_SUPPORT_STATUS}, so it cannot fall out of sync.
99
+ */
100
+ const PLANNED_CIRCUIT_IDS = Object.freeze(ALL_CIRCUIT_IDS.filter((id) => CIRCUIT_SUPPORT_STATUS[id] === 'planned'));
101
+ /**
102
+ * Narrows an unknown value to a canonical circuit identifier.
103
+ *
104
+ * Returns `false` for hyphenated route names such as `'coinbase-kyc'`, which
105
+ * are not circuit IDs.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * isCircuitId('coinbase_attestation'); // true
110
+ * isCircuitId('coinbase-kyc'); // false
111
+ * ```
112
+ */
113
+ function isCircuitId(value) {
114
+ return typeof value === 'string' && ALL_CIRCUIT_IDS.includes(value);
115
+ }
116
+ /**
117
+ * Narrows an unknown value to a circuit identifier that is officially supported
118
+ * today. Planned circuits return `false`.
119
+ *
120
+ * @example
121
+ * ```typescript
122
+ * isSupportedCircuitId('oidc_domain_attestation'); // true
123
+ * isSupportedCircuitId('mdl_kr_age'); // false — planned
124
+ * ```
125
+ */
126
+ function isSupportedCircuitId(value) {
127
+ return isCircuitId(value) && CIRCUIT_SUPPORT_STATUS[value] === 'supported';
128
+ }
129
+ /**
130
+ * Returns the support status of a circuit.
131
+ *
132
+ * @param circuit - A canonical circuit identifier.
133
+ * @throws Error when the value is not a canonical circuit identifier.
134
+ *
135
+ * @example
136
+ * ```typescript
137
+ * getCircuitSupportStatus('giwa_attestation'); // 'planned'
138
+ * ```
139
+ */
140
+ function getCircuitSupportStatus(circuit) {
141
+ if (!isCircuitId(circuit)) {
142
+ throw new Error(`Unknown circuit '${String(circuit)}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`);
143
+ }
144
+ return CIRCUIT_SUPPORT_STATUS[circuit];
145
+ }
146
+
147
+ export { ALL_CIRCUIT_IDS, CIRCUIT_IDS, CIRCUIT_SUPPORT_STATUS, PLANNED_CIRCUIT_IDS, SUPPORTED_CIRCUIT_IDS, getCircuitSupportStatus, isCircuitId, isSupportedCircuitId };
148
+ //# sourceMappingURL=circuits.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"circuits.mjs","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' | '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 /** 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 giwa_attestation: 'planned',\n mdl_kr_ownership: 'planned',\n mdl_kr_age: 'planned',\n mdl_kr_region: 'planned',\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 */\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"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;AAuBG;AAYH;;;;;;;;;;;;;;AAcG;AACI,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC;;AAEvC,IAAA,oBAAoB,EAAE,sBAAsB;;AAE5C,IAAA,4BAA4B,EAAE,8BAA8B;;AAE5D,IAAA,uBAAuB,EAAE,yBAAyB;;AAElD,IAAA,gBAAgB,EAAE,kBAAkB;;AAEpC,IAAA,gBAAgB,EAAE,kBAAkB;;AAEpC,IAAA,UAAU,EAAE,YAAY;;AAExB,IAAA,aAAa,EAAE,eAAe;AACtB,CAAA;AAUV;;;;;;;;;;;;;;AAcG;AACI,MAAM,sBAAsB,GACjC,MAAM,CAAC,MAAM,CAAC;AACZ,IAAA,oBAAoB,EAAE,WAAW;AACjC,IAAA,4BAA4B,EAAE,WAAW;AACzC,IAAA,uBAAuB,EAAE,WAAW;AACpC,IAAA,gBAAgB,EAAE,SAAS;AAC3B,IAAA,gBAAgB,EAAE,SAAS;AAC3B,IAAA,UAAU,EAAE,SAAS;AACrB,IAAA,aAAa,EAAE,SAAS;AAChB,CAAA;AAEZ;;;;;AAKG;AACI,MAAM,eAAe,GAAyB,MAAM,CAAC,MAAM,CAChE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAgB;AAG3C;;;;;AAKG;AACI,MAAM,qBAAqB,GAAyB,MAAM,CAAC,MAAM,CACtE,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,sBAAsB,CAAC,EAAE,CAAC,KAAK,WAAW,CAAC;AAG5E;;;;;AAKG;AACI,MAAM,mBAAmB,GAAyB,MAAM,CAAC,MAAM,CACpE,eAAe,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,sBAAsB,CAAC,EAAE,CAAC,KAAK,SAAS,CAAC;AAG1E;;;;;;;;;;;AAWG;AACG,SAAU,WAAW,CAAC,KAAc,EAAA;IACxC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,eAAqC,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC5F;AAEA;;;;;;;;;AASG;AACG,SAAU,oBAAoB,CAAC,KAAc,EAAA;IACjD,OAAO,WAAW,CAAC,KAAK,CAAC,IAAI,sBAAsB,CAAC,KAAK,CAAC,KAAK,WAAW;AAC5E;AAEA;;;;;;;;;;AAUG;AACG,SAAU,uBAAuB,CAAC,OAAkB,EAAA;AACxD,IAAA,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE;AACzB,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,iBAAA,EAAoB,MAAM,CAAC,OAAO,CAAC,CAAA,oBAAA,EAAuB,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAE,CACvF;IACH;AACA,IAAA,OAAO,sBAAsB,CAAC,OAAO,CAAC;AACxC;;;;"}
@@ -49,7 +49,7 @@ export declare const DEEP_LINK_HOSTS: {
49
49
  * ```typescript
50
50
  * const metadata = CIRCUIT_METADATA['coinbase_attestation'];
51
51
  * console.log(metadata.name); // "Coinbase KYC"
52
- * console.log(metadata.publicInputsCount); // 2
52
+ * console.log(metadata.publicInputsCount); // 128
53
53
  * ```
54
54
  */
55
55
  export declare const CIRCUIT_METADATA: Record<CircuitType, {
@@ -197,12 +197,82 @@ export declare const MAX_RETURN_SCHEME_LENGTH = 128;
197
197
  * value fails fast in the integrator's own code instead of coming back as a
198
198
  * relay 400. The relay re-validates and is the authority.
199
199
  *
200
+ * One shape is accepted: a bare custom scheme such as `mydapp://`. It names an
201
+ * app to switch back to, never a page to visit — so hosts, paths and query
202
+ * strings are rejected, and an https URL is not a valid value. A web page has
203
+ * no app to return to and simply omits the field.
204
+ *
200
205
  * @param value - Candidate return target
201
206
  * @returns `null` when acceptable, otherwise a human-readable error message
202
207
  *
203
208
  * @internal
204
209
  */
205
210
  export declare function validateReturnScheme(value: unknown): string | null;
211
+ /**
212
+ * The return target to use when the integrator named none.
213
+ *
214
+ * Only the requesting PAGE can answer "which browser is this?" — iOS gives the
215
+ * ZKProofport app nothing to work with (`sourceApplication` is nil across team
216
+ * identifiers, and there is no public API to foreground an app by bundle id).
217
+ * So the detection has to happen here, in the SDK, and travel with the request.
218
+ *
219
+ * Two cases are detected, each from a POSITIVE token, and each verified in the
220
+ * browser's own source to foreground WITHOUT navigating anywhere:
221
+ *
222
+ * Chrome for iOS (`CriOS/`) -> `googlechrome://`
223
+ * Firefox for iOS (`FxiOS/`) -> `firefox://`
224
+ *
225
+ * The BARE scheme is the point in both cases: it carries no URL, so the browser
226
+ * comes forward with nothing to open and the user lands on the tab they were
227
+ * already reading — no new tab, no navigation, no reload, JS state intact.
228
+ *
229
+ * Chrome: `ios/chrome/app/startup/chrome_app_startup_parameters.mm` replaces
230
+ * the scheme with `http`, producing `http://`, which fails GURL validation
231
+ * (`if (!externalURL.is_valid()) return nil;`), so the startup parameters are
232
+ * nil and there is nothing to open.
233
+ *
234
+ * Firefox: `firefox://` has an empty host, and
235
+ * `Coordinators/Router/RouteBuilder.swift` resolves the host through
236
+ * `DeeplinkInput.Host(rawValue: "")`, which is nil because no case has an empty
237
+ * raw value (`Coordinators/Router/DeeplinkInput.swift`). The scheme is not http
238
+ * either, so `makeRoute(url:)` falls to its final `else { return nil }`, and
239
+ * `SceneDelegate.handleOpenURL` then hits `guard let route = ... else
240
+ * { return }` and does nothing at all. Verified on the warm path — the browser
241
+ * is already running, which is always true here, because the user came from a
242
+ * page in it.
243
+ *
244
+ * Everything else deliberately returns undefined, and that is not a gap:
245
+ *
246
+ * - Safari has no equivalent. No scheme means "just come forward";
247
+ * `https://<url>` navigates and opens a new tab, `x-web-search://` opens a
248
+ * search page. Both lose the user's page.
249
+ * - Brave and Arc for iOS are UNDETECTABLE. Brave ships no UA token and
250
+ * identifies itself only via Client Hints, which WebKit does not implement,
251
+ * so it looks exactly like Safari. Inferring "Safari" by elimination and
252
+ * firing a Safari-ish scheme would throw Brave and Arc users into a browser
253
+ * they were not using — strictly worse than doing nothing.
254
+ * - In-app webviews (KakaoTalk, Naver, Line, Instagram) are not tabs at all.
255
+ * Any scheme destroys the page; the system "< Back to X" breadcrumb is the
256
+ * only thing that preserves it.
257
+ * - Edge (`EdgiOS`) and Opera (`OPiOS` / `OPT`) for iOS are NOT included.
258
+ * Both are closed source, so `microsoft-edge://` and `opera-http://` cannot
259
+ * be checked the way Chrome's and Firefox's were. Their bare schemes are
260
+ * plausible analogues, and that is exactly why they stay out: an unverified
261
+ * guess that opens a new tab is the bug this field exists to avoid. Add one
262
+ * only with evidence that it foregrounds WITHOUT navigating.
263
+ * - Android needs nothing: the ZKProofport app brings itself to the back
264
+ * (`moveTaskToBack`), which resumes the browser exactly as it was.
265
+ *
266
+ * When this returns undefined the field is omitted and the ZKProofport app
267
+ * tells the user the proof was delivered and to switch back themselves.
268
+ *
269
+ * @param userAgent - override, for tests. Defaults to `navigator.userAgent`.
270
+ * Returns undefined when there is no navigator at all (Node, SSR).
271
+ * @returns a scheme that is safe to open, or undefined to send nothing
272
+ *
273
+ * @internal
274
+ */
275
+ export declare function detectReturnScheme(userAgent?: string): string | undefined;
206
276
  export declare function validateProofRequest(request: ProofRequest): {
207
277
  valid: boolean;
208
278
  error?: string;
package/dist/index.d.ts CHANGED
@@ -27,5 +27,7 @@
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, PLANNED_CIRCUIT_IDS, isCircuitId, isSupportedCircuitId, getCircuitSupportStatus, } from './circuits';
30
31
  export { COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, MDL_KR_PUBLIC_INPUT_LAYOUT, } from './constants';
32
+ export type { CircuitId, CircuitSupportStatus } from './circuits';
31
33
  export type { CircuitType, ProofRequestStatus, CoinbaseKycInputs, CoinbaseCountryInputs, OidcDomainInputs, MdlKrOwnershipInputs, MdlKrAgeInputs, MdlKrRegionInputs, CircuitInputs, ProofRequest, ProofResponse, QRCodeOptions, VerifierContract, ProofportConfig, ChallengeResponse, WalletSigner, RelayProofRequest, RelayProofResult, SDKEnvironment, } from './types';