@oleary-labs/signet-sdk 0.1.0 → 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 +210 -0
- package/dist/generate-inputs.d.ts +26 -0
- package/dist/generate-inputs.d.ts.map +1 -0
- package/dist/generate-inputs.js +106 -0
- package/dist/generate-inputs.js.map +1 -0
- package/dist/partial-sha.d.ts +5 -0
- package/dist/partial-sha.d.ts.map +1 -0
- package/dist/partial-sha.js +89 -0
- package/dist/partial-sha.js.map +1 -0
- package/dist/proof.d.ts +30 -0
- package/dist/proof.d.ts.map +1 -0
- package/dist/proof.js +72 -0
- package/dist/proof.js.map +1 -0
- package/dist/scopedSign.d.ts +27 -3
- package/dist/scopedSign.d.ts.map +1 -1
- package/dist/scopedSign.js +71 -11
- package/dist/scopedSign.js.map +1 -1
- package/dist/witness.d.ts +51 -0
- package/dist/witness.d.ts.map +1 -0
- package/dist/witness.js +81 -0
- package/dist/witness.js.map +1 -0
- package/package.json +93 -27
- package/src/scopedSign.test.ts +97 -0
- package/src/scopedSign.ts +92 -8
package/dist/scopedSign.js
CHANGED
|
@@ -5,18 +5,60 @@
|
|
|
5
5
|
* structured payload that the node verifies against the key's scope
|
|
6
6
|
* before computing the hash and signing.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
import { hashTypedData, keccak256, stringToBytes } from "viem";
|
|
9
|
+
import { signSignRequest } from "./request";
|
|
10
|
+
import { hexToBytes } from "./session";
|
|
11
|
+
/**
|
|
12
|
+
* Encode an EIP-712 type per the spec: the primary type's definition
|
|
13
|
+
* followed by its referenced struct types in alphabetical order, e.g.
|
|
14
|
+
* `TransferWithAuthorization(address from,address to,uint256 value,...)`.
|
|
15
|
+
* Matches go-ethereum's `apitypes.TypeHash` encoding used by the node, so
|
|
16
|
+
* the resulting typeHash byte-matches what the node verifies.
|
|
17
|
+
*/
|
|
18
|
+
function encodeEIP712Type(primaryType, types) {
|
|
19
|
+
const deps = new Set();
|
|
20
|
+
const visit = (t) => {
|
|
21
|
+
const base = t.replace(/(\[\d*\])+$/, ""); // strip array suffixes
|
|
22
|
+
if (!types[base] || deps.has(base))
|
|
23
|
+
return;
|
|
24
|
+
deps.add(base);
|
|
25
|
+
for (const f of types[base])
|
|
26
|
+
visit(f.type);
|
|
27
|
+
};
|
|
28
|
+
for (const f of types[primaryType] ?? [])
|
|
29
|
+
visit(f.type);
|
|
30
|
+
const sorted = [...deps].filter((d) => d !== primaryType).sort();
|
|
31
|
+
const encodeOne = (t) => `${t}(${types[t].map((f) => `${f.type} ${f.name}`).join(",")})`;
|
|
32
|
+
return [primaryType, ...sorted].map(encodeOne).join("");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* EIP-712 typeHash: keccak256(encodeType(primaryType)). This is the value a
|
|
36
|
+
* 0x03 scope binds, and the same value the verifying contract uses — so a
|
|
37
|
+
* key scoped to one method (e.g. TransferWithAuthorization) cannot sign a
|
|
38
|
+
* different method on the same contract (e.g. permit).
|
|
39
|
+
*/
|
|
40
|
+
export function eip712TypeHash(primaryType, types) {
|
|
41
|
+
if (!types[primaryType]) {
|
|
42
|
+
throw new Error(`primaryType "${primaryType}" not declared in types`);
|
|
43
|
+
}
|
|
44
|
+
return keccak256(stringToBytes(encodeEIP712Type(primaryType, types)));
|
|
45
|
+
}
|
|
12
46
|
/**
|
|
13
|
-
* Build an EIP-712 domain scope (scheme 0x03).
|
|
47
|
+
* Build an EIP-712 domain+type scope (scheme 0x03).
|
|
14
48
|
*
|
|
15
49
|
* Format: 0x03 | chainId (8 bytes, uint64 BE) | verifyingContract (20 bytes)
|
|
16
|
-
* Total:
|
|
50
|
+
* | typeHash (32 bytes). Total: 61 bytes.
|
|
51
|
+
*
|
|
52
|
+
* `typeHash` is keccak256(encodeType(primaryType)) — see {@link eip712TypeHash}.
|
|
53
|
+
* Binding the type (not just the domain) prevents a key authorized for one
|
|
54
|
+
* typed-data method from signing a different method on the same contract.
|
|
17
55
|
*/
|
|
18
|
-
export function buildEIP712Scope(chainId, verifyingContract) {
|
|
19
|
-
const
|
|
56
|
+
export function buildEIP712Scope(chainId, verifyingContract, typeHash) {
|
|
57
|
+
const th = typeHash.startsWith("0x") ? typeHash.slice(2) : typeHash;
|
|
58
|
+
if (th.length !== 64) {
|
|
59
|
+
throw new Error(`typeHash must be 32 bytes (64 hex chars), got ${th.length}`);
|
|
60
|
+
}
|
|
61
|
+
const buf = new Uint8Array(61);
|
|
20
62
|
buf[0] = 0x03;
|
|
21
63
|
// chainId as 8-byte big-endian
|
|
22
64
|
const view = new DataView(buf.buffer);
|
|
@@ -28,8 +70,22 @@ export function buildEIP712Scope(chainId, verifyingContract) {
|
|
|
28
70
|
for (let i = 0; i < 20; i++) {
|
|
29
71
|
buf[9 + i] = parseInt(addr.slice(i * 2, i * 2 + 2), 16);
|
|
30
72
|
}
|
|
73
|
+
// typeHash as 32 bytes
|
|
74
|
+
for (let i = 0; i < 32; i++) {
|
|
75
|
+
buf[29 + i] = parseInt(th.slice(i * 2, i * 2 + 2), 16);
|
|
76
|
+
}
|
|
31
77
|
return "0x" + Array.from(buf).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
32
78
|
}
|
|
79
|
+
/**
|
|
80
|
+
* Convenience: build a 0x03 scope directly from an EIP-712 typed-data sample,
|
|
81
|
+
* deriving chainId, verifyingContract, and typeHash from it. Any sample with
|
|
82
|
+
* the intended domain + primary type works (message values are irrelevant to
|
|
83
|
+
* the scope). This is the recommended way to scope a key for a given method.
|
|
84
|
+
*/
|
|
85
|
+
export function buildEIP712ScopeForTypedData(typedData) {
|
|
86
|
+
const typeHash = eip712TypeHash(typedData.primaryType, typedData.types);
|
|
87
|
+
return buildEIP712Scope(typedData.domain.chainId, typedData.domain.verifyingContract, typeHash);
|
|
88
|
+
}
|
|
33
89
|
// ---------------------------------------------------------------------------
|
|
34
90
|
// Structured signing
|
|
35
91
|
// ---------------------------------------------------------------------------
|
|
@@ -50,13 +106,17 @@ export function buildEIP712Scope(chainId, verifyingContract) {
|
|
|
50
106
|
* @param identity - For auth key cert sessions
|
|
51
107
|
*/
|
|
52
108
|
export async function signTypedData(nodeUrl, proxyEndpoint, groupId, keyId, curve, typedData, sessionKeypair, claims, identity) {
|
|
53
|
-
//
|
|
54
|
-
// The canonical hash must use the full sub-key ID (identity + suffix).
|
|
109
|
+
// The canonical request hash must use the full sub-key ID (identity + suffix).
|
|
55
110
|
// Extract suffix from keyId: "oauth:iss:sub:suffix" → suffix is last segment
|
|
56
111
|
// The identity param is "iss:sub", so we need to add the suffix.
|
|
57
112
|
const keyParts = keyId.split(":");
|
|
58
113
|
const keySuffix = keyParts.length > 1 ? keyParts[keyParts.length - 1] : undefined;
|
|
59
|
-
|
|
114
|
+
// Compute the EIP-712 hash locally and bind it into the session request
|
|
115
|
+
// signature. The nodes recompute hashTypedData from the payload and verify
|
|
116
|
+
// the request signature against it — without this binding, a malicious
|
|
117
|
+
// initiator could substitute any payload matching the key's scope.
|
|
118
|
+
const payloadHash = hexToBytes(hashTypedData(typedData).slice(2));
|
|
119
|
+
const signReq = await signSignRequest(sessionKeypair, claims, groupId, payloadHash, keySuffix, identity);
|
|
60
120
|
const res = await fetch(proxyEndpoint, {
|
|
61
121
|
method: "POST",
|
|
62
122
|
headers: {
|
package/dist/scopedSign.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scopedSign.js","sourceRoot":"","sources":["../src/scopedSign.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"scopedSign.js","sourceRoot":"","sources":["../src/scopedSign.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZK proof witness construction for the jwt_auth noir circuit.
|
|
3
|
+
*
|
|
4
|
+
* Uses generateInputs from noir-jwt for the core RSA/JWT witness,
|
|
5
|
+
* then adds the claim assertions and session_pub binding that our
|
|
6
|
+
* circuit requires.
|
|
7
|
+
*/
|
|
8
|
+
import type { IdTokenClaims } from "./types";
|
|
9
|
+
/** Full witness for the jwt_auth circuit (Prover.toml format). */
|
|
10
|
+
export interface FullCircuitWitness {
|
|
11
|
+
data: {
|
|
12
|
+
storage: number[];
|
|
13
|
+
len: number;
|
|
14
|
+
};
|
|
15
|
+
base64_decode_offset: number;
|
|
16
|
+
pubkey_modulus_limbs: string[];
|
|
17
|
+
redc_params_limbs: string[];
|
|
18
|
+
signature_limbs: string[];
|
|
19
|
+
expected_iss: {
|
|
20
|
+
storage: number[];
|
|
21
|
+
len: number;
|
|
22
|
+
};
|
|
23
|
+
expected_sub: {
|
|
24
|
+
storage: number[];
|
|
25
|
+
len: number;
|
|
26
|
+
};
|
|
27
|
+
expected_exp: number;
|
|
28
|
+
expected_aud: {
|
|
29
|
+
storage: number[];
|
|
30
|
+
len: number;
|
|
31
|
+
};
|
|
32
|
+
expected_azp: {
|
|
33
|
+
storage: number[];
|
|
34
|
+
len: number;
|
|
35
|
+
};
|
|
36
|
+
_session_pub: number[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Build full circuit witness from a JWT, JWKS key, and session public key.
|
|
40
|
+
*
|
|
41
|
+
* @param jwt — raw JWT string
|
|
42
|
+
* @param jwksKey — the RSA public key from Google JWKS (as JsonWebKey)
|
|
43
|
+
* @param claims — decoded JWT claims
|
|
44
|
+
* @param sessionPubBytes — 33-byte compressed secp256k1 session public key
|
|
45
|
+
*/
|
|
46
|
+
export declare function buildFullWitness(jwt: string, jwksKey: JsonWebKey, claims: IdTokenClaims, sessionPubBytes: number[]): Promise<FullCircuitWitness>;
|
|
47
|
+
/**
|
|
48
|
+
* Serialize a FullCircuitWitness to Prover.toml format for nargo.
|
|
49
|
+
*/
|
|
50
|
+
export declare function witnessToProverToml(w: FullCircuitWitness): string;
|
|
51
|
+
//# sourceMappingURL=witness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"witness.d.ts","sourceRoot":"","sources":["../src/witness.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IAEjC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACzC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,EAAE,CAAC;IAG1B,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD,YAAY,EAAE;QAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAGjD,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,UAAU,EACnB,MAAM,EAAE,aAAa,EACrB,eAAe,EAAE,MAAM,EAAE,GACxB,OAAO,CAAC,kBAAkB,CAAC,CA8B7B;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CA8BjE"}
|
package/dist/witness.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZK proof witness construction for the jwt_auth noir circuit.
|
|
3
|
+
*
|
|
4
|
+
* Uses generateInputs from noir-jwt for the core RSA/JWT witness,
|
|
5
|
+
* then adds the claim assertions and session_pub binding that our
|
|
6
|
+
* circuit requires.
|
|
7
|
+
*/
|
|
8
|
+
import { generateInputs } from "./generate-inputs";
|
|
9
|
+
/**
|
|
10
|
+
* Build full circuit witness from a JWT, JWKS key, and session public key.
|
|
11
|
+
*
|
|
12
|
+
* @param jwt — raw JWT string
|
|
13
|
+
* @param jwksKey — the RSA public key from Google JWKS (as JsonWebKey)
|
|
14
|
+
* @param claims — decoded JWT claims
|
|
15
|
+
* @param sessionPubBytes — 33-byte compressed secp256k1 session public key
|
|
16
|
+
*/
|
|
17
|
+
export async function buildFullWitness(jwt, jwksKey, claims, sessionPubBytes) {
|
|
18
|
+
// Generate core JWT/RSA inputs using noir-jwt library
|
|
19
|
+
const inputs = await generateInputs({
|
|
20
|
+
jwt,
|
|
21
|
+
pubkey: jwksKey,
|
|
22
|
+
maxSignedDataLength: 1024,
|
|
23
|
+
});
|
|
24
|
+
if (!inputs.data) {
|
|
25
|
+
throw new Error("Expected full data mode (no partial SHA)");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
// Core JWT/RSA witness
|
|
29
|
+
data: inputs.data,
|
|
30
|
+
base64_decode_offset: inputs.base64_decode_offset,
|
|
31
|
+
pubkey_modulus_limbs: inputs.pubkey_modulus_limbs,
|
|
32
|
+
redc_params_limbs: inputs.redc_params_limbs,
|
|
33
|
+
signature_limbs: inputs.signature_limbs,
|
|
34
|
+
// Claim assertions
|
|
35
|
+
expected_iss: toBoundedVec(claims.iss, 128),
|
|
36
|
+
expected_sub: toBoundedVec(claims.sub, 128),
|
|
37
|
+
expected_exp: claims.exp,
|
|
38
|
+
expected_aud: toBoundedVec(claims.aud, 128),
|
|
39
|
+
expected_azp: toBoundedVec(claims.azp, 128),
|
|
40
|
+
// Session binding
|
|
41
|
+
_session_pub: sessionPubBytes,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Serialize a FullCircuitWitness to Prover.toml format for nargo.
|
|
46
|
+
*/
|
|
47
|
+
export function witnessToProverToml(w) {
|
|
48
|
+
const lines = [];
|
|
49
|
+
// Bare keys must come before [table] sections in TOML
|
|
50
|
+
lines.push(`base64_decode_offset = ${w.base64_decode_offset}`);
|
|
51
|
+
lines.push(`expected_exp = ${w.expected_exp}`);
|
|
52
|
+
lines.push(`redc_params_limbs = [${w.redc_params_limbs.map((l) => `"${l}"`).join(", ")}]`);
|
|
53
|
+
lines.push(`signature_limbs = [${w.signature_limbs.map((l) => `"${l}"`).join(", ")}]`);
|
|
54
|
+
lines.push(`pubkey_modulus_limbs = [${w.pubkey_modulus_limbs.map((l) => `"${l}"`).join(", ")}]`);
|
|
55
|
+
lines.push(`_session_pub = [${w._session_pub.join(", ")}]`);
|
|
56
|
+
lines.push("");
|
|
57
|
+
// BoundedVec tables
|
|
58
|
+
lines.push("[data]");
|
|
59
|
+
lines.push(`storage = [${w.data.storage.join(", ")}]`);
|
|
60
|
+
lines.push(`len = ${w.data.len}`);
|
|
61
|
+
lines.push("");
|
|
62
|
+
writeBoundedVecToml(lines, "expected_iss", w.expected_iss);
|
|
63
|
+
writeBoundedVecToml(lines, "expected_sub", w.expected_sub);
|
|
64
|
+
writeBoundedVecToml(lines, "expected_aud", w.expected_aud);
|
|
65
|
+
writeBoundedVecToml(lines, "expected_azp", w.expected_azp);
|
|
66
|
+
return lines.join("\n");
|
|
67
|
+
}
|
|
68
|
+
function toBoundedVec(value, maxLen) {
|
|
69
|
+
const storage = new Array(maxLen).fill(0);
|
|
70
|
+
for (let i = 0; i < value.length; i++) {
|
|
71
|
+
storage[i] = value.charCodeAt(i);
|
|
72
|
+
}
|
|
73
|
+
return { storage, len: value.length };
|
|
74
|
+
}
|
|
75
|
+
function writeBoundedVecToml(lines, name, vec) {
|
|
76
|
+
lines.push(`[${name}]`);
|
|
77
|
+
lines.push(`storage = [${vec.storage.join(", ")}]`);
|
|
78
|
+
lines.push(`len = ${vec.len}`);
|
|
79
|
+
lines.push("");
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=witness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"witness.js","sourceRoot":"","sources":["../src/witness.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,31 +1,91 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oleary-labs/signet-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Signet DKMS SDK — threshold signing, key management, delegation, and x402 payments",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".": {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"./
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"./
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"./
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"./
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./session": {
|
|
14
|
+
"import": "./dist/session.js",
|
|
15
|
+
"types": "./dist/session.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./request": {
|
|
18
|
+
"import": "./dist/request.js",
|
|
19
|
+
"types": "./dist/request.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./keygen": {
|
|
22
|
+
"import": "./dist/keygen.js",
|
|
23
|
+
"types": "./dist/keygen.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./types": {
|
|
26
|
+
"import": "./dist/types.js",
|
|
27
|
+
"types": "./dist/types.d.ts"
|
|
28
|
+
},
|
|
29
|
+
"./jwks": {
|
|
30
|
+
"import": "./dist/jwks.js",
|
|
31
|
+
"types": "./dist/jwks.d.ts"
|
|
32
|
+
},
|
|
33
|
+
"./oauth": {
|
|
34
|
+
"import": "./dist/oauth.js",
|
|
35
|
+
"types": "./dist/oauth.d.ts"
|
|
36
|
+
},
|
|
37
|
+
"./bootstrap": {
|
|
38
|
+
"import": "./dist/bootstrap.js",
|
|
39
|
+
"types": "./dist/bootstrap.d.ts"
|
|
40
|
+
},
|
|
41
|
+
"./authkey-session": {
|
|
42
|
+
"import": "./dist/authkey-session.js",
|
|
43
|
+
"types": "./dist/authkey-session.d.ts"
|
|
44
|
+
},
|
|
45
|
+
"./proof": {
|
|
46
|
+
"import": "./dist/proof.js",
|
|
47
|
+
"types": "./dist/proof.d.ts"
|
|
48
|
+
},
|
|
49
|
+
"./server-prover": {
|
|
50
|
+
"import": "./dist/server-prover.js",
|
|
51
|
+
"types": "./dist/server-prover.d.ts"
|
|
52
|
+
},
|
|
53
|
+
"./witness": {
|
|
54
|
+
"import": "./dist/witness.js",
|
|
55
|
+
"types": "./dist/witness.d.ts"
|
|
56
|
+
},
|
|
57
|
+
"./jwt": {
|
|
58
|
+
"import": "./dist/jwt.js",
|
|
59
|
+
"types": "./dist/jwt.d.ts"
|
|
60
|
+
},
|
|
61
|
+
"./admin": {
|
|
62
|
+
"import": "./dist/admin.js",
|
|
63
|
+
"types": "./dist/admin.d.ts"
|
|
64
|
+
},
|
|
65
|
+
"./delegate": {
|
|
66
|
+
"import": "./dist/delegate.js",
|
|
67
|
+
"types": "./dist/delegate.d.ts"
|
|
68
|
+
},
|
|
69
|
+
"./scopedSign": {
|
|
70
|
+
"import": "./dist/scopedSign.js",
|
|
71
|
+
"types": "./dist/scopedSign.d.ts"
|
|
72
|
+
},
|
|
73
|
+
"./frostVerify": {
|
|
74
|
+
"import": "./dist/frostVerify.js",
|
|
75
|
+
"types": "./dist/frostVerify.d.ts"
|
|
76
|
+
},
|
|
77
|
+
"./x402": {
|
|
78
|
+
"import": "./dist/x402.js",
|
|
79
|
+
"types": "./dist/x402.d.ts"
|
|
80
|
+
},
|
|
81
|
+
"./userop": {
|
|
82
|
+
"import": "./dist/userop.js",
|
|
83
|
+
"types": "./dist/userop.d.ts"
|
|
84
|
+
},
|
|
85
|
+
"./bundler": {
|
|
86
|
+
"import": "./dist/bundler.js",
|
|
87
|
+
"types": "./dist/bundler.d.ts"
|
|
88
|
+
}
|
|
29
89
|
},
|
|
30
90
|
"files": [
|
|
31
91
|
"dist",
|
|
@@ -38,14 +98,20 @@
|
|
|
38
98
|
},
|
|
39
99
|
"peerDependencies": {
|
|
40
100
|
"viem": ">=2.0.0",
|
|
41
|
-
"@noir-lang/noir_js": "
|
|
42
|
-
"@aztec/bb.js": "
|
|
43
|
-
"@oleary-labs/signet-circuits": "
|
|
101
|
+
"@noir-lang/noir_js": "1.0.0-beta.11",
|
|
102
|
+
"@aztec/bb.js": "0.82.2",
|
|
103
|
+
"@oleary-labs/signet-circuits": "^0.3.0"
|
|
44
104
|
},
|
|
45
105
|
"peerDependenciesMeta": {
|
|
46
|
-
"@noir-lang/noir_js": {
|
|
47
|
-
|
|
48
|
-
|
|
106
|
+
"@noir-lang/noir_js": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"@aztec/bb.js": {
|
|
110
|
+
"optional": true
|
|
111
|
+
},
|
|
112
|
+
"@oleary-labs/signet-circuits": {
|
|
113
|
+
"optional": true
|
|
114
|
+
}
|
|
49
115
|
},
|
|
50
116
|
"dependencies": {
|
|
51
117
|
"@noble/curves": "^1.9.0",
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { test, expect } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
eip712TypeHash,
|
|
4
|
+
buildEIP712Scope,
|
|
5
|
+
buildEIP712ScopeForTypedData,
|
|
6
|
+
} from "./scopedSign";
|
|
7
|
+
|
|
8
|
+
// Canonical EIP-3009 TransferWithAuthorization typehash, as used by USDC and
|
|
9
|
+
// every EIP-712 verifier. If our encodeType/typeHash matches this, it matches
|
|
10
|
+
// both the on-chain contract and the node (go-ethereum apitypes.TypeHash).
|
|
11
|
+
const TWA_TYPEHASH =
|
|
12
|
+
"0x7c7c6cdb67a18743f49ec6fa9b35f50d52ed05cbed4cc592e13b44501c1a2267";
|
|
13
|
+
|
|
14
|
+
const TWA_TYPES = {
|
|
15
|
+
EIP712Domain: [
|
|
16
|
+
{ name: "name", type: "string" },
|
|
17
|
+
{ name: "version", type: "string" },
|
|
18
|
+
{ name: "chainId", type: "uint256" },
|
|
19
|
+
{ name: "verifyingContract", type: "address" },
|
|
20
|
+
],
|
|
21
|
+
TransferWithAuthorization: [
|
|
22
|
+
{ name: "from", type: "address" },
|
|
23
|
+
{ name: "to", type: "address" },
|
|
24
|
+
{ name: "value", type: "uint256" },
|
|
25
|
+
{ name: "validAfter", type: "uint256" },
|
|
26
|
+
{ name: "validBefore", type: "uint256" },
|
|
27
|
+
{ name: "nonce", type: "bytes32" },
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
test("eip712TypeHash matches the canonical EIP-3009 typehash", () => {
|
|
32
|
+
expect(eip712TypeHash("TransferWithAuthorization", TWA_TYPES)).toBe(TWA_TYPEHASH);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("eip712TypeHash differs for a different method (permit)", () => {
|
|
36
|
+
const permitTypes = {
|
|
37
|
+
Permit: [
|
|
38
|
+
{ name: "owner", type: "address" },
|
|
39
|
+
{ name: "spender", type: "address" },
|
|
40
|
+
{ name: "value", type: "uint256" },
|
|
41
|
+
{ name: "nonce", type: "uint256" },
|
|
42
|
+
{ name: "deadline", type: "uint256" },
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
expect(eip712TypeHash("Permit", permitTypes)).not.toBe(TWA_TYPEHASH);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("eip712TypeHash includes nested struct dependencies, sorted", () => {
|
|
49
|
+
// encodeType must append referenced structs alphabetically:
|
|
50
|
+
// "Mail(Person from,Person to)Person(address wallet)"
|
|
51
|
+
const types = {
|
|
52
|
+
Mail: [
|
|
53
|
+
{ name: "from", type: "Person" },
|
|
54
|
+
{ name: "to", type: "Person" },
|
|
55
|
+
],
|
|
56
|
+
Person: [{ name: "wallet", type: "address" }],
|
|
57
|
+
};
|
|
58
|
+
// keccak256 of the expected encodeType string.
|
|
59
|
+
// (verified against viem hashStruct / go-ethereum elsewhere)
|
|
60
|
+
const expected =
|
|
61
|
+
eip712TypeHash("Mail", types);
|
|
62
|
+
// sanity: a layout change (drop nested field) yields a different hash.
|
|
63
|
+
const altered = {
|
|
64
|
+
Mail: [
|
|
65
|
+
{ name: "from", type: "Person" },
|
|
66
|
+
{ name: "to", type: "Person" },
|
|
67
|
+
],
|
|
68
|
+
Person: [{ name: "name", type: "string" }],
|
|
69
|
+
};
|
|
70
|
+
expect(eip712TypeHash("Mail", altered)).not.toBe(expected);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
test("buildEIP712Scope produces a 61-byte 0x03 scope with the typeHash", () => {
|
|
74
|
+
const contract = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
75
|
+
const scope = buildEIP712Scope(8453, contract, TWA_TYPEHASH);
|
|
76
|
+
const bytes = scope.slice(2);
|
|
77
|
+
expect(bytes.length).toBe(61 * 2);
|
|
78
|
+
expect(bytes.slice(0, 2)).toBe("03"); // scheme
|
|
79
|
+
// typeHash occupies the final 32 bytes.
|
|
80
|
+
expect("0x" + bytes.slice(29 * 2)).toBe(TWA_TYPEHASH);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("buildEIP712Scope rejects a bad-length typeHash", () => {
|
|
84
|
+
expect(() => buildEIP712Scope(1, "0x" + "11".repeat(20), "0x1234")).toThrow();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("buildEIP712ScopeForTypedData derives chain/contract/type from a sample", () => {
|
|
88
|
+
const contract = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
|
|
89
|
+
const td = {
|
|
90
|
+
domain: { name: "USD Coin", version: "2", chainId: 8453, verifyingContract: contract },
|
|
91
|
+
types: TWA_TYPES,
|
|
92
|
+
primaryType: "TransferWithAuthorization",
|
|
93
|
+
message: {},
|
|
94
|
+
};
|
|
95
|
+
const scope = buildEIP712ScopeForTypedData(td);
|
|
96
|
+
expect(scope).toBe(buildEIP712Scope(8453, contract, TWA_TYPEHASH));
|
|
97
|
+
});
|