@zkproofport-app/sdk 0.2.15 → 0.3.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.
- package/README.md +70 -2
- package/dist/ProofportSDK.d.ts +1 -1
- package/dist/circuits.d.ts +45 -3
- package/dist/circuits.esm.js +58 -10
- package/dist/circuits.esm.js.map +1 -1
- package/dist/circuits.js +59 -9
- package/dist/circuits.js.map +1 -1
- package/dist/circuits.mjs +58 -10
- package/dist/circuits.mjs.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.js +472 -290
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +474 -289
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +472 -290
- package/dist/index.mjs.map +1 -1
- package/dist/typedAction.d.ts +29 -0
- package/dist/typedAction.esm.js +72 -0
- package/dist/typedAction.esm.js.map +1 -0
- package/dist/typedAction.js +75 -0
- package/dist/typedAction.js.map +1 -0
- package/dist/typedAction.mjs +72 -0
- package/dist/typedAction.mjs.map +1 -0
- package/dist/types.d.ts +62 -1
- package/dist/verifier.d.ts +9 -6
- package/package.json +8 -2
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checking the EIP-712 action an `arc_eligibility` proof binds to.
|
|
3
|
+
*
|
|
4
|
+
* Three places need this answer and they have to agree: a dapp building the
|
|
5
|
+
* request, this SDK validating a deep link, and the mobile app before it asks
|
|
6
|
+
* a wallet to sign. The check lived in the mobile app's demo screen and
|
|
7
|
+
* nowhere else, so an action arriving from a dapp reached the prover
|
|
8
|
+
* unexamined — and that is the path that ships.
|
|
9
|
+
*
|
|
10
|
+
* The circuit hashes the domain and the struct and proves the wallet signed
|
|
11
|
+
* them. It never learns what the action says, so a malformed one does not
|
|
12
|
+
* fail: it produces a valid proof of the wrong thing.
|
|
13
|
+
*/
|
|
14
|
+
import type { TypedAction } from './types';
|
|
15
|
+
export type { TypedAction };
|
|
16
|
+
/**
|
|
17
|
+
* The reason the value is not a usable action, or `null` when it is one.
|
|
18
|
+
*
|
|
19
|
+
* A string rather than a boolean because every caller shows it to somebody —
|
|
20
|
+
* a dapp developer reading a validation error, or a person looking at the
|
|
21
|
+
* mobile app's demo screen.
|
|
22
|
+
*/
|
|
23
|
+
export declare function validateTypedAction(value: unknown): string | null;
|
|
24
|
+
/** The action, or the reason it is not one. For text a person typed. */
|
|
25
|
+
export declare function parseTypedAction(text: string): {
|
|
26
|
+
action: TypedAction;
|
|
27
|
+
} | {
|
|
28
|
+
error: string;
|
|
29
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
2
|
+
/**
|
|
3
|
+
* The reason the value is not a usable action, or `null` when it is one.
|
|
4
|
+
*
|
|
5
|
+
* A string rather than a boolean because every caller shows it to somebody —
|
|
6
|
+
* a dapp developer reading a validation error, or a person looking at the
|
|
7
|
+
* mobile app's demo screen.
|
|
8
|
+
*/
|
|
9
|
+
function validateTypedAction(value) {
|
|
10
|
+
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.';
|
|
12
|
+
}
|
|
13
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
14
|
+
return 'action must be an object.';
|
|
15
|
+
}
|
|
16
|
+
const a = value;
|
|
17
|
+
const d = a.domain;
|
|
18
|
+
if (!d || typeof d !== 'object') {
|
|
19
|
+
return 'action.domain is required.';
|
|
20
|
+
}
|
|
21
|
+
for (const k of ['name', 'version', 'verifyingContract']) {
|
|
22
|
+
if (typeof d[k] !== 'string' || !d[k]) {
|
|
23
|
+
return `action.domain.${k} must be a non-empty string.`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {
|
|
27
|
+
return 'action.domain.chainId must be an integer.';
|
|
28
|
+
}
|
|
29
|
+
if (!ADDRESS.test(d.verifyingContract)) {
|
|
30
|
+
return 'action.domain.verifyingContract must be a 20-byte hex address.';
|
|
31
|
+
}
|
|
32
|
+
if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {
|
|
33
|
+
return 'action.types is required.';
|
|
34
|
+
}
|
|
35
|
+
if (typeof a.primaryType !== 'string' || !a.primaryType) {
|
|
36
|
+
return 'action.primaryType is required.';
|
|
37
|
+
}
|
|
38
|
+
if (!(a.primaryType in a.types)) {
|
|
39
|
+
return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;
|
|
40
|
+
}
|
|
41
|
+
if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {
|
|
42
|
+
return 'action.message is required.';
|
|
43
|
+
}
|
|
44
|
+
// Every field the struct declares must be present, or the wallet signs a
|
|
45
|
+
// different message than the one the caller described.
|
|
46
|
+
const fields = a.types[a.primaryType];
|
|
47
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
48
|
+
return `action.types.${a.primaryType} declares no fields.`;
|
|
49
|
+
}
|
|
50
|
+
const missing = fields
|
|
51
|
+
.map(f => f?.name)
|
|
52
|
+
.filter(n => typeof n === 'string' && !(n in a.message));
|
|
53
|
+
if (missing.length) {
|
|
54
|
+
return `action.message is missing: ${missing.join(', ')}`;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
/** The action, or the reason it is not one. For text a person typed. */
|
|
59
|
+
function parseTypedAction(text) {
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = JSON.parse(text);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
return { error: `Not valid JSON: ${e.message}` };
|
|
66
|
+
}
|
|
67
|
+
const error = validateTypedAction(raw);
|
|
68
|
+
return error ? { error } : { action: raw };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { parseTypedAction, validateTypedAction };
|
|
72
|
+
//# sourceMappingURL=typedAction.esm.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
4
|
+
/**
|
|
5
|
+
* The reason the value is not a usable action, or `null` when it is one.
|
|
6
|
+
*
|
|
7
|
+
* A string rather than a boolean because every caller shows it to somebody —
|
|
8
|
+
* a dapp developer reading a validation error, or a person looking at the
|
|
9
|
+
* mobile app's demo screen.
|
|
10
|
+
*/
|
|
11
|
+
function validateTypedAction(value) {
|
|
12
|
+
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.';
|
|
14
|
+
}
|
|
15
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
16
|
+
return 'action must be an object.';
|
|
17
|
+
}
|
|
18
|
+
const a = value;
|
|
19
|
+
const d = a.domain;
|
|
20
|
+
if (!d || typeof d !== 'object') {
|
|
21
|
+
return 'action.domain is required.';
|
|
22
|
+
}
|
|
23
|
+
for (const k of ['name', 'version', 'verifyingContract']) {
|
|
24
|
+
if (typeof d[k] !== 'string' || !d[k]) {
|
|
25
|
+
return `action.domain.${k} must be a non-empty string.`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {
|
|
29
|
+
return 'action.domain.chainId must be an integer.';
|
|
30
|
+
}
|
|
31
|
+
if (!ADDRESS.test(d.verifyingContract)) {
|
|
32
|
+
return 'action.domain.verifyingContract must be a 20-byte hex address.';
|
|
33
|
+
}
|
|
34
|
+
if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {
|
|
35
|
+
return 'action.types is required.';
|
|
36
|
+
}
|
|
37
|
+
if (typeof a.primaryType !== 'string' || !a.primaryType) {
|
|
38
|
+
return 'action.primaryType is required.';
|
|
39
|
+
}
|
|
40
|
+
if (!(a.primaryType in a.types)) {
|
|
41
|
+
return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;
|
|
42
|
+
}
|
|
43
|
+
if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {
|
|
44
|
+
return 'action.message is required.';
|
|
45
|
+
}
|
|
46
|
+
// Every field the struct declares must be present, or the wallet signs a
|
|
47
|
+
// different message than the one the caller described.
|
|
48
|
+
const fields = a.types[a.primaryType];
|
|
49
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
50
|
+
return `action.types.${a.primaryType} declares no fields.`;
|
|
51
|
+
}
|
|
52
|
+
const missing = fields
|
|
53
|
+
.map(f => f?.name)
|
|
54
|
+
.filter(n => typeof n === 'string' && !(n in a.message));
|
|
55
|
+
if (missing.length) {
|
|
56
|
+
return `action.message is missing: ${missing.join(', ')}`;
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
/** The action, or the reason it is not one. For text a person typed. */
|
|
61
|
+
function parseTypedAction(text) {
|
|
62
|
+
let raw;
|
|
63
|
+
try {
|
|
64
|
+
raw = JSON.parse(text);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
return { error: `Not valid JSON: ${e.message}` };
|
|
68
|
+
}
|
|
69
|
+
const error = validateTypedAction(raw);
|
|
70
|
+
return error ? { error } : { action: raw };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
exports.parseTypedAction = parseTypedAction;
|
|
74
|
+
exports.validateTypedAction = validateTypedAction;
|
|
75
|
+
//# sourceMappingURL=typedAction.js.map
|
|
@@ -0,0 +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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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
|
|
2
|
+
/**
|
|
3
|
+
* The reason the value is not a usable action, or `null` when it is one.
|
|
4
|
+
*
|
|
5
|
+
* A string rather than a boolean because every caller shows it to somebody —
|
|
6
|
+
* a dapp developer reading a validation error, or a person looking at the
|
|
7
|
+
* mobile app's demo screen.
|
|
8
|
+
*/
|
|
9
|
+
function validateTypedAction(value) {
|
|
10
|
+
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.';
|
|
12
|
+
}
|
|
13
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
14
|
+
return 'action must be an object.';
|
|
15
|
+
}
|
|
16
|
+
const a = value;
|
|
17
|
+
const d = a.domain;
|
|
18
|
+
if (!d || typeof d !== 'object') {
|
|
19
|
+
return 'action.domain is required.';
|
|
20
|
+
}
|
|
21
|
+
for (const k of ['name', 'version', 'verifyingContract']) {
|
|
22
|
+
if (typeof d[k] !== 'string' || !d[k]) {
|
|
23
|
+
return `action.domain.${k} must be a non-empty string.`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (typeof d.chainId !== 'number' || !Number.isInteger(d.chainId)) {
|
|
27
|
+
return 'action.domain.chainId must be an integer.';
|
|
28
|
+
}
|
|
29
|
+
if (!ADDRESS.test(d.verifyingContract)) {
|
|
30
|
+
return 'action.domain.verifyingContract must be a 20-byte hex address.';
|
|
31
|
+
}
|
|
32
|
+
if (!a.types || typeof a.types !== 'object' || Array.isArray(a.types)) {
|
|
33
|
+
return 'action.types is required.';
|
|
34
|
+
}
|
|
35
|
+
if (typeof a.primaryType !== 'string' || !a.primaryType) {
|
|
36
|
+
return 'action.primaryType is required.';
|
|
37
|
+
}
|
|
38
|
+
if (!(a.primaryType in a.types)) {
|
|
39
|
+
return `action.primaryType '${a.primaryType}' is not one of the structs in action.types.`;
|
|
40
|
+
}
|
|
41
|
+
if (!a.message || typeof a.message !== 'object' || Array.isArray(a.message)) {
|
|
42
|
+
return 'action.message is required.';
|
|
43
|
+
}
|
|
44
|
+
// Every field the struct declares must be present, or the wallet signs a
|
|
45
|
+
// different message than the one the caller described.
|
|
46
|
+
const fields = a.types[a.primaryType];
|
|
47
|
+
if (!Array.isArray(fields) || fields.length === 0) {
|
|
48
|
+
return `action.types.${a.primaryType} declares no fields.`;
|
|
49
|
+
}
|
|
50
|
+
const missing = fields
|
|
51
|
+
.map(f => f?.name)
|
|
52
|
+
.filter(n => typeof n === 'string' && !(n in a.message));
|
|
53
|
+
if (missing.length) {
|
|
54
|
+
return `action.message is missing: ${missing.join(', ')}`;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
/** The action, or the reason it is not one. For text a person typed. */
|
|
59
|
+
function parseTypedAction(text) {
|
|
60
|
+
let raw;
|
|
61
|
+
try {
|
|
62
|
+
raw = JSON.parse(text);
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
return { error: `Not valid JSON: ${e.message}` };
|
|
66
|
+
}
|
|
67
|
+
const error = validateTypedAction(raw);
|
|
68
|
+
return error ? { error } : { action: raw };
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { parseTypedAction, validateTypedAction };
|
|
72
|
+
//# sourceMappingURL=typedAction.mjs.map
|
|
@@ -0,0 +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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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -167,11 +167,72 @@ export interface MdlKrRegionInputs {
|
|
|
167
167
|
*/
|
|
168
168
|
export interface EmptyInputs {
|
|
169
169
|
}
|
|
170
|
+
/**
|
|
171
|
+
* The EIP-712 action an `arc_eligibility` proof binds the wallet's signature to.
|
|
172
|
+
*
|
|
173
|
+
* Exactly what `eth_signTypedData_v4` takes, because that is what the wallet is
|
|
174
|
+
* shown and what it signs. The app does not build this — the dapp does — so the
|
|
175
|
+
* user reads the dapp's own field names and values in their wallet instead of
|
|
176
|
+
* an opaque hash.
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const action: TypedAction = {
|
|
181
|
+
* domain: { name: 'MyVault', version: '1', chainId: 5042002,
|
|
182
|
+
* verifyingContract: '0x…' },
|
|
183
|
+
* types: { Deposit: [ { name: 'amount', type: 'uint256' },
|
|
184
|
+
* { name: 'nonce', type: 'uint256' } ] },
|
|
185
|
+
* primaryType: 'Deposit',
|
|
186
|
+
* message: { amount: '1000000', nonce: '7' },
|
|
187
|
+
* };
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export interface TypedAction {
|
|
191
|
+
domain: {
|
|
192
|
+
name: string;
|
|
193
|
+
version: string;
|
|
194
|
+
chainId: number;
|
|
195
|
+
/** The contract that will verify this signature. */
|
|
196
|
+
verifyingContract: string;
|
|
197
|
+
};
|
|
198
|
+
/** EIP-712 struct definitions. `EIP712Domain` is added by the wallet. */
|
|
199
|
+
types: Record<string, Array<{
|
|
200
|
+
name: string;
|
|
201
|
+
type: string;
|
|
202
|
+
}>>;
|
|
203
|
+
/** Which struct in `types` the message is. */
|
|
204
|
+
primaryType: string;
|
|
205
|
+
message: Record<string, unknown>;
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Input parameters for the Arc eligibility circuit.
|
|
209
|
+
*
|
|
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
|
|
212
|
+
* public inputs then carry the action's domain separator and struct hash, so a
|
|
213
|
+
* verifier checks WHICH action was authorised — not merely that somebody
|
|
214
|
+
* eligible signed something.
|
|
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
|
+
* @property scope - Scope string for nullifier derivation
|
|
221
|
+
* @property action - The EIP-712 action the wallet signs
|
|
222
|
+
* @property userAddress - Ethereum address to prove ownership of (optional)
|
|
223
|
+
* @property rawTransaction - Raw attestation transaction data (optional)
|
|
224
|
+
*/
|
|
225
|
+
export interface ArcEligibilityInputs {
|
|
226
|
+
scope: string;
|
|
227
|
+
action: TypedAction;
|
|
228
|
+
userAddress?: string;
|
|
229
|
+
rawTransaction?: string;
|
|
230
|
+
}
|
|
170
231
|
/**
|
|
171
232
|
* Union type of all circuit-specific input types.
|
|
172
233
|
* Each circuit type has a corresponding input interface.
|
|
173
234
|
*/
|
|
174
|
-
export type CircuitInputs = CoinbaseKycInputs | CoinbaseCountryInputs | OidcDomainInputs | MdlKrOwnershipInputs | MdlKrAgeInputs | MdlKrRegionInputs | EmptyInputs;
|
|
235
|
+
export type CircuitInputs = CoinbaseKycInputs | ArcEligibilityInputs | CoinbaseCountryInputs | OidcDomainInputs | MdlKrOwnershipInputs | MdlKrAgeInputs | MdlKrRegionInputs | EmptyInputs;
|
|
175
236
|
/**
|
|
176
237
|
* Zero-knowledge proof request sent to mobile app via deep link.
|
|
177
238
|
*
|
package/dist/verifier.d.ts
CHANGED
|
@@ -42,7 +42,7 @@ export declare function getDefaultProvider(chainId: number): any;
|
|
|
42
42
|
* This function resolves the verifier contract from SDK config or proof response,
|
|
43
43
|
* connects to the blockchain, and calls the verify() method with the proof and public inputs.
|
|
44
44
|
*
|
|
45
|
-
* @param circuit - The canonical circuit identifier
|
|
45
|
+
* @param circuit - The canonical circuit identifier. REQUIRED.
|
|
46
46
|
* @param parsedProof - Parsed proof object containing proofHex and publicInputsHex
|
|
47
47
|
* @param providerOrSigner - Optional ethers.js Provider or Signer instance. If not provided, uses default RPC for the chain
|
|
48
48
|
* @param customVerifier - Optional custom verifier contract config (takes priority over responseVerifier)
|
|
@@ -101,7 +101,7 @@ export declare function parseProofForOnChain(proof: string, publicInputs: string
|
|
|
101
101
|
/**
|
|
102
102
|
* Get verifier contract address for a circuit.
|
|
103
103
|
*
|
|
104
|
-
* @param circuit - The canonical circuit identifier
|
|
104
|
+
* @param circuit - The canonical circuit identifier. REQUIRED.
|
|
105
105
|
* @param customVerifier - Optional custom verifier contract config
|
|
106
106
|
* @returns Verifier contract address as hex string
|
|
107
107
|
* @throws Error if no verifier is configured for the circuit
|
|
@@ -116,7 +116,7 @@ export declare function getVerifierAddress(circuit: CircuitType, customVerifier?
|
|
|
116
116
|
/**
|
|
117
117
|
* Get chain ID for a circuit's verifier contract.
|
|
118
118
|
*
|
|
119
|
-
* @param circuit - The canonical circuit identifier
|
|
119
|
+
* @param circuit - The canonical circuit identifier. REQUIRED.
|
|
120
120
|
* @param customVerifier - Optional custom verifier contract config
|
|
121
121
|
* @returns Chain ID number (e.g., 11155111 for Sepolia, 84532 for Base Sepolia)
|
|
122
122
|
* @throws Error if no verifier is configured for the circuit
|
|
@@ -144,7 +144,7 @@ export declare function getVerifierChainId(circuit: CircuitType, customVerifier?
|
|
|
144
144
|
* console.log(scope); // '0x7a6b70726f6f66706f72742e636f6d...'
|
|
145
145
|
* ```
|
|
146
146
|
*/
|
|
147
|
-
export declare function extractScopeFromPublicInputs(publicInputsHex: string[], circuit
|
|
147
|
+
export declare function extractScopeFromPublicInputs(publicInputsHex: string[], circuit: string): string | null;
|
|
148
148
|
/**
|
|
149
149
|
* Extracts the nullifier (bytes32) from public inputs based on circuit type.
|
|
150
150
|
*
|
|
@@ -154,7 +154,10 @@ export declare function extractScopeFromPublicInputs(publicInputsHex: string[],
|
|
|
154
154
|
* detection without revealing the wallet address.
|
|
155
155
|
*
|
|
156
156
|
* @param publicInputsHex - Array of hex-encoded field elements
|
|
157
|
-
* @param circuit - Circuit
|
|
157
|
+
* @param circuit - Circuit id. REQUIRED: the layout differs per circuit and
|
|
158
|
+
* cannot be inferred from the proof. It used to default to
|
|
159
|
+
* `coinbase_attestation`, which returned the right-shaped bytes read from
|
|
160
|
+
* the wrong place for every other circuit.
|
|
158
161
|
* @returns Nullifier as hex string (bytes32), or null if publicInputs too short
|
|
159
162
|
*
|
|
160
163
|
* @example
|
|
@@ -163,7 +166,7 @@ export declare function extractScopeFromPublicInputs(publicInputsHex: string[],
|
|
|
163
166
|
* console.log(nullifier); // '0xabc123...'
|
|
164
167
|
* ```
|
|
165
168
|
*/
|
|
166
|
-
export declare function extractNullifierFromPublicInputs(publicInputsHex: string[], circuit
|
|
169
|
+
export declare function extractNullifierFromPublicInputs(publicInputsHex: string[], circuit: string): string | null;
|
|
167
170
|
/**
|
|
168
171
|
* Extract domain string from OIDC Domain Attestation public inputs.
|
|
169
172
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zkproofport-app/sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
"import": "./dist/circuits.esm.js",
|
|
17
17
|
"require": "./dist/circuits.js"
|
|
18
18
|
},
|
|
19
|
+
"./typedAction": {
|
|
20
|
+
"types": "./dist/typedAction.d.ts",
|
|
21
|
+
"import": "./dist/typedAction.esm.js",
|
|
22
|
+
"require": "./dist/typedAction.js"
|
|
23
|
+
},
|
|
19
24
|
"./package.json": "./package.json"
|
|
20
25
|
},
|
|
21
26
|
"files": [
|
|
@@ -29,7 +34,8 @@
|
|
|
29
34
|
"test": "vitest run",
|
|
30
35
|
"demo": "cd demo && node server.js",
|
|
31
36
|
"docs": "typedoc",
|
|
32
|
-
"prepublishOnly": "npm run build"
|
|
37
|
+
"prepublishOnly": "npm run build",
|
|
38
|
+
"test:vk-live": "vitest run --config vitest.live.config.ts"
|
|
33
39
|
},
|
|
34
40
|
"dependencies": {
|
|
35
41
|
"@aztec/bb.js": "1.0.0-nightly.20250723",
|