@nevermined-io/core-kit 1.5.0 → 1.7.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/dist/Instantiable.abstract.d.ts.map +1 -1
- package/dist/Instantiable.abstract.js +23 -4
- package/dist/Instantiable.abstract.js.map +1 -1
- package/dist/contracts/ContractBase.d.ts.map +1 -1
- package/dist/contracts/ContractBase.js +2 -2
- package/dist/contracts/ContractBase.js.map +1 -1
- package/dist/models/Logger.d.ts.map +1 -1
- package/dist/models/Logger.js +4 -1
- package/dist/models/Logger.js.map +1 -1
- package/dist/models/NeverminedOptions.d.ts +8 -0
- package/dist/models/NeverminedOptions.d.ts.map +1 -1
- package/dist/models/NeverminedOptions.js.map +1 -1
- package/dist/models/NvmApiKey.d.ts +9 -1
- package/dist/models/NvmApiKey.d.ts.map +1 -1
- package/dist/models/NvmApiKey.js +6 -0
- package/dist/models/NvmApiKey.js.map +1 -1
- package/dist/nevermined/utils/BlockchainViemUtils.d.ts +70 -11
- package/dist/nevermined/utils/BlockchainViemUtils.d.ts.map +1 -1
- package/dist/nevermined/utils/BlockchainViemUtils.js +206 -25
- package/dist/nevermined/utils/BlockchainViemUtils.js.map +1 -1
- package/dist/nevermined/utils/ZeroDevPolicies.d.ts +2 -2
- package/dist/nevermined/utils/ZeroDevPolicies.d.ts.map +1 -1
- package/dist/nevermined/utils/ZeroDevPolicies.js +87 -35
- package/dist/nevermined/utils/ZeroDevPolicies.js.map +1 -1
- package/dist/utils/Network.d.ts +5 -0
- package/dist/utils/Network.d.ts.map +1 -1
- package/dist/utils/Network.js +228 -222
- package/dist/utils/Network.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { signerToEcdsaValidator } from '@zerodev/ecdsa-validator';
|
|
2
2
|
import { KernelAccountClient } from '@zerodev/sdk';
|
|
3
|
-
import {
|
|
3
|
+
import { KERNEL_V3_1, KERNEL_V3_3 } from '@zerodev/sdk/constants';
|
|
4
|
+
import { Address, type Abi, type AbiEvent, type AbiFunction, type Account, type PublicClient, type SignAuthorizationReturnType, type TransactionReceipt } from 'viem';
|
|
4
5
|
import { SmartAccount } from 'viem/account-abstraction';
|
|
5
6
|
import { Instantiable, InstantiableConfig, Web3Clients } from '../../Instantiable.abstract.js';
|
|
6
7
|
import { Signer } from '@zerodev/sdk/types';
|
|
@@ -34,15 +35,15 @@ export declare function getTransactionReceipt({ txHash, publicClient, }: {
|
|
|
34
35
|
*/
|
|
35
36
|
export declare function getContractInstance(contractAddress: string, abi: Abi, client: Web3Clients): Promise<{
|
|
36
37
|
read: {
|
|
37
|
-
[x: string]: (...parameters: [options?: import("viem").Prettify<import("viem").UnionOmit<import("viem").ReadContractParameters<Abi, string, readonly unknown[]>, "address" | "abi" | "
|
|
38
|
+
[x: string]: (...parameters: [options?: import("viem").Prettify<import("viem").UnionOmit<import("viem").ReadContractParameters<Abi, string, readonly unknown[]>, "address" | "abi" | "functionName" | "args">> | undefined] | [args: readonly unknown[], options?: import("viem").Prettify<import("viem").UnionOmit<import("viem").ReadContractParameters<Abi, string, readonly unknown[]>, "address" | "abi" | "functionName" | "args">> | undefined]) => Promise<import("viem").ReadContractReturnType>;
|
|
38
39
|
};
|
|
39
40
|
estimateGas: {
|
|
40
|
-
[x: string]: (...parameters: [options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "
|
|
41
|
+
[x: string]: (...parameters: [options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "functionName" | "args">>] | [args: readonly unknown[], options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "functionName" | "args">>]) => Promise<import("viem").EstimateContractGasReturnType>;
|
|
41
42
|
} & {
|
|
42
|
-
[x: string]: (...parameters: [options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "
|
|
43
|
+
[x: string]: (...parameters: [options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "functionName" | "args">>] | [args: readonly unknown[], options: import("viem").Prettify<import("viem").UnionOmit<import("viem").EstimateContractGasParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined>, "address" | "abi" | "functionName" | "args">>]) => Promise<import("viem").EstimateContractGasReturnType>;
|
|
43
44
|
};
|
|
44
45
|
simulate: {
|
|
45
|
-
[x: string]: <chainOverride extends import("viem").Chain | undefined = undefined, accountOverride extends Account | Address | undefined = undefined>(...parameters: [options?: Omit<import("viem").SimulateContractParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined, chainOverride, accountOverride>, "address" | "abi" | "
|
|
46
|
+
[x: string]: <chainOverride extends import("viem").Chain | undefined = undefined, accountOverride extends Account | Address | undefined = undefined>(...parameters: [options?: Omit<import("viem").SimulateContractParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined, chainOverride, accountOverride>, "address" | "abi" | "functionName" | "args"> | undefined] | [args: readonly unknown[], options?: Omit<import("viem").SimulateContractParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined, chainOverride, accountOverride>, "address" | "abi" | "functionName" | "args"> | undefined]) => Promise<import("viem").SimulateContractReturnType>;
|
|
46
47
|
};
|
|
47
48
|
createEventFilter: {
|
|
48
49
|
[x: string]: <strict extends boolean | undefined = undefined>(...parameters: [options?: ({
|
|
@@ -68,10 +69,10 @@ export declare function getContractInstance(contractAddress: string, abi: Abi, c
|
|
|
68
69
|
};
|
|
69
70
|
getEvents: {
|
|
70
71
|
[x: string]: (...parameters: [options?: {
|
|
72
|
+
blockHash?: `0x${string}` | undefined;
|
|
71
73
|
strict?: boolean | undefined;
|
|
72
74
|
fromBlock?: bigint | import("viem").BlockTag | undefined;
|
|
73
75
|
toBlock?: bigint | import("viem").BlockTag | undefined;
|
|
74
|
-
blockHash?: `0x${string}` | undefined;
|
|
75
76
|
} | undefined] | [args?: readonly unknown[] | {
|
|
76
77
|
[x: string]: unknown;
|
|
77
78
|
address?: undefined;
|
|
@@ -86,10 +87,10 @@ export declare function getContractInstance(contractAddress: string, abi: Abi, c
|
|
|
86
87
|
batch?: undefined;
|
|
87
88
|
pollingInterval?: undefined;
|
|
88
89
|
} | undefined, options?: {
|
|
90
|
+
blockHash?: `0x${string}` | undefined;
|
|
89
91
|
strict?: boolean | undefined;
|
|
90
92
|
fromBlock?: bigint | import("viem").BlockTag | undefined;
|
|
91
93
|
toBlock?: bigint | import("viem").BlockTag | undefined;
|
|
92
|
-
blockHash?: `0x${string}` | undefined;
|
|
93
94
|
} | undefined]) => Promise<import("viem").GetContractEventsReturnType<Abi, string>>;
|
|
94
95
|
};
|
|
95
96
|
watchEvent: {
|
|
@@ -125,7 +126,7 @@ export declare function getContractInstance(contractAddress: string, abi: Abi, c
|
|
|
125
126
|
} | undefined]) => import("viem").WatchContractEventReturnType;
|
|
126
127
|
};
|
|
127
128
|
write: {
|
|
128
|
-
[x: string]: <chainOverride extends import("viem").Chain | undefined, options extends import("viem").UnionOmit<import("viem").WriteContractParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined, Account | undefined, chainOverride>, "address" | "abi" | "
|
|
129
|
+
[x: string]: <chainOverride extends import("viem").Chain | undefined, options extends import("viem").UnionOmit<import("viem").WriteContractParameters<Abi, string, readonly unknown[], import("viem").Chain | undefined, Account | undefined, chainOverride>, "address" | "abi" | "functionName" | "args"> extends infer T ? { [K in keyof T]: T[K]; } : never, Rest extends unknown[] = [options: options]>(...parameters: Rest | [args: readonly unknown[], ...parameters: Rest]) => Promise<import("viem").WriteContractReturnType>;
|
|
129
130
|
};
|
|
130
131
|
address: `0x${string}`;
|
|
131
132
|
abi: Abi;
|
|
@@ -285,6 +286,17 @@ export declare function estimateUserOperationFees(bundlerClient: any, _publicCli
|
|
|
285
286
|
maxFeePerGas: bigint;
|
|
286
287
|
maxPriorityFeePerGas: bigint;
|
|
287
288
|
}>;
|
|
289
|
+
/**
|
|
290
|
+
* Floors `verificationGasLimit` on Tempo networks before the UserOp is handed to
|
|
291
|
+
* the ZeroDev paymaster, so `zd_sponsorUserOperation` has headroom and does not
|
|
292
|
+
* revert AA26. No-op on every other network. Shared by both paymaster sponsor
|
|
293
|
+
* call sites. Generic so the caller's UserOp type is preserved; typing
|
|
294
|
+
* `verificationGasLimit?: bigint` also turns a plain-number literal (a `bigint`
|
|
295
|
+
* missing its `n`) into a compile error instead of a silent floor-to-30M.
|
|
296
|
+
*/
|
|
297
|
+
export declare function applyTempoVerificationGasFloor<T extends {
|
|
298
|
+
verificationGasLimit?: bigint;
|
|
299
|
+
}>(userOperation: T, chainId: number): T;
|
|
288
300
|
/**
|
|
289
301
|
* It creates a ZeroDev Kernel client.
|
|
290
302
|
* @param signer the signer account
|
|
@@ -304,6 +316,13 @@ export type EcdsaValidator = Awaited<ReturnType<typeof signerToEcdsaValidator>>;
|
|
|
304
316
|
* (e.g. the webapp's localStorage) should stamp this and invalidate on change.
|
|
305
317
|
*/
|
|
306
318
|
export declare const SCA_DERIVATION_VERSION: string;
|
|
319
|
+
export declare const ACCOUNT_CACHE_MAX_ENTRIES = 5000;
|
|
320
|
+
/** Current entry count of the Kernel account-resolution memo (#2206). */
|
|
321
|
+
export declare function getAccountResolutionCacheStats(): {
|
|
322
|
+
size: number;
|
|
323
|
+
};
|
|
324
|
+
/** Clear the account-resolution memo (test isolation / kernel-upgrade invalidation). */
|
|
325
|
+
export declare function clearAccountResolutionCache(): void;
|
|
307
326
|
/**
|
|
308
327
|
* Build the ECDSA sudo validator for a signer. Both `createKernelSmartAccount`
|
|
309
328
|
* and `createSessionKey` need this validator and each derives it via a ZeroDev
|
|
@@ -319,8 +338,48 @@ export declare function createEcdsaValidator(signer: Signer, publicClient: Publi
|
|
|
319
338
|
export declare function createKernelSmartAccount(signer: Signer, publicClient: PublicClient, ecdsaValidator?: EcdsaValidator): Promise<SmartAccount>;
|
|
320
339
|
export declare function getApproval(signer: Signer, publicClient: any, policies: any[]): Promise<string>;
|
|
321
340
|
export declare function useSessionKey(approval: string, signer: Signer, publicClient: any): Promise<import("@zerodev/sdk").CreateKernelAccountReturnType<"0.7">>;
|
|
322
|
-
export declare function createSessionKey(signer: Signer, publicClient: any, policies: any[], ecdsaValidator?: EcdsaValidator): Promise<string>;
|
|
323
|
-
|
|
341
|
+
export declare function createSessionKey(signer: Signer, publicClient: any, policies: any[], ecdsaValidator?: EcdsaValidator, sessionPrivateKey?: `0x${string}`): Promise<string>;
|
|
342
|
+
/**
|
|
343
|
+
* Multi-network session keys (#1929). Generates ONE session private key and
|
|
344
|
+
* serializes the permission account once per network — each serialization
|
|
345
|
+
* carries that network's chain-bound enable signature. The SAME session key
|
|
346
|
+
* works on every supported chain (the smart-account address + init code are
|
|
347
|
+
* identical via CREATE2 parity); only the enable signature differs per chain.
|
|
348
|
+
*
|
|
349
|
+
* Use the returned map (chainId → serialized session key) to build a single
|
|
350
|
+
* multi-network API key: the backend selects the entry for the operation's
|
|
351
|
+
* network. Avoids the `EnableNotApproved` revert when an API key minted on one
|
|
352
|
+
* chain is used on another.
|
|
353
|
+
*
|
|
354
|
+
* @param signer the smart-account owner (e.g. the Privy EOA) — signs each
|
|
355
|
+
* network's enable signature
|
|
356
|
+
* @param publicClientByChainId map of chainId → a PublicClient for that chain
|
|
357
|
+
* @param policies the permission policies (same on every chain)
|
|
358
|
+
*/
|
|
359
|
+
export declare function createSessionKeysForNetworks(signer: Signer, publicClientByChainId: Record<number, any>, policies: any[], requiredChainId?: number): Promise<Record<number, string>>;
|
|
360
|
+
/**
|
|
361
|
+
* The canonical, CREATE2-deterministic Kernel v3.3 implementation that an EOA
|
|
362
|
+
* delegates to under EIP-7702 (same address on Base mainnet + Base Sepolia).
|
|
363
|
+
* This is the `contract`/`address` passed to Privy `sign7702Authorization` and
|
|
364
|
+
* carried in the type-4 authorization. See #2148.
|
|
365
|
+
*/
|
|
366
|
+
export declare const KERNEL_7702_IMPL_ADDRESS = "0xd6CEDDe84be40893d153Be9d467CD6aD37875b28";
|
|
367
|
+
export { KERNEL_V3_1, KERNEL_V3_3 };
|
|
368
|
+
export type KernelVersion = typeof KERNEL_V3_1 | typeof KERNEL_V3_3;
|
|
369
|
+
/**
|
|
370
|
+
* Resolves a user's EIP-7702 account: the Privy EOA delegated to Kernel v3.3.
|
|
371
|
+
* The resulting account's address **equals the EOA** (no counterfactual SCA),
|
|
372
|
+
* so it both signs EIP-3009 as a plain EOA (Router) and acts as a 4337 smart
|
|
373
|
+
* account (credits/session-keys). `eip7702Auth` is the signed type-4
|
|
374
|
+
* authorization (from Privy `sign7702Authorization`); omit it once the account
|
|
375
|
+
* is already delegated on-chain.
|
|
376
|
+
*
|
|
377
|
+
* ponytail: on-chain correctness (delegation designator, UserOp submission)
|
|
378
|
+
* is validated on Base Sepolia in Phase 0 (#2153); this wrapper only pins the
|
|
379
|
+
* SDK call shape.
|
|
380
|
+
*/
|
|
381
|
+
export declare function createKernel7702Account(signer: Signer, publicClient: PublicClient, eip7702Auth?: SignAuthorizationReturnType): Promise<SmartAccount>;
|
|
382
|
+
export declare function getSessionKey(serializedSessionKey: string, publicClient: any, kernelVersion?: KernelVersion): Promise<import("@zerodev/sdk").CreateKernelAccountReturnType<"0.7">>;
|
|
324
383
|
/**
|
|
325
384
|
* Creates a delegated session key for an existing kernel account.
|
|
326
385
|
* The resulting serialized session key can be deserialized into a SmartAccount
|
|
@@ -331,7 +390,7 @@ export declare function getSessionKey(serializedSessionKey: string, publicClient
|
|
|
331
390
|
* @param policies Array of policies to enforce for this session key
|
|
332
391
|
* @returns Serialized session key string
|
|
333
392
|
*/
|
|
334
|
-
export declare function createDelegatedSessionKeyFromKernel(kernelAccount: SmartAccount, publicClient: PublicClient, policies: any[]): Promise<string>;
|
|
393
|
+
export declare function createDelegatedSessionKeyFromKernel(kernelAccount: SmartAccount, publicClient: PublicClient, policies: any[], kernelVersion?: KernelVersion): Promise<string>;
|
|
335
394
|
export declare const WalletUtils: {
|
|
336
395
|
makeWallet: typeof makeWallet;
|
|
337
396
|
makeWallets: typeof makeWallets;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BlockchainViemUtils.d.ts","sourceRoot":"","sources":["../../../src/nevermined/utils/BlockchainViemUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AAOjE,OAAO,EAML,mBAAmB,EAEpB,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"BlockchainViemUtils.d.ts","sourceRoot":"","sources":["../../../src/nevermined/utils/BlockchainViemUtils.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,12 @@ import { signerToEcdsaValidator } from '@zerodev/ecdsa-validator';
|
|
|
2
2
|
import { deserializePermissionAccount, serializePermissionAccount, toPermissionValidator } from '@zerodev/permissions';
|
|
3
3
|
import { toECDSASigner } from '@zerodev/permissions/signers';
|
|
4
4
|
import { addressToEmptyAccount, createKernelAccount, createKernelAccountClient, createZeroDevPaymasterClient, getUserOperationGasPrice } from '@zerodev/sdk';
|
|
5
|
-
import { KERNEL_V3_1, getEntryPoint } from '@zerodev/sdk/constants';
|
|
5
|
+
import { KERNEL_V3_1, KERNEL_V3_3, KERNEL_7702_DELEGATION_ADDRESS, getEntryPoint } from '@zerodev/sdk/constants';
|
|
6
6
|
import { encodeAbiParameters, getAbiItem, getAddress, getContract, http, isAddress, pad, stringToBytes, stringToHex, toBytes, keccak256 as viemKeccak256 } from 'viem';
|
|
7
7
|
import { english, generateMnemonic, generatePrivateKey, mnemonicToAccount, privateKeyToAccount } from 'viem/accounts';
|
|
8
8
|
import { Instantiable } from '../../Instantiable.abstract.js';
|
|
9
9
|
import { ContractsError } from '../../errors/NeverminedErrors.js';
|
|
10
|
-
import { getChain } from '../../utils/Network.js';
|
|
10
|
+
import { getChain, isTempoNetwork } from '../../utils/Network.js';
|
|
11
11
|
const ENTRY_POINT_VERSION = '0.7';
|
|
12
12
|
/**
|
|
13
13
|
* Utility class with methods that allow the interaction with the blockchain.
|
|
@@ -244,10 +244,13 @@ const TRANSACTION_RECEIPT_POLLING_INTERVAL_MS = 1_500;
|
|
|
244
244
|
* `BUNDLER_RPC_URL_OVERRIDE` is set.
|
|
245
245
|
*/ export function getBundlerRpcUrl(zeroDevProjectId, chainId, useUltraRelay = false) {
|
|
246
246
|
const base = `https://rpc.zerodev.app/api/v3/${zeroDevProjectId}/chain/${chainId}`;
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
//
|
|
250
|
-
|
|
247
|
+
// Per-chain override wins, then the global override, then the canonical URL.
|
|
248
|
+
// The per-chain form (`BUNDLER_RPC_URL_OVERRIDE_<chainId>`) lets a single
|
|
249
|
+
// process route UserOps for different networks to different local bundlers —
|
|
250
|
+
// e.g. a dual-fork dev stack (base-sepolia bundler :4337 + tempo bundler
|
|
251
|
+
// :4338). `||` (not `??`) because Vite replaces missing browser env vars with
|
|
252
|
+
// the empty string at build time; an empty override is equivalent to none.
|
|
253
|
+
return process.env[`BUNDLER_RPC_URL_OVERRIDE_${chainId}`] || process.env.BUNDLER_RPC_URL_OVERRIDE || (useUltraRelay ? `${base}?provider=ULTRA_RELAY` : base);
|
|
251
254
|
}
|
|
252
255
|
/**
|
|
253
256
|
* Returns the paymaster RPC URL (ZeroDev-only; the local fork stack uses
|
|
@@ -280,6 +283,32 @@ const TRANSACTION_RECEIPT_POLLING_INTERVAL_MS = 1_500;
|
|
|
280
283
|
}
|
|
281
284
|
return getUserOperationGasPrice(bundlerClient);
|
|
282
285
|
}
|
|
286
|
+
// Tempo undersizes the ZeroDev bundler's `verificationGasLimit` estimate (cold
|
|
287
|
+
// SCA deploy + session-key enable under TIP-20 gas), so `zd_sponsorUserOperation`
|
|
288
|
+
// re-simulates with that too-low ceiling and reverts `AA26 over
|
|
289
|
+
// verificationGasLimit` (see #1929, staging createPlan on tempo-moderato). We give
|
|
290
|
+
// the sponsor an explicit floor so it stops undersizing. A multiplier is useless
|
|
291
|
+
// here — viem calls getPaymasterData with verificationGasLimit still 0/undefined,
|
|
292
|
+
// so `x * n` is 0. An absolute floor covers both the 0 and the too-low cases.
|
|
293
|
+
// NOTE(#1929): fixed floor — bump if a Tempo op still AA26s (env-tunable if it ever needs per-deploy calibration).
|
|
294
|
+
// needs per-deploy calibration).
|
|
295
|
+
const TEMPO_MIN_VERIFICATION_GAS = 30_000_000n;
|
|
296
|
+
/**
|
|
297
|
+
* Floors `verificationGasLimit` on Tempo networks before the UserOp is handed to
|
|
298
|
+
* the ZeroDev paymaster, so `zd_sponsorUserOperation` has headroom and does not
|
|
299
|
+
* revert AA26. No-op on every other network. Shared by both paymaster sponsor
|
|
300
|
+
* call sites. Generic so the caller's UserOp type is preserved; typing
|
|
301
|
+
* `verificationGasLimit?: bigint` also turns a plain-number literal (a `bigint`
|
|
302
|
+
* missing its `n`) into a compile error instead of a silent floor-to-30M.
|
|
303
|
+
*/ export function applyTempoVerificationGasFloor(userOperation, chainId) {
|
|
304
|
+
if (!isTempoNetwork(chainId)) return userOperation;
|
|
305
|
+
const current = typeof userOperation.verificationGasLimit === 'bigint' ? userOperation.verificationGasLimit : 0n;
|
|
306
|
+
const floored = current > TEMPO_MIN_VERIFICATION_GAS ? current : TEMPO_MIN_VERIFICATION_GAS;
|
|
307
|
+
return {
|
|
308
|
+
...userOperation,
|
|
309
|
+
verificationGasLimit: floored
|
|
310
|
+
};
|
|
311
|
+
}
|
|
283
312
|
/**
|
|
284
313
|
* It creates a ZeroDev Kernel client.
|
|
285
314
|
* @param signer the signer account
|
|
@@ -305,7 +334,7 @@ const TRANSACTION_RECEIPT_POLLING_INTERVAL_MS = 1_500;
|
|
|
305
334
|
transport: http(paymasterRpc)
|
|
306
335
|
});
|
|
307
336
|
return zerodevPaymaster.sponsorUserOperation({
|
|
308
|
-
userOperation
|
|
337
|
+
userOperation: applyTempoVerificationGasFloor(userOperation, chainId)
|
|
309
338
|
});
|
|
310
339
|
}
|
|
311
340
|
}
|
|
@@ -323,6 +352,71 @@ const TRANSACTION_RECEIPT_POLLING_INTERVAL_MS = 1_500;
|
|
|
323
352
|
* bump here means the same EOA derives a different SCA. Persisted SCA caches
|
|
324
353
|
* (e.g. the webapp's localStorage) should stamp this and invalidate on change.
|
|
325
354
|
*/ export const SCA_DERIVATION_VERSION = `${ENTRY_POINT_VERSION}:${KERNEL_V3_1}`;
|
|
355
|
+
// ponytail: in-process memo for ZeroDev Kernel account resolution. Every
|
|
356
|
+
// deserializePermissionAccount / createKernelAccount reads the EIP-1967 impl
|
|
357
|
+
// slot (eth_getStorageAt) of a deployed account — ~56% of backend Infura RPC
|
|
358
|
+
// volume, and the same session key/owner is re-resolved per request and twice
|
|
359
|
+
// per x402 payment (verify + settle). See #2206. Safe to reuse the resolved
|
|
360
|
+
// account: the Kernel account fetches its nonce fresh at send time, so a cached
|
|
361
|
+
// account never signs against a stale nonce. Keyed by the deterministic inputs
|
|
362
|
+
// (serialized key / owner + kernel version + chainId); short TTL bounds
|
|
363
|
+
// staleness across a kernel upgrade. Single-process only — cross-pod dedup is
|
|
364
|
+
// out of scope (#2206 notes). Upgrade path: swap the Map for a shared store.
|
|
365
|
+
const ACCOUNT_CACHE_TTL_MS = 60_000;
|
|
366
|
+
// Bound the cache: `getSessionKey` runs behind `getAccountAttributes` on every
|
|
367
|
+
// authenticated request, keyed per-API-key, so an entry never re-requested
|
|
368
|
+
// would otherwise sit past its TTL for the life of the (long-lived) apps/api
|
|
369
|
+
// process — a slow leak. Cardinality ≈ distinct API keys ever seen; cap + sweep
|
|
370
|
+
// keep it bounded (matches BlockchainCacheService's MAX_ENTRIES + cleanup()).
|
|
371
|
+
export const ACCOUNT_CACHE_MAX_ENTRIES = 5_000;
|
|
372
|
+
const accountResolutionCache = new Map();
|
|
373
|
+
function memoResolveAccount(key, resolver) {
|
|
374
|
+
const now = Date.now();
|
|
375
|
+
const cached = accountResolutionCache.get(key);
|
|
376
|
+
if (cached && cached.expiresAt > now) {
|
|
377
|
+
return cached.value;
|
|
378
|
+
}
|
|
379
|
+
// Sweep expired entries + bound size so keys never re-requested don't
|
|
380
|
+
// accumulate for the life of the process (Map keeps insertion order → FIFO).
|
|
381
|
+
for (const [k, e] of accountResolutionCache){
|
|
382
|
+
if (e.expiresAt <= now) accountResolutionCache.delete(k);
|
|
383
|
+
}
|
|
384
|
+
if (accountResolutionCache.size >= ACCOUNT_CACHE_MAX_ENTRIES) {
|
|
385
|
+
accountResolutionCache.delete(accountResolutionCache.keys().next().value);
|
|
386
|
+
}
|
|
387
|
+
const entry = {
|
|
388
|
+
value: undefined,
|
|
389
|
+
expiresAt: now + ACCOUNT_CACHE_TTL_MS
|
|
390
|
+
};
|
|
391
|
+
// Coalesce concurrent identical resolutions; evict on rejection so a transient
|
|
392
|
+
// RPC failure isn't cached — but only if this exact entry is still current, so
|
|
393
|
+
// a resolver that hangs past its TTL and then rejects can't drop a newer one.
|
|
394
|
+
entry.value = resolver().catch((err)=>{
|
|
395
|
+
if (accountResolutionCache.get(key) === entry) accountResolutionCache.delete(key);
|
|
396
|
+
throw err;
|
|
397
|
+
});
|
|
398
|
+
accountResolutionCache.set(key, entry);
|
|
399
|
+
return entry.value;
|
|
400
|
+
}
|
|
401
|
+
/** Current entry count of the Kernel account-resolution memo (#2206). */ export function getAccountResolutionCacheStats() {
|
|
402
|
+
return {
|
|
403
|
+
size: accountResolutionCache.size
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
/** Clear the account-resolution memo (test isolation / kernel-upgrade invalidation). */ export function clearAccountResolutionCache() {
|
|
407
|
+
accountResolutionCache.clear();
|
|
408
|
+
}
|
|
409
|
+
function chainIdOf(publicClient) {
|
|
410
|
+
const id = publicClient?.chain?.id;
|
|
411
|
+
// chainId is the ONLY discriminator in the sca:/7702:/sk: keys, and SCA /
|
|
412
|
+
// session-key addresses are identical across chains by CREATE2 design — so an
|
|
413
|
+
// id-less client must fail closed rather than alias two networks under one
|
|
414
|
+
// bucket and serve a chain-A account to a chain-B request (latent until #1933).
|
|
415
|
+
if (id == null) {
|
|
416
|
+
throw new Error('account-resolution cache: publicClient.chain.id is required for keying');
|
|
417
|
+
}
|
|
418
|
+
return id;
|
|
419
|
+
}
|
|
326
420
|
/**
|
|
327
421
|
* Build the ECDSA sudo validator for a signer. Both `createKernelSmartAccount`
|
|
328
422
|
* and `createSessionKey` need this validator and each derives it via a ZeroDev
|
|
@@ -341,14 +435,21 @@ const TRANSACTION_RECEIPT_POLLING_INTERVAL_MS = 1_500;
|
|
|
341
435
|
});
|
|
342
436
|
}
|
|
343
437
|
export async function createKernelSmartAccount(signer, publicClient, ecdsaValidator) {
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
438
|
+
const build = async ()=>{
|
|
439
|
+
const validator = ecdsaValidator ?? await createEcdsaValidator(signer, publicClient);
|
|
440
|
+
return createKernelAccount(publicClient, {
|
|
441
|
+
plugins: {
|
|
442
|
+
sudo: validator
|
|
443
|
+
},
|
|
444
|
+
entryPoint: getEntryPoint(ENTRY_POINT_VERSION),
|
|
445
|
+
kernelVersion: KERNEL_V3_1
|
|
446
|
+
});
|
|
447
|
+
};
|
|
448
|
+
// A caller-supplied validator isn't part of the key — bypass the memo (like
|
|
449
|
+
// createKernel7702Account does for eip7702Auth) rather than let a cache entry
|
|
450
|
+
// built by a different call silently ignore it (the mismatch createEcdsaValidator warns about).
|
|
451
|
+
if (ecdsaValidator) return build();
|
|
452
|
+
return memoResolveAccount(`sca:${chainIdOf(publicClient)}:${SCA_DERIVATION_VERSION}:${signer.address}`, build);
|
|
352
453
|
}
|
|
353
454
|
export async function getApproval(signer, publicClient, policies) {
|
|
354
455
|
const ecdsaValidator = await signerToEcdsaValidator(publicClient, {
|
|
@@ -383,9 +484,8 @@ export async function useSessionKey(approval, signer, publicClient) {
|
|
|
383
484
|
const sessionKeyAccount = await deserializePermissionAccount(publicClient, getEntryPoint(ENTRY_POINT_VERSION), KERNEL_V3_1, approval, sessionKeySigner);
|
|
384
485
|
return sessionKeyAccount;
|
|
385
486
|
}
|
|
386
|
-
export async function createSessionKey(signer, publicClient, policies, ecdsaValidator) {
|
|
487
|
+
export async function createSessionKey(signer, publicClient, policies, ecdsaValidator, sessionPrivateKey = generatePrivateKey()) {
|
|
387
488
|
const validator = ecdsaValidator ?? await createEcdsaValidator(signer, publicClient);
|
|
388
|
-
const sessionPrivateKey = generatePrivateKey();
|
|
389
489
|
const masterAccount = privateKeyToAccount(sessionPrivateKey);
|
|
390
490
|
const sessionKeySigner = await toECDSASigner({
|
|
391
491
|
signer: masterAccount
|
|
@@ -404,11 +504,86 @@ export async function createSessionKey(signer, publicClient, policies, ecdsaVali
|
|
|
404
504
|
},
|
|
405
505
|
kernelVersion: KERNEL_V3_1
|
|
406
506
|
});
|
|
507
|
+
// serializePermissionAccount embeds the ENABLE signature for `publicClient`'s
|
|
508
|
+
// chain (signed by the sudo/owner). That signature is chain-bound, which is
|
|
509
|
+
// why one serialization only validates on the chain it was made for. #1929
|
|
407
510
|
return serializePermissionAccount(sessionKeyAccount, sessionPrivateKey);
|
|
408
511
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
512
|
+
/**
|
|
513
|
+
* Multi-network session keys (#1929). Generates ONE session private key and
|
|
514
|
+
* serializes the permission account once per network — each serialization
|
|
515
|
+
* carries that network's chain-bound enable signature. The SAME session key
|
|
516
|
+
* works on every supported chain (the smart-account address + init code are
|
|
517
|
+
* identical via CREATE2 parity); only the enable signature differs per chain.
|
|
518
|
+
*
|
|
519
|
+
* Use the returned map (chainId → serialized session key) to build a single
|
|
520
|
+
* multi-network API key: the backend selects the entry for the operation's
|
|
521
|
+
* network. Avoids the `EnableNotApproved` revert when an API key minted on one
|
|
522
|
+
* chain is used on another.
|
|
523
|
+
*
|
|
524
|
+
* @param signer the smart-account owner (e.g. the Privy EOA) — signs each
|
|
525
|
+
* network's enable signature
|
|
526
|
+
* @param publicClientByChainId map of chainId → a PublicClient for that chain
|
|
527
|
+
* @param policies the permission policies (same on every chain)
|
|
528
|
+
*/ export async function createSessionKeysForNetworks(signer, publicClientByChainId, policies, requiredChainId) {
|
|
529
|
+
const sessionPrivateKey = generatePrivateKey();
|
|
530
|
+
const out = {};
|
|
531
|
+
for (const [chainIdStr, publicClient] of Object.entries(publicClientByChainId)){
|
|
532
|
+
const chainId = Number(chainIdStr);
|
|
533
|
+
try {
|
|
534
|
+
out[chainId] = await createSessionKey(signer, publicClient, policies, undefined, sessionPrivateKey);
|
|
535
|
+
} catch (err) {
|
|
536
|
+
// Best-effort: a secondary network whose RPC is unreachable must not break
|
|
537
|
+
// key generation (e.g. login). `requiredChainId` (the primary) still throws.
|
|
538
|
+
if (requiredChainId != null && chainId === Number(requiredChainId)) throw err;
|
|
539
|
+
console.warn(`[createSessionKeysForNetworks] skipping network ${chainId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
// Enforce the `requiredChainId` contract even when it is ABSENT from the input
|
|
543
|
+
// map (the loop above only throws when it is present AND fails). Without this,
|
|
544
|
+
// callers read `out[primary]` → undefined → an API key with no primary session
|
|
545
|
+
// key, which fails opaquely downstream.
|
|
546
|
+
if (requiredChainId != null && out[requiredChainId] == null) {
|
|
547
|
+
throw new Error(`createSessionKeysForNetworks: required network ${requiredChainId} was not in the public-client map`);
|
|
548
|
+
}
|
|
549
|
+
return out;
|
|
550
|
+
}
|
|
551
|
+
/**
|
|
552
|
+
* The canonical, CREATE2-deterministic Kernel v3.3 implementation that an EOA
|
|
553
|
+
* delegates to under EIP-7702 (same address on Base mainnet + Base Sepolia).
|
|
554
|
+
* This is the `contract`/`address` passed to Privy `sign7702Authorization` and
|
|
555
|
+
* carried in the type-4 authorization. See #2148.
|
|
556
|
+
*/ export const KERNEL_7702_IMPL_ADDRESS = KERNEL_7702_DELEGATION_ADDRESS;
|
|
557
|
+
// The two Kernel versions the platform runs: v3.1 for the legacy counterfactual
|
|
558
|
+
// SCA, v3.3 for the EIP-7702-delegated EOA account. Re-exported so the API
|
|
559
|
+
// layer can pick the right version for (de)serializing session keys.
|
|
560
|
+
export { KERNEL_V3_1, KERNEL_V3_3 };
|
|
561
|
+
/**
|
|
562
|
+
* Resolves a user's EIP-7702 account: the Privy EOA delegated to Kernel v3.3.
|
|
563
|
+
* The resulting account's address **equals the EOA** (no counterfactual SCA),
|
|
564
|
+
* so it both signs EIP-3009 as a plain EOA (Router) and acts as a 4337 smart
|
|
565
|
+
* account (credits/session-keys). `eip7702Auth` is the signed type-4
|
|
566
|
+
* authorization (from Privy `sign7702Authorization`); omit it once the account
|
|
567
|
+
* is already delegated on-chain.
|
|
568
|
+
*
|
|
569
|
+
* ponytail: on-chain correctness (delegation designator, UserOp submission)
|
|
570
|
+
* is validated on Base Sepolia in Phase 0 (#2153); this wrapper only pins the
|
|
571
|
+
* SDK call shape.
|
|
572
|
+
*/ export async function createKernel7702Account(signer, publicClient, eip7702Auth) {
|
|
573
|
+
const build = ()=>createKernelAccount(publicClient, {
|
|
574
|
+
eip7702Account: signer,
|
|
575
|
+
...eip7702Auth ? {
|
|
576
|
+
eip7702Auth
|
|
577
|
+
} : {},
|
|
578
|
+
entryPoint: getEntryPoint(ENTRY_POINT_VERSION),
|
|
579
|
+
kernelVersion: KERNEL_V3_3
|
|
580
|
+
});
|
|
581
|
+
// The install path (auth attached) is a one-time mutating op — never cache it.
|
|
582
|
+
if (eip7702Auth) return build();
|
|
583
|
+
return memoResolveAccount(`7702:${chainIdOf(publicClient)}:${signer.address}`, build);
|
|
584
|
+
}
|
|
585
|
+
export async function getSessionKey(serializedSessionKey, publicClient, kernelVersion = KERNEL_V3_1) {
|
|
586
|
+
return memoResolveAccount(`sk:${chainIdOf(publicClient)}:${kernelVersion}:${serializedSessionKey}`, ()=>deserializePermissionAccount(publicClient, getEntryPoint(ENTRY_POINT_VERSION), kernelVersion, serializedSessionKey));
|
|
412
587
|
}
|
|
413
588
|
/**
|
|
414
589
|
* Creates a delegated session key for an existing kernel account.
|
|
@@ -419,7 +594,7 @@ export async function getSessionKey(serializedSessionKey, publicClient) {
|
|
|
419
594
|
* @param publicClient Viem PublicClient instance
|
|
420
595
|
* @param policies Array of policies to enforce for this session key
|
|
421
596
|
* @returns Serialized session key string
|
|
422
|
-
*/ export async function createDelegatedSessionKeyFromKernel(kernelAccount, publicClient, policies) {
|
|
597
|
+
*/ export async function createDelegatedSessionKeyFromKernel(kernelAccount, publicClient, policies, kernelVersion = KERNEL_V3_1) {
|
|
423
598
|
// 1) Generate ephemeral session private key (used only for the permission plugin)
|
|
424
599
|
const sessionPrivateKey = generatePrivateKey();
|
|
425
600
|
const sessionAccount = privateKeyToAccount(sessionPrivateKey);
|
|
@@ -427,12 +602,14 @@ export async function getSessionKey(serializedSessionKey, publicClient) {
|
|
|
427
602
|
const sessionKeySigner = await toECDSASigner({
|
|
428
603
|
signer: sessionAccount
|
|
429
604
|
});
|
|
430
|
-
// 3) Create the permission validator plugin
|
|
605
|
+
// 3) Create the permission validator plugin — MUST match the parent kernel's
|
|
606
|
+
// version (v3.3 for a 7702 account, v3.1 for the legacy SCA), otherwise the
|
|
607
|
+
// serialized blob deserializes/validates against the wrong kernel.
|
|
431
608
|
const permissionValidator = await toPermissionValidator(publicClient, {
|
|
432
609
|
entryPoint: getEntryPoint(ENTRY_POINT_VERSION),
|
|
433
610
|
signer: sessionKeySigner,
|
|
434
611
|
policies,
|
|
435
|
-
kernelVersion
|
|
612
|
+
kernelVersion
|
|
436
613
|
});
|
|
437
614
|
// 4) Extract the sudo validator from the existing kernel account
|
|
438
615
|
const kernelAccountTyped = kernelAccount;
|
|
@@ -440,14 +617,18 @@ export async function getSessionKey(serializedSessionKey, publicClient) {
|
|
|
440
617
|
if (!sudoValidator) {
|
|
441
618
|
throw new Error('Kernel account does not have a sudo validator');
|
|
442
619
|
}
|
|
443
|
-
// 5) Create a new kernel account with both sudo (from original) and permission
|
|
620
|
+
// 5) Create a new kernel account with both sudo (from original) and permission
|
|
621
|
+
// validator, at the same address as the parent kernel. For a 7702 account
|
|
622
|
+
// that address is the EOA; pinning `address` keeps the session-key account
|
|
623
|
+
// on the same account rather than a fresh counterfactual one.
|
|
444
624
|
const sessionKeyAccount = await createKernelAccount(publicClient, {
|
|
445
625
|
entryPoint: getEntryPoint(ENTRY_POINT_VERSION),
|
|
626
|
+
address: kernelAccountTyped.address,
|
|
446
627
|
plugins: {
|
|
447
628
|
sudo: sudoValidator,
|
|
448
629
|
regular: permissionValidator
|
|
449
630
|
},
|
|
450
|
-
kernelVersion
|
|
631
|
+
kernelVersion
|
|
451
632
|
});
|
|
452
633
|
// 6) Serialize the session key account with the ephemeral private key
|
|
453
634
|
const serialized = await serializePermissionAccount(sessionKeyAccount, sessionPrivateKey);
|