@zkproofport-app/core 0.1.0 → 0.1.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.
@@ -248,4 +248,4 @@ const CIRCUIT_NEEDS_WALLET_SIGNATURE = {
248
248
  };
249
249
 
250
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 };
251
- //# sourceMappingURL=circuits.esm.js.map
251
+ //# 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' | '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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"}
@@ -866,4 +866,4 @@ function reconstructBytes32FromFields(fields) {
866
866
  }
867
867
 
868
868
  export { ALL_CIRCUIT_IDS, CIRCUIT_ACTION_BINDING, CIRCUIT_IDS, CIRCUIT_NEEDS_WALLET_SIGNATURE, CIRCUIT_SUPPORT_STATUS, CIRCUIT_VK_PATHS, COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT, COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT, EXPERIMENTAL_CIRCUIT_IDS, MDL_KR_PUBLIC_INPUT_LAYOUT, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT, PLANNED_CIRCUIT_IDS, RPC_ENDPOINTS, SUPPORTED_CIRCUIT_IDS, VERIFIER_ABI, circuitActionBinding, extractDomainFromPublicInputs, extractNullifierFromPublicInputs, extractScopeFromPublicInputs, getCircuitSupportStatus, getDefaultProvider, getVerifierAddress, getVerifierChainId, getVerifierContract, isCircuitId, isSupportedCircuitId, parseProofForOnChain, parseTypedAction, validateTypedAction, verifyProofOnChain };
869
- //# sourceMappingURL=index.esm.js.map
869
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/circuits.ts","../src/typedAction.ts","../src/chain.ts","../src/verifier.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","/**\n * Checking the EIP-712 action a `giwa_attestation` proof binds to.\n *\n * Three places need this answer and they have to agree: a dapp building the\n * request, this SDK validating a deep link, and the mobile app before it asks\n * a wallet to sign. The check lived in the mobile app's demo screen and\n * nowhere else, so an action arriving from a dapp reached the prover\n * unexamined — and that is the path that ships.\n *\n * The circuit hashes the domain and the struct and proves the wallet signed\n * them. It never learns what the action says, so a malformed one does not\n * fail: it produces a valid proof of the wrong thing.\n */\nimport type { TypedAction } from './types';\n\nexport type { TypedAction };\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\n/**\n * The reason the value is not a usable action, or `null` when it is one.\n *\n * Structural validation only, not application authorization policy. Consumers\n * (e.g. EligibilityGate) must independently enforce the expected chain, verifying\n * contract, actor, action parameters, nonce and deadline as applicable.\n * EIP-712 signs only fields declared in types, not extra message properties.\n *\n * A string rather than a boolean because every caller shows it to somebody —\n * a dapp developer reading a validation error, or a person looking at the\n * mobile app's demo screen.\n */\nexport function validateTypedAction(value: unknown): string | null {\n if (value === undefined || value === null) {\n return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';\n }\n if (typeof value !== 'object' || Array.isArray(value)) {\n return 'action must be an object.';\n }\n const a = value as Partial<TypedAction>;\n\n const d = a.domain;\n if (!d || typeof d !== 'object') {\n return 'action.domain is required.';\n }\n for (const k of ['name', 'version', 'verifyingContract'] as const) {\n if (typeof d[k] !== 'string' || !d[k]) {\n return `action.domain.${k} must be a non-empty string.`;\n }\n }\n if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {\n return 'action.domain.chainId must be an integer.';\n }\n if (!ADDRESS.test(d.verifyingContract)) {\n return 'action.domain.verifyingContract must be a 20-byte hex address.';\n }\n\n if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {\n return 'action.types is required.';\n }\n if (typeof a.primaryType !== 'string' || !a.primaryType) {\n return 'action.primaryType is required.';\n }\n if (!(a.primaryType in a.types)) {\n return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;\n }\n if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {\n return 'action.message is required.';\n }\n\n // Every field the struct declares must be present, or the wallet signs a\n // different message than the one the caller described.\n const fields = a.types[a.primaryType];\n if (!Array.isArray(fields) || fields.length === 0) {\n return `action.types.${a.primaryType} declares no fields.`;\n }\n const missing = fields\n .map(f => f?.name)\n .filter(n => typeof n === 'string' && !(n in (a.message as object)));\n if (missing.length) {\n return `action.message is missing: ${missing.join(', ')}`;\n }\n\n return null;\n}\n\n/** The action, or the reason it is not one. For text a person typed. */\nexport function parseTypedAction(text: string): { action: TypedAction } | { error: string } {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (e) {\n return { error: `Not valid JSON: ${(e as Error).message}` };\n }\n const error = validateTypedAction(raw);\n return error ? { error } : { action: raw as TypedAction };\n}\n","/**\n * What on-chain verification needs: the verifier ABI, public RPC endpoints,\n * and where each circuit's values sit in its flat public-input array.\n */\n\n/**\n * Standard verifier contract ABI shared across all Barretenberg-generated verifiers.\n * This ABI defines the interface for calling the verify function on deployed verifier contracts.\n *\n * Uses ethers v6 human-readable ABI format.\n *\n * @example\n * ```typescript\n * import { Contract } from 'ethers';\n *\n * const verifier = new Contract(verifierAddress, VERIFIER_ABI, provider);\n * const isValid = await verifier.verify(proofBytes, publicInputs);\n * ```\n */\nexport const VERIFIER_ABI = [\n 'function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool)',\n];\n\n/**\n * Public RPC endpoint URLs for supported blockchain networks.\n * Used as fallback when no custom provider is supplied.\n *\n * Supported networks:\n * - 84532: Base Sepolia (testnet)\n * - 8453: Base Mainnet (production)\n * - 91342: GIWA Sepolia (testnet) — where the GIWA account circuit verifies\n *\n * A chain missing from this map is not a quiet degradation: `getDefaultProvider`\n * throws \"No RPC endpoint configured for chain N\". That is what a caller saw\n * when verifying a GIWA proof on chain 91342 — the verifier contract had been\n * deployed and the proof was valid, but the SDK had no way to reach the chain\n * to ask. Deploying a verifier to a new network means adding it here too.\n *\n * @example\n * ```typescript\n * import { JsonRpcProvider } from 'ethers';\n *\n * const provider = new JsonRpcProvider(RPC_ENDPOINTS[84532]);\n * ```\n */\nexport const RPC_ENDPOINTS: Record<number, string> = {\n 84532: 'https://sepolia.base.org', // Base Sepolia\n 8453: 'https://mainnet.base.org', // Base Mainnet\n 91342: 'https://sepolia-rpc.giwa.io', // GIWA Sepolia\n};\n\n/**\n * Coinbase Attestation circuit public input layout (byte offsets).\n * Defines the byte positions of each field in the flattened public inputs array.\n *\n * Public inputs are packed as bytes32 values:\n * - signal_hash: bytes 0-31\n * - merkle_root: bytes 32-63\n * - scope: bytes 64-95\n *\n * @example\n * ```typescript\n * const publicInputs = response.publicInputs;\n * const signalHash = publicInputs.slice(\n * COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT.SIGNAL_HASH_START,\n * COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT.SIGNAL_HASH_END + 1\n * );\n * ```\n */\nexport const COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT = {\n SIGNAL_HASH_START: 0,\n SIGNAL_HASH_END: 31,\n MERKLE_ROOT_START: 32,\n MERKLE_ROOT_END: 63,\n SCOPE_START: 64,\n SCOPE_END: 95,\n NULLIFIER_START: 96,\n NULLIFIER_END: 127,\n} as const;\n\n/**\n * Coinbase Country Attestation circuit public input layout (byte offsets).\n * Defines the byte positions of each field in the flattened public inputs array.\n *\n * Public inputs are packed as bytes32 values:\n * - signal_hash: bytes 0-31\n * - merkle_root: bytes 32-63\n * - country_list: bytes 64-83 (20 bytes for 10 countries)\n * - country_list_length: byte 84\n * - is_included: byte 85\n * - scope: bytes 86-117\n *\n * @example\n * ```typescript\n * const publicInputs = response.publicInputs;\n * const countryList = publicInputs.slice(\n * COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT.COUNTRY_LIST_START,\n * COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT.COUNTRY_LIST_END + 1\n * );\n * ```\n */\nexport const COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT = {\n SIGNAL_HASH_START: 0,\n SIGNAL_HASH_END: 31,\n MERKLE_ROOT_START: 32,\n MERKLE_ROOT_END: 63,\n COUNTRY_LIST_START: 64,\n COUNTRY_LIST_END: 83,\n COUNTRY_LIST_LENGTH: 84,\n IS_INCLUDED: 85,\n SCOPE_START: 86,\n SCOPE_END: 117,\n NULLIFIER_START: 118,\n NULLIFIER_END: 149,\n} as const;\n\n/**\n * Korea Mobile ID (mDL) circuit public input layout (field offsets).\n * All three mDL circuits share the same prefix: scope [0..31] and\n * nullifier_value [32..63], each stored one byte per field element.\n * The suffix differs per predicate circuit:\n * - mdl_kr_ownership (97 inputs): disclose_flags [64], owner_commit [65..96]\n * - mdl_kr_age (66 inputs): age_threshold [64], current_year [65]\n * - mdl_kr_region (96 inputs): region_code [64..95]\n *\n * @example\n * ```typescript\n * const nullifier = publicInputs.slice(\n * MDL_KR_PUBLIC_INPUT_LAYOUT.NULLIFIER_START,\n * MDL_KR_PUBLIC_INPUT_LAYOUT.NULLIFIER_END + 1\n * );\n * ```\n */\nexport const MDL_KR_PUBLIC_INPUT_LAYOUT = {\n SCOPE_START: 0,\n SCOPE_END: 31,\n NULLIFIER_START: 32,\n NULLIFIER_END: 63,\n OWNERSHIP_DISCLOSE_FLAGS: 64,\n OWNERSHIP_OWNER_COMMIT_START: 65,\n OWNERSHIP_OWNER_COMMIT_END: 96,\n AGE_THRESHOLD: 64,\n AGE_CURRENT_YEAR: 65,\n REGION_CODE_START: 64,\n REGION_CODE_END: 95,\n} as const;\n\n/**\n * OIDC Domain Attestation circuit public input layout (field offsets).\n * Defines the field positions in the flattened public inputs array (148 fields total).\n *\n * Circuit public inputs (from main.nr):\n * - pubkey_modulus_limbs: pub [u128; 18] → 18 fields (0–17)\n * - domain: pub BoundedVec<u8, 64> → 1 len + 64 storage = 65 fields (18–82)\n * - scope: pub [u8; 32] → 32 fields (83–114)\n * - nullifier: pub [u8; 32] → 32 fields (115–146)\n * - provider: pub u8 → 1 field (147)\n *\n * @example\n * ```typescript\n * const scope = publicInputs.slice(\n * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_START,\n * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_END + 1\n * );\n * ```\n */\nexport const OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT = {\n PUBKEY_MODULUS_START: 0,\n PUBKEY_MODULUS_END: 17,\n DOMAIN_STORAGE_START: 18,\n DOMAIN_STORAGE_END: 81,\n DOMAIN_LEN: 82,\n SCOPE_START: 83,\n SCOPE_END: 114,\n NULLIFIER_START: 115,\n NULLIFIER_END: 146,\n PROVIDER: 147,\n /** @deprecated Use DOMAIN_STORAGE_START */\n DOMAIN_START: 18,\n /** @deprecated Use DOMAIN_LEN */\n DOMAIN_END: 82,\n} as const;\n","/**\n * On-chain verification utilities for ZKProofport SDK\n *\n * Compatible with both ethers v5 and v6.\n */\n\nimport { ethers } from 'ethers';\nimport type { CircuitType, ParsedProof, VerifierContract } from './types';\nimport { VERIFIER_ABI, RPC_ENDPOINTS, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT } from './chain';\nimport { ALL_CIRCUIT_IDS, isCircuitId, type CircuitId } from './circuits';\n\n// ethers v5/v6 compatibility shims\nconst _ethers = ethers as any;\n\n/** @internal ethers v5/v6 compatibility shim */\nfunction hexZeroPad(value: string, length: number): string {\n // v6: ethers.zeroPadValue, v5: ethers.utils.hexZeroPad\n if (typeof _ethers.zeroPadValue === 'function') return _ethers.zeroPadValue(value, length);\n if (_ethers.utils?.hexZeroPad) return _ethers.utils.hexZeroPad(value, length);\n // manual fallback\n const hex = value.startsWith('0x') ? value.slice(2) : value;\n return '0x' + hex.padStart(length * 2, '0');\n}\n\n/** @internal ethers v5/v6 compatibility shim */\nfunction createJsonRpcProvider(url: string) {\n // v6: ethers.JsonRpcProvider, v5: ethers.providers.JsonRpcProvider\n if (typeof _ethers.JsonRpcProvider === 'function') return new _ethers.JsonRpcProvider(url);\n if (_ethers.providers?.JsonRpcProvider) return new _ethers.providers.JsonRpcProvider(url);\n throw new Error('No JsonRpcProvider found in ethers');\n}\n\n/**\n * @internal Resolve verifier from SDK config or proof response.\n * SDK config (customVerifier) takes priority over response-provided verifier.\n */\nfunction resolveVerifier(\n customVerifier?: VerifierContract,\n responseVerifier?: { verifierAddress?: string; chainId?: number }\n): VerifierContract | null {\n if (customVerifier) return customVerifier;\n if (responseVerifier?.verifierAddress) {\n return {\n address: responseVerifier.verifierAddress,\n chainId: responseVerifier.chainId ?? 0,\n abi: VERIFIER_ABI,\n };\n }\n return null;\n}\n\n/**\n * Get verifier contract instance for interacting with on-chain verifier contracts.\n *\n * @param providerOrSigner - ethers.js Provider or Signer instance (v5 or v6 compatible)\n * @param verifier - Verifier contract configuration containing address and ABI\n * @returns ethers.Contract instance connected to the verifier\n *\n * @example\n * ```typescript\n * const provider = new ethers.JsonRpcProvider(rpcUrl);\n * const contract = getVerifierContract(provider, {\n * address: '0x...',\n * chainId: 11155111,\n * abi: VERIFIER_ABI\n * });\n * ```\n */\nexport function getVerifierContract(\n providerOrSigner: any,\n verifier: VerifierContract\n): ethers.Contract {\n return new ethers.Contract(\n verifier.address,\n verifier.abi,\n providerOrSigner\n );\n}\n\n/**\n * Get default JSON-RPC provider for a chain using pre-configured RPC endpoints.\n *\n * @param chainId - The chain ID (e.g., 11155111 for Sepolia, 84532 for Base Sepolia)\n * @returns ethers.JsonRpcProvider instance for the specified chain\n * @throws Error if no RPC endpoint is configured for the chain\n *\n * @example\n * ```typescript\n * const provider = getDefaultProvider(11155111); // Sepolia\n * ```\n */\nexport function getDefaultProvider(chainId: number) {\n const rpcUrl = RPC_ENDPOINTS[chainId];\n if (!rpcUrl) {\n throw new Error(\n `No RPC endpoint configured for chain ${chainId}. Known chains: ${Object.keys(RPC_ENDPOINTS).join(', ')}`,\n );\n }\n return createJsonRpcProvider(rpcUrl);\n}\n\n/**\n * Verify a zero-knowledge proof on-chain by calling the verifier smart contract.\n *\n * This function resolves the verifier contract from SDK config or proof response,\n * connects to the blockchain, and calls the verify() method with the proof and public inputs.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param parsedProof - Parsed proof object containing proofHex and publicInputsHex\n * @param providerOrSigner - Optional ethers.js Provider or Signer instance. If not provided, uses default RPC for the chain\n * @param customVerifier - Optional custom verifier contract config (takes priority over responseVerifier)\n * @param responseVerifier - Optional verifier info from proof generation response\n * @returns Promise resolving to verification result with valid flag and optional error message\n *\n * @example\n * ```typescript\n * const parsed = parseProofForOnChain(proof, publicInputs, numPublicInputs);\n * const result = await verifyProofOnChain(\n * 'coinbase_attestation',\n * parsed,\n * provider,\n * { address: '0x...', chainId: 11155111, abi: VERIFIER_ABI }\n * );\n *\n * if (result.valid) {\n * console.log('Proof is valid!');\n * } else {\n * console.error('Verification failed:', result.error);\n * }\n * ```\n */\nexport async function verifyProofOnChain(\n circuit: CircuitType,\n parsedProof: ParsedProof,\n providerOrSigner?: any,\n customVerifier?: VerifierContract,\n responseVerifier?: { verifierAddress?: string; chainId?: number }\n): Promise<{ valid: boolean; error?: string }> {\n const verifier = resolveVerifier(customVerifier, responseVerifier);\n if (!verifier) {\n return {\n valid: false,\n error: 'No verifier address provided. Configure via SDK or ensure proof response includes verifierAddress.',\n };\n }\n\n const provider = providerOrSigner || (verifier.chainId > 0 ? getDefaultProvider(verifier.chainId) : null);\n if (!provider) {\n return {\n valid: false,\n error: 'No provider available. Provide a provider or ensure chainId is set for RPC lookup.',\n };\n }\n\n const contract = getVerifierContract(provider, verifier);\n\n try {\n const isValid = await contract.verify(\n parsedProof.proofHex,\n parsedProof.publicInputsHex\n );\n\n return { valid: isValid };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { valid: false, error: errorMessage };\n }\n}\n\n/** @internal Ensure a hex string has the 0x prefix */\nfunction ensureHexPrefix(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/**\n * Parse proof response into format suitable for on-chain verification.\n *\n * Converts proof and public inputs from relay response format to the format\n * expected by Solidity verifier contracts. Public inputs are zero-padded to\n * 32 bytes (bytes32) to match Solidity's bytes32[] type.\n *\n * @param proof - Proof bytes as hex string (with or without 0x prefix)\n * @param publicInputs - Array of public input values as hex strings\n * @param numPublicInputs - Number of public inputs (for validation)\n * @returns Parsed proof object ready for on-chain verification\n *\n * @example\n * ```typescript\n * const parsed = parseProofForOnChain(\n * '0x1a2b3c...',\n * ['0x01', '0x02', '0x03'],\n * 3\n * );\n *\n * // parsed.proofHex: '0x1a2b3c...'\n * // parsed.publicInputsHex: ['0x0000...01', '0x0000...02', '0x0000...03']\n * ```\n */\nexport function parseProofForOnChain(\n proof: string,\n publicInputs: string[],\n numPublicInputs: number\n): ParsedProof {\n const proofHex = ensureHexPrefix(proof);\n\n const publicInputsHex = publicInputs.map((input) => {\n return hexZeroPad(ensureHexPrefix(input), 32);\n });\n\n return {\n proofHex,\n publicInputsHex,\n numPublicInputs,\n };\n}\n\n/** @internal Require a verifier or throw with a helpful message */\nfunction requireVerifier(circuit: CircuitType, verifier?: VerifierContract): VerifierContract {\n if (!verifier) {\n throw new Error(`No verifier configured for circuit '${circuit}'. Configure via SDK verifiers option.`);\n }\n return verifier;\n}\n\n/**\n * Get verifier contract address for a circuit.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param customVerifier - Optional custom verifier contract config\n * @returns Verifier contract address as hex string\n * @throws Error if no verifier is configured for the circuit\n *\n * @example\n * ```typescript\n * const address = getVerifierAddress('coinbase_attestation', verifierConfig);\n * console.log(address); // '0x1234...'\n * ```\n */\nexport function getVerifierAddress(\n circuit: CircuitType,\n customVerifier?: VerifierContract\n): string {\n return requireVerifier(circuit, customVerifier).address;\n}\n\n/**\n * Get chain ID for a circuit's verifier contract.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param customVerifier - Optional custom verifier contract config\n * @returns Chain ID number (e.g., 11155111 for Sepolia, 84532 for Base Sepolia)\n * @throws Error if no verifier is configured for the circuit\n *\n * @example\n * ```typescript\n * const chainId = getVerifierChainId('coinbase_attestation', verifierConfig);\n * console.log(chainId); // 11155111\n * ```\n */\nexport function getVerifierChainId(\n circuit: CircuitType,\n customVerifier?: VerifierContract\n): number {\n return requireVerifier(circuit, customVerifier).chainId;\n}\n\n\n/**\n * Where `scope` and `nullifier` sit in each circuit's public inputs.\n *\n * Keyed by `CircuitId`, which is the point: adding a circuit to the SDK makes\n * this object a compile error until somebody opens that circuit's `fn main`\n * and writes its offsets down. Nothing here can be inferred from the proof —\n * the public inputs are a flat array of bytes with no framing.\n *\n * It replaced an `if / else if / else` chain whose final `else` handed every\n * unrecognised circuit — and every call that named no circuit at all —\n * Coinbase's offsets. For `giwa_attestation` that is not a near miss: its\n * public inputs are signal_hash, domain_separator, action_hash, merkle root,\n * scope, nullifier, so the nullifier slot under Coinbase's offsets holds the\n * MERKLE ROOT, a value identical for every user. Duplicate detection built on\n * it would report one person.\n */\nconst PUBLIC_INPUT_OFFSETS: Readonly<Record<CircuitId, { scope: readonly [number, number]; nullifier: readonly [number, number] }>> = Object.freeze({\n // signal_hash, signer_list_merkle_root, scope, nullifier\n coinbase_attestation: { scope: [64, 95], nullifier: [96, 127] },\n // No longer Coinbase's layout. The GIWA circuit gained the EIP-712 pair, so\n // it reads: signal_hash, domain_separator, action_hash, merkle root, then\n // scope and nullifier 64 bytes further along than Coinbase.\n giwa_attestation: { scope: [128, 159], nullifier: [160, 191] },\n // signal_hash, domain_separator, action_hash, scope, nullifier: GIWA's\n // order without the merkle root, since there is no issuer list.\n dojang_playground: { scope: [96, 127], nullifier: [128, 159] },\n // country_list, country_list_length and is_included sit before scope.\n coinbase_country_attestation: { scope: [86, 117], nullifier: [118, 149] },\n // pubkey_modulus_limbs and the bounded domain sit before scope.\n oidc_domain_attestation: { scope: [83, 114], nullifier: [115, 146] },\n // The Korea mDL circuits open with the pair; signal_hash is commented out.\n mdl_kr_ownership: { scope: [0, 31], nullifier: [32, 63] },\n mdl_kr_age: { scope: [0, 31], nullifier: [32, 63] },\n mdl_kr_region: { scope: [0, 31], nullifier: [32, 63] },\n});\n\n/**\n * The offsets for a circuit, or an error naming what was asked for.\n *\n * Throwing is the whole point. A caller that omits the circuit, or names one\n * this SDK has never heard of, is asking a question with no answer; returning\n * a guess produced a scope and a nullifier that belong to different bytes and\n * looked exactly like real ones.\n */\nfunction offsetsFor(circuit: string | undefined): { scope: readonly [number, number]; nullifier: readonly [number, number] } {\n if (circuit === undefined) {\n throw new Error(\n `A circuit id is required to read public inputs: the layout differs per circuit and cannot be inferred from the proof. Pass one of: ${ALL_CIRCUIT_IDS.join(', ')}`,\n );\n }\n if (!isCircuitId(circuit)) {\n throw new Error(\n `Unknown circuit '${circuit}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`,\n );\n }\n return PUBLIC_INPUT_OFFSETS[circuit];\n}\n\n/**\n * Extract scope value from public inputs array.\n *\n * The scope is a bytes32 value encoded across 32 consecutive field elements\n * in the public inputs. The exact position depends on the circuit type.\n *\n * @param publicInputsHex - Array of public input hex strings (zero-padded to 32 bytes)\n * @param circuit - Optional circuit identifier to determine field positions\n * @returns Reconstructed scope as hex string with 0x prefix, or null if inputs are insufficient\n *\n * @example\n * ```typescript\n * const scope = extractScopeFromPublicInputs(publicInputsHex, 'coinbase_attestation');\n * console.log(scope); // '0x7a6b70726f6f66706f72742e636f6d...'\n * ```\n */\nexport function extractScopeFromPublicInputs(\n publicInputsHex: string[],\n circuit: string,\n): string | null {\n const [start, end] = offsetsFor(circuit).scope;\n if (publicInputsHex.length <= end) return null;\n const scopeFields = publicInputsHex.slice(start, end + 1);\n return reconstructBytes32FromFields(scopeFields);\n}\n\n/**\n * Extracts the nullifier (bytes32) from public inputs based on circuit type.\n *\n * The nullifier is a unique, deterministic hash derived from the user's attestation\n * and scope. It serves as a privacy-preserving user identifier — the same user\n * with the same scope always produces the same nullifier, enabling duplicate\n * detection without revealing the wallet address.\n *\n * @param publicInputsHex - Array of hex-encoded field elements\n * @param circuit - Circuit id. REQUIRED: the layout differs per circuit and\n * cannot be inferred from the proof. It used to default to\n * `coinbase_attestation`, which returned the right-shaped bytes read from\n * the wrong place for every other circuit.\n * @returns Nullifier as hex string (bytes32), or null if publicInputs too short\n *\n * @example\n * ```typescript\n * const nullifier = extractNullifierFromPublicInputs(publicInputs, 'coinbase_attestation');\n * console.log(nullifier); // '0xabc123...'\n * ```\n */\nexport function extractNullifierFromPublicInputs(\n publicInputsHex: string[],\n circuit: string,\n): string | null {\n const [start, end] = offsetsFor(circuit).nullifier;\n if (publicInputsHex.length <= end) return null;\n const nullifierFields = publicInputsHex.slice(start, end + 1);\n return reconstructBytes32FromFields(nullifierFields);\n}\n\n/**\n * Extract domain string from OIDC Domain Attestation public inputs.\n *\n * The domain is stored as a Noir BoundedVec<u8, 64>, which serializes as\n * [storage[0..64], len]. Each storage element is a u8 value in a field element.\n *\n * @param publicInputsHex - Array of public input hex strings\n * @param circuit - Circuit identifier (must be 'oidc_domain_attestation')\n * @returns Domain as ASCII string, or null if circuit doesn't match or inputs are insufficient\n *\n * @example\n * ```typescript\n * const domain = extractDomainFromPublicInputs(publicInputs, 'oidc_domain_attestation');\n * console.log(domain); // 'example.com'\n * ```\n */\nexport function extractDomainFromPublicInputs(\n publicInputsHex: string[],\n circuit?: string,\n): string | null {\n if (circuit !== 'oidc_domain_attestation') return null;\n\n const layout = OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT;\n if (publicInputsHex.length <= layout.DOMAIN_LEN) return null;\n\n const len = Number(BigInt(publicInputsHex[layout.DOMAIN_LEN]) & 0xFFn);\n if (len === 0 || len > 64) return null;\n\n const storageFields = publicInputsHex.slice(\n layout.DOMAIN_STORAGE_START,\n layout.DOMAIN_STORAGE_START + len,\n );\n\n const chars = storageFields.map(f => {\n const byte = Number(BigInt(f) & 0xFFn);\n return String.fromCharCode(byte);\n });\n\n return chars.join('');\n}\n\n/** @internal Reconstruct a bytes32 value from 32 individual field elements */\nfunction reconstructBytes32FromFields(fields: string[]): string {\n if (fields.length !== 32) {\n throw new Error(`Expected 32 fields, got ${fields.length}`);\n }\n const bytes = fields.map(f => {\n const byte = BigInt(f) & 0xFFn;\n return byte.toString(16).padStart(2, '0');\n }).join('');\n return '0x' + bytes;\n}\n"],"names":[],"mappings":"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"}
@@ -74,4 +74,4 @@ function parseTypedAction(text) {
74
74
  }
75
75
 
76
76
  export { parseTypedAction, validateTypedAction };
77
- //# sourceMappingURL=typedAction.esm.js.map
77
+ //# sourceMappingURL=typedAction.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"typedAction.mjs","sources":["../src/typedAction.ts"],"sourcesContent":["/**\n * Checking the EIP-712 action a `giwa_attestation` proof binds to.\n *\n * Three places need this answer and they have to agree: a dapp building the\n * request, this SDK validating a deep link, and the mobile app before it asks\n * a wallet to sign. The check lived in the mobile app's demo screen and\n * nowhere else, so an action arriving from a dapp reached the prover\n * unexamined — and that is the path that ships.\n *\n * The circuit hashes the domain and the struct and proves the wallet signed\n * them. It never learns what the action says, so a malformed one does not\n * fail: it produces a valid proof of the wrong thing.\n */\nimport type { TypedAction } from './types';\n\nexport type { TypedAction };\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\n/**\n * The reason the value is not a usable action, or `null` when it is one.\n *\n * Structural validation only, not application authorization policy. Consumers\n * (e.g. EligibilityGate) must independently enforce the expected chain, verifying\n * contract, actor, action parameters, nonce and deadline as applicable.\n * EIP-712 signs only fields declared in types, not extra message properties.\n *\n * A string rather than a boolean because every caller shows it to somebody —\n * a dapp developer reading a validation error, or a person looking at the\n * mobile app's demo screen.\n */\nexport function validateTypedAction(value: unknown): string | null {\n if (value === undefined || value === null) {\n return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';\n }\n if (typeof value !== 'object' || Array.isArray(value)) {\n return 'action must be an object.';\n }\n const a = value as Partial<TypedAction>;\n\n const d = a.domain;\n if (!d || typeof d !== 'object') {\n return 'action.domain is required.';\n }\n for (const k of ['name', 'version', 'verifyingContract'] as const) {\n if (typeof d[k] !== 'string' || !d[k]) {\n return `action.domain.${k} must be a non-empty string.`;\n }\n }\n if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {\n return 'action.domain.chainId must be an integer.';\n }\n if (!ADDRESS.test(d.verifyingContract)) {\n return 'action.domain.verifyingContract must be a 20-byte hex address.';\n }\n\n if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {\n return 'action.types is required.';\n }\n if (typeof a.primaryType !== 'string' || !a.primaryType) {\n return 'action.primaryType is required.';\n }\n if (!(a.primaryType in a.types)) {\n return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;\n }\n if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {\n return 'action.message is required.';\n }\n\n // Every field the struct declares must be present, or the wallet signs a\n // different message than the one the caller described.\n const fields = a.types[a.primaryType];\n if (!Array.isArray(fields) || fields.length === 0) {\n return `action.types.${a.primaryType} declares no fields.`;\n }\n const missing = fields\n .map(f => f?.name)\n .filter(n => typeof n === 'string' && !(n in (a.message as object)));\n if (missing.length) {\n return `action.message is missing: ${missing.join(', ')}`;\n }\n\n return null;\n}\n\n/** The action, or the reason it is not one. For text a person typed. */\nexport function parseTypedAction(text: string): { action: TypedAction } | { error: string } {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (e) {\n return { error: `Not valid JSON: ${(e as Error).message}` };\n }\n const error = validateTypedAction(raw);\n return error ? { error } : { action: raw as TypedAction };\n}\n"],"names":[],"mappings":"AAiBA,MAAM,OAAO,GAAG,qBAAqB;AAErC;;;;;;;;;;;AAWG;AACG,SAAU,mBAAmB,CAAC,KAAc,EAAA;IAChD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,EAAE;AACzC,QAAA,OAAO,2HAA2H;IACpI;AACA,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACrD,QAAA,OAAO,2BAA2B;IACpC;IACA,MAAM,CAAC,GAAG,KAA6B;AAEvC,IAAA,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM;IAClB,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE;AAC/B,QAAA,OAAO,4BAA4B;IACrC;IACA,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,mBAAmB,CAAU,EAAE;AACjE,QAAA,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;YACrC,OAAO,CAAA,cAAA,EAAiB,CAAC,CAAA,4BAAA,CAA8B;QACzD;IACF;AACA,IAAA,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE;AACjE,QAAA,OAAO,2CAA2C;IACpD;IACA,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,CAAC,EAAE;AACtC,QAAA,OAAO,gEAAgE;IACzE;IAEA,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;AACrE,QAAA,OAAO,2BAA2B;IACpC;AACA,IAAA,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE;AACvD,QAAA,OAAO,iCAAiC;IAC1C;IACA,IAAI,EAAE,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC/B,QAAA,OAAO,CAAA,oBAAA,EAAuB,CAAC,CAAC,WAAW,8CAA8C;IAC3F;IACA,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE;AAC3E,QAAA,OAAO,6BAA6B;IACtC;;;IAIA,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;AACrC,IAAA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AACjD,QAAA,OAAO,CAAA,aAAA,EAAgB,CAAC,CAAC,WAAW,sBAAsB;IAC5D;IACA,MAAM,OAAO,GAAG;SACb,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI;AAChB,SAAA,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAK,CAAC,CAAC,OAAkB,CAAC,CAAC;AACtE,IAAA,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,OAAO,CAAA,2BAAA,EAA8B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;IAC3D;AAEA,IAAA,OAAO,IAAI;AACb;AAEA;AACM,SAAU,gBAAgB,CAAC,IAAY,EAAA;AAC3C,IAAA,IAAI,GAAY;AAChB,IAAA,IAAI;AACF,QAAA,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACxB;IAAE,OAAO,CAAC,EAAE;QACV,OAAO,EAAE,KAAK,EAAE,CAAA,gBAAA,EAAoB,CAAW,CAAC,OAAO,CAAA,CAAE,EAAE;IAC7D;AACA,IAAA,MAAM,KAAK,GAAG,mBAAmB,CAAC,GAAG,CAAC;AACtC,IAAA,OAAO,KAAK,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAkB,EAAE;AAC3D;;;;"}
package/package.json CHANGED
@@ -1,25 +1,25 @@
1
1
  {
2
2
  "name": "@zkproofport-app/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "ZKProofport circuit identifiers, EIP-712 action check and on-chain proof verification",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",
7
- "module": "./dist/index.esm.js",
7
+ "module": "./dist/index.mjs",
8
8
  "types": "./dist/index.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
11
  "types": "./dist/index.d.ts",
12
- "import": "./dist/index.esm.js",
12
+ "import": "./dist/index.mjs",
13
13
  "require": "./dist/index.js"
14
14
  },
15
15
  "./circuits": {
16
16
  "types": "./dist/circuits.d.ts",
17
- "import": "./dist/circuits.esm.js",
17
+ "import": "./dist/circuits.mjs",
18
18
  "require": "./dist/circuits.js"
19
19
  },
20
20
  "./typedAction": {
21
21
  "types": "./dist/typedAction.d.ts",
22
- "import": "./dist/typedAction.esm.js",
22
+ "import": "./dist/typedAction.mjs",
23
23
  "require": "./dist/typedAction.js"
24
24
  },
25
25
  "./package.json": "./package.json"
@@ -1 +0,0 @@
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 +0,0 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/circuits.ts","../src/typedAction.ts","../src/chain.ts","../src/verifier.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","/**\n * Checking the EIP-712 action a `giwa_attestation` proof binds to.\n *\n * Three places need this answer and they have to agree: a dapp building the\n * request, this SDK validating a deep link, and the mobile app before it asks\n * a wallet to sign. The check lived in the mobile app's demo screen and\n * nowhere else, so an action arriving from a dapp reached the prover\n * unexamined — and that is the path that ships.\n *\n * The circuit hashes the domain and the struct and proves the wallet signed\n * them. It never learns what the action says, so a malformed one does not\n * fail: it produces a valid proof of the wrong thing.\n */\nimport type { TypedAction } from './types';\n\nexport type { TypedAction };\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\n/**\n * The reason the value is not a usable action, or `null` when it is one.\n *\n * Structural validation only, not application authorization policy. Consumers\n * (e.g. EligibilityGate) must independently enforce the expected chain, verifying\n * contract, actor, action parameters, nonce and deadline as applicable.\n * EIP-712 signs only fields declared in types, not extra message properties.\n *\n * A string rather than a boolean because every caller shows it to somebody —\n * a dapp developer reading a validation error, or a person looking at the\n * mobile app's demo screen.\n */\nexport function validateTypedAction(value: unknown): string | null {\n if (value === undefined || value === null) {\n return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';\n }\n if (typeof value !== 'object' || Array.isArray(value)) {\n return 'action must be an object.';\n }\n const a = value as Partial<TypedAction>;\n\n const d = a.domain;\n if (!d || typeof d !== 'object') {\n return 'action.domain is required.';\n }\n for (const k of ['name', 'version', 'verifyingContract'] as const) {\n if (typeof d[k] !== 'string' || !d[k]) {\n return `action.domain.${k} must be a non-empty string.`;\n }\n }\n if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {\n return 'action.domain.chainId must be an integer.';\n }\n if (!ADDRESS.test(d.verifyingContract)) {\n return 'action.domain.verifyingContract must be a 20-byte hex address.';\n }\n\n if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {\n return 'action.types is required.';\n }\n if (typeof a.primaryType !== 'string' || !a.primaryType) {\n return 'action.primaryType is required.';\n }\n if (!(a.primaryType in a.types)) {\n return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;\n }\n if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {\n return 'action.message is required.';\n }\n\n // Every field the struct declares must be present, or the wallet signs a\n // different message than the one the caller described.\n const fields = a.types[a.primaryType];\n if (!Array.isArray(fields) || fields.length === 0) {\n return `action.types.${a.primaryType} declares no fields.`;\n }\n const missing = fields\n .map(f => f?.name)\n .filter(n => typeof n === 'string' && !(n in (a.message as object)));\n if (missing.length) {\n return `action.message is missing: ${missing.join(', ')}`;\n }\n\n return null;\n}\n\n/** The action, or the reason it is not one. For text a person typed. */\nexport function parseTypedAction(text: string): { action: TypedAction } | { error: string } {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (e) {\n return { error: `Not valid JSON: ${(e as Error).message}` };\n }\n const error = validateTypedAction(raw);\n return error ? { error } : { action: raw as TypedAction };\n}\n","/**\n * What on-chain verification needs: the verifier ABI, public RPC endpoints,\n * and where each circuit's values sit in its flat public-input array.\n */\n\n/**\n * Standard verifier contract ABI shared across all Barretenberg-generated verifiers.\n * This ABI defines the interface for calling the verify function on deployed verifier contracts.\n *\n * Uses ethers v6 human-readable ABI format.\n *\n * @example\n * ```typescript\n * import { Contract } from 'ethers';\n *\n * const verifier = new Contract(verifierAddress, VERIFIER_ABI, provider);\n * const isValid = await verifier.verify(proofBytes, publicInputs);\n * ```\n */\nexport const VERIFIER_ABI = [\n 'function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool)',\n];\n\n/**\n * Public RPC endpoint URLs for supported blockchain networks.\n * Used as fallback when no custom provider is supplied.\n *\n * Supported networks:\n * - 84532: Base Sepolia (testnet)\n * - 8453: Base Mainnet (production)\n * - 91342: GIWA Sepolia (testnet) — where the GIWA account circuit verifies\n *\n * A chain missing from this map is not a quiet degradation: `getDefaultProvider`\n * throws \"No RPC endpoint configured for chain N\". That is what a caller saw\n * when verifying a GIWA proof on chain 91342 — the verifier contract had been\n * deployed and the proof was valid, but the SDK had no way to reach the chain\n * to ask. Deploying a verifier to a new network means adding it here too.\n *\n * @example\n * ```typescript\n * import { JsonRpcProvider } from 'ethers';\n *\n * const provider = new JsonRpcProvider(RPC_ENDPOINTS[84532]);\n * ```\n */\nexport const RPC_ENDPOINTS: Record<number, string> = {\n 84532: 'https://sepolia.base.org', // Base Sepolia\n 8453: 'https://mainnet.base.org', // Base Mainnet\n 91342: 'https://sepolia-rpc.giwa.io', // GIWA Sepolia\n};\n\n/**\n * Coinbase Attestation circuit public input layout (byte offsets).\n * Defines the byte positions of each field in the flattened public inputs array.\n *\n * Public inputs are packed as bytes32 values:\n * - signal_hash: bytes 0-31\n * - merkle_root: bytes 32-63\n * - scope: bytes 64-95\n *\n * @example\n * ```typescript\n * const publicInputs = response.publicInputs;\n * const signalHash = publicInputs.slice(\n * COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT.SIGNAL_HASH_START,\n * COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT.SIGNAL_HASH_END + 1\n * );\n * ```\n */\nexport const COINBASE_ATTESTATION_PUBLIC_INPUT_LAYOUT = {\n SIGNAL_HASH_START: 0,\n SIGNAL_HASH_END: 31,\n MERKLE_ROOT_START: 32,\n MERKLE_ROOT_END: 63,\n SCOPE_START: 64,\n SCOPE_END: 95,\n NULLIFIER_START: 96,\n NULLIFIER_END: 127,\n} as const;\n\n/**\n * Coinbase Country Attestation circuit public input layout (byte offsets).\n * Defines the byte positions of each field in the flattened public inputs array.\n *\n * Public inputs are packed as bytes32 values:\n * - signal_hash: bytes 0-31\n * - merkle_root: bytes 32-63\n * - country_list: bytes 64-83 (20 bytes for 10 countries)\n * - country_list_length: byte 84\n * - is_included: byte 85\n * - scope: bytes 86-117\n *\n * @example\n * ```typescript\n * const publicInputs = response.publicInputs;\n * const countryList = publicInputs.slice(\n * COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT.COUNTRY_LIST_START,\n * COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT.COUNTRY_LIST_END + 1\n * );\n * ```\n */\nexport const COINBASE_COUNTRY_PUBLIC_INPUT_LAYOUT = {\n SIGNAL_HASH_START: 0,\n SIGNAL_HASH_END: 31,\n MERKLE_ROOT_START: 32,\n MERKLE_ROOT_END: 63,\n COUNTRY_LIST_START: 64,\n COUNTRY_LIST_END: 83,\n COUNTRY_LIST_LENGTH: 84,\n IS_INCLUDED: 85,\n SCOPE_START: 86,\n SCOPE_END: 117,\n NULLIFIER_START: 118,\n NULLIFIER_END: 149,\n} as const;\n\n/**\n * Korea Mobile ID (mDL) circuit public input layout (field offsets).\n * All three mDL circuits share the same prefix: scope [0..31] and\n * nullifier_value [32..63], each stored one byte per field element.\n * The suffix differs per predicate circuit:\n * - mdl_kr_ownership (97 inputs): disclose_flags [64], owner_commit [65..96]\n * - mdl_kr_age (66 inputs): age_threshold [64], current_year [65]\n * - mdl_kr_region (96 inputs): region_code [64..95]\n *\n * @example\n * ```typescript\n * const nullifier = publicInputs.slice(\n * MDL_KR_PUBLIC_INPUT_LAYOUT.NULLIFIER_START,\n * MDL_KR_PUBLIC_INPUT_LAYOUT.NULLIFIER_END + 1\n * );\n * ```\n */\nexport const MDL_KR_PUBLIC_INPUT_LAYOUT = {\n SCOPE_START: 0,\n SCOPE_END: 31,\n NULLIFIER_START: 32,\n NULLIFIER_END: 63,\n OWNERSHIP_DISCLOSE_FLAGS: 64,\n OWNERSHIP_OWNER_COMMIT_START: 65,\n OWNERSHIP_OWNER_COMMIT_END: 96,\n AGE_THRESHOLD: 64,\n AGE_CURRENT_YEAR: 65,\n REGION_CODE_START: 64,\n REGION_CODE_END: 95,\n} as const;\n\n/**\n * OIDC Domain Attestation circuit public input layout (field offsets).\n * Defines the field positions in the flattened public inputs array (148 fields total).\n *\n * Circuit public inputs (from main.nr):\n * - pubkey_modulus_limbs: pub [u128; 18] → 18 fields (0–17)\n * - domain: pub BoundedVec<u8, 64> → 1 len + 64 storage = 65 fields (18–82)\n * - scope: pub [u8; 32] → 32 fields (83–114)\n * - nullifier: pub [u8; 32] → 32 fields (115–146)\n * - provider: pub u8 → 1 field (147)\n *\n * @example\n * ```typescript\n * const scope = publicInputs.slice(\n * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_START,\n * OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT.SCOPE_END + 1\n * );\n * ```\n */\nexport const OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT = {\n PUBKEY_MODULUS_START: 0,\n PUBKEY_MODULUS_END: 17,\n DOMAIN_STORAGE_START: 18,\n DOMAIN_STORAGE_END: 81,\n DOMAIN_LEN: 82,\n SCOPE_START: 83,\n SCOPE_END: 114,\n NULLIFIER_START: 115,\n NULLIFIER_END: 146,\n PROVIDER: 147,\n /** @deprecated Use DOMAIN_STORAGE_START */\n DOMAIN_START: 18,\n /** @deprecated Use DOMAIN_LEN */\n DOMAIN_END: 82,\n} as const;\n","/**\n * On-chain verification utilities for ZKProofport SDK\n *\n * Compatible with both ethers v5 and v6.\n */\n\nimport { ethers } from 'ethers';\nimport type { CircuitType, ParsedProof, VerifierContract } from './types';\nimport { VERIFIER_ABI, RPC_ENDPOINTS, OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT } from './chain';\nimport { ALL_CIRCUIT_IDS, isCircuitId, type CircuitId } from './circuits';\n\n// ethers v5/v6 compatibility shims\nconst _ethers = ethers as any;\n\n/** @internal ethers v5/v6 compatibility shim */\nfunction hexZeroPad(value: string, length: number): string {\n // v6: ethers.zeroPadValue, v5: ethers.utils.hexZeroPad\n if (typeof _ethers.zeroPadValue === 'function') return _ethers.zeroPadValue(value, length);\n if (_ethers.utils?.hexZeroPad) return _ethers.utils.hexZeroPad(value, length);\n // manual fallback\n const hex = value.startsWith('0x') ? value.slice(2) : value;\n return '0x' + hex.padStart(length * 2, '0');\n}\n\n/** @internal ethers v5/v6 compatibility shim */\nfunction createJsonRpcProvider(url: string) {\n // v6: ethers.JsonRpcProvider, v5: ethers.providers.JsonRpcProvider\n if (typeof _ethers.JsonRpcProvider === 'function') return new _ethers.JsonRpcProvider(url);\n if (_ethers.providers?.JsonRpcProvider) return new _ethers.providers.JsonRpcProvider(url);\n throw new Error('No JsonRpcProvider found in ethers');\n}\n\n/**\n * @internal Resolve verifier from SDK config or proof response.\n * SDK config (customVerifier) takes priority over response-provided verifier.\n */\nfunction resolveVerifier(\n customVerifier?: VerifierContract,\n responseVerifier?: { verifierAddress?: string; chainId?: number }\n): VerifierContract | null {\n if (customVerifier) return customVerifier;\n if (responseVerifier?.verifierAddress) {\n return {\n address: responseVerifier.verifierAddress,\n chainId: responseVerifier.chainId ?? 0,\n abi: VERIFIER_ABI,\n };\n }\n return null;\n}\n\n/**\n * Get verifier contract instance for interacting with on-chain verifier contracts.\n *\n * @param providerOrSigner - ethers.js Provider or Signer instance (v5 or v6 compatible)\n * @param verifier - Verifier contract configuration containing address and ABI\n * @returns ethers.Contract instance connected to the verifier\n *\n * @example\n * ```typescript\n * const provider = new ethers.JsonRpcProvider(rpcUrl);\n * const contract = getVerifierContract(provider, {\n * address: '0x...',\n * chainId: 11155111,\n * abi: VERIFIER_ABI\n * });\n * ```\n */\nexport function getVerifierContract(\n providerOrSigner: any,\n verifier: VerifierContract\n): ethers.Contract {\n return new ethers.Contract(\n verifier.address,\n verifier.abi,\n providerOrSigner\n );\n}\n\n/**\n * Get default JSON-RPC provider for a chain using pre-configured RPC endpoints.\n *\n * @param chainId - The chain ID (e.g., 11155111 for Sepolia, 84532 for Base Sepolia)\n * @returns ethers.JsonRpcProvider instance for the specified chain\n * @throws Error if no RPC endpoint is configured for the chain\n *\n * @example\n * ```typescript\n * const provider = getDefaultProvider(11155111); // Sepolia\n * ```\n */\nexport function getDefaultProvider(chainId: number) {\n const rpcUrl = RPC_ENDPOINTS[chainId];\n if (!rpcUrl) {\n throw new Error(\n `No RPC endpoint configured for chain ${chainId}. Known chains: ${Object.keys(RPC_ENDPOINTS).join(', ')}`,\n );\n }\n return createJsonRpcProvider(rpcUrl);\n}\n\n/**\n * Verify a zero-knowledge proof on-chain by calling the verifier smart contract.\n *\n * This function resolves the verifier contract from SDK config or proof response,\n * connects to the blockchain, and calls the verify() method with the proof and public inputs.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param parsedProof - Parsed proof object containing proofHex and publicInputsHex\n * @param providerOrSigner - Optional ethers.js Provider or Signer instance. If not provided, uses default RPC for the chain\n * @param customVerifier - Optional custom verifier contract config (takes priority over responseVerifier)\n * @param responseVerifier - Optional verifier info from proof generation response\n * @returns Promise resolving to verification result with valid flag and optional error message\n *\n * @example\n * ```typescript\n * const parsed = parseProofForOnChain(proof, publicInputs, numPublicInputs);\n * const result = await verifyProofOnChain(\n * 'coinbase_attestation',\n * parsed,\n * provider,\n * { address: '0x...', chainId: 11155111, abi: VERIFIER_ABI }\n * );\n *\n * if (result.valid) {\n * console.log('Proof is valid!');\n * } else {\n * console.error('Verification failed:', result.error);\n * }\n * ```\n */\nexport async function verifyProofOnChain(\n circuit: CircuitType,\n parsedProof: ParsedProof,\n providerOrSigner?: any,\n customVerifier?: VerifierContract,\n responseVerifier?: { verifierAddress?: string; chainId?: number }\n): Promise<{ valid: boolean; error?: string }> {\n const verifier = resolveVerifier(customVerifier, responseVerifier);\n if (!verifier) {\n return {\n valid: false,\n error: 'No verifier address provided. Configure via SDK or ensure proof response includes verifierAddress.',\n };\n }\n\n const provider = providerOrSigner || (verifier.chainId > 0 ? getDefaultProvider(verifier.chainId) : null);\n if (!provider) {\n return {\n valid: false,\n error: 'No provider available. Provide a provider or ensure chainId is set for RPC lookup.',\n };\n }\n\n const contract = getVerifierContract(provider, verifier);\n\n try {\n const isValid = await contract.verify(\n parsedProof.proofHex,\n parsedProof.publicInputsHex\n );\n\n return { valid: isValid };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return { valid: false, error: errorMessage };\n }\n}\n\n/** @internal Ensure a hex string has the 0x prefix */\nfunction ensureHexPrefix(hex: string): string {\n return hex.startsWith('0x') ? hex : `0x${hex}`;\n}\n\n/**\n * Parse proof response into format suitable for on-chain verification.\n *\n * Converts proof and public inputs from relay response format to the format\n * expected by Solidity verifier contracts. Public inputs are zero-padded to\n * 32 bytes (bytes32) to match Solidity's bytes32[] type.\n *\n * @param proof - Proof bytes as hex string (with or without 0x prefix)\n * @param publicInputs - Array of public input values as hex strings\n * @param numPublicInputs - Number of public inputs (for validation)\n * @returns Parsed proof object ready for on-chain verification\n *\n * @example\n * ```typescript\n * const parsed = parseProofForOnChain(\n * '0x1a2b3c...',\n * ['0x01', '0x02', '0x03'],\n * 3\n * );\n *\n * // parsed.proofHex: '0x1a2b3c...'\n * // parsed.publicInputsHex: ['0x0000...01', '0x0000...02', '0x0000...03']\n * ```\n */\nexport function parseProofForOnChain(\n proof: string,\n publicInputs: string[],\n numPublicInputs: number\n): ParsedProof {\n const proofHex = ensureHexPrefix(proof);\n\n const publicInputsHex = publicInputs.map((input) => {\n return hexZeroPad(ensureHexPrefix(input), 32);\n });\n\n return {\n proofHex,\n publicInputsHex,\n numPublicInputs,\n };\n}\n\n/** @internal Require a verifier or throw with a helpful message */\nfunction requireVerifier(circuit: CircuitType, verifier?: VerifierContract): VerifierContract {\n if (!verifier) {\n throw new Error(`No verifier configured for circuit '${circuit}'. Configure via SDK verifiers option.`);\n }\n return verifier;\n}\n\n/**\n * Get verifier contract address for a circuit.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param customVerifier - Optional custom verifier contract config\n * @returns Verifier contract address as hex string\n * @throws Error if no verifier is configured for the circuit\n *\n * @example\n * ```typescript\n * const address = getVerifierAddress('coinbase_attestation', verifierConfig);\n * console.log(address); // '0x1234...'\n * ```\n */\nexport function getVerifierAddress(\n circuit: CircuitType,\n customVerifier?: VerifierContract\n): string {\n return requireVerifier(circuit, customVerifier).address;\n}\n\n/**\n * Get chain ID for a circuit's verifier contract.\n *\n * @param circuit - The canonical circuit identifier. REQUIRED.\n * @param customVerifier - Optional custom verifier contract config\n * @returns Chain ID number (e.g., 11155111 for Sepolia, 84532 for Base Sepolia)\n * @throws Error if no verifier is configured for the circuit\n *\n * @example\n * ```typescript\n * const chainId = getVerifierChainId('coinbase_attestation', verifierConfig);\n * console.log(chainId); // 11155111\n * ```\n */\nexport function getVerifierChainId(\n circuit: CircuitType,\n customVerifier?: VerifierContract\n): number {\n return requireVerifier(circuit, customVerifier).chainId;\n}\n\n\n/**\n * Where `scope` and `nullifier` sit in each circuit's public inputs.\n *\n * Keyed by `CircuitId`, which is the point: adding a circuit to the SDK makes\n * this object a compile error until somebody opens that circuit's `fn main`\n * and writes its offsets down. Nothing here can be inferred from the proof —\n * the public inputs are a flat array of bytes with no framing.\n *\n * It replaced an `if / else if / else` chain whose final `else` handed every\n * unrecognised circuit — and every call that named no circuit at all —\n * Coinbase's offsets. For `giwa_attestation` that is not a near miss: its\n * public inputs are signal_hash, domain_separator, action_hash, merkle root,\n * scope, nullifier, so the nullifier slot under Coinbase's offsets holds the\n * MERKLE ROOT, a value identical for every user. Duplicate detection built on\n * it would report one person.\n */\nconst PUBLIC_INPUT_OFFSETS: Readonly<Record<CircuitId, { scope: readonly [number, number]; nullifier: readonly [number, number] }>> = Object.freeze({\n // signal_hash, signer_list_merkle_root, scope, nullifier\n coinbase_attestation: { scope: [64, 95], nullifier: [96, 127] },\n // No longer Coinbase's layout. The GIWA circuit gained the EIP-712 pair, so\n // it reads: signal_hash, domain_separator, action_hash, merkle root, then\n // scope and nullifier 64 bytes further along than Coinbase.\n giwa_attestation: { scope: [128, 159], nullifier: [160, 191] },\n // signal_hash, domain_separator, action_hash, scope, nullifier: GIWA's\n // order without the merkle root, since there is no issuer list.\n dojang_playground: { scope: [96, 127], nullifier: [128, 159] },\n // country_list, country_list_length and is_included sit before scope.\n coinbase_country_attestation: { scope: [86, 117], nullifier: [118, 149] },\n // pubkey_modulus_limbs and the bounded domain sit before scope.\n oidc_domain_attestation: { scope: [83, 114], nullifier: [115, 146] },\n // The Korea mDL circuits open with the pair; signal_hash is commented out.\n mdl_kr_ownership: { scope: [0, 31], nullifier: [32, 63] },\n mdl_kr_age: { scope: [0, 31], nullifier: [32, 63] },\n mdl_kr_region: { scope: [0, 31], nullifier: [32, 63] },\n});\n\n/**\n * The offsets for a circuit, or an error naming what was asked for.\n *\n * Throwing is the whole point. A caller that omits the circuit, or names one\n * this SDK has never heard of, is asking a question with no answer; returning\n * a guess produced a scope and a nullifier that belong to different bytes and\n * looked exactly like real ones.\n */\nfunction offsetsFor(circuit: string | undefined): { scope: readonly [number, number]; nullifier: readonly [number, number] } {\n if (circuit === undefined) {\n throw new Error(\n `A circuit id is required to read public inputs: the layout differs per circuit and cannot be inferred from the proof. Pass one of: ${ALL_CIRCUIT_IDS.join(', ')}`,\n );\n }\n if (!isCircuitId(circuit)) {\n throw new Error(\n `Unknown circuit '${circuit}'. Expected one of: ${ALL_CIRCUIT_IDS.join(', ')}`,\n );\n }\n return PUBLIC_INPUT_OFFSETS[circuit];\n}\n\n/**\n * Extract scope value from public inputs array.\n *\n * The scope is a bytes32 value encoded across 32 consecutive field elements\n * in the public inputs. The exact position depends on the circuit type.\n *\n * @param publicInputsHex - Array of public input hex strings (zero-padded to 32 bytes)\n * @param circuit - Optional circuit identifier to determine field positions\n * @returns Reconstructed scope as hex string with 0x prefix, or null if inputs are insufficient\n *\n * @example\n * ```typescript\n * const scope = extractScopeFromPublicInputs(publicInputsHex, 'coinbase_attestation');\n * console.log(scope); // '0x7a6b70726f6f66706f72742e636f6d...'\n * ```\n */\nexport function extractScopeFromPublicInputs(\n publicInputsHex: string[],\n circuit: string,\n): string | null {\n const [start, end] = offsetsFor(circuit).scope;\n if (publicInputsHex.length <= end) return null;\n const scopeFields = publicInputsHex.slice(start, end + 1);\n return reconstructBytes32FromFields(scopeFields);\n}\n\n/**\n * Extracts the nullifier (bytes32) from public inputs based on circuit type.\n *\n * The nullifier is a unique, deterministic hash derived from the user's attestation\n * and scope. It serves as a privacy-preserving user identifier — the same user\n * with the same scope always produces the same nullifier, enabling duplicate\n * detection without revealing the wallet address.\n *\n * @param publicInputsHex - Array of hex-encoded field elements\n * @param circuit - Circuit id. REQUIRED: the layout differs per circuit and\n * cannot be inferred from the proof. It used to default to\n * `coinbase_attestation`, which returned the right-shaped bytes read from\n * the wrong place for every other circuit.\n * @returns Nullifier as hex string (bytes32), or null if publicInputs too short\n *\n * @example\n * ```typescript\n * const nullifier = extractNullifierFromPublicInputs(publicInputs, 'coinbase_attestation');\n * console.log(nullifier); // '0xabc123...'\n * ```\n */\nexport function extractNullifierFromPublicInputs(\n publicInputsHex: string[],\n circuit: string,\n): string | null {\n const [start, end] = offsetsFor(circuit).nullifier;\n if (publicInputsHex.length <= end) return null;\n const nullifierFields = publicInputsHex.slice(start, end + 1);\n return reconstructBytes32FromFields(nullifierFields);\n}\n\n/**\n * Extract domain string from OIDC Domain Attestation public inputs.\n *\n * The domain is stored as a Noir BoundedVec<u8, 64>, which serializes as\n * [storage[0..64], len]. Each storage element is a u8 value in a field element.\n *\n * @param publicInputsHex - Array of public input hex strings\n * @param circuit - Circuit identifier (must be 'oidc_domain_attestation')\n * @returns Domain as ASCII string, or null if circuit doesn't match or inputs are insufficient\n *\n * @example\n * ```typescript\n * const domain = extractDomainFromPublicInputs(publicInputs, 'oidc_domain_attestation');\n * console.log(domain); // 'example.com'\n * ```\n */\nexport function extractDomainFromPublicInputs(\n publicInputsHex: string[],\n circuit?: string,\n): string | null {\n if (circuit !== 'oidc_domain_attestation') return null;\n\n const layout = OIDC_DOMAIN_ATTESTATION_PUBLIC_INPUT_LAYOUT;\n if (publicInputsHex.length <= layout.DOMAIN_LEN) return null;\n\n const len = Number(BigInt(publicInputsHex[layout.DOMAIN_LEN]) & 0xFFn);\n if (len === 0 || len > 64) return null;\n\n const storageFields = publicInputsHex.slice(\n layout.DOMAIN_STORAGE_START,\n layout.DOMAIN_STORAGE_START + len,\n );\n\n const chars = storageFields.map(f => {\n const byte = Number(BigInt(f) & 0xFFn);\n return String.fromCharCode(byte);\n });\n\n return chars.join('');\n}\n\n/** @internal Reconstruct a bytes32 value from 32 individual field elements */\nfunction reconstructBytes32FromFields(fields: string[]): string {\n if (fields.length !== 32) {\n throw new Error(`Expected 32 fields, got ${fields.length}`);\n }\n const bytes = fields.map(f => {\n const byte = BigInt(f) & 0xFFn;\n return byte.toString(16).padStart(2, '0');\n }).join('');\n return '0x' + bytes;\n}\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"typedAction.esm.js","sources":["../src/typedAction.ts"],"sourcesContent":["/**\n * Checking the EIP-712 action a `giwa_attestation` proof binds to.\n *\n * Three places need this answer and they have to agree: a dapp building the\n * request, this SDK validating a deep link, and the mobile app before it asks\n * a wallet to sign. The check lived in the mobile app's demo screen and\n * nowhere else, so an action arriving from a dapp reached the prover\n * unexamined — and that is the path that ships.\n *\n * The circuit hashes the domain and the struct and proves the wallet signed\n * them. It never learns what the action says, so a malformed one does not\n * fail: it produces a valid proof of the wrong thing.\n */\nimport type { TypedAction } from './types';\n\nexport type { TypedAction };\n\nconst ADDRESS = /^0x[0-9a-fA-F]{40}$/;\n\n/**\n * The reason the value is not a usable action, or `null` when it is one.\n *\n * Structural validation only, not application authorization policy. Consumers\n * (e.g. EligibilityGate) must independently enforce the expected chain, verifying\n * contract, actor, action parameters, nonce and deadline as applicable.\n * EIP-712 signs only fields declared in types, not extra message properties.\n *\n * A string rather than a boolean because every caller shows it to somebody —\n * a dapp developer reading a validation error, or a person looking at the\n * mobile app's demo screen.\n */\nexport function validateTypedAction(value: unknown): string | null {\n if (value === undefined || value === null) {\n return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';\n }\n if (typeof value !== 'object' || Array.isArray(value)) {\n return 'action must be an object.';\n }\n const a = value as Partial<TypedAction>;\n\n const d = a.domain;\n if (!d || typeof d !== 'object') {\n return 'action.domain is required.';\n }\n for (const k of ['name', 'version', 'verifyingContract'] as const) {\n if (typeof d[k] !== 'string' || !d[k]) {\n return `action.domain.${k} must be a non-empty string.`;\n }\n }\n if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {\n return 'action.domain.chainId must be an integer.';\n }\n if (!ADDRESS.test(d.verifyingContract)) {\n return 'action.domain.verifyingContract must be a 20-byte hex address.';\n }\n\n if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {\n return 'action.types is required.';\n }\n if (typeof a.primaryType !== 'string' || !a.primaryType) {\n return 'action.primaryType is required.';\n }\n if (!(a.primaryType in a.types)) {\n return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;\n }\n if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {\n return 'action.message is required.';\n }\n\n // Every field the struct declares must be present, or the wallet signs a\n // different message than the one the caller described.\n const fields = a.types[a.primaryType];\n if (!Array.isArray(fields) || fields.length === 0) {\n return `action.types.${a.primaryType} declares no fields.`;\n }\n const missing = fields\n .map(f => f?.name)\n .filter(n => typeof n === 'string' && !(n in (a.message as object)));\n if (missing.length) {\n return `action.message is missing: ${missing.join(', ')}`;\n }\n\n return null;\n}\n\n/** The action, or the reason it is not one. For text a person typed. */\nexport function parseTypedAction(text: string): { action: TypedAction } | { error: string } {\n let raw: unknown;\n try {\n raw = JSON.parse(text);\n } catch (e) {\n return { error: `Not valid JSON: ${(e as Error).message}` };\n }\n const error = validateTypedAction(raw);\n return error ? { error } : { action: raw as TypedAction };\n}\n"],"names":[],"mappings":"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"}