kawasekit 0.8.0 → 0.9.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,31 +1,54 @@
1
1
  import { isSupportedChainId } from './chunk-SOTYGX67.js';
2
2
  import { signerToEcdsaValidator } from '@zerodev/ecdsa-validator';
3
- import { toPermissionValidator, serializePermissionAccount, deserializePermissionAccount } from '@zerodev/permissions';
3
+ import { serializePermissionAccount, deserializePermissionAccount, toPermissionValidator } from '@zerodev/permissions';
4
4
  import { toECDSASigner } from '@zerodev/permissions/signers';
5
5
  import { createKernelAccount, uninstallPlugin } from '@zerodev/sdk';
6
- import { getEntryPoint, KERNEL_V3_1 } from '@zerodev/sdk/constants';
7
- import { getAddress, isAddress } from 'viem';
6
+ import { getEntryPoint, KERNEL_V3_1, VALIDATOR_TYPE } from '@zerodev/sdk/constants';
7
+ import { parseAbi, getAddress, concatHex, pad, encodeFunctionData, isAddress } from 'viem';
8
8
 
9
+ async function resolveSudoValidator(params) {
10
+ if (params.ownerSigner !== void 0 && params.sudoValidator !== void 0) {
11
+ throw new Error("kawasekit: pass exactly one of `ownerSigner` or `sudoValidator`, not both.");
12
+ }
13
+ if (params.sudoValidator !== void 0) return params.sudoValidator;
14
+ if (params.ownerSigner === void 0) {
15
+ throw new Error("kawasekit: pass one of `ownerSigner` (ECDSA) or `sudoValidator` (pre-built).");
16
+ }
17
+ return signerToEcdsaValidator(params.publicClient, {
18
+ signer: params.ownerSigner,
19
+ entryPoint: params.entryPoint,
20
+ kernelVersion: params.kernelVersion
21
+ });
22
+ }
23
+ async function buildSessionPermissionValidator(params) {
24
+ const signer = await toECDSASigner({ signer: params.sessionKeySigner });
25
+ return toPermissionValidator(params.publicClient, {
26
+ signer,
27
+ policies: [...params.policies],
28
+ entryPoint: params.entryPoint,
29
+ kernelVersion: params.kernelVersion
30
+ });
31
+ }
9
32
  async function createAgentSmartAccount(params) {
10
33
  const entryPoint = params.entryPoint ?? getEntryPoint("0.7");
11
34
  const kernelVersion = params.kernelVersion ?? KERNEL_V3_1;
12
- const sudoValidator = await signerToEcdsaValidator(params.publicClient, {
13
- signer: params.ownerSigner,
35
+ const sudoValidator = await resolveSudoValidator({
36
+ publicClient: params.publicClient,
37
+ ownerSigner: params.ownerSigner,
38
+ sudoValidator: params.sudoValidator,
14
39
  entryPoint,
15
40
  kernelVersion
16
41
  });
17
- const modularSessionSigner = await toECDSASigner({ signer: params.sessionKeySigner });
18
- const permissionValidator = await toPermissionValidator(params.publicClient, {
19
- signer: modularSessionSigner,
20
- policies: [...params.policies],
42
+ const permissionValidator = await buildSessionPermissionValidator({
43
+ publicClient: params.publicClient,
44
+ sessionKeySigner: params.sessionKeySigner,
45
+ policies: params.policies,
21
46
  entryPoint,
22
47
  kernelVersion
23
48
  });
24
49
  return createKernelAccount(params.publicClient, {
25
- plugins: {
26
- sudo: sudoValidator,
27
- regular: permissionValidator
28
- },
50
+ plugins: { sudo: sudoValidator, regular: permissionValidator },
51
+ ...params.address !== void 0 ? { address: params.address } : {},
29
52
  entryPoint,
30
53
  kernelVersion
31
54
  });
@@ -185,15 +208,28 @@ async function issueSessionKey(params) {
185
208
  const supportedChainId = chainId;
186
209
  const entryPoint = params.entryPoint ?? getEntryPoint("0.7");
187
210
  const kernelVersion = params.kernelVersion ?? KERNEL_V3_1;
188
- const account = await createAgentSmartAccount({
211
+ const sudoValidator = await resolveSudoValidator({
189
212
  publicClient: params.publicClient,
190
213
  ownerSigner: params.ownerSigner,
214
+ sudoValidator: params.sudoValidator,
215
+ entryPoint,
216
+ kernelVersion
217
+ });
218
+ const permissionValidator = await buildSessionPermissionValidator({
219
+ publicClient: params.publicClient,
191
220
  sessionKeySigner: params.sessionKeySigner,
192
221
  policies: params.policies,
193
222
  entryPoint,
194
223
  kernelVersion
195
224
  });
196
- const serialized = await serializePermissionAccount(account);
225
+ const account = await createKernelAccount(params.publicClient, {
226
+ plugins: { sudo: sudoValidator, regular: permissionValidator },
227
+ ...params.address !== void 0 ? { address: params.address } : {},
228
+ entryPoint,
229
+ kernelVersion
230
+ });
231
+ const enableSignature = params.approveEnable ? await params.approveEnable(permissionValidator) : void 0;
232
+ const serialized = enableSignature ? await serializePermissionAccount(account, void 0, enableSignature) : await serializePermissionAccount(account);
197
233
  const base = {
198
234
  kawasekitVersion: KAWASEKIT_SESSION_ENVELOPE_VERSION,
199
235
  chainId: supportedChainId,
@@ -269,10 +305,10 @@ async function revokeSessionKey(params) {
269
305
  "revokeSessionKey: ownerKernelClient.client is undefined \u2014 pass `client: publicClient` when constructing the Kernel client so the validator can be reconstructed."
270
306
  );
271
307
  }
272
- const modularSigner = await toECDSASigner({ signer: sessionKeySigner });
273
- const permissionPlugin = await toPermissionValidator(ownerKernelClient.client, {
274
- signer: modularSigner,
275
- policies: [...policies],
308
+ const permissionPlugin = await buildSessionPermissionValidator({
309
+ publicClient: ownerKernelClient.client,
310
+ sessionKeySigner,
311
+ policies,
276
312
  entryPoint,
277
313
  kernelVersion
278
314
  });
@@ -291,6 +327,30 @@ async function revokeSessionKey(params) {
291
327
  success: receipt.success
292
328
  };
293
329
  }
330
+ var UNINSTALL_VALIDATION_ABI = parseAbi([
331
+ "function uninstallValidation(bytes21 vId, bytes deinitData, bytes hookDeinitData)"
332
+ ]);
333
+ async function buildRevokeSessionKeyCall(params) {
334
+ const entryPoint = params.entryPoint ?? getEntryPoint("0.7");
335
+ const kernelVersion = params.kernelVersion ?? KERNEL_V3_1;
336
+ const plugin = await buildSessionPermissionValidator({
337
+ publicClient: params.publicClient,
338
+ sessionKeySigner: params.sessionKeySigner,
339
+ policies: params.policies,
340
+ entryPoint,
341
+ kernelVersion
342
+ });
343
+ const vId = concatHex([
344
+ VALIDATOR_TYPE.PERMISSION,
345
+ pad(plugin.getIdentifier(), { size: 20, dir: "right" })
346
+ ]);
347
+ const deinitData = await plugin.getEnableData(getAddress(params.smartAccountAddress));
348
+ return encodeFunctionData({
349
+ abi: UNINSTALL_VALIDATION_ABI,
350
+ functionName: "uninstallValidation",
351
+ args: [vId, deinitData, "0x"]
352
+ });
353
+ }
294
354
 
295
355
  // src/session/rotate.ts
296
356
  async function rotateSessionKey(params) {
@@ -299,6 +359,6 @@ async function rotateSessionKey(params) {
299
359
  return { revoke, envelope };
300
360
  }
301
361
 
302
- export { KAWASEKIT_SESSION_ENVELOPE_VERSION, SessionEnvelopeChainMismatchError, SessionEnvelopeParseError, SessionEnvelopeSignerMismatchError, SessionEnvelopeVersionError, createAgentSmartAccount, issueSessionKey, parseSessionEnvelope, restoreSessionAccount, revokeSessionKey, rotateSessionKey, serializeSessionEnvelope };
303
- //# sourceMappingURL=chunk-N3CVLISJ.js.map
304
- //# sourceMappingURL=chunk-N3CVLISJ.js.map
362
+ export { KAWASEKIT_SESSION_ENVELOPE_VERSION, SessionEnvelopeChainMismatchError, SessionEnvelopeParseError, SessionEnvelopeSignerMismatchError, SessionEnvelopeVersionError, buildRevokeSessionKeyCall, createAgentSmartAccount, issueSessionKey, parseSessionEnvelope, restoreSessionAccount, revokeSessionKey, rotateSessionKey, serializeSessionEnvelope };
363
+ //# sourceMappingURL=chunk-KYVAOUQV.js.map
364
+ //# sourceMappingURL=chunk-KYVAOUQV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/account/session-key.ts","../src/session/errors.ts","../src/session/envelope.ts","../src/session/issue.ts","../src/session/restore.ts","../src/session/revoke.ts","../src/session/rotate.ts"],"names":["getEntryPoint","KERNEL_V3_1","createKernelAccount","toECDSASigner","getAddress"],"mappings":"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","file":"chunk-KYVAOUQV.js","sourcesContent":["/**\n * Agent smart account = Kernel v3.1 + ECDSA sudo validator + session-key\n * permission validator.\n *\n * The owner EOA keeps full control (sudo) and can revoke / rotate the session\n * key at any time. The session key is the day-to-day signer the AI agent\n * holds; whatever policies you attach (see {@link createJpycDailyLimitPolicies})\n * are enforced at the ERC-4337 validation phase by ZeroDev's\n * `PermissionValidator`. Violating userOps revert before execution — they\n * never spend any of the smart account's funds, and a sponsored bundler\n * cannot be tricked into paying for them either.\n *\n * @packageDocumentation\n */\n\nimport { signerToEcdsaValidator } from \"@zerodev/ecdsa-validator\";\nimport type { Policy } from \"@zerodev/permissions\";\nimport { toPermissionValidator } from \"@zerodev/permissions\";\nimport { toECDSASigner } from \"@zerodev/permissions/signers\";\nimport type { CreateKernelAccountReturnType, KernelValidator } from \"@zerodev/sdk\";\nimport { createKernelAccount } from \"@zerodev/sdk\";\nimport { getEntryPoint, KERNEL_V3_1 } from \"@zerodev/sdk/constants\";\nimport type { EntryPointType, GetKernelVersion } from \"@zerodev/sdk/types\";\nimport type { Address, Chain, Client, LocalAccount, PublicClient, Transport } from \"viem\";\n\n/**\n * Owner = ECDSA convenience XOR a pre-built sudo validator (weighted / passkey / MPC).\n *\n * @remarks Pass a pre-built validator via `sudoValidator`, never via `ownerSigner`.\n * Because ZeroDev's `KernelValidator` structurally extends `LocalAccount`, a validator\n * mis-passed in the `ownerSigner` slot type-checks and would be wrapped as an ECDSA\n * signer (confusing downstream failure) rather than used as the sudo directly.\n */\nexport type AgentOwner =\n\t| { readonly ownerSigner: LocalAccount; readonly sudoValidator?: never }\n\t| { readonly sudoValidator: KernelValidator; readonly ownerSigner?: never };\n\n/**\n * Resolve the sudo validator: a caller-injected `sudoValidator`, or the ECDSA\n * convenience path from `ownerSigner`. Throws (before any chain access) if both\n * or neither is supplied — the runtime guard behind the {@link AgentOwner} union.\n */\nexport async function resolveSudoValidator(params: {\n\treadonly publicClient: PublicClient<Transport, Chain | undefined>;\n\t// `| undefined` (not just `?`) so callers may forward the `AgentOwner` union's\n\t// inactive arm verbatim under `exactOptionalPropertyTypes`.\n\treadonly ownerSigner?: LocalAccount | undefined;\n\treadonly sudoValidator?: KernelValidator | undefined;\n\treadonly entryPoint: EntryPointType<\"0.7\">;\n\treadonly kernelVersion: GetKernelVersion<\"0.7\">;\n}): Promise<KernelValidator> {\n\tif (params.ownerSigner !== undefined && params.sudoValidator !== undefined) {\n\t\tthrow new Error(\"kawasekit: pass exactly one of `ownerSigner` or `sudoValidator`, not both.\");\n\t}\n\tif (params.sudoValidator !== undefined) return params.sudoValidator;\n\tif (params.ownerSigner === undefined) {\n\t\tthrow new Error(\"kawasekit: pass one of `ownerSigner` (ECDSA) or `sudoValidator` (pre-built).\");\n\t}\n\treturn signerToEcdsaValidator(params.publicClient, {\n\t\tsigner: params.ownerSigner,\n\t\tentryPoint: params.entryPoint,\n\t\tkernelVersion: params.kernelVersion,\n\t});\n}\n\n/**\n * Build the session-key permission validator. Intended as the **single shared\n * builder** for both issuance and revocation so they derive the identical\n * validator identifier from the same `(sessionKeySigner, policies)` — pass\n * identical policies in identical ORDER, since the identifier hashes the ordered\n * policy array (a mismatch makes revoke target the wrong validator). Issuance\n * uses it today; revocation migrates onto it in the U-B2 builder.\n */\nexport async function buildSessionPermissionValidator(params: {\n\t// `Client` (not `PublicClient`) — `toPermissionValidator` only needs a viem `Client`,\n\t// and this lets a Kernel client's `.client` be reused verbatim at revoke time.\n\treadonly publicClient: Client;\n\treadonly sessionKeySigner: LocalAccount;\n\treadonly policies: readonly Policy[];\n\treadonly entryPoint: EntryPointType<\"0.7\">;\n\treadonly kernelVersion: GetKernelVersion<\"0.7\">;\n}): Promise<KernelValidator> {\n\tconst signer = await toECDSASigner({ signer: params.sessionKeySigner });\n\treturn toPermissionValidator(params.publicClient, {\n\t\tsigner,\n\t\tpolicies: [...params.policies],\n\t\tentryPoint: params.entryPoint,\n\t\tkernelVersion: params.kernelVersion,\n\t});\n}\n\n/** Parameters for {@link createAgentSmartAccount}. */\nexport type CreateAgentSmartAccountParams = {\n\treadonly publicClient: PublicClient<Transport, Chain | undefined>;\n\treadonly sessionKeySigner: LocalAccount;\n\treadonly policies: readonly Policy[];\n\t/** Bind to an existing deployed account (e.g. re-provision after recovery). */\n\treadonly address?: Address;\n\treadonly entryPoint?: EntryPointType<\"0.7\">;\n\treadonly kernelVersion?: GetKernelVersion<\"0.7\">;\n} & AgentOwner;\n\n/**\n * Builds a Kernel v3.1 smart account with sudo (owner) + regular (session key)\n * validators wired up.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * createAgentSmartAccount,\n * createJpycDailyLimitPolicies,\n * getJpycAddress,\n * JPYC_DECIMALS,\n * polygonAmoy,\n * } from \"kawasekit\";\n *\n * const owner = privateKeyToAccount(process.env.OWNER_PRIVATE_KEY as `0x${string}`);\n * const sessionKey = privateKeyToAccount(process.env.SESSION_KEY_PRIVATE_KEY as `0x${string}`);\n *\n * const account = await createAgentSmartAccount({\n * publicClient,\n * ownerSigner: owner,\n * sessionKeySigner: sessionKey,\n * policies: createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS),\n * maxTransfersPerDay: 10,\n * }),\n * });\n * ```\n */\nexport async function createAgentSmartAccount(\n\tparams: CreateAgentSmartAccountParams,\n): Promise<CreateKernelAccountReturnType<\"0.7\">> {\n\tconst entryPoint = params.entryPoint ?? getEntryPoint(\"0.7\");\n\tconst kernelVersion = params.kernelVersion ?? KERNEL_V3_1;\n\n\tconst sudoValidator = await resolveSudoValidator({\n\t\tpublicClient: params.publicClient,\n\t\townerSigner: params.ownerSigner,\n\t\tsudoValidator: params.sudoValidator,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\tconst permissionValidator = await buildSessionPermissionValidator({\n\t\tpublicClient: params.publicClient,\n\t\tsessionKeySigner: params.sessionKeySigner,\n\t\tpolicies: params.policies,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\n\treturn createKernelAccount(params.publicClient, {\n\t\tplugins: { sudo: sudoValidator, regular: permissionValidator },\n\t\t...(params.address !== undefined ? { address: params.address } : {}),\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n}\n","/**\n * Typed errors thrown by the `kawasekit/session` modules.\n *\n * Centralised so consumers can `instanceof`-discriminate without importing\n * deep paths.\n *\n * @packageDocumentation\n */\n\nimport type { Address } from \"viem\";\n\n/**\n * Thrown when {@link parseSessionEnvelope} encounters an envelope whose\n * `kawasekitVersion` does not match the current\n * {@link KAWASEKIT_SESSION_ENVELOPE_VERSION}.\n *\n * The version field is intentionally a string (\"1\") so that future migrations\n * can introduce non-numeric variants (e.g. \"1-jwe\") without breaking the\n * parser ordering.\n */\nexport class SessionEnvelopeVersionError extends Error {\n\treadonly expected: string;\n\treadonly received: unknown;\n\n\tconstructor(expected: string, received: unknown) {\n\t\tsuper(\n\t\t\t`Session envelope version mismatch: expected ${JSON.stringify(expected)}, got ${JSON.stringify(received)}.`,\n\t\t);\n\t\tthis.name = \"SessionEnvelopeVersionError\";\n\t\tthis.expected = expected;\n\t\tthis.received = received;\n\t}\n}\n\n/**\n * Thrown by `restoreSessionAccount()` when an envelope's `chainId` differs\n * from the chain the consumer is restoring on. Catches the common mistake of\n * issuing on Polygon Amoy and trying to restore on Polygon mainnet.\n */\nexport class SessionEnvelopeChainMismatchError extends Error {\n\treadonly envelopeChainId: number;\n\treadonly clientChainId: number;\n\n\tconstructor(envelopeChainId: number, clientChainId: number) {\n\t\tsuper(\n\t\t\t`Session envelope is for chain ${envelopeChainId} but the restore client is on chain ${clientChainId}.`,\n\t\t);\n\t\tthis.name = \"SessionEnvelopeChainMismatchError\";\n\t\tthis.envelopeChainId = envelopeChainId;\n\t\tthis.clientChainId = clientChainId;\n\t}\n}\n\n/**\n * Thrown by `restoreSessionAccount()` when the session-key signer the consumer\n * passes does not match the `sessionKeyAddress` recorded in the envelope.\n *\n * Defence against accidentally restoring with the wrong private key — which\n * would otherwise succeed locally and only fail at UserOp validation time.\n */\nexport class SessionEnvelopeSignerMismatchError extends Error {\n\treadonly envelopeSignerAddress: Address;\n\treadonly providedSignerAddress: Address;\n\n\tconstructor(envelopeSignerAddress: Address, providedSignerAddress: Address) {\n\t\tsuper(\n\t\t\t`Session envelope was issued for signer ${envelopeSignerAddress}, but the provided session-key signer is ${providedSignerAddress}.`,\n\t\t);\n\t\tthis.name = \"SessionEnvelopeSignerMismatchError\";\n\t\tthis.envelopeSignerAddress = envelopeSignerAddress;\n\t\tthis.providedSignerAddress = providedSignerAddress;\n\t}\n}\n\n/**\n * Thrown when {@link parseSessionEnvelope} cannot decode the input as a\n * structurally valid envelope (malformed JSON, missing fields, bad types).\n */\nexport class SessionEnvelopeParseError extends Error {\n\treadonly reason: string;\n\n\tconstructor(reason: string, options?: { cause?: unknown }) {\n\t\tsuper(`Failed to parse session envelope: ${reason}`, options);\n\t\tthis.name = \"SessionEnvelopeParseError\";\n\t\tthis.reason = reason;\n\t}\n}\n","/**\n * `KawasekitSessionEnvelope` — kawasekit's typed wrapper around ZeroDev's\n * opaque `serializePermissionAccount` blob.\n *\n * Why wrap ZeroDev's blob rather than use it directly?\n *\n * - **Fail-fast on restore**: chainId / version / signer mismatches surface as\n * typed errors instead of confusing UserOp-time reverts.\n * - **Host-UI affordances**: `expiresAt` and `policySummary` are advisory\n * fields a wallet can render (\"this session expires in 2 hours, max 100\n * JPYC/day\") before handing the blob to {@link restoreSessionAccount}.\n * - **Version pin**: when ZeroDev changes their serialization format we bump\n * {@link KAWASEKIT_SESSION_ENVELOPE_VERSION} and provide a migration; the\n * inner `serialized` field stays opaque.\n *\n * Wire format: a single JSON string. Bigint fields (`expiresAt`,\n * `policySummary.maxPerTransfer`) round-trip via decimal-string encoding so\n * the JSON itself is portable through any transport (env var, HTTP header,\n * file).\n *\n * @packageDocumentation\n */\n\nimport { type Address, isAddress } from \"viem\";\nimport { isSupportedChainId, type SupportedChainId } from \"../chains\";\nimport { SessionEnvelopeParseError, SessionEnvelopeVersionError } from \"./errors\";\n\n/**\n * Current envelope format version. Bumped when the envelope schema changes\n * in a way that breaks backward compatibility.\n */\nexport const KAWASEKIT_SESSION_ENVELOPE_VERSION = \"1\" as const;\n\n/** Type of {@link KAWASEKIT_SESSION_ENVELOPE_VERSION}. */\nexport type KawasekitSessionEnvelopeVersion = typeof KAWASEKIT_SESSION_ENVELOPE_VERSION;\n\n/**\n * Advisory summary of the spending policy attached to a session key. Useful\n * for host UI; **not** consulted at validation time (the on-chain validator\n * is the source of truth).\n */\nexport interface KawasekitSessionPolicySummary {\n\treadonly jpycAddress: Address;\n\treadonly maxPerTransfer: bigint;\n\treadonly maxTransfersPerDay: number;\n}\n\n/** kawasekit's typed envelope around a ZeroDev session-key serialization. */\nexport interface KawasekitSessionEnvelope {\n\treadonly kawasekitVersion: KawasekitSessionEnvelopeVersion;\n\treadonly chainId: SupportedChainId;\n\treadonly smartAccountAddress: Address;\n\treadonly sessionKeyAddress: Address;\n\t/** Optional unix-seconds expiry. Advisory + ideally enforced by a `TimestampPolicy`. */\n\treadonly expiresAt?: bigint;\n\treadonly policySummary?: KawasekitSessionPolicySummary;\n\t/** Opaque ZeroDev `serializePermissionAccount` output. */\n\treadonly serialized: string;\n}\n\n// ---------------------------------------------------------------------------\n// Wire (JSON) shape\n// ---------------------------------------------------------------------------\n\n/**\n * Internal: the JSON shape we (de)serialize to/from. Bigint fields are stored\n * as decimal strings. Kept separate from {@link KawasekitSessionEnvelope} so\n * the public type stays bigint-friendly while the wire stays string-only.\n */\ninterface SessionEnvelopeJson {\n\treadonly kawasekitVersion: string;\n\treadonly chainId: number;\n\treadonly smartAccountAddress: string;\n\treadonly sessionKeyAddress: string;\n\treadonly expiresAt?: string;\n\treadonly policySummary?: {\n\t\treadonly jpycAddress: string;\n\t\treadonly maxPerTransfer: string;\n\t\treadonly maxTransfersPerDay: number;\n\t};\n\treadonly serialized: string;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers\n// ---------------------------------------------------------------------------\n\nconst UINT_DECIMAL = /^(0|[1-9][0-9]*)$/;\n\nfunction assertAddress(value: unknown, field: string): Address {\n\tif (typeof value !== \"string\" || !isAddress(value, { strict: false })) {\n\t\tthrow new SessionEnvelopeParseError(`\\`${field}\\` is not a valid address: ${String(value)}`);\n\t}\n\treturn value as Address;\n}\n\nfunction assertString(value: unknown, field: string): string {\n\tif (typeof value !== \"string\" || value === \"\") {\n\t\tthrow new SessionEnvelopeParseError(`\\`${field}\\` must be a non-empty string`);\n\t}\n\treturn value;\n}\n\nfunction assertNumber(value: unknown, field: string): number {\n\tif (typeof value !== \"number\" || !Number.isFinite(value)) {\n\t\tthrow new SessionEnvelopeParseError(`\\`${field}\\` must be a finite number`);\n\t}\n\treturn value;\n}\n\nfunction parseBigIntString(value: unknown, field: string): bigint {\n\tif (typeof value !== \"string\" || !UINT_DECIMAL.test(value)) {\n\t\tthrow new SessionEnvelopeParseError(\n\t\t\t`\\`${field}\\` must be a non-negative decimal string: ${String(value)}`,\n\t\t);\n\t}\n\treturn BigInt(value);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Serialises a {@link KawasekitSessionEnvelope} to a transportable JSON string.\n *\n * The output is plain UTF-8 JSON (no base64). Callers who need\n * URL-/header-safe transport can base64-encode the result themselves.\n *\n * @example\n * ```ts\n * import { serializeSessionEnvelope } from \"kawasekit\";\n *\n * const blob = serializeSessionEnvelope(envelope);\n * fs.writeFileSync(\"agent.session\", blob);\n * ```\n */\nexport function serializeSessionEnvelope(envelope: KawasekitSessionEnvelope): string {\n\tconst json: SessionEnvelopeJson = {\n\t\tkawasekitVersion: envelope.kawasekitVersion,\n\t\tchainId: envelope.chainId,\n\t\tsmartAccountAddress: envelope.smartAccountAddress,\n\t\tsessionKeyAddress: envelope.sessionKeyAddress,\n\t\tserialized: envelope.serialized,\n\t\t...(envelope.expiresAt !== undefined ? { expiresAt: envelope.expiresAt.toString() } : {}),\n\t\t...(envelope.policySummary !== undefined\n\t\t\t? {\n\t\t\t\t\tpolicySummary: {\n\t\t\t\t\t\tjpycAddress: envelope.policySummary.jpycAddress,\n\t\t\t\t\t\tmaxPerTransfer: envelope.policySummary.maxPerTransfer.toString(),\n\t\t\t\t\t\tmaxTransfersPerDay: envelope.policySummary.maxTransfersPerDay,\n\t\t\t\t\t},\n\t\t\t\t}\n\t\t\t: {}),\n\t};\n\treturn JSON.stringify(json);\n}\n\n/**\n * Parses a JSON string back into a {@link KawasekitSessionEnvelope}, asserting\n * shape and version invariants.\n *\n * @throws {SessionEnvelopeParseError} On malformed JSON or structural errors.\n * @throws {SessionEnvelopeVersionError} On `kawasekitVersion` mismatch.\n *\n * @example\n * ```ts\n * import { parseSessionEnvelope } from \"kawasekit\";\n *\n * const envelope = parseSessionEnvelope(fs.readFileSync(\"agent.session\", \"utf8\"));\n * ```\n */\nexport function parseSessionEnvelope(input: string): KawasekitSessionEnvelope {\n\tlet raw: unknown;\n\ttry {\n\t\traw = JSON.parse(input);\n\t} catch (cause) {\n\t\tthrow new SessionEnvelopeParseError(\"input is not valid JSON\", { cause });\n\t}\n\tif (raw === null || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\tthrow new SessionEnvelopeParseError(\"input is not a JSON object\");\n\t}\n\tconst obj = raw as {\n\t\tkawasekitVersion?: unknown;\n\t\tchainId?: unknown;\n\t\tsmartAccountAddress?: unknown;\n\t\tsessionKeyAddress?: unknown;\n\t\tserialized?: unknown;\n\t\texpiresAt?: unknown;\n\t\tpolicySummary?: unknown;\n\t};\n\n\tif (obj.kawasekitVersion !== KAWASEKIT_SESSION_ENVELOPE_VERSION) {\n\t\tthrow new SessionEnvelopeVersionError(KAWASEKIT_SESSION_ENVELOPE_VERSION, obj.kawasekitVersion);\n\t}\n\tconst chainIdNum = assertNumber(obj.chainId, \"chainId\");\n\tif (!isSupportedChainId(chainIdNum)) {\n\t\tthrow new SessionEnvelopeParseError(`chainId ${chainIdNum} is not a kawasekit-supported chain`);\n\t}\n\tconst chainId: SupportedChainId = chainIdNum;\n\tconst smartAccountAddress = assertAddress(obj.smartAccountAddress, \"smartAccountAddress\");\n\tconst sessionKeyAddress = assertAddress(obj.sessionKeyAddress, \"sessionKeyAddress\");\n\tconst serialized = assertString(obj.serialized, \"serialized\");\n\n\tconst expiresAt =\n\t\tobj.expiresAt !== undefined ? parseBigIntString(obj.expiresAt, \"expiresAt\") : undefined;\n\n\tlet policySummary: KawasekitSessionPolicySummary | undefined;\n\tif (obj.policySummary !== undefined) {\n\t\tif (\n\t\t\tobj.policySummary === null ||\n\t\t\ttypeof obj.policySummary !== \"object\" ||\n\t\t\tArray.isArray(obj.policySummary)\n\t\t) {\n\t\t\tthrow new SessionEnvelopeParseError(\"`policySummary` must be a JSON object\");\n\t\t}\n\t\tconst ps = obj.policySummary as {\n\t\t\tjpycAddress?: unknown;\n\t\t\tmaxPerTransfer?: unknown;\n\t\t\tmaxTransfersPerDay?: unknown;\n\t\t};\n\t\tpolicySummary = {\n\t\t\tjpycAddress: assertAddress(ps.jpycAddress, \"policySummary.jpycAddress\"),\n\t\t\tmaxPerTransfer: parseBigIntString(ps.maxPerTransfer, \"policySummary.maxPerTransfer\"),\n\t\t\tmaxTransfersPerDay: assertNumber(ps.maxTransfersPerDay, \"policySummary.maxTransfersPerDay\"),\n\t\t};\n\t}\n\n\tconst base = {\n\t\tkawasekitVersion: KAWASEKIT_SESSION_ENVELOPE_VERSION,\n\t\tchainId,\n\t\tsmartAccountAddress,\n\t\tsessionKeyAddress,\n\t\tserialized,\n\t} as const;\n\tif (expiresAt !== undefined && policySummary !== undefined) {\n\t\treturn { ...base, expiresAt, policySummary };\n\t}\n\tif (expiresAt !== undefined) {\n\t\treturn { ...base, expiresAt };\n\t}\n\tif (policySummary !== undefined) {\n\t\treturn { ...base, policySummary };\n\t}\n\treturn base;\n}\n","/**\n * `issueSessionKey()` — owner-side primitive that builds a Kernel agent\n * account and wraps ZeroDev's `serializePermissionAccount` output in a\n * {@link KawasekitSessionEnvelope}.\n *\n * The envelope is portable: callers can hand it to an agent on a different\n * machine, the agent passes it to {@link restoreSessionAccount} along with the\n * session-key private key, and it ends up holding a `KernelAccountClient`\n * scoped to the policies installed at issue time.\n *\n * The owner retains sudo authority on-chain and can revoke at any time via\n * `revokeSessionKey()` (task 2.5).\n *\n * @packageDocumentation\n */\n\nimport type { Policy } from \"@zerodev/permissions\";\nimport { serializePermissionAccount } from \"@zerodev/permissions\";\nimport type { KernelValidator } from \"@zerodev/sdk\";\nimport { createKernelAccount } from \"@zerodev/sdk\";\nimport { getEntryPoint, KERNEL_V3_1 } from \"@zerodev/sdk/constants\";\nimport type { EntryPointType, GetKernelVersion } from \"@zerodev/sdk/types\";\nimport type { Address, Chain, Hex, LocalAccount, PublicClient, Transport } from \"viem\";\nimport {\n\ttype AgentOwner,\n\tbuildSessionPermissionValidator,\n\tresolveSudoValidator,\n} from \"../account/session-key\";\nimport { isSupportedChainId, type SupportedChainId } from \"../chains\";\nimport {\n\tKAWASEKIT_SESSION_ENVELOPE_VERSION,\n\ttype KawasekitSessionEnvelope,\n\ttype KawasekitSessionPolicySummary,\n} from \"./envelope\";\n\n/** Parameters for {@link issueSessionKey}. */\nexport type IssueSessionKeyParams = {\n\treadonly publicClient: PublicClient<Transport, Chain>;\n\treadonly sessionKeySigner: LocalAccount;\n\t/**\n\t * Policies the session key must satisfy at userOp validation time (e.g.\n\t * {@link createJpycDailyLimitPolicies}). Supply the SAME policies in the SAME\n\t * order to issue and to revoke (`buildRevokeSessionKeyCall`) — the validator\n\t * identifier hashes the ordered policy array.\n\t */\n\treadonly policies: readonly Policy[];\n\t/** Bind issuance to an existing deployed account (re-provision after recovery). */\n\treadonly address?: Address;\n\t/**\n\t * Weighted-enable seam (RFC-0003 U-B1). Called with the SDK-built permission\n\t * validator; returns the enable signature for `serializePermissionAccount`'s\n\t * 3rd arg. Omit for an ECDSA owner (the default single-signer enable). For a\n\t * weighted sudo this is `approvePlugin(plugin)` + `encodeSignatures([approval], true)`,\n\t * computed by the caller with their weighted client. A mismatch surfaces on-chain\n\t * as `EnableNotApproved` at first use.\n\t */\n\treadonly approveEnable?: (permissionValidator: KernelValidator) => Promise<Hex>;\n\t/** Optional advisory expiry (unix seconds). Recorded in the envelope. */\n\treadonly expiresAt?: bigint;\n\t/** Optional advisory policy summary for host UI. */\n\treadonly policySummary?: KawasekitSessionPolicySummary;\n\t/** EntryPoint override. Defaults to v0.7. */\n\treadonly entryPoint?: EntryPointType<\"0.7\">;\n\t/** Kernel version override. Defaults to {@link KERNEL_V3_1}. */\n\treadonly kernelVersion?: GetKernelVersion<\"0.7\">;\n} & AgentOwner;\n\n/**\n * Issues a fresh session key for an agent smart account.\n *\n * Notes:\n * - The session-key **private key is not embedded** in the returned envelope.\n * The agent must receive the private key out-of-band; the envelope alone is\n * not enough to spend.\n * - The smart account is **not deployed** by this call. It will be deployed\n * on first userOp from `restoreSessionAccount`.\n *\n * @example\n * ```ts\n * import { parseUnits } from \"viem\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * createJpycDailyLimitPolicies,\n * getJpycAddress,\n * issueSessionKey,\n * JPYC_DECIMALS,\n * polygonAmoy,\n * serializeSessionEnvelope,\n * } from \"kawasekit\";\n *\n * const owner = privateKeyToAccount(process.env.OWNER_PRIVATE_KEY as `0x${string}`);\n * const sessionKey = privateKeyToAccount(process.env.SESSION_KEY_PRIVATE_KEY as `0x${string}`);\n *\n * const envelope = await issueSessionKey({\n * publicClient,\n * ownerSigner: owner,\n * sessionKeySigner: sessionKey,\n * policies: createJpycDailyLimitPolicies({\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS),\n * maxTransfersPerDay: 10,\n * }),\n * policySummary: {\n * jpycAddress: getJpycAddress(polygonAmoy.id),\n * maxPerTransfer: parseUnits(\"100\", JPYC_DECIMALS),\n * maxTransfersPerDay: 10,\n * },\n * });\n *\n * fs.writeFileSync(\"agent.session\", serializeSessionEnvelope(envelope));\n * ```\n */\nexport async function issueSessionKey(\n\tparams: IssueSessionKeyParams,\n): Promise<KawasekitSessionEnvelope> {\n\tconst chainId = params.publicClient.chain.id;\n\tif (!isSupportedChainId(chainId)) {\n\t\tthrow new Error(\n\t\t\t`issueSessionKey: publicClient.chain.id ${chainId} is not a kawasekit-supported chain`,\n\t\t);\n\t}\n\tconst supportedChainId: SupportedChainId = chainId;\n\tconst entryPoint = params.entryPoint ?? getEntryPoint(\"0.7\");\n\tconst kernelVersion = params.kernelVersion ?? KERNEL_V3_1;\n\n\tconst sudoValidator = await resolveSudoValidator({\n\t\tpublicClient: params.publicClient,\n\t\townerSigner: params.ownerSigner,\n\t\tsudoValidator: params.sudoValidator,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\tconst permissionValidator = await buildSessionPermissionValidator({\n\t\tpublicClient: params.publicClient,\n\t\tsessionKeySigner: params.sessionKeySigner,\n\t\tpolicies: params.policies,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\tconst account = await createKernelAccount(params.publicClient, {\n\t\tplugins: { sudo: sudoValidator, regular: permissionValidator },\n\t\t...(params.address !== undefined ? { address: params.address } : {}),\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\n\tconst enableSignature = params.approveEnable\n\t\t? await params.approveEnable(permissionValidator)\n\t\t: undefined;\n\tconst serialized = enableSignature\n\t\t? await serializePermissionAccount(account, undefined, enableSignature)\n\t\t: await serializePermissionAccount(account);\n\n\tconst base = {\n\t\tkawasekitVersion: KAWASEKIT_SESSION_ENVELOPE_VERSION,\n\t\tchainId: supportedChainId,\n\t\tsmartAccountAddress: account.address,\n\t\tsessionKeyAddress: params.sessionKeySigner.address,\n\t\tserialized,\n\t} as const;\n\tif (params.expiresAt !== undefined && params.policySummary !== undefined) {\n\t\treturn {\n\t\t\t...base,\n\t\t\texpiresAt: params.expiresAt,\n\t\t\tpolicySummary: params.policySummary,\n\t\t};\n\t}\n\tif (params.expiresAt !== undefined) {\n\t\treturn { ...base, expiresAt: params.expiresAt };\n\t}\n\tif (params.policySummary !== undefined) {\n\t\treturn { ...base, policySummary: params.policySummary };\n\t}\n\treturn base;\n}\n","/**\n * `restoreSessionAccount()` — agent-side primitive that unwraps a\n * {@link KawasekitSessionEnvelope} back into a usable Kernel account scoped\n * to the policies installed at issue time.\n *\n * Three invariants are checked **before** touching ZeroDev's deserialization\n * so that misconfiguration manifests as a typed error here, not a confusing\n * UserOp-time revert:\n *\n * 1. `envelope.kawasekitVersion` matches the current envelope version\n * (already enforced by {@link parseSessionEnvelope}; re-checked here for\n * callers who construct the envelope object directly).\n * 2. `envelope.chainId === publicClient.chain.id`.\n * 3. `envelope.sessionKeyAddress` matches the provided `sessionKeySigner`.\n *\n * @packageDocumentation\n */\n\nimport { deserializePermissionAccount } from \"@zerodev/permissions\";\nimport { toECDSASigner } from \"@zerodev/permissions/signers\";\nimport type { CreateKernelAccountReturnType } from \"@zerodev/sdk\";\nimport { getEntryPoint, KERNEL_V3_1 } from \"@zerodev/sdk/constants\";\nimport type { EntryPointType, GetKernelVersion } from \"@zerodev/sdk/types\";\nimport { type Chain, getAddress, type LocalAccount, type PublicClient, type Transport } from \"viem\";\nimport { KAWASEKIT_SESSION_ENVELOPE_VERSION, type KawasekitSessionEnvelope } from \"./envelope\";\nimport {\n\tSessionEnvelopeChainMismatchError,\n\tSessionEnvelopeSignerMismatchError,\n\tSessionEnvelopeVersionError,\n} from \"./errors\";\n\n/** Parameters for {@link restoreSessionAccount}. */\nexport interface RestoreSessionAccountParams {\n\t/** Must be on the same chain the envelope was issued for. */\n\treadonly publicClient: PublicClient<Transport, Chain>;\n\t/** Envelope produced by {@link issueSessionKey} (or parsed via {@link parseSessionEnvelope}). */\n\treadonly envelope: KawasekitSessionEnvelope;\n\t/**\n\t * The session-key signer the agent holds. Its address MUST equal\n\t * `envelope.sessionKeyAddress` — otherwise the restored account would\n\t * sign userOps that the on-chain permission validator rejects.\n\t */\n\treadonly sessionKeySigner: LocalAccount;\n\t/** EntryPoint override. Defaults to v0.7. */\n\treadonly entryPoint?: EntryPointType<\"0.7\">;\n\t/** Kernel version override. Defaults to {@link KERNEL_V3_1}. */\n\treadonly kernelVersion?: GetKernelVersion<\"0.7\">;\n}\n\n/**\n * Rebuilds the Kernel account from an envelope + the session-key signer.\n *\n * @throws {SessionEnvelopeVersionError} If `envelope.kawasekitVersion` does\n * not match the current envelope version.\n * @throws {SessionEnvelopeChainMismatchError} If `envelope.chainId !==\n * publicClient.chain.id`.\n * @throws {SessionEnvelopeSignerMismatchError} If `sessionKeySigner.address !==\n * envelope.sessionKeyAddress`.\n *\n * @example\n * ```ts\n * import { createPublicClient, http } from \"viem\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n * import {\n * parseSessionEnvelope,\n * polygonAmoy,\n * restoreSessionAccount,\n * } from \"kawasekit\";\n *\n * const publicClient = createPublicClient({\n * chain: polygonAmoy,\n * transport: http(),\n * });\n * const envelope = parseSessionEnvelope(fs.readFileSync(\"agent.session\", \"utf8\"));\n * const sessionKey = privateKeyToAccount(process.env.SESSION_KEY_PRIVATE_KEY as `0x${string}`);\n *\n * const account = await restoreSessionAccount({\n * publicClient,\n * envelope,\n * sessionKeySigner: sessionKey,\n * });\n * ```\n */\nexport async function restoreSessionAccount(\n\tparams: RestoreSessionAccountParams,\n): Promise<CreateKernelAccountReturnType<\"0.7\">> {\n\tconst { publicClient, envelope, sessionKeySigner } = params;\n\n\tif (envelope.kawasekitVersion !== KAWASEKIT_SESSION_ENVELOPE_VERSION) {\n\t\tthrow new SessionEnvelopeVersionError(\n\t\t\tKAWASEKIT_SESSION_ENVELOPE_VERSION,\n\t\t\tenvelope.kawasekitVersion,\n\t\t);\n\t}\n\tif (publicClient.chain.id !== envelope.chainId) {\n\t\tthrow new SessionEnvelopeChainMismatchError(envelope.chainId, publicClient.chain.id);\n\t}\n\tif (getAddress(sessionKeySigner.address) !== getAddress(envelope.sessionKeyAddress)) {\n\t\tthrow new SessionEnvelopeSignerMismatchError(\n\t\t\tenvelope.sessionKeyAddress,\n\t\t\tsessionKeySigner.address,\n\t\t);\n\t}\n\n\tconst entryPoint = params.entryPoint ?? getEntryPoint(\"0.7\");\n\tconst kernelVersion = params.kernelVersion ?? KERNEL_V3_1;\n\tconst modularSigner = await toECDSASigner({ signer: sessionKeySigner });\n\n\treturn deserializePermissionAccount(\n\t\tpublicClient,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t\tenvelope.serialized,\n\t\tmodularSigner,\n\t);\n}\n","/**\n * `revokeSessionKey()` — owner-side primitive that uninstalls a session-key\n * permission validator from the agent's smart account.\n *\n * Implementation strategy (per plan §risk #3): ZeroDev does not expose a\n * dedicated revoke helper, so we re-derive the `PermissionPlugin` from the\n * envelope's `sessionKeyAddress` + the same policies that were installed at\n * issue time, then submit a sudo UserOp via `@zerodev/sdk`'s\n * {@link uninstallPlugin} action. After the receipt, the session key can no\n * longer sign UserOps the validator would accept.\n *\n * In-flight UserOps already submitted to the bundler but not yet mined can\n * still settle before the uninstall transaction lands. A future \"soft revoke\"\n * via `invalidateNonce` on the session-key validator's nonce key will close\n * that race; tracked for M5 (the helper signature accepts an\n * `invalidateInFlightNonces` option today and throws `\"not implemented\"` to\n * lock in the API shape). Until M5 lands, see\n * `docs/recipes/revoke-race-mitigation.md` for the four-layer operator\n * playbook (SDK call → merchant kill-switch → paymaster sponsorship\n * freeze → bundler mempool monitoring).\n *\n * @packageDocumentation\n */\n\nimport type { Policy } from \"@zerodev/permissions\";\nimport { uninstallPlugin } from \"@zerodev/sdk\";\nimport { getEntryPoint, KERNEL_V3_1, VALIDATOR_TYPE } from \"@zerodev/sdk/constants\";\nimport type { EntryPointType, GetKernelVersion } from \"@zerodev/sdk/types\";\nimport {\n\ttype Address,\n\ttype Chain,\n\tconcatHex,\n\tencodeFunctionData,\n\tgetAddress,\n\ttype Hash,\n\ttype Hex,\n\ttype LocalAccount,\n\ttype PublicClient,\n\tpad,\n\tparseAbi,\n\ttype Transport,\n} from \"viem\";\nimport { buildSessionPermissionValidator } from \"../account/session-key\";\nimport type { ConfiguredKernelClient } from \"../client/transfer-jpyc\";\nimport type { KawasekitSessionEnvelope } from \"./envelope\";\nimport { SessionEnvelopeSignerMismatchError } from \"./errors\";\n\n/** Parameters for {@link revokeSessionKey}. */\nexport interface RevokeSessionKeyParams {\n\t/**\n\t * The owner's sudo Kernel client — the only entity that can call\n\t * `uninstallValidation` on the agent account.\n\t *\n\t * **CRITICAL: must be a SUDO-ONLY kernel account** (i.e.\n\t * `createKernelAccount(publicClient, { plugins: { sudo: ecdsaValidator } })`\n\t * — no `regular` plugin). If you pass a client whose account also has the\n\t * session-key permission validator wired as `regular`, ZeroDev signs\n\t * userOps with that validator by default and the spending policy will\n\t * reject `uninstallValidation` at the validation phase (`AA23 reverted`).\n\t *\n\t * The counterfactual smart-account address only depends on the sudo\n\t * validator in Kernel v3.1, so a sudo-only client points at the SAME\n\t * account as one built with both sudo + regular.\n\t *\n\t * Its `account.address` MUST equal `envelope.smartAccountAddress`.\n\t */\n\treadonly ownerKernelClient: ConfiguredKernelClient;\n\t/** The envelope of the session being revoked. */\n\treadonly envelope: KawasekitSessionEnvelope;\n\t/**\n\t * A LocalAccount whose address equals `envelope.sessionKeyAddress`. Used\n\t * to reconstruct the validator's on-chain identifier; no signing is\n\t * actually performed with this account during revoke.\n\t */\n\treadonly sessionKeySigner: LocalAccount;\n\t/**\n\t * The policies that were installed at issue time. ZeroDev does not store\n\t * these on-chain in a retrievable form, so the caller MUST re-supply\n\t * them. Mismatches surface as an `uninstallValidation` revert at userOp\n\t * validation time.\n\t */\n\treadonly policies: readonly Policy[];\n\t/**\n\t * Future option: also invalidate the session-key validator's nonce key\n\t * to kill in-flight UserOps. Not implemented today — passing `true`\n\t * throws. Tracked for M5; see `docs/THREAT_MODEL.md` §6.3 and\n\t * `docs/recipes/revoke-race-mitigation.md` for the operator playbook to\n\t * use until then.\n\t */\n\treadonly invalidateInFlightNonces?: boolean;\n\t/** EntryPoint override. Defaults to v0.7. */\n\treadonly entryPoint?: EntryPointType<\"0.7\">;\n\t/** Kernel version override. Defaults to {@link KERNEL_V3_1}. */\n\treadonly kernelVersion?: GetKernelVersion<\"0.7\">;\n\t/**\n\t * If `false`, return after submitting the UserOp without waiting for the\n\t * bundler receipt. Default `true` (wait).\n\t */\n\treadonly waitForReceipt?: boolean;\n}\n\n/** Result of {@link revokeSessionKey}. */\nexport interface RevokeSessionKeyResult {\n\t/** Hash of the uninstall UserOp. */\n\treadonly userOpHash: Hash;\n\t/** Bundler transaction hash, present when `waitForReceipt` (default true). */\n\treadonly transactionHash: Hash | null;\n\t/** `true` if the bundler reported success, `null` if not awaited. */\n\treadonly success: boolean | null;\n}\n\n/**\n * Uninstalls a session-key permission validator from the agent's smart\n * account. After the returned UserOp lands, the session key can no longer\n * authorise actions.\n *\n * @throws {SessionEnvelopeSignerMismatchError} If `sessionKeySigner.address`\n * does not match `envelope.sessionKeyAddress`.\n * @throws {Error} If `invalidateInFlightNonces` is `true` (planned for M5;\n * see `docs/THREAT_MODEL.md` §6.3 and\n * `docs/recipes/revoke-race-mitigation.md` for the four-layer\n * operator playbook to use until then).\n *\n * @example\n * ```ts\n * import { signerToEcdsaValidator } from \"@zerodev/ecdsa-validator\";\n * import { createKernelAccount, createKernelAccountClient } from \"@zerodev/sdk\";\n * import { getEntryPoint, KERNEL_V3_1 } from \"@zerodev/sdk/constants\";\n * import { revokeSessionKey } from \"kawasekit\";\n *\n * // Build a SUDO-ONLY kernel account for the owner — see param JSDoc.\n * const sudoValidator = await signerToEcdsaValidator(publicClient, {\n * signer: owner,\n * entryPoint: getEntryPoint(\"0.7\"),\n * kernelVersion: KERNEL_V3_1,\n * });\n * const ownerSudoAccount = await createKernelAccount(publicClient, {\n * plugins: { sudo: sudoValidator },\n * entryPoint: getEntryPoint(\"0.7\"),\n * kernelVersion: KERNEL_V3_1,\n * });\n * const ownerKernelClient = createKernelAccountClient({\n * account: ownerSudoAccount,\n * chain,\n * client: publicClient,\n * bundlerTransport,\n * paymaster,\n * });\n *\n * await revokeSessionKey({\n * ownerKernelClient,\n * envelope,\n * sessionKeySigner,\n * policies: createJpycDailyLimitPolicies({ ... }),\n * });\n * ```\n */\nexport async function revokeSessionKey(\n\tparams: RevokeSessionKeyParams,\n): Promise<RevokeSessionKeyResult> {\n\tconst { ownerKernelClient, envelope, sessionKeySigner, policies } = params;\n\n\tif (params.invalidateInFlightNonces === true) {\n\t\tthrow new Error(\n\t\t\t\"revokeSessionKey: `invalidateInFlightNonces` is not implemented yet — the helper signature accepts the option to lock in the API shape, but in-flight nonce invalidation lands in M5. Hard revoke via uninstallPlugin is what runs today; see docs/recipes/revoke-race-mitigation.md for the four-layer operator playbook to use until then.\",\n\t\t);\n\t}\n\n\tif (getAddress(sessionKeySigner.address) !== getAddress(envelope.sessionKeyAddress)) {\n\t\tthrow new SessionEnvelopeSignerMismatchError(\n\t\t\tenvelope.sessionKeyAddress,\n\t\t\tsessionKeySigner.address,\n\t\t);\n\t}\n\n\tif (getAddress(ownerKernelClient.account.address) !== getAddress(envelope.smartAccountAddress)) {\n\t\tthrow new Error(\n\t\t\t`revokeSessionKey: ownerKernelClient is bound to ${ownerKernelClient.account.address}, but envelope is for ${envelope.smartAccountAddress}.`,\n\t\t);\n\t}\n\n\tconst entryPoint = params.entryPoint ?? getEntryPoint(\"0.7\");\n\tconst kernelVersion = params.kernelVersion ?? KERNEL_V3_1;\n\n\tif (ownerKernelClient.client === undefined) {\n\t\tthrow new Error(\n\t\t\t\"revokeSessionKey: ownerKernelClient.client is undefined — pass `client: publicClient` when constructing the Kernel client so the validator can be reconstructed.\",\n\t\t);\n\t}\n\n\t// Same shared builder as issuance + buildRevokeSessionKeyCall → identical vId.\n\tconst permissionPlugin = await buildSessionPermissionValidator({\n\t\tpublicClient: ownerKernelClient.client,\n\t\tsessionKeySigner,\n\t\tpolicies,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\n\tconst userOpHash = await uninstallPlugin(ownerKernelClient, {\n\t\tplugin: permissionPlugin,\n\t});\n\n\tif (params.waitForReceipt === false) {\n\t\treturn { userOpHash, transactionHash: null, success: null };\n\t}\n\n\tconst receipt = await ownerKernelClient.waitForUserOperationReceipt({\n\t\thash: userOpHash,\n\t});\n\treturn {\n\t\tuserOpHash,\n\t\ttransactionHash: receipt.receipt.transactionHash,\n\t\tsuccess: receipt.success,\n\t};\n}\n\nconst UNINSTALL_VALIDATION_ABI = parseAbi([\n\t\"function uninstallValidation(bytes21 vId, bytes deinitData, bytes hookDeinitData)\",\n]);\n\n/** Parameters for {@link buildRevokeSessionKeyCall}. */\nexport interface BuildRevokeSessionKeyCallParams {\n\t/** A viem public client (the public API stays `PublicClient`; the shared builder widens to `Client` internally). */\n\treadonly publicClient: PublicClient<Transport, Chain>;\n\t/** The session-key signer the key was ISSUED with. */\n\treadonly sessionKeySigner: LocalAccount;\n\t/**\n\t * The policies the key was issued with — identical policies in identical\n\t * ORDER, since the validator identifier hashes the ordered policy array.\n\t * A mismatch reverts at `uninstallValidation`.\n\t */\n\treadonly policies: readonly Policy[];\n\t/** The deployed agent smart-account address. */\n\treadonly smartAccountAddress: Address;\n\treadonly entryPoint?: EntryPointType<\"0.7\">;\n\treadonly kernelVersion?: GetKernelVersion<\"0.7\">;\n}\n\n/**\n * Build the `uninstallValidation(vId, deinitData, hookDeinitData)` call that\n * removes a session-key permission validator — a byte-exact reproduction of\n * `@zerodev/sdk`'s `uninstallPlugin` inner call, which the SDK cannot call\n * directly because it hardcodes the single-signer `sendUserOperation` path a\n * weighted/passkey/MPC owner rejects.\n *\n * Submit it yourself: single-signer owners via {@link revokeSessionKey};\n * weighted/passkey/MPC owners via their aggregate flow —\n * `account.encodeCalls([{ to: smartAccountAddress, value: 0n, data }])` →\n * `sendUserOperationWithSignatures`.\n *\n * @example\n * ```ts\n * const data = await buildRevokeSessionKeyCall({\n * publicClient, sessionKeySigner, policies, smartAccountAddress,\n * });\n * const callData = await weightedAccount.encodeCalls([{ to: smartAccountAddress, value: 0n, data }]);\n * // …approveUserOperation per signer → sendUserOperationWithSignatures(callData, signatures)\n * ```\n */\nexport async function buildRevokeSessionKeyCall(\n\tparams: BuildRevokeSessionKeyCallParams,\n): Promise<Hex> {\n\tconst entryPoint = params.entryPoint ?? getEntryPoint(\"0.7\");\n\tconst kernelVersion = params.kernelVersion ?? KERNEL_V3_1;\n\tconst plugin = await buildSessionPermissionValidator({\n\t\tpublicClient: params.publicClient,\n\t\tsessionKeySigner: params.sessionKeySigner,\n\t\tpolicies: params.policies,\n\t\tentryPoint,\n\t\tkernelVersion,\n\t});\n\t// vId = VALIDATOR_TYPE.PERMISSION ‖ getIdentifier() right-padded to 20 bytes (bytes21).\n\tconst vId = concatHex([\n\t\tVALIDATOR_TYPE.PERMISSION,\n\t\tpad(plugin.getIdentifier(), { size: 20, dir: \"right\" }),\n\t]);\n\tconst deinitData = await plugin.getEnableData(getAddress(params.smartAccountAddress));\n\treturn encodeFunctionData({\n\t\tabi: UNINSTALL_VALIDATION_ABI,\n\t\tfunctionName: \"uninstallValidation\",\n\t\targs: [vId, deinitData, \"0x\"],\n\t});\n}\n","/**\n * `rotateSessionKey()` — a thin compositional helper that revokes the\n * current session key and issues a new one in sequence.\n *\n * Compose-don't-conflate: rotate is just `revoke` followed by `issue`. Both\n * primitives are exposed individually so callers who need finer control\n * (e.g. revoke now, issue tomorrow with different policies) can chain them\n * themselves.\n *\n * @packageDocumentation\n */\n\nimport type { KawasekitSessionEnvelope } from \"./envelope\";\nimport { type IssueSessionKeyParams, issueSessionKey } from \"./issue\";\nimport {\n\ttype RevokeSessionKeyParams,\n\ttype RevokeSessionKeyResult,\n\trevokeSessionKey,\n} from \"./revoke\";\n\n/** Parameters for {@link rotateSessionKey}. */\nexport interface RotateSessionKeyParams {\n\t/** Inputs for revoking the current session. `waitForReceipt` is forced `true`. */\n\treadonly revoke: Omit<RevokeSessionKeyParams, \"waitForReceipt\">;\n\t/** Inputs for issuing the replacement session. */\n\treadonly issue: IssueSessionKeyParams;\n}\n\n/** Result of {@link rotateSessionKey}. */\nexport interface RotateSessionKeyResult {\n\t/** Outcome of the revoke step. */\n\treadonly revoke: RevokeSessionKeyResult;\n\t/** The freshly issued replacement envelope. */\n\treadonly envelope: KawasekitSessionEnvelope;\n}\n\n/**\n * Atomically rotate the agent's session key: revoke the old, issue the new.\n *\n * The revoke is always awaited to the bundler receipt — issuing a replacement\n * before the old key is actually disarmed would leave two valid signers at\n * once, defeating the point.\n *\n * @example\n * ```ts\n * import { rotateSessionKey } from \"kawasekit\";\n *\n * const { revoke, envelope } = await rotateSessionKey({\n * revoke: {\n * ownerKernelClient,\n * envelope: oldEnvelope,\n * sessionKeySigner: oldSessionKeySigner,\n * policies: oldPolicies,\n * },\n * issue: {\n * publicClient,\n * ownerSigner,\n * sessionKeySigner: newSessionKeySigner,\n * policies: newPolicies,\n * },\n * });\n * ```\n */\nexport async function rotateSessionKey(\n\tparams: RotateSessionKeyParams,\n): Promise<RotateSessionKeyResult> {\n\tconst revoke = await revokeSessionKey({ ...params.revoke, waitForReceipt: true });\n\tconst envelope = await issueSessionKey(params.issue);\n\treturn { revoke, envelope };\n}\n"]}
@@ -365,28 +365,27 @@ var require_main = __commonJS({
365
365
  module.exports = DotenvModule;
366
366
  }
367
367
  });
368
- async function createAgentSmartAccount(params) {
369
- const entryPoint = params.entryPoint ?? constants.getEntryPoint("0.7");
370
- const kernelVersion = params.kernelVersion ?? constants.KERNEL_V3_1;
371
- const sudoValidator = await ecdsaValidator.signerToEcdsaValidator(params.publicClient, {
368
+ async function resolveSudoValidator(params) {
369
+ if (params.ownerSigner !== void 0 && params.sudoValidator !== void 0) {
370
+ throw new Error("kawasekit: pass exactly one of `ownerSigner` or `sudoValidator`, not both.");
371
+ }
372
+ if (params.sudoValidator !== void 0) return params.sudoValidator;
373
+ if (params.ownerSigner === void 0) {
374
+ throw new Error("kawasekit: pass one of `ownerSigner` (ECDSA) or `sudoValidator` (pre-built).");
375
+ }
376
+ return ecdsaValidator.signerToEcdsaValidator(params.publicClient, {
372
377
  signer: params.ownerSigner,
373
- entryPoint,
374
- kernelVersion
378
+ entryPoint: params.entryPoint,
379
+ kernelVersion: params.kernelVersion
375
380
  });
376
- const modularSessionSigner = await signers.toECDSASigner({ signer: params.sessionKeySigner });
377
- const permissionValidator = await permissions.toPermissionValidator(params.publicClient, {
378
- signer: modularSessionSigner,
381
+ }
382
+ async function buildSessionPermissionValidator(params) {
383
+ const signer = await signers.toECDSASigner({ signer: params.sessionKeySigner });
384
+ return permissions.toPermissionValidator(params.publicClient, {
385
+ signer,
379
386
  policies: [...params.policies],
380
- entryPoint,
381
- kernelVersion
382
- });
383
- return sdk.createKernelAccount(params.publicClient, {
384
- plugins: {
385
- sudo: sudoValidator,
386
- regular: permissionValidator
387
- },
388
- entryPoint,
389
- kernelVersion
387
+ entryPoint: params.entryPoint,
388
+ kernelVersion: params.kernelVersion
390
389
  });
391
390
  }
392
391
  var avalanche = {
@@ -924,15 +923,28 @@ async function issueSessionKey(params) {
924
923
  const supportedChainId = chainId;
925
924
  const entryPoint = params.entryPoint ?? constants.getEntryPoint("0.7");
926
925
  const kernelVersion = params.kernelVersion ?? constants.KERNEL_V3_1;
927
- const account = await createAgentSmartAccount({
926
+ const sudoValidator = await resolveSudoValidator({
928
927
  publicClient: params.publicClient,
929
928
  ownerSigner: params.ownerSigner,
929
+ sudoValidator: params.sudoValidator,
930
+ entryPoint,
931
+ kernelVersion
932
+ });
933
+ const permissionValidator = await buildSessionPermissionValidator({
934
+ publicClient: params.publicClient,
930
935
  sessionKeySigner: params.sessionKeySigner,
931
936
  policies: params.policies,
932
937
  entryPoint,
933
938
  kernelVersion
934
939
  });
935
- const serialized = await permissions.serializePermissionAccount(account);
940
+ const account = await sdk.createKernelAccount(params.publicClient, {
941
+ plugins: { sudo: sudoValidator, regular: permissionValidator },
942
+ ...params.address !== void 0 ? { address: params.address } : {},
943
+ entryPoint,
944
+ kernelVersion
945
+ });
946
+ const enableSignature = params.approveEnable ? await params.approveEnable(permissionValidator) : void 0;
947
+ const serialized = enableSignature ? await permissions.serializePermissionAccount(account, void 0, enableSignature) : await permissions.serializePermissionAccount(account);
936
948
  const base = {
937
949
  kawasekitVersion: KAWASEKIT_SESSION_ENVELOPE_VERSION,
938
950
  chainId: supportedChainId,
@@ -1008,10 +1020,10 @@ async function revokeSessionKey(params) {
1008
1020
  "revokeSessionKey: ownerKernelClient.client is undefined \u2014 pass `client: publicClient` when constructing the Kernel client so the validator can be reconstructed."
1009
1021
  );
1010
1022
  }
1011
- const modularSigner = await signers.toECDSASigner({ signer: sessionKeySigner });
1012
- const permissionPlugin = await permissions.toPermissionValidator(ownerKernelClient.client, {
1013
- signer: modularSigner,
1014
- policies: [...policies],
1023
+ const permissionPlugin = await buildSessionPermissionValidator({
1024
+ publicClient: ownerKernelClient.client,
1025
+ sessionKeySigner,
1026
+ policies,
1015
1027
  entryPoint,
1016
1028
  kernelVersion
1017
1029
  });
@@ -1030,6 +1042,9 @@ async function revokeSessionKey(params) {
1030
1042
  success: receipt.success
1031
1043
  };
1032
1044
  }
1045
+ viem.parseAbi([
1046
+ "function uninstallValidation(bytes21 vId, bytes deinitData, bytes hookDeinitData)"
1047
+ ]);
1033
1048
 
1034
1049
  // src/session/rotate.ts
1035
1050
  async function rotateSessionKey(params) {
@@ -1675,7 +1690,7 @@ function registerTransferCommand(program2) {
1675
1690
  }
1676
1691
 
1677
1692
  // cli/index.ts
1678
- var CLI_VERSION = "0.8.0" ;
1693
+ var CLI_VERSION = "0.9.0" ;
1679
1694
  var program = new commander.Command();
1680
1695
  program.name("kawasekit").description(
1681
1696
  "kawasekit \u2014 CLI for the kawasekit SDK (AI-agent stablecoin payments, Japan-first, JPYC-native)."