@zkproofport-app/sdk 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Checking the EIP-712 action an `arc_eligibility` proof binds to.
2
+ * Checking the EIP-712 action a `giwa_attestation` proof binds to.
3
3
  *
4
4
  * Three places need this answer and they have to agree: a dapp building the
5
5
  * request, this SDK validating a deep link, and the mobile app before it asks
@@ -16,6 +16,11 @@ export type { TypedAction };
16
16
  /**
17
17
  * The reason the value is not a usable action, or `null` when it is one.
18
18
  *
19
+ * Structural validation only, not application authorization policy. Consumers
20
+ * (e.g. EligibilityGate) must independently enforce the expected chain, verifying
21
+ * contract, actor, action parameters, nonce and deadline as applicable.
22
+ * EIP-712 signs only fields declared in types, not extra message properties.
23
+ *
19
24
  * A string rather than a boolean because every caller shows it to somebody —
20
25
  * a dapp developer reading a validation error, or a person looking at the
21
26
  * mobile app's demo screen.
@@ -2,13 +2,18 @@ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
2
2
  /**
3
3
  * The reason the value is not a usable action, or `null` when it is one.
4
4
  *
5
+ * Structural validation only, not application authorization policy. Consumers
6
+ * (e.g. EligibilityGate) must independently enforce the expected chain, verifying
7
+ * contract, actor, action parameters, nonce and deadline as applicable.
8
+ * EIP-712 signs only fields declared in types, not extra message properties.
9
+ *
5
10
  * A string rather than a boolean because every caller shows it to somebody —
6
11
  * a dapp developer reading a validation error, or a person looking at the
7
12
  * mobile app's demo screen.
8
13
  */
9
14
  function validateTypedAction(value) {
10
15
  if (value === undefined || value === null) {
11
- return 'action is required for arc_eligibility. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
16
+ return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
12
17
  }
13
18
  if (typeof value !== 'object' || Array.isArray(value)) {
14
19
  return 'action must be an object.';
@@ -1 +1 @@
1
- {"version":3,"file":"typedAction.esm.js","sources":["../src/typedAction.ts"],"sourcesContent":["/**\n * Checking the EIP-712 action an `arc_eligibility` 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 * 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 for arc_eligibility. 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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"}
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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"}
@@ -4,13 +4,18 @@ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
4
4
  /**
5
5
  * The reason the value is not a usable action, or `null` when it is one.
6
6
  *
7
+ * Structural validation only, not application authorization policy. Consumers
8
+ * (e.g. EligibilityGate) must independently enforce the expected chain, verifying
9
+ * contract, actor, action parameters, nonce and deadline as applicable.
10
+ * EIP-712 signs only fields declared in types, not extra message properties.
11
+ *
7
12
  * A string rather than a boolean because every caller shows it to somebody —
8
13
  * a dapp developer reading a validation error, or a person looking at the
9
14
  * mobile app's demo screen.
10
15
  */
11
16
  function validateTypedAction(value) {
12
17
  if (value === undefined || value === null) {
13
- return 'action is required for arc_eligibility. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
18
+ return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
14
19
  }
15
20
  if (typeof value !== 'object' || Array.isArray(value)) {
16
21
  return 'action must be an object.';
@@ -1 +1 @@
1
- {"version":3,"file":"typedAction.js","sources":["../src/typedAction.ts"],"sourcesContent":["/**\n * Checking the EIP-712 action an `arc_eligibility` 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 * 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 for arc_eligibility. 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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"}
1
+ {"version":3,"file":"typedAction.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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"}
@@ -2,13 +2,18 @@ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
2
2
  /**
3
3
  * The reason the value is not a usable action, or `null` when it is one.
4
4
  *
5
+ * Structural validation only, not application authorization policy. Consumers
6
+ * (e.g. EligibilityGate) must independently enforce the expected chain, verifying
7
+ * contract, actor, action parameters, nonce and deadline as applicable.
8
+ * EIP-712 signs only fields declared in types, not extra message properties.
9
+ *
5
10
  * A string rather than a boolean because every caller shows it to somebody —
6
11
  * a dapp developer reading a validation error, or a person looking at the
7
12
  * mobile app's demo screen.
8
13
  */
9
14
  function validateTypedAction(value) {
10
15
  if (value === undefined || value === null) {
11
- return 'action is required for arc_eligibility. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
16
+ return 'action is required. The circuit proves that a wallet authorised ONE EIP-712 action; there is nothing to prove without it.';
12
17
  }
13
18
  if (typeof value !== 'object' || Array.isArray(value)) {
14
19
  return 'action must be an object.';
@@ -1 +1 @@
1
- {"version":3,"file":"typedAction.mjs","sources":["../src/typedAction.ts"],"sourcesContent":["/**\n * Checking the EIP-712 action an `arc_eligibility` 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 * 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 for arc_eligibility. 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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"}
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":"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"}
package/dist/types.d.ts CHANGED
@@ -168,7 +168,7 @@ export interface MdlKrRegionInputs {
168
168
  export interface EmptyInputs {
169
169
  }
170
170
  /**
171
- * The EIP-712 action an `arc_eligibility` proof binds the wallet's signature to.
171
+ * The EIP-712 action a `giwa_attestation` proof binds the wallet's signature to.
172
172
  *
173
173
  * Exactly what `eth_signTypedData_v4` takes, because that is what the wallet is
174
174
  * shown and what it signs. The app does not build this — the dapp does — so the
@@ -178,7 +178,7 @@ export interface EmptyInputs {
178
178
  * @example
179
179
  * ```typescript
180
180
  * const action: TypedAction = {
181
- * domain: { name: 'MyVault', version: '1', chainId: 5042002,
181
+ * domain: { name: 'MyVault', version: '1', chainId: 91342,
182
182
  * verifyingContract: '0x…' },
183
183
  * types: { Deposit: [ { name: 'amount', type: 'uint256' },
184
184
  * { name: 'nonce', type: 'uint256' } ] },
@@ -205,34 +205,42 @@ export interface TypedAction {
205
205
  message: Record<string, unknown>;
206
206
  }
207
207
  /**
208
- * Input parameters for the Arc eligibility circuit.
208
+ * Input parameters for circuits that can bind an EIP-712 action
209
+ * (`giwa_attestation`).
209
210
  *
210
- * Proves the same Coinbase attestation as `coinbase_attestation`, with the
211
- * wallet signing a typed action instead of an opaque signal hash. The proof's
211
+ * The wallet signs a typed action instead of an opaque signal hash. The proof's
212
212
  * public inputs then carry the action's domain separator and struct hash, so a
213
213
  * verifier checks WHICH action was authorised — not merely that somebody
214
214
  * eligible signed something.
215
215
  *
216
- * `action` is REQUIRED. There is no version of this circuit without one: its
217
- * public inputs have the two slots and nothing else can fill them. Ask for
218
- * `coinbase_attestation` when there is no action to bind.
219
- *
220
216
  * @property scope - Scope string for nullifier derivation
221
217
  * @property action - The EIP-712 action the wallet signs
222
218
  * @property userAddress - Ethereum address to prove ownership of (optional)
223
219
  * @property rawTransaction - Raw attestation transaction data (optional)
224
220
  */
225
- export interface ArcEligibilityInputs {
221
+ export interface ActionBoundInputs {
226
222
  scope: string;
227
- action: TypedAction;
228
223
  userAddress?: string;
229
224
  rawTransaction?: string;
225
+ /**
226
+ * The EIP-712 action this proof authorizes.
227
+ *
228
+ * Optional in the TYPE; whether a circuit requires it is the circuit's
229
+ * property (`giwa_attestation` signs its signal hash instead when none is
230
+ * given). That difference lives in `CIRCUIT_ACTION_BINDING` and is
231
+ * enforced by `createRelayRequest` and the deep-link validator, so it is not
232
+ * written a second time here -- two copies of one rule drift, and the copy
233
+ * that drifts is the one nobody is looking at.
234
+ */
235
+ action?: TypedAction;
230
236
  }
237
+ /** The same shape, for the circuit whose action is optional. */
238
+ export type GiwaAttestationInputs = ActionBoundInputs;
231
239
  /**
232
240
  * Union type of all circuit-specific input types.
233
241
  * Each circuit type has a corresponding input interface.
234
242
  */
235
- export type CircuitInputs = CoinbaseKycInputs | ArcEligibilityInputs | CoinbaseCountryInputs | OidcDomainInputs | MdlKrOwnershipInputs | MdlKrAgeInputs | MdlKrRegionInputs | EmptyInputs;
243
+ export type CircuitInputs = CoinbaseKycInputs | ActionBoundInputs | CoinbaseCountryInputs | OidcDomainInputs | MdlKrOwnershipInputs | MdlKrAgeInputs | MdlKrRegionInputs | EmptyInputs;
236
244
  /**
237
245
  * Zero-knowledge proof request sent to mobile app via deep link.
238
246
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zkproofport-app/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "ZKProofport SDK for requesting zero-knowledge proofs from the ZKProofport mobile app and verifying them on-chain",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",