@oleary-labs/signet-sdk 0.1.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.
Files changed (95) hide show
  1. package/dist/admin.d.ts +38 -0
  2. package/dist/admin.d.ts.map +1 -0
  3. package/dist/admin.js +112 -0
  4. package/dist/admin.js.map +1 -0
  5. package/dist/authkey-session.d.ts +64 -0
  6. package/dist/authkey-session.d.ts.map +1 -0
  7. package/dist/authkey-session.js +164 -0
  8. package/dist/authkey-session.js.map +1 -0
  9. package/dist/bootstrap.d.ts +30 -0
  10. package/dist/bootstrap.d.ts.map +1 -0
  11. package/dist/bootstrap.js +60 -0
  12. package/dist/bootstrap.js.map +1 -0
  13. package/dist/bundler.d.ts +85 -0
  14. package/dist/bundler.d.ts.map +1 -0
  15. package/dist/bundler.js +160 -0
  16. package/dist/bundler.js.map +1 -0
  17. package/dist/delegate.d.ts +57 -0
  18. package/dist/delegate.d.ts.map +1 -0
  19. package/dist/delegate.js +111 -0
  20. package/dist/delegate.js.map +1 -0
  21. package/dist/frostVerify.d.ts +23 -0
  22. package/dist/frostVerify.d.ts.map +1 -0
  23. package/dist/frostVerify.js +69 -0
  24. package/dist/frostVerify.js.map +1 -0
  25. package/dist/index.d.ts +32 -0
  26. package/dist/index.d.ts.map +1 -0
  27. package/dist/index.js +38 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/jwks.d.ts +28 -0
  30. package/dist/jwks.d.ts.map +1 -0
  31. package/dist/jwks.js +81 -0
  32. package/dist/jwks.js.map +1 -0
  33. package/dist/jwt.d.ts +27 -0
  34. package/dist/jwt.d.ts.map +1 -0
  35. package/dist/jwt.js +50 -0
  36. package/dist/jwt.js.map +1 -0
  37. package/dist/keygen.d.ts +26 -0
  38. package/dist/keygen.d.ts.map +1 -0
  39. package/dist/keygen.js +60 -0
  40. package/dist/keygen.js.map +1 -0
  41. package/dist/oauth.d.ts +34 -0
  42. package/dist/oauth.d.ts.map +1 -0
  43. package/dist/oauth.js +119 -0
  44. package/dist/oauth.js.map +1 -0
  45. package/dist/request.d.ts +42 -0
  46. package/dist/request.d.ts.map +1 -0
  47. package/dist/request.js +115 -0
  48. package/dist/request.js.map +1 -0
  49. package/dist/scopedSign.d.ts +82 -0
  50. package/dist/scopedSign.d.ts.map +1 -0
  51. package/dist/scopedSign.js +130 -0
  52. package/dist/scopedSign.js.map +1 -0
  53. package/dist/server-prover.d.ts +29 -0
  54. package/dist/server-prover.d.ts.map +1 -0
  55. package/dist/server-prover.js +54 -0
  56. package/dist/server-prover.js.map +1 -0
  57. package/dist/session.d.ts +14 -0
  58. package/dist/session.d.ts.map +1 -0
  59. package/dist/session.js +29 -0
  60. package/dist/session.js.map +1 -0
  61. package/dist/types.d.ts +56 -0
  62. package/dist/types.d.ts.map +1 -0
  63. package/dist/types.js +5 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/userop.d.ts +104 -0
  66. package/dist/userop.d.ts.map +1 -0
  67. package/dist/userop.js +212 -0
  68. package/dist/userop.js.map +1 -0
  69. package/dist/x402.d.ts +127 -0
  70. package/dist/x402.d.ts.map +1 -0
  71. package/dist/x402.js +167 -0
  72. package/dist/x402.js.map +1 -0
  73. package/package.json +64 -0
  74. package/src/admin.ts +178 -0
  75. package/src/authkey-session.ts +241 -0
  76. package/src/bootstrap.ts +106 -0
  77. package/src/bundler.ts +256 -0
  78. package/src/delegate.ts +163 -0
  79. package/src/frostVerify.ts +79 -0
  80. package/src/generate-inputs.ts +158 -0
  81. package/src/index.ts +43 -0
  82. package/src/jwks.ts +92 -0
  83. package/src/jwt.ts +74 -0
  84. package/src/keygen.ts +89 -0
  85. package/src/oauth.ts +157 -0
  86. package/src/partial-sha.ts +99 -0
  87. package/src/proof.ts +99 -0
  88. package/src/request.ts +174 -0
  89. package/src/scopedSign.ts +184 -0
  90. package/src/server-prover.ts +76 -0
  91. package/src/session.ts +33 -0
  92. package/src/types.ts +63 -0
  93. package/src/userop.ts +368 -0
  94. package/src/witness.ts +132 -0
  95. package/src/x402.ts +275 -0
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Admin API authentication for Signet group management.
3
+ *
4
+ * Admin auth is stateless: sign SHA256(group_id : nonce : timestamp_BE)
5
+ * with a trusted auth key. For Schnorr auth keys (prefix 0x01), the
6
+ * signature is produced via FROST threshold signing through the bootstrap
7
+ * group.
8
+ */
9
+ import type { SessionKeypair, IdTokenClaims } from "./types";
10
+ export interface AdminAuthConfig {
11
+ nodeProxyUrl: string;
12
+ bootstrapGroup: string;
13
+ bootstrapNodes: string[];
14
+ }
15
+ export interface AdminAuth {
16
+ group_id: string;
17
+ auth_key_pub: string;
18
+ signature: string;
19
+ nonce: string;
20
+ timestamp: number;
21
+ }
22
+ /**
23
+ * Build an admin auth payload by threshold-signing the admin hash
24
+ * via the bootstrap group.
25
+ *
26
+ * The admin hash is: SHA256(group_id + ":" + nonce + ":" + timestamp_8BE)
27
+ * The signature is a 65-byte FROST Schnorr signature.
28
+ */
29
+ export declare function buildAdminAuth(config: AdminAuthConfig, groupId: string, authKeyPub: string, sessionKeypair: SessionKeypair, claims: IdTokenClaims): Promise<AdminAuth>;
30
+ /**
31
+ * Call an admin endpoint with auth.
32
+ *
33
+ * If the signing request fails with a 401 "session not found" error and
34
+ * a reauthenticate callback is provided, re-establishes the node session
35
+ * and retries once.
36
+ */
37
+ export declare function adminRequest<T>(config: AdminAuthConfig, nodeUrl: string, path: string, groupId: string, authKeyPub: string, sessionKeypair: SessionKeypair, claims: IdTokenClaims, extraBody?: Record<string, unknown>, reauthenticate?: () => Promise<void>): Promise<T>;
38
+ //# sourceMappingURL=admin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.d.ts","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7D,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,SAAS,CAAC,CAwCpB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAClC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,aAAa,EACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GACnC,OAAO,CAAC,CAAC,CAAC,CAWZ"}
package/dist/admin.js ADDED
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Admin API authentication for Signet group management.
3
+ *
4
+ * Admin auth is stateless: sign SHA256(group_id : nonce : timestamp_BE)
5
+ * with a trusted auth key. For Schnorr auth keys (prefix 0x01), the
6
+ * signature is produced via FROST threshold signing through the bootstrap
7
+ * group.
8
+ */
9
+ import { signSignRequest } from "./request";
10
+ import { bytesToHex } from "./session";
11
+ /**
12
+ * Build an admin auth payload by threshold-signing the admin hash
13
+ * via the bootstrap group.
14
+ *
15
+ * The admin hash is: SHA256(group_id + ":" + nonce + ":" + timestamp_8BE)
16
+ * The signature is a 65-byte FROST Schnorr signature.
17
+ */
18
+ export async function buildAdminAuth(config, groupId, authKeyPub, sessionKeypair, claims) {
19
+ const normalizedGroupId = groupId.toLowerCase();
20
+ const nonce = generateNonce();
21
+ const timestamp = Math.floor(Date.now() / 1000);
22
+ // Build the admin hash: SHA256(group_id + ":" + nonce + ":" + timestamp_8BE)
23
+ const adminHash = await computeAdminHash(normalizedGroupId, nonce, timestamp);
24
+ // Threshold-sign the hash via bootstrap group
25
+ const signReq = await signSignRequest(sessionKeypair, claims, config.bootstrapGroup, adminHash);
26
+ const signRes = await fetch(config.nodeProxyUrl, {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ "x-node-url": config.bootstrapNodes[0],
31
+ "x-node-path": "/v1/sign",
32
+ },
33
+ body: JSON.stringify(signReq),
34
+ });
35
+ if (!signRes.ok) {
36
+ const body = await signRes.text();
37
+ throw new Error(`Admin signing failed: ${signRes.status} — ${body}`);
38
+ }
39
+ const { ethereum_signature } = await signRes.json();
40
+ return {
41
+ group_id: normalizedGroupId,
42
+ auth_key_pub: authKeyPub,
43
+ signature: ethereum_signature,
44
+ nonce,
45
+ timestamp,
46
+ };
47
+ }
48
+ /**
49
+ * Call an admin endpoint with auth.
50
+ *
51
+ * If the signing request fails with a 401 "session not found" error and
52
+ * a reauthenticate callback is provided, re-establishes the node session
53
+ * and retries once.
54
+ */
55
+ export async function adminRequest(config, nodeUrl, path, groupId, authKeyPub, sessionKeypair, claims, extraBody, reauthenticate) {
56
+ try {
57
+ return await adminRequestInner(config, nodeUrl, path, groupId, authKeyPub, sessionKeypair, claims, extraBody);
58
+ }
59
+ catch (err) {
60
+ const msg = err instanceof Error ? err.message : String(err);
61
+ if (reauthenticate && /session not found/i.test(msg)) {
62
+ await reauthenticate();
63
+ return await adminRequestInner(config, nodeUrl, path, groupId, authKeyPub, sessionKeypair, claims, extraBody);
64
+ }
65
+ throw err;
66
+ }
67
+ }
68
+ async function adminRequestInner(config, nodeUrl, path, groupId, authKeyPub, sessionKeypair, claims, extraBody) {
69
+ const auth = await buildAdminAuth(config, groupId, authKeyPub, sessionKeypair, claims);
70
+ const res = await fetch(config.nodeProxyUrl, {
71
+ method: "POST",
72
+ headers: {
73
+ "Content-Type": "application/json",
74
+ "x-node-url": nodeUrl,
75
+ "x-node-path": path,
76
+ },
77
+ body: JSON.stringify({ ...auth, ...extraBody }),
78
+ });
79
+ if (!res.ok) {
80
+ const body = await res.text();
81
+ throw new Error(`Admin ${path} failed: ${res.status} — ${body}`);
82
+ }
83
+ return res.json();
84
+ }
85
+ async function computeAdminHash(groupId, nonce, timestamp) {
86
+ const enc = new TextEncoder();
87
+ const parts = [];
88
+ parts.push(enc.encode(groupId));
89
+ parts.push(enc.encode(":"));
90
+ parts.push(enc.encode(nonce));
91
+ parts.push(enc.encode(":"));
92
+ // timestamp as 8-byte big-endian
93
+ const tsBuf = new ArrayBuffer(8);
94
+ const view = new DataView(tsBuf);
95
+ view.setBigUint64(0, BigInt(timestamp));
96
+ parts.push(new Uint8Array(tsBuf));
97
+ const total = parts.reduce((n, p) => n + p.length, 0);
98
+ const buf = new Uint8Array(total);
99
+ let offset = 0;
100
+ for (const p of parts) {
101
+ buf.set(p, offset);
102
+ offset += p.length;
103
+ }
104
+ const digest = await crypto.subtle.digest("SHA-256", buf);
105
+ return new Uint8Array(digest);
106
+ }
107
+ function generateNonce() {
108
+ const bytes = new Uint8Array(16);
109
+ crypto.getRandomValues(bytes);
110
+ return bytesToHex(bytes);
111
+ }
112
+ //# sourceMappingURL=admin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin.js","sourceRoot":"","sources":["../src/admin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Auth key certificate session flow.
3
+ *
4
+ * Creates a node session using an ECDSA auth key certificate instead of
5
+ * an OAuth/ZK proof. This enables keygen and signing without user login —
6
+ * useful for backend services, AI agents, or any programmatic access.
7
+ *
8
+ * Flow:
9
+ * 1. Sign a certificate binding an identity + session pub to the auth key
10
+ * 2. POST /v1/auth with the certificate to establish a session
11
+ * 3. Use the session key for subsequent keygen/sign requests (same as OAuth flow)
12
+ *
13
+ * The identity becomes the key namespace: keys are stored as "authkey:<identity>"
14
+ * (or "authkey:<identity>:<suffix>" with key_suffix).
15
+ */
16
+ import type { SessionKeypair } from "./types";
17
+ export interface AuthKeyCertConfig {
18
+ /** Base URL or proxy URL for the node */
19
+ nodeUrl: string;
20
+ /** If set, requests go through this proxy (for CORS) */
21
+ proxyEndpoint?: string;
22
+ }
23
+ export interface AuthKeyCertResult {
24
+ identity: string;
25
+ expiresAt: number;
26
+ }
27
+ /**
28
+ * Authenticate with a node using an auth key certificate.
29
+ *
30
+ * @param config - Node URL / proxy config
31
+ * @param groupId - Group contract address
32
+ * @param authPrivateKey - 32-byte ECDSA private key (matches an on-chain auth key)
33
+ * @param identity - Logical identity string (e.g. "my-backend", "agent-1")
34
+ * @param sessionKeypair - Ephemeral session keypair for subsequent requests
35
+ * @param expiry - Certificate expiry (unix seconds). Default: 1 hour from now.
36
+ */
37
+ export declare function authenticateWithAuthKey(config: AuthKeyCertConfig, groupId: string, authPrivateKey: Uint8Array, identity: string, sessionKeypair: SessionKeypair, expiry?: number): Promise<AuthKeyCertResult>;
38
+ /**
39
+ * Authenticate with a node using a Schnorr auth key certificate.
40
+ *
41
+ * The certificate hash is threshold-signed via the bootstrap group (FROST),
42
+ * producing a 65-byte Schnorr signature. This works for auth keys registered
43
+ * on-chain with the 0x01 (Schnorr) prefix.
44
+ *
45
+ * @param config - Bootstrap group config for threshold signing
46
+ * @param targetNodeUrl - The target group node to authenticate with
47
+ * @param proxyEndpoint - CORS proxy URL
48
+ * @param targetGroupId - The target group contract address
49
+ * @param authKeyPub - Auth key with 0x01 prefix (e.g. "0x0103d767f7...")
50
+ * @param identity - Logical identity string (e.g. "key-tester")
51
+ * @param sessionKeypair - Session keypair for the target group node
52
+ * @param bootstrapSessionKeypair - Session keypair for the bootstrap group (already authed)
53
+ * @param claims - OAuth claims for signing requests to the bootstrap group
54
+ * @param expiry - Certificate expiry (unix seconds). Default: 1 hour from now.
55
+ */
56
+ export declare function authenticateWithSchnorrAuthKey(config: {
57
+ bootstrapGroup: string;
58
+ bootstrapNodes: string[];
59
+ nodeProxyUrl: string;
60
+ }, targetNodeUrl: string, proxyEndpoint: string, targetGroupId: string, authKeyPub: string, identity: string, sessionKeypair: SessionKeypair, bootstrapSessionKeypair: SessionKeypair, claims: {
61
+ iss: string;
62
+ sub: string;
63
+ }, expiry?: number): Promise<AuthKeyCertResult>;
64
+ //# sourceMappingURL=authkey-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authkey-session.d.ts","sourceRoot":"","sources":["../src/authkey-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,iBAAiB,EACzB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,UAAU,EAC1B,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAwD5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE;IACN,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB,EACD,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,cAAc,EAC9B,uBAAuB,EAAE,cAAc,EACvC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EACpC,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAqE5B"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Auth key certificate session flow.
3
+ *
4
+ * Creates a node session using an ECDSA auth key certificate instead of
5
+ * an OAuth/ZK proof. This enables keygen and signing without user login —
6
+ * useful for backend services, AI agents, or any programmatic access.
7
+ *
8
+ * Flow:
9
+ * 1. Sign a certificate binding an identity + session pub to the auth key
10
+ * 2. POST /v1/auth with the certificate to establish a session
11
+ * 3. Use the session key for subsequent keygen/sign requests (same as OAuth flow)
12
+ *
13
+ * The identity becomes the key namespace: keys are stored as "authkey:<identity>"
14
+ * (or "authkey:<identity>:<suffix>" with key_suffix).
15
+ */
16
+ import { bytesToHex } from "./session";
17
+ /**
18
+ * Authenticate with a node using an auth key certificate.
19
+ *
20
+ * @param config - Node URL / proxy config
21
+ * @param groupId - Group contract address
22
+ * @param authPrivateKey - 32-byte ECDSA private key (matches an on-chain auth key)
23
+ * @param identity - Logical identity string (e.g. "my-backend", "agent-1")
24
+ * @param sessionKeypair - Ephemeral session keypair for subsequent requests
25
+ * @param expiry - Certificate expiry (unix seconds). Default: 1 hour from now.
26
+ */
27
+ export async function authenticateWithAuthKey(config, groupId, authPrivateKey, identity, sessionKeypair, expiry) {
28
+ const { getPublicKey, signAsync } = await import("@noble/secp256k1");
29
+ const normalizedGroupId = groupId.toLowerCase();
30
+ const certExpiry = expiry ?? Math.floor(Date.now() / 1000) + 3600;
31
+ // Derive the auth key public key (with ECDSA prefix 0x00)
32
+ const authPubBytes = getPublicKey(authPrivateKey, true);
33
+ const authKeyPub = `0x00${bytesToHex(authPubBytes)}`;
34
+ // Sign certificate: SHA256(identity + ":" + group_id + ":" + session_pub_hex + ":" + expiry_8BE)
35
+ const certHash = await computeCertHash(identity, normalizedGroupId, sessionKeypair.publicKeyHex, certExpiry);
36
+ const certSig = await signAsync(certHash, authPrivateKey, {
37
+ lowS: true,
38
+ prehash: false,
39
+ });
40
+ const certSigHex = bytesToHex(new Uint8Array(certSig));
41
+ // POST /v1/auth with certificate
42
+ const url = config.proxyEndpoint ?? `${config.nodeUrl}/v1/auth`;
43
+ const headers = { "Content-Type": "application/json" };
44
+ if (config.proxyEndpoint) {
45
+ headers["x-node-url"] = config.nodeUrl;
46
+ headers["x-node-path"] = "/v1/auth";
47
+ }
48
+ const res = await fetch(url, {
49
+ method: "POST",
50
+ headers,
51
+ body: JSON.stringify({
52
+ group_id: normalizedGroupId,
53
+ session_pub: sessionKeypair.publicKeyHex,
54
+ certificate: {
55
+ identity,
56
+ expiry: certExpiry,
57
+ auth_key_pub: authKeyPub,
58
+ signature: certSigHex,
59
+ },
60
+ }),
61
+ });
62
+ if (!res.ok) {
63
+ const body = await res.text();
64
+ throw new Error(`Auth key auth failed: ${res.status} — ${body}`);
65
+ }
66
+ const data = await res.json();
67
+ return {
68
+ identity: data.identity ?? identity,
69
+ expiresAt: data.expires_at ?? certExpiry,
70
+ };
71
+ }
72
+ /**
73
+ * Authenticate with a node using a Schnorr auth key certificate.
74
+ *
75
+ * The certificate hash is threshold-signed via the bootstrap group (FROST),
76
+ * producing a 65-byte Schnorr signature. This works for auth keys registered
77
+ * on-chain with the 0x01 (Schnorr) prefix.
78
+ *
79
+ * @param config - Bootstrap group config for threshold signing
80
+ * @param targetNodeUrl - The target group node to authenticate with
81
+ * @param proxyEndpoint - CORS proxy URL
82
+ * @param targetGroupId - The target group contract address
83
+ * @param authKeyPub - Auth key with 0x01 prefix (e.g. "0x0103d767f7...")
84
+ * @param identity - Logical identity string (e.g. "key-tester")
85
+ * @param sessionKeypair - Session keypair for the target group node
86
+ * @param bootstrapSessionKeypair - Session keypair for the bootstrap group (already authed)
87
+ * @param claims - OAuth claims for signing requests to the bootstrap group
88
+ * @param expiry - Certificate expiry (unix seconds). Default: 1 hour from now.
89
+ */
90
+ export async function authenticateWithSchnorrAuthKey(config, targetNodeUrl, proxyEndpoint, targetGroupId, authKeyPub, identity, sessionKeypair, bootstrapSessionKeypair, claims, expiry) {
91
+ const { signSignRequest } = await import("./request");
92
+ const normalizedGroupId = targetGroupId.toLowerCase();
93
+ const certExpiry = expiry ?? Math.floor(Date.now() / 1000) + 3600;
94
+ // Compute certificate hash
95
+ const certHash = await computeCertHash(identity, normalizedGroupId, sessionKeypair.publicKeyHex, certExpiry);
96
+ // Threshold-sign the cert hash via bootstrap group
97
+ const signReq = await signSignRequest(bootstrapSessionKeypair, claims, config.bootstrapGroup, certHash);
98
+ const signRes = await fetch(config.nodeProxyUrl, {
99
+ method: "POST",
100
+ headers: {
101
+ "Content-Type": "application/json",
102
+ "x-node-url": config.bootstrapNodes[0],
103
+ "x-node-path": "/v1/sign",
104
+ },
105
+ body: JSON.stringify(signReq),
106
+ });
107
+ if (!signRes.ok) {
108
+ const body = await signRes.text();
109
+ throw new Error(`Schnorr cert signing failed: ${signRes.status} — ${body}`);
110
+ }
111
+ const { ethereum_signature } = await signRes.json();
112
+ // POST /v1/auth on the target group node with the Schnorr-signed certificate
113
+ const res = await fetch(proxyEndpoint, {
114
+ method: "POST",
115
+ headers: {
116
+ "Content-Type": "application/json",
117
+ "x-node-url": targetNodeUrl,
118
+ "x-node-path": "/v1/auth",
119
+ },
120
+ body: JSON.stringify({
121
+ group_id: normalizedGroupId,
122
+ session_pub: sessionKeypair.publicKeyHex,
123
+ certificate: {
124
+ identity,
125
+ expiry: certExpiry,
126
+ auth_key_pub: authKeyPub,
127
+ signature: ethereum_signature,
128
+ },
129
+ }),
130
+ });
131
+ if (!res.ok) {
132
+ const body = await res.text();
133
+ throw new Error(`Schnorr auth key auth failed: ${res.status} — ${body}`);
134
+ }
135
+ const data = await res.json();
136
+ return {
137
+ identity: data.identity ?? identity,
138
+ expiresAt: data.expires_at ?? certExpiry,
139
+ };
140
+ }
141
+ async function computeCertHash(identity, groupId, sessionPubHex, expiry) {
142
+ const enc = new TextEncoder();
143
+ const expiryBuf = new ArrayBuffer(8);
144
+ new DataView(expiryBuf).setBigUint64(0, BigInt(expiry));
145
+ const parts = [
146
+ enc.encode(identity),
147
+ enc.encode(":"),
148
+ enc.encode(groupId),
149
+ enc.encode(":"),
150
+ enc.encode(sessionPubHex),
151
+ enc.encode(":"),
152
+ new Uint8Array(expiryBuf),
153
+ ];
154
+ const total = parts.reduce((n, p) => n + p.length, 0);
155
+ const buf = new Uint8Array(total);
156
+ let offset = 0;
157
+ for (const p of parts) {
158
+ buf.set(p, offset);
159
+ offset += p.length;
160
+ }
161
+ const digest = await crypto.subtle.digest("SHA-256", buf);
162
+ return new Uint8Array(digest);
163
+ }
164
+ //# sourceMappingURL=authkey-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authkey-session.js","sourceRoot":"","sources":["../src/authkey-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Bootstrap group node authentication.
3
+ *
4
+ * After generating a ZK proof of the JWT, POST it to each
5
+ * bootstrap node to register the session key.
6
+ */
7
+ export interface BootstrapConfig {
8
+ groupId: string;
9
+ nodeUrls: string[];
10
+ /** Proxy endpoint for CORS — if set, requests go through this instead of directly to nodes */
11
+ proxyEndpoint?: string;
12
+ }
13
+ export interface AuthResult {
14
+ identity: string;
15
+ expiresAt: number;
16
+ }
17
+ /**
18
+ * Authenticate with all bootstrap nodes.
19
+ *
20
+ * Posts the ZK proof + session public key to each node's /v1/auth.
21
+ * All nodes must accept the session for signing to work.
22
+ */
23
+ export declare function authenticateWithBootstrap(config: BootstrapConfig, proof: Uint8Array, sessionPubHex: string, claims: {
24
+ iss: string;
25
+ sub: string;
26
+ exp: number;
27
+ aud: string;
28
+ azp: string;
29
+ }, jwksModulusBytes: Uint8Array): Promise<AuthResult>;
30
+ //# sourceMappingURL=bootstrap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAC3E,gBAAgB,EAAE,UAAU,GAC3B,OAAO,CAAC,UAAU,CAAC,CA2CrB"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Bootstrap group node authentication.
3
+ *
4
+ * After generating a ZK proof of the JWT, POST it to each
5
+ * bootstrap node to register the session key.
6
+ */
7
+ import { bytesToHex } from "./session";
8
+ /**
9
+ * Authenticate with all bootstrap nodes.
10
+ *
11
+ * Posts the ZK proof + session public key to each node's /v1/auth.
12
+ * All nodes must accept the session for signing to work.
13
+ */
14
+ export async function authenticateWithBootstrap(config, proof, sessionPubHex, claims, jwksModulusBytes) {
15
+ const request = {
16
+ group_id: config.groupId,
17
+ session_pub: sessionPubHex,
18
+ proof: bytesToHex(proof),
19
+ sub: claims.sub,
20
+ iss: claims.iss,
21
+ exp: claims.exp,
22
+ aud: claims.aud,
23
+ azp: claims.azp,
24
+ jwks_modulus: bytesToHex(jwksModulusBytes),
25
+ };
26
+ // Auth with all nodes in parallel
27
+ const results = await Promise.allSettled(config.nodeUrls.map((url) => authWithNode(url, request, config.proxyEndpoint)));
28
+ // Check that at least one succeeded
29
+ const successes = results.filter((r) => r.status === "fulfilled");
30
+ const failures = results.filter((r) => r.status === "rejected");
31
+ if (successes.length === 0) {
32
+ const reasons = failures.map((f) => f.reason?.message ?? String(f.reason));
33
+ throw new Error(`All bootstrap nodes rejected auth: ${reasons.join("; ")}`);
34
+ }
35
+ if (failures.length > 0) {
36
+ console.warn(`${failures.length}/${config.nodeUrls.length} bootstrap nodes failed auth:`, failures.map((f) => f.reason?.message));
37
+ }
38
+ return successes[0].value;
39
+ }
40
+ async function authWithNode(baseUrl, request, proxyEndpoint) {
41
+ const url = proxyEndpoint ?? `${baseUrl}/v1/auth`;
42
+ const headers = {
43
+ "Content-Type": "application/json",
44
+ };
45
+ if (proxyEndpoint) {
46
+ headers["x-node-url"] = baseUrl;
47
+ headers["x-node-path"] = "/v1/auth";
48
+ }
49
+ const res = await fetch(url, {
50
+ method: "POST",
51
+ headers,
52
+ body: JSON.stringify(request),
53
+ });
54
+ if (!res.ok) {
55
+ const body = await res.text();
56
+ throw new Error(`${baseUrl}: ${res.status} — ${body}`);
57
+ }
58
+ return res.json();
59
+ }
60
+ //# sourceMappingURL=bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Bundler RPC client for ERC-4337 UserOperations.
3
+ *
4
+ * Framework-agnostic — all config is passed in, no env imports.
5
+ * Handles serialization between the packed UserOp format (used
6
+ * internally and for hashing) and the unpacked v0.7 RPC format
7
+ * expected by signet-min-bundler.
8
+ */
9
+ import { type Address, type Hex } from "viem";
10
+ import type { PackedUserOperation } from "./userop";
11
+ export interface BundlerSendResult {
12
+ userOpHash: Hex;
13
+ }
14
+ export interface UserOpReceipt {
15
+ userOpHash: Hex;
16
+ transactionHash: Hex;
17
+ success: boolean;
18
+ }
19
+ export interface GasEstimate {
20
+ preVerificationGas: Hex;
21
+ verificationGasLimit: Hex;
22
+ callGasLimit: Hex;
23
+ }
24
+ /**
25
+ * ERC-7677 paymaster sponsorship result.
26
+ *
27
+ * The bundler returns paymaster gas limits as separate fields, but
28
+ * signet-min-bundler's wire format for eth_sendUserOperation expects
29
+ * them packed into the front of `paymasterData` (see packPaymasterData
30
+ * and the note on the getHash comment in internal/paymaster/paymaster.go).
31
+ */
32
+ export interface PaymasterSponsorship {
33
+ paymaster: Address;
34
+ paymasterData: Hex;
35
+ paymasterVerificationGasLimit: Hex;
36
+ paymasterPostOpGasLimit: Hex;
37
+ }
38
+ /**
39
+ * ERC-7677 context object passed as the 4th parameter to
40
+ * pm_getPaymasterStubData / pm_getPaymasterData.
41
+ */
42
+ export interface PaymasterContext {
43
+ invite_code?: string;
44
+ }
45
+ export declare function sendUserOp(bundlerUrl: string, entryPointAddress: Address, userOp: PackedUserOperation): Promise<BundlerSendResult>;
46
+ export declare function getUserOpReceipt(bundlerUrl: string, userOpHash: Hex): Promise<UserOpReceipt | null>;
47
+ export declare function estimateUserOpGas(bundlerUrl: string, entryPointAddress: Address, userOp: PackedUserOperation): Promise<GasEstimate>;
48
+ /**
49
+ * Call pm_getPaymasterStubData.
50
+ *
51
+ * Returns paymaster fields with a correctly-sized but zeroed signature,
52
+ * suitable for gas estimation. Call this BEFORE eth_estimateUserOperationGas
53
+ * so the estimate accounts for the paymaster's verification overhead.
54
+ */
55
+ export declare function getPaymasterStubData(bundlerUrl: string, entryPointAddress: Address, chainId: number, userOp: PackedUserOperation, context?: PaymasterContext): Promise<PaymasterSponsorship>;
56
+ /**
57
+ * Call pm_getPaymasterData.
58
+ *
59
+ * Returns a real paymaster signature. The bundler first checks the
60
+ * paymaster contract's shouldSponsor() policy via eth_call; if sponsorship
61
+ * is rejected, this throws.
62
+ *
63
+ * IMPORTANT: call AFTER gas estimation, because the paymaster signs over
64
+ * the gas fields. Changing gas after this call invalidates the signature.
65
+ */
66
+ export declare function getPaymasterData(bundlerUrl: string, entryPointAddress: Address, chainId: number, userOp: PackedUserOperation, context?: PaymasterContext): Promise<PaymasterSponsorship>;
67
+ /**
68
+ * Pack an ERC-7677 sponsorship response into the on-chain paymasterAndData
69
+ * layout expected by EntryPoint v0.7:
70
+ *
71
+ * [paymaster:20][verifGasLimit:16][postOpGasLimit:16][paymasterData:rest]
72
+ *
73
+ * The paymaster's getHash function reads paymasterAndData[20:52] as the
74
+ * packed (verifGasLimit || postOpGasLimit) uint128 pair — so the returned
75
+ * layout must match exactly or the paymaster signature will not verify
76
+ * on-chain (AA34 signature error).
77
+ *
78
+ * NOTE on the bundler's wire format: signet-min-bundler's FromRPC
79
+ * concatenates the JSON `paymaster` + `paymasterData` fields directly
80
+ * into paymasterAndData. It does NOT re-insert gas-limit bytes. So when
81
+ * serializing for eth_sendUserOperation, the `paymasterData` on the wire
82
+ * already includes the packed gas limits.
83
+ */
84
+ export declare function applyPaymasterSponsorship(userOp: PackedUserOperation, s: PaymasterSponsorship): PackedUserOperation;
85
+ //# sourceMappingURL=bundler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundler.d.ts","sourceRoot":"","sources":["../src/bundler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,GAAG,EAAU,MAAM,MAAM,CAAC;AACtD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAMpD,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,GAAG,CAAC;IAChB,eAAe,EAAE,GAAG,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,GAAG,CAAC;IACxB,oBAAoB,EAAE,GAAG,CAAC;IAC1B,YAAY,EAAE,GAAG,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,GAAG,CAAC;IACnB,6BAA6B,EAAE,GAAG,CAAC;IACnC,uBAAuB,EAAE,GAAG,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,OAAO,EAC1B,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAM5B;AAED,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,GAAG,GACd,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAY/B;AAED,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,OAAO,EAC1B,MAAM,EAAE,mBAAmB,GAC1B,OAAO,CAAC,WAAW,CAAC,CAMtB;AAMD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,OAAO,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,iBAAiB,EAAE,OAAO,EAC1B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,oBAAoB,CAAC,CAE/B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,mBAAmB,EAC3B,CAAC,EAAE,oBAAoB,GACtB,mBAAmB,CAQrB"}