@nevermined-io/core-kit 0.5.20 → 0.5.22
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/contracts/ContractBase.d.ts +9 -0
- package/dist/contracts/ContractBase.d.ts.map +1 -1
- package/dist/contracts/ContractBase.js +101 -8
- package/dist/contracts/ContractBase.js.map +1 -1
- package/dist/models/AgentX402AccessToken.d.ts +107 -2
- package/dist/models/AgentX402AccessToken.d.ts.map +1 -1
- package/dist/models/AgentX402AccessToken.js +89 -4
- package/dist/models/AgentX402AccessToken.js.map +1 -1
- package/package.json +15 -8
|
@@ -33,6 +33,15 @@ export declare abstract class ContractBase extends Instantiable {
|
|
|
33
33
|
simulateMulticall(calls: SimulateMulticallEntry[], from: Account | SmartAccount, params?: TxParameters): Promise<boolean>;
|
|
34
34
|
simulate(functionName: string, from: Account | SmartAccount, args: any[], params?: TxParameters): Promise<boolean>;
|
|
35
35
|
send(functionName: string, from: Account | SmartAccount, args: any[], params?: TxParameters): Promise<TransactionReceipt | UserOperationReceipt>;
|
|
36
|
+
/**
|
|
37
|
+
* Poll a previously-submitted UserOperation's receipt by hash WITHOUT
|
|
38
|
+
* blocking. Returns the receipt once the bundler has mined it, or `null`
|
|
39
|
+
* while it is still in the mempool / not yet known. A client-side
|
|
40
|
+
* receipt-wait timeout does NOT cancel a submitted UserOp, so callers that
|
|
41
|
+
* persist the hash (e.g. the onchain-mirror worker, nvm-monorepo#1508) use
|
|
42
|
+
* this to confirm a prior submission instead of resubmitting a duplicate.
|
|
43
|
+
*/
|
|
44
|
+
getUserOperationReceipt(hash: `0x${string}`): Promise<UserOperationReceipt | null>;
|
|
36
45
|
private internalMulticallSmartAccount;
|
|
37
46
|
private assertUserOpSucceeded;
|
|
38
47
|
private internalSendSmartAccount;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContractBase.d.ts","sourceRoot":"","sources":["../../src/contracts/ContractBase.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,GAAG,EACH,OAAO,EACP,OAAO,EAQP,kBAAkB,EACnB,MAAM,MAAM,CAAA;AACb,OAAO,
|
|
1
|
+
{"version":3,"file":"ContractBase.d.ts","sourceRoot":"","sources":["../../src/contracts/ContractBase.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,GAAG,EACH,OAAO,EACP,OAAO,EAQP,kBAAkB,EACnB,MAAM,MAAM,CAAA;AACb,OAAO,EAGL,YAAY,EACZ,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAKxD,MAAM,WAAW,cAAc;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,OAAO,CAAA;IACxB,GAAG,EAAE,GAAG,CAAA;IACR,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,GAAG,EAAE,CAAA;CACZ;AA0CD,MAAM,WAAW,sBAAsB;IACrC,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,GAAG,CAAA;IACR,IAAI,EAAE,GAAG,EAAE,CAAA;IACX,EAAE,EAAE,OAAO,CAAA;CACZ;AAED,8BAAsB,YAAa,SAAQ,YAAY;IACrD,SAAgB,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,EAAE,GAAG,CAAA;IACb,OAAO,EAAE,OAAO,CAAA;IACvB,OAAO,CAAC,iBAAiB,CAA+D;gBAE5E,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;cAMlC,IAAI,CAClB,MAAM,EAAE,kBAAkB,EAC1B,cAAc,EAAE;QAAE,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,GAAG,CAAA;KAAE;IAYzC,IAAI,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAiBrE,qBAAqB,CAChC,MAAM,EAAE,oBAAoB,GAAG,kBAAkB,GAChD,OAAO,CAAC,kBAAkB,CAAC;IAiBvB,kBAAkB,CACvB,SAAS,EAAE,kBAAkB,GAAG,oBAAoB,EACpD,SAAS,CAAC,EAAE,MAAM,GAOZ,GAAG,EAAE;IAGA,SAAS,CACpB,KAAK,EAAE,cAAc,EAAE,EACvB,IAAI,EAAE,OAAO,GAAG,YAAY,EAC5B,MAAM,GAAE,YAAiB;IAgBd,iBAAiB,CAC5B,KAAK,EAAE,sBAAsB,EAAE,EAC/B,IAAI,EAAE,OAAO,GAAG,YAAY,EAC5B,MAAM,GAAE,YAAiB;IAgBd,QAAQ,CACnB,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,GAAG,YAAY,EAC5B,IAAI,EAAE,GAAG,EAAE,EACX,MAAM,GAAE,YAAiB;IAgBd,IAAI,CACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,OAAO,GAAG,YAAY,EAC5B,IAAI,EAAE,GAAG,EAAE,EACX,MAAM,GAAE,YAAiB,GACxB,OAAO,CAAC,kBAAkB,GAAG,oBAAoB,CAAC;IAiBrD;;;;;;;OAOG;IACU,uBAAuB,CAAC,IAAI,EAAE,KAAK,MAAM,EAAE,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YA8BjF,6BAA6B;IAuF3C,OAAO,CAAC,qBAAqB;YAaf,wBAAwB;YAmMxB,4BAA4B;YAuB5B,oBAAoB;YAuBpB,gBAAgB;YAmIhB,qBAAqB;YAyBrB,6BAA6B;YAqB7B,qCAAqC;IAkEnD,OAAO,CAAC,oBAAoB;IAU5B;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;IAW1B,SAAS,CAAC,aAAa,IAAI,MAAM;IAcjC,OAAO,CAAC,eAAe;CAYxB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createKernelAccountClient, createZeroDevPaymasterClient } from '@zerodev/sdk';
|
|
2
2
|
import { estimateUserOperationFees, getBundlerRpcUrl, getPaymasterRpcUrl, isRelayerMode } from '../nevermined/utils/BlockchainViemUtils.js';
|
|
3
3
|
import { BaseError, ContractFunctionRevertedError, encodeFunctionData, getContract, http, parseAbi, parseEventLogs } from 'viem';
|
|
4
|
+
import { createBundlerClient, getUserOperationHash } from 'viem/account-abstraction';
|
|
4
5
|
import { ContractsError, ContractSimulationError } from '../errors/index.js';
|
|
5
6
|
import { Instantiable } from '../Instantiable.abstract.js';
|
|
6
7
|
import { getInputsOfFunctionFormatted, getTransactionReceipt } from '../nevermined/index.js';
|
|
@@ -151,6 +152,42 @@ export class ContractBase extends Instantiable {
|
|
|
151
152
|
throw new ContractsError(`Account not supported`);
|
|
152
153
|
}
|
|
153
154
|
}
|
|
155
|
+
/**
|
|
156
|
+
* Poll a previously-submitted UserOperation's receipt by hash WITHOUT
|
|
157
|
+
* blocking. Returns the receipt once the bundler has mined it, or `null`
|
|
158
|
+
* while it is still in the mempool / not yet known. A client-side
|
|
159
|
+
* receipt-wait timeout does NOT cancel a submitted UserOp, so callers that
|
|
160
|
+
* persist the hash (e.g. the onchain-mirror worker, nvm-monorepo#1508) use
|
|
161
|
+
* this to confirm a prior submission instead of resubmitting a duplicate.
|
|
162
|
+
*/ async getUserOperationReceipt(hash) {
|
|
163
|
+
try {
|
|
164
|
+
const bundlerClient = createBundlerClient({
|
|
165
|
+
chain: getChain(this.config.chainId),
|
|
166
|
+
transport: http(this.getBundlerRPC()),
|
|
167
|
+
client: this.client.public
|
|
168
|
+
});
|
|
169
|
+
return await bundlerClient.getUserOperationReceipt({
|
|
170
|
+
hash
|
|
171
|
+
}) ?? null;
|
|
172
|
+
} catch (err) {
|
|
173
|
+
// A genuinely-absent receipt (UserOp still in the mempool) is expected
|
|
174
|
+
// and benign — some bundlers signal it by throwing rather than returning
|
|
175
|
+
// null. Anything else (RPC/transport/config fault) must NOT masquerade as
|
|
176
|
+
// "still pending": surface it at `warn` so a bundler outage is visible
|
|
177
|
+
// instead of silently driving the caller's grace-window logic. Either
|
|
178
|
+
// way we return null so the caller re-polls rather than consuming a retry.
|
|
179
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
180
|
+
if (/not[\s_]?found|UserOperationReceiptNotFound/i.test(message)) {
|
|
181
|
+
this.logger.debug(`getUserOperationReceipt(${hash}): not yet mined`);
|
|
182
|
+
} else {
|
|
183
|
+
// Redact URLs before logging: the bundler RPC URL embeds the ZeroDev
|
|
184
|
+
// project id, which should not leak into logs.
|
|
185
|
+
const safeMessage = message.replace(/https?:\/\/[^\s'")]+/gi, '<redacted-url>');
|
|
186
|
+
this.logger.warn(`getUserOperationReceipt(${hash}) lookup error (treating as not-yet-mined): ${safeMessage}`);
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
154
191
|
async internalMulticallSmartAccount(calls, from, txparams, progress) {
|
|
155
192
|
if (progress) {
|
|
156
193
|
progress({
|
|
@@ -289,16 +326,72 @@ export class ContractBase extends Instantiable {
|
|
|
289
326
|
const nonce = await from.getNonce({
|
|
290
327
|
key: getRandomBigInt(ZERODEV_NONCE_KEY_BITS)
|
|
291
328
|
});
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
329
|
+
const callData = await kernelClient.account.encodeCalls([
|
|
330
|
+
{
|
|
331
|
+
to: this.address,
|
|
332
|
+
value: txparams.value || 0n,
|
|
333
|
+
data
|
|
334
|
+
}
|
|
335
|
+
]);
|
|
336
|
+
// When a caller supplies a `progress` callback it may need the UserOp
|
|
337
|
+
// hash BEFORE the send completes — the onchain-mirror worker races the
|
|
338
|
+
// send against a per-tick deadline and must persist the hash even if the
|
|
339
|
+
// send is cut off mid-flight, otherwise it resubmits and double-burns
|
|
340
|
+
// (#1508/#1904). So prepare the UserOp here, surface its hash via
|
|
341
|
+
// `progress({stage:'prepared'})`, and send that exact prepared op so the
|
|
342
|
+
// bundler-returned hash matches. Best-effort and GATED ON `progress`:
|
|
343
|
+
// any failure falls back to the normal send, and callers that pass no
|
|
344
|
+
// progress callback keep the original send path byte-for-byte.
|
|
345
|
+
let preparedUserOp;
|
|
346
|
+
let preparedHash;
|
|
347
|
+
if (progress) {
|
|
348
|
+
try {
|
|
349
|
+
preparedUserOp = await kernelClient.prepareUserOperation({
|
|
350
|
+
callData,
|
|
351
|
+
nonce
|
|
352
|
+
});
|
|
353
|
+
preparedHash = getUserOperationHash({
|
|
354
|
+
chainId: this.config.chainId,
|
|
355
|
+
entryPointAddress: from.entryPoint.address,
|
|
356
|
+
entryPointVersion: from.entryPoint.version,
|
|
357
|
+
userOperation: preparedUserOp
|
|
358
|
+
});
|
|
359
|
+
progress({
|
|
360
|
+
stage: 'prepared',
|
|
361
|
+
args: functionInputs,
|
|
362
|
+
userOpHash: preparedHash,
|
|
363
|
+
method: name,
|
|
364
|
+
from: from,
|
|
365
|
+
value,
|
|
366
|
+
contractName: this.contractName,
|
|
367
|
+
contractAddress: this.address,
|
|
368
|
+
gasLimit
|
|
369
|
+
});
|
|
370
|
+
} catch (prepErr) {
|
|
371
|
+
this.logger.warn(`prepareUserOperation (pre-send hash) failed for "${name}"; ` + `sending without an early hash: ${prepErr}`);
|
|
372
|
+
preparedUserOp = undefined;
|
|
373
|
+
preparedHash = undefined;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
userOpHash = await kernelClient.sendUserOperation(// Re-send the exact prepared op (stripping the estimation stub
|
|
377
|
+
// signature so the kernel re-signs) so the bundler hash matches the one
|
|
378
|
+
// emitted above. Falls back to the original {callData, nonce} path
|
|
379
|
+
// (which prepares internally) when no early hash was prepared.
|
|
380
|
+
preparedUserOp ? {
|
|
381
|
+
...preparedUserOp,
|
|
382
|
+
signature: undefined
|
|
383
|
+
} : {
|
|
384
|
+
callData,
|
|
300
385
|
nonce
|
|
301
386
|
});
|
|
387
|
+
// Determinism guard: the 'prepared' hash should equal the bundler's. If a
|
|
388
|
+
// paymaster re-request changed the op it won't — a caller that persisted
|
|
389
|
+
// the 'prepared' hash then just fails to find it and reconciles safely
|
|
390
|
+
// (never a double-burn), but we log so we can see whether the early-hash
|
|
391
|
+
// path is actually holding in practice.
|
|
392
|
+
if (preparedHash && userOpHash !== preparedHash) {
|
|
393
|
+
this.logger.warn(`UserOp 'prepared' hash ${preparedHash} != sent hash ${userOpHash} for "${name}"; ` + `early-hash callers will reconcile via receipt-not-found`);
|
|
394
|
+
}
|
|
302
395
|
} catch (err) {
|
|
303
396
|
if (err instanceof BaseError) {
|
|
304
397
|
const revertError = err.walk((err)=>err instanceof ContractFunctionRevertedError);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/contracts/ContractBase.ts"],"sourcesContent":["import { createKernelAccountClient, createZeroDevPaymasterClient } from '@zerodev/sdk'\nimport {\n estimateUserOperationFees,\n getBundlerRpcUrl,\n getPaymasterRpcUrl,\n isRelayerMode,\n} from '../nevermined/utils/BlockchainViemUtils.js'\nimport {\n Abi,\n Account,\n Address,\n BaseError,\n ContractFunctionRevertedError,\n encodeFunctionData,\n getContract,\n http,\n parseAbi,\n parseEventLogs,\n TransactionReceipt,\n} from 'viem'\nimport { SmartAccount, UserOperationReceipt } from 'viem/account-abstraction'\nimport { ContractsError, ContractSimulationError } from '../errors/index.js'\nimport { Instantiable, InstantiableConfig } from '../Instantiable.abstract.js'\nimport { TxParameters } from '../models/Transactions.js'\nimport { getInputsOfFunctionFormatted, getTransactionReceipt } from '../nevermined/index.js'\nimport { getRandomBigInt } from '../utils/helpers.js'\nimport { getChain } from '../utils/Network.js'\n\nexport interface MulticallEntry {\n contractName?: string\n contractAddress: Address\n abi: Abi\n functionName: string\n args: any[]\n}\n\n/**\n * When a testnet RPC (Base Sepolia) fails internally, some providers return\n * `eth_estimateGas` values equal to — or even above — the block gas limit\n * instead of a real error. Using that value causes the node to reject the tx\n * with `intrinsic gas too high` before it ever reaches the mempool.\n *\n * `writeContract` in viem re-estimates gas internally when `gas` isn't\n * already set on the request (viem's `simulateContract` only performs\n * `eth_call`, not `eth_estimateGas`). That means the naïve path has no\n * chance to intercept a bogus estimate. We run the estimation ourselves\n * here, sanity-check the result, and always pass an explicit gas value\n * into `writeContract` so it doesn't re-query the misbehaving RPC.\n */\nconst GAS_SANITY_THRESHOLD = 25_000_000n\nconst GAS_FALLBACK_CAP = 5_000_000n\n\n// EntryPoint v0.7: ZeroDev's `toKernelPluginManager` rejects `customNonceKey > maxUint16`.\n// 16 bits = 65 536 channels — collision probability for the SDK's expected concurrency\n// (k=2–5 parallel sends from one SCA) is negligible (< 0.02 %). High-fan-out callers\n// (k > 50) should consider a per-process monotonic counter instead. See issue #1579.\nconst ZERODEV_NONCE_KEY_BITS = 16\n\n// Client-side cap on `waitForUserOperationReceipt`. The userOp is already in the bundler\n// mempool when this fires — a client-side timeout does NOT cancel it. Callers that catch\n// the resulting `ContractsError` MUST poll `bundlerClient.getUserOperationReceipt(hash)`\n// before retrying; otherwise a retry can produce a duplicate on-chain op.\nconst USEROP_RECEIPT_TIMEOUT_MS = 90_000\n\nfunction capForBogusEstimate(\n estimatedGas: bigint,\n logger: { warn: (msg: string) => void },\n): bigint {\n if (estimatedGas < GAS_SANITY_THRESHOLD) return estimatedGas\n logger.warn(\n `Estimated gas (${estimatedGas}) exceeds sanity threshold ` +\n `(${GAS_SANITY_THRESHOLD}); overriding with ${GAS_FALLBACK_CAP} to bypass misbehaving RPC estimate.`,\n )\n return GAS_FALLBACK_CAP\n}\n\nexport interface SimulateMulticallEntry {\n functionName: string\n value?: bigint\n abi: Abi\n args: any[]\n to: Address\n}\n\nexport abstract class ContractBase extends Instantiable {\n public readonly contractName: string\n public contract: any\n public address: Address\n private _zeroDevPaymaster: ReturnType<typeof createZeroDevPaymasterClient> | null = null\n\n constructor(contractName: string, address: Address) {\n super()\n this.contractName = contractName\n this.address = address\n }\n\n protected async init(\n config: InstantiableConfig,\n contractConfig: { address: `0x${string}`; abi: Abi },\n ) {\n this.setInstanceConfig(config)\n this.address = contractConfig.address\n\n this.contract = getContract({\n address: contractConfig.address,\n abi: contractConfig.abi,\n client: { public: this.publicClient, wallet: this.walletClient },\n })\n }\n\n public async call<T>(functionName: string, args: any[], from?: string): Promise<T> {\n try {\n return (await this.client.public.readContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: parseAbi([functionName]),\n args,\n ...(from && { account: from as `0x${string}` }),\n })) as T\n //return await this.contract[functionSignature](...args, { from })\n } catch (err) {\n throw new ContractsError(\n `Calling method \"${functionName}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n }\n\n public async getTransactionReceipt(\n txHash: UserOperationReceipt | TransactionReceipt,\n ): Promise<TransactionReceipt> {\n // Get the transaction receipt depending on the type of txHash\n if ('transactionHash' in txHash) {\n // txHash is TransactionReceipt\n return txHash\n } else if ('userOpHash' in txHash) {\n // txHash is UserOperationReceipt, fetch the actual receipt using the utility function with retry logic\n const hash = txHash.receipt.transactionHash\n return await getTransactionReceipt({\n txHash: hash,\n publicClient: this.client.public,\n })\n } else {\n throw new Error('Unknown transaction type')\n }\n }\n\n public getTransactionLogs(\n txReceipt: TransactionReceipt | UserOperationReceipt,\n eventName?: string,\n ) {\n return parseEventLogs({\n abi: this.contract.abi,\n logs: txReceipt.logs,\n eventName,\n strict: false,\n }) as any[]\n }\n\n public async multicall(\n calls: MulticallEntry[],\n from: Account | SmartAccount,\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Blockchain Multicall using Local account`)\n return await this.localAccountMulticall(calls, from, params, params.progress)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Blockchain Multicall using JSON-RPC account`)\n return await this.localAccountMulticall(calls, from, params, params.progress)\n } else if (from.type === 'smart') {\n this.logger.debug(`Blockchain Multicall using ZeroDev account`)\n return await this.internalMulticallSmartAccount(calls, from, params, params.progress)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async simulateMulticall(\n calls: SimulateMulticallEntry[],\n from: Account | SmartAccount,\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Simulating calls using Local account`)\n return await this.localAccountSimulateMulticall(calls, from, params)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Simulating calls using JSON-RPC account`)\n return await this.localAccountSimulateMulticall(calls, from, params)\n } else if (from.type === 'smart') {\n this.logger.debug(`Simulating calls using Smart Account account`)\n return await this.internalSimulateMulticallSmartAccount(calls, from, params)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async simulate(\n functionName: string,\n from: Account | SmartAccount,\n args: any[],\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Simulating calls using Local account`)\n return await this.localAccountSimulate(functionName, from, args, params)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Simulating calls using JSON-RPC account`)\n return await this.localAccountSimulate(functionName, from, args, params)\n } else if (from.type === 'smart') {\n this.logger.debug(`Simulating calls using Smart Account account`)\n return await this.internalSimulateSmartAccount(functionName, from, args, params)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async send(\n functionName: string,\n from: Account | SmartAccount,\n args: any[],\n params: TxParameters = {},\n ): Promise<TransactionReceipt | UserOperationReceipt> {\n if (from.type === 'local') {\n this.logger.debug(\n `Blockchain Send using Local account with functionName: ${functionName} and following args: ${args}`,\n )\n return await this.localAccountSend(functionName, from, args, params, params.progress)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Blockchain Send using JSON-RPC account to ${functionName}`)\n return await this.localAccountSend(functionName, from, args, params, params.progress)\n } else if (from.type === 'smart') {\n this.logger.debug(`Blockchain Send using ZeroDev account`)\n return await this.internalSendSmartAccount(functionName, from, args, params, params.progress)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n private async internalMulticallSmartAccount(\n calls: MulticallEntry[],\n from: SmartAccount,\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ) {\n if (progress) {\n progress({\n stage: 'multicall-sending',\n args: [],\n method: '',\n from: from,\n contractAddress: this.address,\n })\n }\n\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n\n const encodedCalls: any[] = []\n calls.map((call) => {\n encodedCalls.push({\n to: call.contractAddress || this.address,\n value: txparams.value || 0n,\n data: encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args,\n }),\n })\n })\n\n let userOpHash: `0x${string}` | undefined\n try {\n // Random nonce key per send so concurrent userOps from the same SCA\n // hit distinct EntryPoint nonce channels instead of colliding on the\n // default `customNonceKey=0n`. See issue #1579.\n const nonce = await from.getNonce({ key: getRandomBigInt(ZERODEV_NONCE_KEY_BITS) })\n userOpHash = await kernelClient.sendUserOperation({\n callData: await kernelClient.account.encodeCalls(encodedCalls),\n nonce,\n })\n\n if (progress) {\n progress({\n stage: 'multicall-sent',\n args: [],\n method: '',\n from: from,\n contractAddress: this.address,\n })\n }\n\n // Wait for the transaction to be mined\n this.logger.debug(`Waiting for transaction to be mined... ${userOpHash}`)\n const txReceipt = await kernelClient.waitForUserOperationReceipt({\n hash: userOpHash,\n timeout: USEROP_RECEIPT_TIMEOUT_MS,\n })\n this.logger.debug(`Transaction mined - UserOperationHash: ${userOpHash}`)\n this.logger.debug(\n `Transaction receipt - TransactionHash: ${txReceipt.receipt.transactionHash}`,\n )\n this.assertUserOpSucceeded(txReceipt, 'multicall', userOpHash)\n return txReceipt.receipt\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n // Surface userOpHash so callers can poll for eventual inclusion before\n // retrying — a client-side receipt-wait timeout does NOT cancel the userOp.\n const hashSuffix = userOpHash ? ` userOpHash=${userOpHash}` : ''\n throw new ContractsError(`Multicall failed:${hashSuffix} ${err}`)\n }\n }\n\n private assertUserOpSucceeded(\n txReceipt: UserOperationReceipt,\n method: string,\n userOpHash: string,\n ): void {\n if (txReceipt.success) return\n throw new ContractsError(\n `UserOp inner call reverted for \"${method}\" on \"${this.contractName}\". ` +\n `userOpHash=${userOpHash} txHash=${txReceipt.receipt.transactionHash} ` +\n `reason=${txReceipt.reason ?? 'unknown'}`,\n )\n }\n\n private async internalSendSmartAccount(\n name: string,\n from: SmartAccount,\n args: any[],\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ): Promise<UserOperationReceipt> {\n const functionInputs = getInputsOfFunctionFormatted(this.contract.abi, name, args)\n\n const { gasLimit, value } = txparams\n if (progress) {\n progress({\n stage: 'sending',\n args: functionInputs,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n const data = encodeFunctionData({ abi: this.contract.abi, functionName: name, args })\n\n let userOpHash\n try {\n // Random nonce key per send so concurrent userOps from the same SCA\n // hit distinct EntryPoint nonce channels instead of colliding on the\n // default `customNonceKey=0n`. See issue #1579.\n const nonce = await from.getNonce({ key: getRandomBigInt(ZERODEV_NONCE_KEY_BITS) })\n userOpHash = await kernelClient.sendUserOperation({\n callData: await kernelClient.account.encodeCalls([\n {\n to: this.address,\n value: txparams.value || 0n,\n data,\n },\n ]),\n nonce,\n })\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n if (progress) {\n progress({\n stage: 'sent',\n args: functionInputs,\n userOpHash,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n let txReceipt: UserOperationReceipt\n try {\n txReceipt = await kernelClient.waitForUserOperationReceipt({\n hash: userOpHash,\n timeout: USEROP_RECEIPT_TIMEOUT_MS,\n })\n } catch (err) {\n // The userOp is already in the bundler mempool — a client-side timeout\n // does NOT cancel it. Surface userOpHash so callers can poll for eventual\n // inclusion before retrying, otherwise a retry can produce a duplicate\n // on-chain op. Wrap symmetric to `internalMulticallSmartAccount`.\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" timed out ` +\n `waiting for UserOp receipt. userOpHash=${userOpHash} — confirm on-chain ` +\n `inclusion before retrying. Underlying: ${err}`,\n )\n }\n\n this.assertUserOpSucceeded(txReceipt, name, userOpHash)\n\n if (progress) {\n progress({\n stage: 'receipt',\n args: functionInputs,\n txReceipt,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n return txReceipt\n }\n\n private async internalSimulateSmartAccount(\n name: string,\n from: SmartAccount,\n args: any[],\n txparams: any,\n ) {\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from.address,\n ...(txparams.value && { value: txparams.value }),\n })\n return true\n } catch (err) {\n throw new ContractSimulationError(\n `Error Simulating contract call \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n }\n\n private async localAccountSimulate(\n name: string,\n from: Account | `0x${string}`,\n args: any[],\n txparams: any,\n ) {\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n } catch (err) {\n throw new ContractSimulationError(\n `Error Simulating contract call \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n return true\n }\n\n private async localAccountSend(\n name: string,\n from: Account | `0x${string}`,\n args: any[],\n txparams: any,\n progress: ((data: any) => void) | undefined,\n _contractAbi?: Abi,\n _contractAddress?: Address,\n _contractName?: string,\n ) {\n const abi = _contractAbi || this.contract.abi\n const contractAddress = _contractAddress || this.address\n const contractName = _contractName || this.contractName\n\n const functionInputs = getInputsOfFunctionFormatted(abi, name, args)\n // Uncomment to debug contract calls\n // if (name === 'order') {\n // const functionSignature = getSignatureOfFunction(this.contract.abi, name, args)\n // this.logger.info(`Making contract call ....: ${name} - ${from}`)\n // this.logger.info(`With args: `, JSON.stringify(args, jsonReplacer))\n // this.logger.info(`And signature: ${JSON.stringify(functionSignature, jsonReplacer)}`)\n // this.logger.info('And amount: ', txparams.value)\n // }\n // abi.filter(({name, inputs}) => name === 'closeSignals' && inputs.length === 1)\n // const abiFilter = this.contract.abi.filter((abi) => abi.name === name && abi.inputs.length === args.length)\n // const abiFilter = this.contract.abi.filter((abi) => abi.name === name && abi.type === 'function')\n // console.debug('abi', this.contract.abi.filter((abi) => abi.name === name))\n // console.debug('abiFilter', abiFilter)\n // if (!abiFilter)\n // throw new ContractsError(\n // `No ABI found for method \"${name}\" with ${args.length} arguments on contract \"${this.contractName}\"`,\n // )\n\n const { gasLimit, value } = txparams\n // make the call\n if (progress) {\n progress({\n stage: 'sending',\n args: functionInputs,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n\n let txHash: `0x${string}` | undefined\n try {\n const { request } = await this.client.public.simulateContract({\n address: contractAddress,\n abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n\n // Resolve gas ourselves so `writeContract` never falls back to its own\n // `eth_estimateGas`. An explicit caller `gasLimit` always wins; otherwise\n // we estimate, apply the block-limit sanity check, and pin the result.\n // If estimation itself fails we still honour any explicit cap.\n let resolvedGas: bigint | undefined = gasLimit\n if (resolvedGas === undefined) {\n try {\n const estimate = await this.client.public.estimateContractGas({\n address: contractAddress,\n abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n resolvedGas = capForBogusEstimate(estimate, this.logger)\n } catch (estErr) {\n this.logger.warn(\n `estimateContractGas for \"${name}\" on \"${contractName}\" failed (${estErr}); ` +\n `falling back to ${GAS_FALLBACK_CAP} to avoid a bogus RPC re-estimate in writeContract.`,\n )\n resolvedGas = GAS_FALLBACK_CAP\n }\n }\n\n txHash = await this.client.wallet.writeContract({\n ...request,\n account: from,\n gas: resolvedGas,\n })\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n if (progress) {\n progress({\n stage: 'sent',\n args: functionInputs,\n txHash,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n const txReceipt = getTransactionReceipt({ txHash, publicClient: this.client.public })\n\n if (progress) {\n progress({\n stage: 'receipt',\n args: functionInputs,\n txReceipt,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n\n return txReceipt\n }\n\n private async localAccountMulticall(\n calls: MulticallEntry[],\n from: Account,\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ): Promise<TransactionReceipt> {\n const receipts: TransactionReceipt[] = []\n for (const call of calls) {\n receipts.push(\n await this.localAccountSend(\n call.functionName,\n from,\n call.args,\n txparams,\n progress,\n call.abi,\n call.contractAddress,\n call.contractName,\n ),\n )\n }\n if (receipts.length > 0) return receipts.pop() as TransactionReceipt\n else throw new ContractsError(`No receipts found for multicall`)\n }\n\n private async localAccountSimulateMulticall(\n calls: SimulateMulticallEntry[],\n from: Account,\n txparams: any,\n ) {\n try {\n const { results } = await this.client.public.simulateCalls({\n calls,\n account: from,\n })\n this.logger.debug(`Simulated multicall - ${results}`)\n return true\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(`Error simulating multicall - ${err}`)\n }\n }\n\n private async internalSimulateMulticallSmartAccount(\n calls: SimulateMulticallEntry[],\n from: SmartAccount,\n txparams: any,\n ) {\n try {\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n\n const encodedCalls = []\n for (const call of calls) {\n encodedCalls.push({\n to: call.to,\n value: call.value || 0n,\n data: encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args,\n }),\n })\n }\n\n // DONT DELETE THE COMMENTED LINES - ARE NECESSARY FOR F***ING ZERODEV DEBUGGING\n\n // this.logger.info(`Encoded multicall - ${JSON.stringify(encodedCalls, jsonReplacer)}`)\n // const code = await this.client.public.getCode({ address: from.address })\n // const isDeployed = code !== undefined && code !== '0x'\n // this.logger.info(`++++++ Smart account ${from.address} deployment status: ${isDeployed ? 'DEPLOYED' : 'NOT DEPLOYED'}`)\n\n // // Log account details\n // this.logger.info(`Account type: ${from.type}`)\n // this.logger.info(`Account address: ${from.address}`)\n\n // // Log the calls being made\n // this.logger.info(`Number of calls: ${encodedCalls.length}`)\n // encodedCalls.forEach((call, index) => {\n // this.logger.info(`Call ${index}: to=${call.to}, value=${call.value}, data=${call.data.slice(0, 10)}...`)\n // })\n\n await kernelClient.prepareUserOperation({\n callData: await kernelClient.account.encodeCalls(encodedCalls),\n })\n\n return true\n } catch (err) {\n this.logger.error(`Error details: ${JSON.stringify(err, null, 2)}`)\n if (err instanceof BaseError) {\n const revertError = err.walk((e) => e instanceof ContractFunctionRevertedError)\n if (revertError) {\n this.logger.error(`Revert error: ${String(revertError)}`)\n }\n }\n throw new ContractSimulationError(`Error Simulating Multicalls - ${err}`)\n }\n }\n\n private getOrCreatePaymaster() {\n if (!this._zeroDevPaymaster) {\n this._zeroDevPaymaster = createZeroDevPaymasterClient({\n chain: getChain(this.config.chainId),\n transport: http(this.getPaymasterRPC()),\n })\n }\n return this._zeroDevPaymaster\n }\n\n /**\n * Builds the `paymaster` partial for `createKernelAccountClient`. In relayer\n * mode (e.g. local `ultra-relay` for tests) returns an empty object so the\n * kernel client submits UserOps without paymaster fields and the bundler\n * pays gas via its executor key. In production returns the ZeroDev paymaster\n * sponsorship callback.\n */\n private getPaymasterConfig() {\n if (isRelayerMode()) return {}\n const zerodevPaymaster = this.getOrCreatePaymaster()\n return {\n paymaster: {\n getPaymasterData: (userOperation: any) =>\n zerodevPaymaster.sponsorUserOperation({ userOperation }),\n },\n }\n }\n\n protected getBundlerRPC(): string {\n // In relayer mode `getBundlerRpcUrl` reads `BUNDLER_RPC_URL_OVERRIDE`\n // and never touches the project id, so an empty value is harmless. In\n // production callers must pass a project id — surface a clear error if\n // the SDK was instantiated without one and we need it.\n const projectId = this.config.zeroDevProjectId\n if (!projectId && !isRelayerMode()) {\n throw new ContractsError(\n 'getBundlerRPC: zeroDevProjectId is required for non-relayer (production) mode',\n )\n }\n return getBundlerRpcUrl(projectId ?? '', this.config.chainId)\n }\n\n private getPaymasterRPC(): string {\n // Only ever consulted when `getPaymasterConfig` decides to attach a\n // paymaster, which is gated on `!isRelayerMode()`. A missing project\n // id at this point is a configuration bug worth surfacing.\n const projectId = this.config.zeroDevProjectId\n if (!projectId) {\n throw new ContractsError(\n 'getPaymasterRPC: zeroDevProjectId is required to build the paymaster URL',\n )\n }\n return getPaymasterRpcUrl(projectId, this.config.chainId)\n }\n}\n"],"names":["createKernelAccountClient","createZeroDevPaymasterClient","estimateUserOperationFees","getBundlerRpcUrl","getPaymasterRpcUrl","isRelayerMode","BaseError","ContractFunctionRevertedError","encodeFunctionData","getContract","http","parseAbi","parseEventLogs","ContractsError","ContractSimulationError","Instantiable","getInputsOfFunctionFormatted","getTransactionReceipt","getRandomBigInt","getChain","GAS_SANITY_THRESHOLD","GAS_FALLBACK_CAP","ZERODEV_NONCE_KEY_BITS","USEROP_RECEIPT_TIMEOUT_MS","capForBogusEstimate","estimatedGas","logger","warn","ContractBase","contractName","address","_zeroDevPaymaster","init","config","contractConfig","setInstanceConfig","contract","abi","client","public","publicClient","wallet","walletClient","call","functionName","args","from","readContract","account","err","txHash","hash","receipt","transactionHash","Error","getTransactionLogs","txReceipt","eventName","logs","strict","multicall","calls","params","type","debug","localAccountMulticall","progress","internalMulticallSmartAccount","simulateMulticall","localAccountSimulateMulticall","internalSimulateMulticallSmartAccount","simulate","localAccountSimulate","internalSimulateSmartAccount","send","localAccountSend","internalSendSmartAccount","txparams","stage","method","contractAddress","kernelClient","chain","chainId","bundlerTransport","getBundlerRPC","getPaymasterConfig","userOperation","estimateFeesPerGas","bundlerClient","encodedCalls","map","push","to","value","data","userOpHash","nonce","getNonce","key","sendUserOperation","callData","encodeCalls","waitForUserOperationReceipt","timeout","assertUserOpSucceeded","revertError","walk","error","String","hashSuffix","success","reason","name","functionInputs","gasLimit","simulateContract","_contractAbi","_contractAddress","_contractName","request","resolvedGas","undefined","estimate","estimateContractGas","estErr","writeContract","gas","receipts","length","pop","results","simulateCalls","prepareUserOperation","JSON","stringify","e","getOrCreatePaymaster","transport","getPaymasterRPC","zerodevPaymaster","paymaster","getPaymasterData","sponsorUserOperation","projectId","zeroDevProjectId"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/contracts/ContractBase.ts"],"sourcesContent":["import { createKernelAccountClient, createZeroDevPaymasterClient } from '@zerodev/sdk'\nimport {\n estimateUserOperationFees,\n getBundlerRpcUrl,\n getPaymasterRpcUrl,\n isRelayerMode,\n} from '../nevermined/utils/BlockchainViemUtils.js'\nimport {\n Abi,\n Account,\n Address,\n BaseError,\n ContractFunctionRevertedError,\n encodeFunctionData,\n getContract,\n http,\n parseAbi,\n parseEventLogs,\n TransactionReceipt,\n} from 'viem'\nimport {\n createBundlerClient,\n getUserOperationHash,\n SmartAccount,\n UserOperationReceipt,\n} from 'viem/account-abstraction'\nimport { ContractsError, ContractSimulationError } from '../errors/index.js'\nimport { Instantiable, InstantiableConfig } from '../Instantiable.abstract.js'\nimport { TxParameters } from '../models/Transactions.js'\nimport { getInputsOfFunctionFormatted, getTransactionReceipt } from '../nevermined/index.js'\nimport { getRandomBigInt } from '../utils/helpers.js'\nimport { getChain } from '../utils/Network.js'\n\nexport interface MulticallEntry {\n contractName?: string\n contractAddress: Address\n abi: Abi\n functionName: string\n args: any[]\n}\n\n/**\n * When a testnet RPC (Base Sepolia) fails internally, some providers return\n * `eth_estimateGas` values equal to — or even above — the block gas limit\n * instead of a real error. Using that value causes the node to reject the tx\n * with `intrinsic gas too high` before it ever reaches the mempool.\n *\n * `writeContract` in viem re-estimates gas internally when `gas` isn't\n * already set on the request (viem's `simulateContract` only performs\n * `eth_call`, not `eth_estimateGas`). That means the naïve path has no\n * chance to intercept a bogus estimate. We run the estimation ourselves\n * here, sanity-check the result, and always pass an explicit gas value\n * into `writeContract` so it doesn't re-query the misbehaving RPC.\n */\nconst GAS_SANITY_THRESHOLD = 25_000_000n\nconst GAS_FALLBACK_CAP = 5_000_000n\n\n// EntryPoint v0.7: ZeroDev's `toKernelPluginManager` rejects `customNonceKey > maxUint16`.\n// 16 bits = 65 536 channels — collision probability for the SDK's expected concurrency\n// (k=2–5 parallel sends from one SCA) is negligible (< 0.02 %). High-fan-out callers\n// (k > 50) should consider a per-process monotonic counter instead. See issue #1579.\nconst ZERODEV_NONCE_KEY_BITS = 16\n\n// Client-side cap on `waitForUserOperationReceipt`. The userOp is already in the bundler\n// mempool when this fires — a client-side timeout does NOT cancel it. Callers that catch\n// the resulting `ContractsError` MUST poll `bundlerClient.getUserOperationReceipt(hash)`\n// before retrying; otherwise a retry can produce a duplicate on-chain op.\nconst USEROP_RECEIPT_TIMEOUT_MS = 90_000\n\nfunction capForBogusEstimate(\n estimatedGas: bigint,\n logger: { warn: (msg: string) => void },\n): bigint {\n if (estimatedGas < GAS_SANITY_THRESHOLD) return estimatedGas\n logger.warn(\n `Estimated gas (${estimatedGas}) exceeds sanity threshold ` +\n `(${GAS_SANITY_THRESHOLD}); overriding with ${GAS_FALLBACK_CAP} to bypass misbehaving RPC estimate.`,\n )\n return GAS_FALLBACK_CAP\n}\n\nexport interface SimulateMulticallEntry {\n functionName: string\n value?: bigint\n abi: Abi\n args: any[]\n to: Address\n}\n\nexport abstract class ContractBase extends Instantiable {\n public readonly contractName: string\n public contract: any\n public address: Address\n private _zeroDevPaymaster: ReturnType<typeof createZeroDevPaymasterClient> | null = null\n\n constructor(contractName: string, address: Address) {\n super()\n this.contractName = contractName\n this.address = address\n }\n\n protected async init(\n config: InstantiableConfig,\n contractConfig: { address: `0x${string}`; abi: Abi },\n ) {\n this.setInstanceConfig(config)\n this.address = contractConfig.address\n\n this.contract = getContract({\n address: contractConfig.address,\n abi: contractConfig.abi,\n client: { public: this.publicClient, wallet: this.walletClient },\n })\n }\n\n public async call<T>(functionName: string, args: any[], from?: string): Promise<T> {\n try {\n return (await this.client.public.readContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: parseAbi([functionName]),\n args,\n ...(from && { account: from as `0x${string}` }),\n })) as T\n //return await this.contract[functionSignature](...args, { from })\n } catch (err) {\n throw new ContractsError(\n `Calling method \"${functionName}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n }\n\n public async getTransactionReceipt(\n txHash: UserOperationReceipt | TransactionReceipt,\n ): Promise<TransactionReceipt> {\n // Get the transaction receipt depending on the type of txHash\n if ('transactionHash' in txHash) {\n // txHash is TransactionReceipt\n return txHash\n } else if ('userOpHash' in txHash) {\n // txHash is UserOperationReceipt, fetch the actual receipt using the utility function with retry logic\n const hash = txHash.receipt.transactionHash\n return await getTransactionReceipt({\n txHash: hash,\n publicClient: this.client.public,\n })\n } else {\n throw new Error('Unknown transaction type')\n }\n }\n\n public getTransactionLogs(\n txReceipt: TransactionReceipt | UserOperationReceipt,\n eventName?: string,\n ) {\n return parseEventLogs({\n abi: this.contract.abi,\n logs: txReceipt.logs,\n eventName,\n strict: false,\n }) as any[]\n }\n\n public async multicall(\n calls: MulticallEntry[],\n from: Account | SmartAccount,\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Blockchain Multicall using Local account`)\n return await this.localAccountMulticall(calls, from, params, params.progress)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Blockchain Multicall using JSON-RPC account`)\n return await this.localAccountMulticall(calls, from, params, params.progress)\n } else if (from.type === 'smart') {\n this.logger.debug(`Blockchain Multicall using ZeroDev account`)\n return await this.internalMulticallSmartAccount(calls, from, params, params.progress)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async simulateMulticall(\n calls: SimulateMulticallEntry[],\n from: Account | SmartAccount,\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Simulating calls using Local account`)\n return await this.localAccountSimulateMulticall(calls, from, params)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Simulating calls using JSON-RPC account`)\n return await this.localAccountSimulateMulticall(calls, from, params)\n } else if (from.type === 'smart') {\n this.logger.debug(`Simulating calls using Smart Account account`)\n return await this.internalSimulateMulticallSmartAccount(calls, from, params)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async simulate(\n functionName: string,\n from: Account | SmartAccount,\n args: any[],\n params: TxParameters = {},\n ) {\n if (from.type === 'local') {\n this.logger.debug(`Simulating calls using Local account`)\n return await this.localAccountSimulate(functionName, from, args, params)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Simulating calls using JSON-RPC account`)\n return await this.localAccountSimulate(functionName, from, args, params)\n } else if (from.type === 'smart') {\n this.logger.debug(`Simulating calls using Smart Account account`)\n return await this.internalSimulateSmartAccount(functionName, from, args, params)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n public async send(\n functionName: string,\n from: Account | SmartAccount,\n args: any[],\n params: TxParameters = {},\n ): Promise<TransactionReceipt | UserOperationReceipt> {\n if (from.type === 'local') {\n this.logger.debug(\n `Blockchain Send using Local account with functionName: ${functionName} and following args: ${args}`,\n )\n return await this.localAccountSend(functionName, from, args, params, params.progress)\n } else if (from.type === 'json-rpc') {\n this.logger.debug(`Blockchain Send using JSON-RPC account to ${functionName}`)\n return await this.localAccountSend(functionName, from, args, params, params.progress)\n } else if (from.type === 'smart') {\n this.logger.debug(`Blockchain Send using ZeroDev account`)\n return await this.internalSendSmartAccount(functionName, from, args, params, params.progress)\n } else {\n throw new ContractsError(`Account not supported`)\n }\n }\n\n /**\n * Poll a previously-submitted UserOperation's receipt by hash WITHOUT\n * blocking. Returns the receipt once the bundler has mined it, or `null`\n * while it is still in the mempool / not yet known. A client-side\n * receipt-wait timeout does NOT cancel a submitted UserOp, so callers that\n * persist the hash (e.g. the onchain-mirror worker, nvm-monorepo#1508) use\n * this to confirm a prior submission instead of resubmitting a duplicate.\n */\n public async getUserOperationReceipt(hash: `0x${string}`): Promise<UserOperationReceipt | null> {\n try {\n const bundlerClient = createBundlerClient({\n chain: getChain(this.config.chainId),\n transport: http(this.getBundlerRPC()),\n client: this.client.public,\n })\n return (await bundlerClient.getUserOperationReceipt({ hash })) ?? null\n } catch (err) {\n // A genuinely-absent receipt (UserOp still in the mempool) is expected\n // and benign — some bundlers signal it by throwing rather than returning\n // null. Anything else (RPC/transport/config fault) must NOT masquerade as\n // \"still pending\": surface it at `warn` so a bundler outage is visible\n // instead of silently driving the caller's grace-window logic. Either\n // way we return null so the caller re-polls rather than consuming a retry.\n const message = err instanceof Error ? err.message : String(err)\n if (/not[\\s_]?found|UserOperationReceiptNotFound/i.test(message)) {\n this.logger.debug(`getUserOperationReceipt(${hash}): not yet mined`)\n } else {\n // Redact URLs before logging: the bundler RPC URL embeds the ZeroDev\n // project id, which should not leak into logs.\n const safeMessage = message.replace(/https?:\\/\\/[^\\s'\")]+/gi, '<redacted-url>')\n this.logger.warn(\n `getUserOperationReceipt(${hash}) lookup error (treating as not-yet-mined): ${safeMessage}`,\n )\n }\n return null\n }\n }\n\n private async internalMulticallSmartAccount(\n calls: MulticallEntry[],\n from: SmartAccount,\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ) {\n if (progress) {\n progress({\n stage: 'multicall-sending',\n args: [],\n method: '',\n from: from,\n contractAddress: this.address,\n })\n }\n\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n\n const encodedCalls: any[] = []\n calls.map((call) => {\n encodedCalls.push({\n to: call.contractAddress || this.address,\n value: txparams.value || 0n,\n data: encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args,\n }),\n })\n })\n\n let userOpHash: `0x${string}` | undefined\n try {\n // Random nonce key per send so concurrent userOps from the same SCA\n // hit distinct EntryPoint nonce channels instead of colliding on the\n // default `customNonceKey=0n`. See issue #1579.\n const nonce = await from.getNonce({ key: getRandomBigInt(ZERODEV_NONCE_KEY_BITS) })\n userOpHash = await kernelClient.sendUserOperation({\n callData: await kernelClient.account.encodeCalls(encodedCalls),\n nonce,\n })\n\n if (progress) {\n progress({\n stage: 'multicall-sent',\n args: [],\n method: '',\n from: from,\n contractAddress: this.address,\n })\n }\n\n // Wait for the transaction to be mined\n this.logger.debug(`Waiting for transaction to be mined... ${userOpHash}`)\n const txReceipt = await kernelClient.waitForUserOperationReceipt({\n hash: userOpHash,\n timeout: USEROP_RECEIPT_TIMEOUT_MS,\n })\n this.logger.debug(`Transaction mined - UserOperationHash: ${userOpHash}`)\n this.logger.debug(\n `Transaction receipt - TransactionHash: ${txReceipt.receipt.transactionHash}`,\n )\n this.assertUserOpSucceeded(txReceipt, 'multicall', userOpHash)\n return txReceipt.receipt\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n // Surface userOpHash so callers can poll for eventual inclusion before\n // retrying — a client-side receipt-wait timeout does NOT cancel the userOp.\n const hashSuffix = userOpHash ? ` userOpHash=${userOpHash}` : ''\n throw new ContractsError(`Multicall failed:${hashSuffix} ${err}`)\n }\n }\n\n private assertUserOpSucceeded(\n txReceipt: UserOperationReceipt,\n method: string,\n userOpHash: string,\n ): void {\n if (txReceipt.success) return\n throw new ContractsError(\n `UserOp inner call reverted for \"${method}\" on \"${this.contractName}\". ` +\n `userOpHash=${userOpHash} txHash=${txReceipt.receipt.transactionHash} ` +\n `reason=${txReceipt.reason ?? 'unknown'}`,\n )\n }\n\n private async internalSendSmartAccount(\n name: string,\n from: SmartAccount,\n args: any[],\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ): Promise<UserOperationReceipt> {\n const functionInputs = getInputsOfFunctionFormatted(this.contract.abi, name, args)\n\n const { gasLimit, value } = txparams\n if (progress) {\n progress({\n stage: 'sending',\n args: functionInputs,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n const data = encodeFunctionData({ abi: this.contract.abi, functionName: name, args })\n\n let userOpHash\n try {\n // Random nonce key per send so concurrent userOps from the same SCA\n // hit distinct EntryPoint nonce channels instead of colliding on the\n // default `customNonceKey=0n`. See issue #1579.\n const nonce = await from.getNonce({ key: getRandomBigInt(ZERODEV_NONCE_KEY_BITS) })\n const callData = await kernelClient.account.encodeCalls([\n {\n to: this.address,\n value: txparams.value || 0n,\n data,\n },\n ])\n\n // When a caller supplies a `progress` callback it may need the UserOp\n // hash BEFORE the send completes — the onchain-mirror worker races the\n // send against a per-tick deadline and must persist the hash even if the\n // send is cut off mid-flight, otherwise it resubmits and double-burns\n // (#1508/#1904). So prepare the UserOp here, surface its hash via\n // `progress({stage:'prepared'})`, and send that exact prepared op so the\n // bundler-returned hash matches. Best-effort and GATED ON `progress`:\n // any failure falls back to the normal send, and callers that pass no\n // progress callback keep the original send path byte-for-byte.\n let preparedUserOp: Awaited<ReturnType<typeof kernelClient.prepareUserOperation>> | undefined\n let preparedHash: `0x${string}` | undefined\n if (progress) {\n try {\n preparedUserOp = await kernelClient.prepareUserOperation({ callData, nonce })\n preparedHash = getUserOperationHash({\n chainId: this.config.chainId,\n entryPointAddress: from.entryPoint.address,\n entryPointVersion: from.entryPoint.version,\n userOperation: preparedUserOp,\n })\n progress({\n stage: 'prepared',\n args: functionInputs,\n userOpHash: preparedHash,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n } catch (prepErr) {\n this.logger.warn(\n `prepareUserOperation (pre-send hash) failed for \"${name}\"; ` +\n `sending without an early hash: ${prepErr}`,\n )\n preparedUserOp = undefined\n preparedHash = undefined\n }\n }\n\n userOpHash = await kernelClient.sendUserOperation(\n // Re-send the exact prepared op (stripping the estimation stub\n // signature so the kernel re-signs) so the bundler hash matches the one\n // emitted above. Falls back to the original {callData, nonce} path\n // (which prepares internally) when no early hash was prepared.\n preparedUserOp\n ? ({ ...preparedUserOp, signature: undefined } as Parameters<\n typeof kernelClient.sendUserOperation\n >[0])\n : { callData, nonce },\n )\n\n // Determinism guard: the 'prepared' hash should equal the bundler's. If a\n // paymaster re-request changed the op it won't — a caller that persisted\n // the 'prepared' hash then just fails to find it and reconciles safely\n // (never a double-burn), but we log so we can see whether the early-hash\n // path is actually holding in practice.\n if (preparedHash && userOpHash !== preparedHash) {\n this.logger.warn(\n `UserOp 'prepared' hash ${preparedHash} != sent hash ${userOpHash} for \"${name}\"; ` +\n `early-hash callers will reconcile via receipt-not-found`,\n )\n }\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n if (progress) {\n progress({\n stage: 'sent',\n args: functionInputs,\n userOpHash,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n let txReceipt: UserOperationReceipt\n try {\n txReceipt = await kernelClient.waitForUserOperationReceipt({\n hash: userOpHash,\n timeout: USEROP_RECEIPT_TIMEOUT_MS,\n })\n } catch (err) {\n // The userOp is already in the bundler mempool — a client-side timeout\n // does NOT cancel it. Surface userOpHash so callers can poll for eventual\n // inclusion before retrying, otherwise a retry can produce a duplicate\n // on-chain op. Wrap symmetric to `internalMulticallSmartAccount`.\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${this.contractName}\" timed out ` +\n `waiting for UserOp receipt. userOpHash=${userOpHash} — confirm on-chain ` +\n `inclusion before retrying. Underlying: ${err}`,\n )\n }\n\n this.assertUserOpSucceeded(txReceipt, name, userOpHash)\n\n if (progress) {\n progress({\n stage: 'receipt',\n args: functionInputs,\n txReceipt,\n method: name,\n from: from,\n value,\n contractName: this.contractName,\n contractAddress: this.address,\n gasLimit,\n })\n }\n\n return txReceipt\n }\n\n private async internalSimulateSmartAccount(\n name: string,\n from: SmartAccount,\n args: any[],\n txparams: any,\n ) {\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from.address,\n ...(txparams.value && { value: txparams.value }),\n })\n return true\n } catch (err) {\n throw new ContractSimulationError(\n `Error Simulating contract call \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n }\n\n private async localAccountSimulate(\n name: string,\n from: Account | `0x${string}`,\n args: any[],\n txparams: any,\n ) {\n try {\n await this.client.public.simulateContract({\n address: this.address,\n abi: this.contract.abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n } catch (err) {\n throw new ContractSimulationError(\n `Error Simulating contract call \"${name}\" on contract \"${this.contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n return true\n }\n\n private async localAccountSend(\n name: string,\n from: Account | `0x${string}`,\n args: any[],\n txparams: any,\n progress: ((data: any) => void) | undefined,\n _contractAbi?: Abi,\n _contractAddress?: Address,\n _contractName?: string,\n ) {\n const abi = _contractAbi || this.contract.abi\n const contractAddress = _contractAddress || this.address\n const contractName = _contractName || this.contractName\n\n const functionInputs = getInputsOfFunctionFormatted(abi, name, args)\n // Uncomment to debug contract calls\n // if (name === 'order') {\n // const functionSignature = getSignatureOfFunction(this.contract.abi, name, args)\n // this.logger.info(`Making contract call ....: ${name} - ${from}`)\n // this.logger.info(`With args: `, JSON.stringify(args, jsonReplacer))\n // this.logger.info(`And signature: ${JSON.stringify(functionSignature, jsonReplacer)}`)\n // this.logger.info('And amount: ', txparams.value)\n // }\n // abi.filter(({name, inputs}) => name === 'closeSignals' && inputs.length === 1)\n // const abiFilter = this.contract.abi.filter((abi) => abi.name === name && abi.inputs.length === args.length)\n // const abiFilter = this.contract.abi.filter((abi) => abi.name === name && abi.type === 'function')\n // console.debug('abi', this.contract.abi.filter((abi) => abi.name === name))\n // console.debug('abiFilter', abiFilter)\n // if (!abiFilter)\n // throw new ContractsError(\n // `No ABI found for method \"${name}\" with ${args.length} arguments on contract \"${this.contractName}\"`,\n // )\n\n const { gasLimit, value } = txparams\n // make the call\n if (progress) {\n progress({\n stage: 'sending',\n args: functionInputs,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n\n let txHash: `0x${string}` | undefined\n try {\n const { request } = await this.client.public.simulateContract({\n address: contractAddress,\n abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n\n // Resolve gas ourselves so `writeContract` never falls back to its own\n // `eth_estimateGas`. An explicit caller `gasLimit` always wins; otherwise\n // we estimate, apply the block-limit sanity check, and pin the result.\n // If estimation itself fails we still honour any explicit cap.\n let resolvedGas: bigint | undefined = gasLimit\n if (resolvedGas === undefined) {\n try {\n const estimate = await this.client.public.estimateContractGas({\n address: contractAddress,\n abi,\n functionName: name,\n args,\n account: from,\n ...(txparams.value && { value: txparams.value }),\n })\n resolvedGas = capForBogusEstimate(estimate, this.logger)\n } catch (estErr) {\n this.logger.warn(\n `estimateContractGas for \"${name}\" on \"${contractName}\" failed (${estErr}); ` +\n `falling back to ${GAS_FALLBACK_CAP} to avoid a bogus RPC re-estimate in writeContract.`,\n )\n resolvedGas = GAS_FALLBACK_CAP\n }\n }\n\n txHash = await this.client.wallet.writeContract({\n ...request,\n account: from,\n gas: resolvedGas,\n })\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(\n `Calling method \"${name}\" on contract \"${contractName}\" failed. Args: ${args} - ${err}`,\n )\n }\n\n if (progress) {\n progress({\n stage: 'sent',\n args: functionInputs,\n txHash,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n const txReceipt = getTransactionReceipt({ txHash, publicClient: this.client.public })\n\n if (progress) {\n progress({\n stage: 'receipt',\n args: functionInputs,\n txReceipt,\n method: name,\n from,\n value,\n contractName,\n contractAddress,\n gasLimit,\n })\n }\n\n return txReceipt\n }\n\n private async localAccountMulticall(\n calls: MulticallEntry[],\n from: Account,\n txparams: any,\n progress: ((data: any) => void) | undefined,\n ): Promise<TransactionReceipt> {\n const receipts: TransactionReceipt[] = []\n for (const call of calls) {\n receipts.push(\n await this.localAccountSend(\n call.functionName,\n from,\n call.args,\n txparams,\n progress,\n call.abi,\n call.contractAddress,\n call.contractName,\n ),\n )\n }\n if (receipts.length > 0) return receipts.pop() as TransactionReceipt\n else throw new ContractsError(`No receipts found for multicall`)\n }\n\n private async localAccountSimulateMulticall(\n calls: SimulateMulticallEntry[],\n from: Account,\n txparams: any,\n ) {\n try {\n const { results } = await this.client.public.simulateCalls({\n calls,\n account: from,\n })\n this.logger.debug(`Simulated multicall - ${results}`)\n return true\n } catch (err) {\n if (err instanceof BaseError) {\n const revertError = err.walk((err) => err instanceof ContractFunctionRevertedError)\n this.logger.error(`revertError: ${String(revertError)}`)\n }\n throw new ContractsError(`Error simulating multicall - ${err}`)\n }\n }\n\n private async internalSimulateMulticallSmartAccount(\n calls: SimulateMulticallEntry[],\n from: SmartAccount,\n txparams: any,\n ) {\n try {\n const kernelClient = createKernelAccountClient({\n account: from,\n chain: getChain(this.config.chainId),\n bundlerTransport: http(this.getBundlerRPC()),\n client: this.client.public,\n ...this.getPaymasterConfig(),\n userOperation: {\n estimateFeesPerGas: async ({ bundlerClient }) => {\n return estimateUserOperationFees(bundlerClient, this.client.public)\n },\n },\n })\n\n const encodedCalls = []\n for (const call of calls) {\n encodedCalls.push({\n to: call.to,\n value: call.value || 0n,\n data: encodeFunctionData({\n abi: call.abi,\n functionName: call.functionName,\n args: call.args,\n }),\n })\n }\n\n // DONT DELETE THE COMMENTED LINES - ARE NECESSARY FOR F***ING ZERODEV DEBUGGING\n\n // this.logger.info(`Encoded multicall - ${JSON.stringify(encodedCalls, jsonReplacer)}`)\n // const code = await this.client.public.getCode({ address: from.address })\n // const isDeployed = code !== undefined && code !== '0x'\n // this.logger.info(`++++++ Smart account ${from.address} deployment status: ${isDeployed ? 'DEPLOYED' : 'NOT DEPLOYED'}`)\n\n // // Log account details\n // this.logger.info(`Account type: ${from.type}`)\n // this.logger.info(`Account address: ${from.address}`)\n\n // // Log the calls being made\n // this.logger.info(`Number of calls: ${encodedCalls.length}`)\n // encodedCalls.forEach((call, index) => {\n // this.logger.info(`Call ${index}: to=${call.to}, value=${call.value}, data=${call.data.slice(0, 10)}...`)\n // })\n\n await kernelClient.prepareUserOperation({\n callData: await kernelClient.account.encodeCalls(encodedCalls),\n })\n\n return true\n } catch (err) {\n this.logger.error(`Error details: ${JSON.stringify(err, null, 2)}`)\n if (err instanceof BaseError) {\n const revertError = err.walk((e) => e instanceof ContractFunctionRevertedError)\n if (revertError) {\n this.logger.error(`Revert error: ${String(revertError)}`)\n }\n }\n throw new ContractSimulationError(`Error Simulating Multicalls - ${err}`)\n }\n }\n\n private getOrCreatePaymaster() {\n if (!this._zeroDevPaymaster) {\n this._zeroDevPaymaster = createZeroDevPaymasterClient({\n chain: getChain(this.config.chainId),\n transport: http(this.getPaymasterRPC()),\n })\n }\n return this._zeroDevPaymaster\n }\n\n /**\n * Builds the `paymaster` partial for `createKernelAccountClient`. In relayer\n * mode (e.g. local `ultra-relay` for tests) returns an empty object so the\n * kernel client submits UserOps without paymaster fields and the bundler\n * pays gas via its executor key. In production returns the ZeroDev paymaster\n * sponsorship callback.\n */\n private getPaymasterConfig() {\n if (isRelayerMode()) return {}\n const zerodevPaymaster = this.getOrCreatePaymaster()\n return {\n paymaster: {\n getPaymasterData: (userOperation: any) =>\n zerodevPaymaster.sponsorUserOperation({ userOperation }),\n },\n }\n }\n\n protected getBundlerRPC(): string {\n // In relayer mode `getBundlerRpcUrl` reads `BUNDLER_RPC_URL_OVERRIDE`\n // and never touches the project id, so an empty value is harmless. In\n // production callers must pass a project id — surface a clear error if\n // the SDK was instantiated without one and we need it.\n const projectId = this.config.zeroDevProjectId\n if (!projectId && !isRelayerMode()) {\n throw new ContractsError(\n 'getBundlerRPC: zeroDevProjectId is required for non-relayer (production) mode',\n )\n }\n return getBundlerRpcUrl(projectId ?? '', this.config.chainId)\n }\n\n private getPaymasterRPC(): string {\n // Only ever consulted when `getPaymasterConfig` decides to attach a\n // paymaster, which is gated on `!isRelayerMode()`. A missing project\n // id at this point is a configuration bug worth surfacing.\n const projectId = this.config.zeroDevProjectId\n if (!projectId) {\n throw new ContractsError(\n 'getPaymasterRPC: zeroDevProjectId is required to build the paymaster URL',\n )\n }\n return getPaymasterRpcUrl(projectId, this.config.chainId)\n }\n}\n"],"names":["createKernelAccountClient","createZeroDevPaymasterClient","estimateUserOperationFees","getBundlerRpcUrl","getPaymasterRpcUrl","isRelayerMode","BaseError","ContractFunctionRevertedError","encodeFunctionData","getContract","http","parseAbi","parseEventLogs","createBundlerClient","getUserOperationHash","ContractsError","ContractSimulationError","Instantiable","getInputsOfFunctionFormatted","getTransactionReceipt","getRandomBigInt","getChain","GAS_SANITY_THRESHOLD","GAS_FALLBACK_CAP","ZERODEV_NONCE_KEY_BITS","USEROP_RECEIPT_TIMEOUT_MS","capForBogusEstimate","estimatedGas","logger","warn","ContractBase","contractName","address","_zeroDevPaymaster","init","config","contractConfig","setInstanceConfig","contract","abi","client","public","publicClient","wallet","walletClient","call","functionName","args","from","readContract","account","err","txHash","hash","receipt","transactionHash","Error","getTransactionLogs","txReceipt","eventName","logs","strict","multicall","calls","params","type","debug","localAccountMulticall","progress","internalMulticallSmartAccount","simulateMulticall","localAccountSimulateMulticall","internalSimulateMulticallSmartAccount","simulate","localAccountSimulate","internalSimulateSmartAccount","send","localAccountSend","internalSendSmartAccount","getUserOperationReceipt","bundlerClient","chain","chainId","transport","getBundlerRPC","message","String","test","safeMessage","replace","txparams","stage","method","contractAddress","kernelClient","bundlerTransport","getPaymasterConfig","userOperation","estimateFeesPerGas","encodedCalls","map","push","to","value","data","userOpHash","nonce","getNonce","key","sendUserOperation","callData","encodeCalls","waitForUserOperationReceipt","timeout","assertUserOpSucceeded","revertError","walk","error","hashSuffix","success","reason","name","functionInputs","gasLimit","simulateContract","preparedUserOp","preparedHash","prepareUserOperation","entryPointAddress","entryPoint","entryPointVersion","version","prepErr","undefined","signature","_contractAbi","_contractAddress","_contractName","request","resolvedGas","estimate","estimateContractGas","estErr","writeContract","gas","receipts","length","pop","results","simulateCalls","JSON","stringify","e","getOrCreatePaymaster","getPaymasterRPC","zerodevPaymaster","paymaster","getPaymasterData","sponsorUserOperation","projectId","zeroDevProjectId"],"mappings":"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"}
|
|
@@ -37,6 +37,13 @@ export type X402Erc4337Payload = {
|
|
|
37
37
|
id: string;
|
|
38
38
|
data: string;
|
|
39
39
|
}[];
|
|
40
|
+
/**
|
|
41
|
+
* Signed planId (#1678). Present on v2 tokens (minted after #1678) and
|
|
42
|
+
* covered by the EIP-712 signature, so it is tamper-evident on its own.
|
|
43
|
+
* OPTIONAL on the wire type only for backwards-compat: genuinely-old v1
|
|
44
|
+
* tokens carry no `planId` here and verify against the legacy type list.
|
|
45
|
+
*/
|
|
46
|
+
planId?: string;
|
|
40
47
|
};
|
|
41
48
|
};
|
|
42
49
|
/**
|
|
@@ -69,6 +76,16 @@ export type NeverminedTypedDataDomain = {
|
|
|
69
76
|
chainId: number;
|
|
70
77
|
verifyingContract: `0x${string}`;
|
|
71
78
|
};
|
|
79
|
+
/**
|
|
80
|
+
* EIP-712 `Authorization` struct WITH a signed `planId` (#1678).
|
|
81
|
+
*
|
|
82
|
+
* `planId` is appended LAST so the change is purely additive to the EIP-712
|
|
83
|
+
* encoding of the legacy (v1) struct. Signing the planId makes the token's plan
|
|
84
|
+
* tamper-evident on its own — defense-in-depth atop the resource server's
|
|
85
|
+
* `validateAcceptedMatchesRequirements` demand-match, which remains the primary
|
|
86
|
+
* gate. See `NeverminedTypedDataTypesV1` for the legacy struct that pre-#1678
|
|
87
|
+
* tokens were signed over; both shapes verify against the same signer.
|
|
88
|
+
*/
|
|
72
89
|
export type NeverminedTypedData = {
|
|
73
90
|
SessionKey: [{
|
|
74
91
|
name: 'id';
|
|
@@ -93,11 +110,55 @@ export type NeverminedTypedData = {
|
|
|
93
110
|
{
|
|
94
111
|
name: 'sessionKeys';
|
|
95
112
|
type: 'SessionKey[]';
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
name: 'planId';
|
|
116
|
+
type: 'string';
|
|
96
117
|
}
|
|
97
118
|
];
|
|
98
119
|
};
|
|
99
120
|
export declare const NeverminedTypedDataTypes: NeverminedTypedData;
|
|
100
|
-
|
|
121
|
+
/**
|
|
122
|
+
* Legacy (v1) EIP-712 `Authorization` struct — WITHOUT a signed `planId`.
|
|
123
|
+
*
|
|
124
|
+
* Retained so `verifyAgentX402AccessToken` can still validate genuinely-old
|
|
125
|
+
* tokens minted before #1678 (their `authorization` carries no `planId`, and
|
|
126
|
+
* EIP-712 hashes the type set, so they only verify against THIS type list).
|
|
127
|
+
* Mint always produces the v2 (with-planId) shape going forward.
|
|
128
|
+
*/
|
|
129
|
+
export type NeverminedTypedDataV1 = {
|
|
130
|
+
SessionKey: [{
|
|
131
|
+
name: 'id';
|
|
132
|
+
type: 'string';
|
|
133
|
+
}, {
|
|
134
|
+
name: 'data';
|
|
135
|
+
type: 'string';
|
|
136
|
+
}];
|
|
137
|
+
SessionKeys: [{
|
|
138
|
+
name: 'sessionKeys';
|
|
139
|
+
type: 'SessionKey[]';
|
|
140
|
+
}];
|
|
141
|
+
Authorization: [
|
|
142
|
+
{
|
|
143
|
+
name: 'from';
|
|
144
|
+
type: 'address';
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: 'sessionKeysProvider';
|
|
148
|
+
type: 'string';
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: 'sessionKeys';
|
|
152
|
+
type: 'SessionKey[]';
|
|
153
|
+
}
|
|
154
|
+
];
|
|
155
|
+
};
|
|
156
|
+
export declare const NeverminedTypedDataTypesV1: NeverminedTypedDataV1;
|
|
157
|
+
/**
|
|
158
|
+
* Legacy (v1) signed message shape — no `planId`. Mirrors `NeverminedTypedDataTypesV1`.
|
|
159
|
+
* Only genuinely-old tokens carry this shape; mint never produces it.
|
|
160
|
+
*/
|
|
161
|
+
export type NeverminedTypedDataMessageV1 = {
|
|
101
162
|
from: `0x${string}`;
|
|
102
163
|
sessionKeysProvider: string;
|
|
103
164
|
sessionKeys: {
|
|
@@ -105,6 +166,15 @@ export type NeverminedTypedDataMessage = {
|
|
|
105
166
|
data: string;
|
|
106
167
|
}[];
|
|
107
168
|
};
|
|
169
|
+
/**
|
|
170
|
+
* The v2 signed message shape — `planId` is REQUIRED. Mint always produces this
|
|
171
|
+
* shape (#1678), so `planId` is non-optional here; the v1 variant above models
|
|
172
|
+
* the legacy no-planId message. Mirrors `NeverminedTypedDataTypes`.
|
|
173
|
+
*/
|
|
174
|
+
export type NeverminedTypedDataMessage = NeverminedTypedDataMessageV1 & {
|
|
175
|
+
/** Signed planId (#1678) — always present on v2 (minted) tokens. */
|
|
176
|
+
planId: string;
|
|
177
|
+
};
|
|
108
178
|
/**
|
|
109
179
|
* Options for generating an x402 access token
|
|
110
180
|
*/
|
|
@@ -130,7 +200,42 @@ export type GenerateX402TokenOptions = {
|
|
|
130
200
|
*/
|
|
131
201
|
export declare const generateAgentX402AccessToken: (options: GenerateX402TokenOptions) => Promise<AgentX402AccessToken>;
|
|
132
202
|
/**
|
|
133
|
-
*
|
|
203
|
+
* True when `authorization` carries a GENUINE signed planId (#1678) — a present,
|
|
204
|
+
* non-empty string. This is the single v1/v2 discriminator: verification keys off
|
|
205
|
+
* it to choose the matching EIP-712 type list, the handler keys off it to decide
|
|
206
|
+
* whether the signed-vs-unsigned consistency guard fires. Keying off genuine
|
|
207
|
+
* presence (not just `'planId' in authorization`) ensures a `planId: ''` / nullish
|
|
208
|
+
* value can never be mistaken for a real signed claim.
|
|
209
|
+
*/
|
|
210
|
+
export declare const hasSignedPlanId: (authorization: X402Erc4337Payload["authorization"]) => authorization is X402Erc4337Payload["authorization"] & {
|
|
211
|
+
planId: string;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* The signed-vs-unsigned planId consistency invariant (#1678), co-located with
|
|
215
|
+
* `hasSignedPlanId` so signer, verifier, and the API handler share ONE
|
|
216
|
+
* definition (no drift between where the planId is signed and where the guard
|
|
217
|
+
* enforces it).
|
|
218
|
+
*
|
|
219
|
+
* For a v2 token (signed planId present) the tamperable unsigned `accepted.planId`
|
|
220
|
+
* MUST exactly equal the signed `authorization.planId` — anything else is a
|
|
221
|
+
* post-signing edit of the outer JSON. Returns `true` for v1 tokens (no signed
|
|
222
|
+
* planId): there is no signed value to be consistent with, so the guard does not
|
|
223
|
+
* apply (the caller handles the legacy fallback separately). The API handler maps
|
|
224
|
+
* a `false` result to its forgery-gated rejection.
|
|
225
|
+
*/
|
|
226
|
+
export declare const isSignedPlanIdConsistent: (authorization: X402Erc4337Payload["authorization"], acceptedPlanId: string | null | undefined) => boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Verify an x402 access token signature.
|
|
229
|
+
*
|
|
230
|
+
* EIP-712 hashes the type set, so a token signed over the v2 (with-planId)
|
|
231
|
+
* struct cannot verify against the v1 type list and vice-versa. We therefore
|
|
232
|
+
* detect which shape the token carries (genuine signed planId → v2) and verify
|
|
233
|
+
* against the matching type list. This keeps genuinely-old v1 tokens valid
|
|
234
|
+
* (#1678 backwards-compat) while v2 tokens are checked over the signed planId.
|
|
235
|
+
*
|
|
236
|
+
* Downgrade-safe: a v2 token was signed over the with-planId digest, so stripping
|
|
237
|
+
* `authorization.planId` to force the v1 branch changes the digest and the
|
|
238
|
+
* signature fails — an attacker cannot demote a signed token to dodge the planId.
|
|
134
239
|
*
|
|
135
240
|
* @param accessToken - The x402 access token to verify
|
|
136
241
|
* @param publicClient - Viem public client
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AgentX402AccessToken.d.ts","sourceRoot":"","sources":["../../src/models/AgentX402AccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAgC,MAAM,MAAM,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEvD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,qBAAqB,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,KAAK,MAAM,EAAE,CAAA;IACxB,aAAa,EAAE;QACb,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;QACnB,mBAAmB,EAAE,MAAM,CAAA;QAC3B,WAAW,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"AgentX402AccessToken.d.ts","sourceRoot":"","sources":["../../src/models/AgentX402AccessToken.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,YAAY,EAAgC,MAAM,MAAM,CAAA;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAEvD;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,aAAa,GAAG,qBAAqB,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,UAAU,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,KAAK,MAAM,EAAE,CAAA;IACxB,aAAa,EAAE;QACb,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;QACnB,mBAAmB,EAAE,MAAM,CAAA;QAC3B,WAAW,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;QAC3C;;;;;WAKG;QACH,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAA;CACF,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,WAAW,EAAE,CAAC,CAAA;IACd,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,QAAQ,EAAE,YAAY,CAAA;IACtB,OAAO,EAAE,kBAAkB,GAAG,yBAAyB,CAAA;IACvD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,YAAY,CAAA;IAClB,OAAO,EAAE,GAAG,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,iBAAiB,EAAE,KAAK,MAAM,EAAE,CAAA;CACjC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,UAAU,EAAE,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAA;IAC9E,WAAW,EAAE,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,CAAA;IAC5D,aAAa,EAAE;QACb;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,SAAS,CAAA;SAAE;QACjC;YAAE,IAAI,EAAE,qBAAqB,CAAC;YAAC,IAAI,EAAE,QAAQ,CAAA;SAAE;QAC/C;YAAE,IAAI,EAAE,aAAa,CAAC;YAAC,IAAI,EAAE,cAAc,CAAA;SAAE;QAC7C;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,IAAI,EAAE,QAAQ,CAAA;SAAE;KACnC,CAAA;CACF,CAAA;AAED,eAAO,MAAM,wBAAwB,EAAE,mBAYtC,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,UAAU,EAAE,CAAC;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,CAAA;KAAE,CAAC,CAAA;IAC9E,WAAW,EAAE,CAAC;QAAE,IAAI,EAAE,aAAa,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,CAAA;IAC5D,aAAa,EAAE;QACb;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,SAAS,CAAA;SAAE;QACjC;YAAE,IAAI,EAAE,qBAAqB,CAAC;YAAC,IAAI,EAAE,QAAQ,CAAA;SAAE;QAC/C;YAAE,IAAI,EAAE,aAAa,CAAC;YAAC,IAAI,EAAE,cAAc,CAAA;SAAE;KAC9C,CAAA;CACF,CAAA;AAED,eAAO,MAAM,0BAA0B,EAAE,qBAWxC,CAAA;AAED;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC,IAAI,EAAE,KAAK,MAAM,EAAE,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,WAAW,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC5C,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,4BAA4B,GAAG;IACtE,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAA;CACf,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,UAAU,EAAE,YAAY,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,YAAY,EAAE,YAAY,CAAA;IAC1B,MAAM,EAAE,MAAM,CAAA;IACd,oEAAoE;IACpE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,GACvC,SAAS,wBAAwB,KAChC,OAAO,CAAC,oBAAoB,CA0F9B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAC1B,eAAe,kBAAkB,CAAC,eAAe,CAAC,KACjD,aAAa,IAAI,kBAAkB,CAAC,eAAe,CAAC,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAEzE,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,GACnC,eAAe,kBAAkB,CAAC,eAAe,CAAC,EAClD,gBAAgB,MAAM,GAAG,IAAI,GAAG,SAAS,KACxC,OAGF,CAAA;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,GACrC,aAAa,oBAAoB,EACjC,cAAc,YAAY,KACzB,OAAO,CAAC,OAAO,CAuBjB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAUD,eAAO,MAAM,0BAA0B,GAAI,OAAO,OAAO,KAAG,yBA4F3D,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,aAAa,oBAAoB,KAAG,MAE5E,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,SAAS,MAAM,KAAG,oBAE1D,CAAA"}
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
import { keccak256, toBytes } from 'viem';
|
|
2
2
|
export const NeverminedTypedDataTypes = {
|
|
3
|
+
SessionKey: [
|
|
4
|
+
{
|
|
5
|
+
name: 'id',
|
|
6
|
+
type: 'string'
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
name: 'data',
|
|
10
|
+
type: 'string'
|
|
11
|
+
}
|
|
12
|
+
],
|
|
13
|
+
SessionKeys: [
|
|
14
|
+
{
|
|
15
|
+
name: 'sessionKeys',
|
|
16
|
+
type: 'SessionKey[]'
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
Authorization: [
|
|
20
|
+
{
|
|
21
|
+
name: 'from',
|
|
22
|
+
type: 'address'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'sessionKeysProvider',
|
|
26
|
+
type: 'string'
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'sessionKeys',
|
|
30
|
+
type: 'SessionKey[]'
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'planId',
|
|
34
|
+
type: 'string'
|
|
35
|
+
}
|
|
36
|
+
]
|
|
37
|
+
};
|
|
38
|
+
export const NeverminedTypedDataTypesV1 = {
|
|
3
39
|
SessionKey: [
|
|
4
40
|
{
|
|
5
41
|
name: 'id',
|
|
@@ -38,10 +74,20 @@ export const NeverminedTypedDataTypes = {
|
|
|
38
74
|
* @returns x402 access token with EIP-712 signature
|
|
39
75
|
*/ export const generateAgentX402AccessToken = async (options)=>{
|
|
40
76
|
const { subscriber, orderSessionKey, redeemSessionKey, publicClient, planId, schemeVersion = '1', agentId, resource, httpVerb, validUntil } = options;
|
|
77
|
+
// A v2 token MUST carry a non-empty signed planId (#1678) — an empty/blank
|
|
78
|
+
// planId would otherwise be signed into `authorization.planId` and could be
|
|
79
|
+
// misread as a "present but empty" signed claim, blurring the v1/v2 boundary
|
|
80
|
+
// that verification keys off genuine presence. erc4337 already requires a
|
|
81
|
+
// planId upstream (`validateX402TokenStructure`), so this is a hard invariant.
|
|
82
|
+
if (typeof planId !== 'string' || planId.trim() === '') {
|
|
83
|
+
throw new Error('generateAgentX402AccessToken: planId is required and must be a non-empty string');
|
|
84
|
+
}
|
|
41
85
|
// hash the session keys
|
|
42
86
|
const redeemSessionKeyHash = keccak256(toBytes(redeemSessionKey));
|
|
43
87
|
const orderSessionKeyHash = keccak256(toBytes(orderSessionKey));
|
|
44
|
-
// generate the message with `from` address
|
|
88
|
+
// generate the message with `from` address and the SIGNED planId (#1678).
|
|
89
|
+
// Including `planId` here puts it inside the EIP-712 digest, so it cannot be
|
|
90
|
+
// altered without invalidating the signature.
|
|
45
91
|
const message = {
|
|
46
92
|
from: subscriber.address,
|
|
47
93
|
sessionKeysProvider: 'zerodev',
|
|
@@ -54,7 +100,8 @@ export const NeverminedTypedDataTypes = {
|
|
|
54
100
|
id: 'redeem',
|
|
55
101
|
data: redeemSessionKeyHash
|
|
56
102
|
}
|
|
57
|
-
]
|
|
103
|
+
],
|
|
104
|
+
planId
|
|
58
105
|
};
|
|
59
106
|
const domain = {
|
|
60
107
|
name: 'Nevermined',
|
|
@@ -103,7 +150,43 @@ export const NeverminedTypedDataTypes = {
|
|
|
103
150
|
};
|
|
104
151
|
};
|
|
105
152
|
/**
|
|
106
|
-
*
|
|
153
|
+
* True when `authorization` carries a GENUINE signed planId (#1678) — a present,
|
|
154
|
+
* non-empty string. This is the single v1/v2 discriminator: verification keys off
|
|
155
|
+
* it to choose the matching EIP-712 type list, the handler keys off it to decide
|
|
156
|
+
* whether the signed-vs-unsigned consistency guard fires. Keying off genuine
|
|
157
|
+
* presence (not just `'planId' in authorization`) ensures a `planId: ''` / nullish
|
|
158
|
+
* value can never be mistaken for a real signed claim.
|
|
159
|
+
*/ export const hasSignedPlanId = (authorization)=>{
|
|
160
|
+
return typeof authorization?.planId === 'string' && authorization.planId.trim() !== '';
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* The signed-vs-unsigned planId consistency invariant (#1678), co-located with
|
|
164
|
+
* `hasSignedPlanId` so signer, verifier, and the API handler share ONE
|
|
165
|
+
* definition (no drift between where the planId is signed and where the guard
|
|
166
|
+
* enforces it).
|
|
167
|
+
*
|
|
168
|
+
* For a v2 token (signed planId present) the tamperable unsigned `accepted.planId`
|
|
169
|
+
* MUST exactly equal the signed `authorization.planId` — anything else is a
|
|
170
|
+
* post-signing edit of the outer JSON. Returns `true` for v1 tokens (no signed
|
|
171
|
+
* planId): there is no signed value to be consistent with, so the guard does not
|
|
172
|
+
* apply (the caller handles the legacy fallback separately). The API handler maps
|
|
173
|
+
* a `false` result to its forgery-gated rejection.
|
|
174
|
+
*/ export const isSignedPlanIdConsistent = (authorization, acceptedPlanId)=>{
|
|
175
|
+
if (!hasSignedPlanId(authorization)) return true;
|
|
176
|
+
return acceptedPlanId === authorization.planId;
|
|
177
|
+
};
|
|
178
|
+
/**
|
|
179
|
+
* Verify an x402 access token signature.
|
|
180
|
+
*
|
|
181
|
+
* EIP-712 hashes the type set, so a token signed over the v2 (with-planId)
|
|
182
|
+
* struct cannot verify against the v1 type list and vice-versa. We therefore
|
|
183
|
+
* detect which shape the token carries (genuine signed planId → v2) and verify
|
|
184
|
+
* against the matching type list. This keeps genuinely-old v1 tokens valid
|
|
185
|
+
* (#1678 backwards-compat) while v2 tokens are checked over the signed planId.
|
|
186
|
+
*
|
|
187
|
+
* Downgrade-safe: a v2 token was signed over the with-planId digest, so stripping
|
|
188
|
+
* `authorization.planId` to force the v1 branch changes the digest and the
|
|
189
|
+
* signature fails — an attacker cannot demote a signed token to dodge the planId.
|
|
107
190
|
*
|
|
108
191
|
* @param accessToken - The x402 access token to verify
|
|
109
192
|
* @param publicClient - Viem public client
|
|
@@ -122,7 +205,9 @@ export const NeverminedTypedDataTypes = {
|
|
|
122
205
|
const isValid = await publicClient.verifyTypedData({
|
|
123
206
|
address: subscriberAddress,
|
|
124
207
|
signature,
|
|
125
|
-
|
|
208
|
+
// v2 (signed planId) verifies over the with-planId type list; legacy v1
|
|
209
|
+
// tokens (no signed planId) verify over the original type list.
|
|
210
|
+
types: hasSignedPlanId(authorization) ? NeverminedTypedDataTypes : NeverminedTypedDataTypesV1,
|
|
126
211
|
domain,
|
|
127
212
|
message: authorization,
|
|
128
213
|
primaryType: 'Authorization'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/models/AgentX402AccessToken.ts"],"sourcesContent":["import { keccak256, PublicClient, toBytes, TypedDataDefinition } from 'viem'\nimport { SmartAccount } from 'viem/account-abstraction'\n\n/**\n * x402 Resource information\n */\nexport type X402Resource = {\n url: string\n description?: string\n mimeType?: string\n}\n\n/**\n * Supported x402 payment schemes\n */\nexport type X402Scheme = 'nvm:erc4337' | 'nvm:card-delegation'\n\n/**\n * x402 Accepted scheme fields (common to all schemes)\n */\nexport type X402Accepted = {\n scheme: X402Scheme\n network: string\n planId?: string\n extra: {\n version: string\n agentId?: string\n httpVerb?: string\n }\n}\n\n/**\n * Payload specific to the nvm:erc4337 scheme\n */\nexport type X402Erc4337Payload = {\n signature: `0x${string}`\n authorization: {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n }\n}\n\n/**\n * Payload specific to the nvm:card-delegation scheme\n */\nexport type X402CardDelegationPayload = {\n token: string\n}\n\n/**\n * x402 Access Token aligned with x402 v2 spec\n *\n * Key changes from previous version:\n * - `subscriberAddress` moved to `payload.authorization.from`\n * - `planId` is now in `accepted` (optional — required for erc4337, optional for card-delegation)\n * - `agentId` moved to `accepted.extra.agentId` (optional)\n * - `scheme` and `network` moved to `accepted`\n * - Added `resource` and `extensions` for x402 v2 alignment\n */\nexport type AgentX402AccessToken = {\n x402Version: 2\n resource?: X402Resource\n accepted: X402Accepted\n payload: X402Erc4337Payload | X402CardDelegationPayload\n validUntil?: number\n extensions: Record<string, unknown>\n}\n\nexport type NeverminedTypedDataDomain = {\n name: 'Nevermined'\n version: '1'\n chainId: number\n verifyingContract: `0x${string}`\n}\n\nexport type NeverminedTypedData = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n ]\n}\n\nexport const NeverminedTypedDataTypes: NeverminedTypedData = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n ],\n}\n\nexport type NeverminedTypedDataMessage = {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n}\n\n/**\n * Options for generating an x402 access token\n */\nexport type GenerateX402TokenOptions = {\n subscriber: SmartAccount\n orderSessionKey: string\n redeemSessionKey: string\n publicClient: PublicClient\n planId: string\n /** Scheme version (e.g., '1') - stored in accepted.extra.version */\n schemeVersion?: string\n agentId?: string\n resource?: X402Resource\n httpVerb?: string\n /** Token expiration timestamp in seconds (Unix epoch) */\n validUntil?: number\n}\n\n/**\n * Generate an x402 access token aligned with x402 v2 spec\n *\n * @param options - Token generation options\n * @returns x402 access token with EIP-712 signature\n */\nexport const generateAgentX402AccessToken = async (\n options: GenerateX402TokenOptions,\n): Promise<AgentX402AccessToken> => {\n const {\n subscriber,\n orderSessionKey,\n redeemSessionKey,\n publicClient,\n planId,\n schemeVersion = '1',\n agentId,\n resource,\n httpVerb,\n validUntil,\n } = options\n\n // hash the session keys\n const redeemSessionKeyHash = keccak256(toBytes(redeemSessionKey))\n const orderSessionKeyHash = keccak256(toBytes(orderSessionKey))\n\n // generate the message with `from` address\n const message: NeverminedTypedDataMessage = {\n from: subscriber.address,\n sessionKeysProvider: 'zerodev',\n sessionKeys: [\n {\n id: 'order',\n data: orderSessionKeyHash,\n },\n {\n id: 'redeem',\n data: redeemSessionKeyHash,\n },\n ],\n }\n\n const domain: NeverminedTypedDataDomain = {\n name: 'Nevermined',\n version: '1',\n chainId: publicClient.chain?.id as number,\n verifyingContract: subscriber.address,\n }\n\n // generate the eip712 data\n const eip712Data = {\n domain,\n\n types: NeverminedTypedDataTypes,\n primaryType: 'Authorization',\n message,\n } satisfies TypedDataDefinition<NeverminedTypedData, 'Authorization'>\n\n const signature = await subscriber.signTypedData(eip712Data)\n\n // Get network in CAIP-2 format (eip155:chainId)\n const chainId = publicClient.chain?.id\n const network = chainId ? `eip155:${chainId}` : (publicClient.chain?.name as string)\n\n return {\n x402Version: 2,\n ...(resource && { resource }),\n accepted: {\n scheme: 'nvm:erc4337',\n network,\n planId,\n extra: {\n version: schemeVersion,\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n },\n },\n payload: {\n signature,\n authorization: message,\n },\n ...(validUntil !== undefined && { validUntil }),\n extensions: {},\n }\n}\n\n/**\n * Verify an x402 access token signature\n *\n * @param accessToken - The x402 access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentX402AccessToken = async (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> => {\n const erc4337Payload = accessToken.payload as X402Erc4337Payload\n // Extract subscriber address from payload.authorization.from\n const subscriberAddress = erc4337Payload.authorization.from\n\n const domain: NeverminedTypedDataDomain = {\n name: 'Nevermined',\n version: '1',\n chainId: publicClient.chain?.id as number,\n verifyingContract: subscriberAddress,\n }\n const { signature, authorization } = erc4337Payload\n const isValid = await publicClient.verifyTypedData({\n address: subscriberAddress,\n signature,\n types: NeverminedTypedDataTypes,\n domain,\n message: authorization,\n primaryType: 'Authorization',\n })\n return isValid\n}\n\n/**\n * Validation result for x402 token structure\n */\nexport type X402TokenValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Validate the structure of an x402 access token\n *\n * @param token - The token to validate (unknown type for safety)\n * @returns Validation result with errors if any\n */\nconst SUPPORTED_SCHEMES: X402Scheme[] = ['nvm:erc4337', 'nvm:card-delegation']\n\nexport const validateX402TokenStructure = (token: unknown): X402TokenValidationResult => {\n const errors: string[] = []\n\n if (!token || typeof token !== 'object') {\n return { valid: false, errors: ['Token must be an object'] }\n }\n\n const t = token as Record<string, unknown>\n\n // Validate x402Version\n if (t.x402Version !== 2) {\n errors.push('x402Version must be 2')\n }\n\n // Validate accepted object\n if (!t.accepted || typeof t.accepted !== 'object') {\n errors.push('accepted is required')\n } else {\n const accepted = t.accepted as Record<string, unknown>\n const scheme = accepted.scheme as string\n\n if (!SUPPORTED_SCHEMES.includes(scheme as X402Scheme)) {\n errors.push(`scheme must be one of: ${SUPPORTED_SCHEMES.join(', ')}`)\n }\n\n if (!accepted.network || typeof accepted.network !== 'string') {\n errors.push('network is required in accepted')\n }\n\n // Validate extra\n if (!accepted.extra || typeof accepted.extra !== 'object') {\n errors.push('extra is required in accepted')\n } else {\n const extra = accepted.extra as Record<string, unknown>\n if (!extra.version || typeof extra.version !== 'string') {\n errors.push('version is required in accepted.extra')\n }\n }\n\n // Scheme-specific accepted validation\n if (scheme === 'nvm:erc4337') {\n if (!accepted.planId || typeof accepted.planId !== 'string') {\n errors.push('planId is required in accepted for nvm:erc4337')\n }\n }\n }\n\n // Validate payload\n if (!t.payload || typeof t.payload !== 'object') {\n errors.push('payload is required')\n } else {\n const accepted = t.accepted as Record<string, unknown> | undefined\n const scheme = accepted?.scheme as string | undefined\n const payload = t.payload as Record<string, unknown>\n\n if (scheme === 'nvm:erc4337') {\n if (!payload.signature || typeof payload.signature !== 'string') {\n errors.push('signature is required in payload')\n }\n\n if (!payload.authorization || typeof payload.authorization !== 'object') {\n errors.push('authorization is required in payload')\n } else {\n const auth = payload.authorization as Record<string, unknown>\n\n if (!auth.from || typeof auth.from !== 'string') {\n errors.push('from address is required in payload.authorization')\n } else if (!auth.from.startsWith('0x')) {\n errors.push('from must be a valid hex address')\n }\n\n if (!auth.sessionKeysProvider || typeof auth.sessionKeysProvider !== 'string') {\n errors.push('sessionKeysProvider is required in payload.authorization')\n }\n\n if (!Array.isArray(auth.sessionKeys)) {\n errors.push('sessionKeys array is required in payload.authorization')\n }\n }\n } else if (scheme === 'nvm:card-delegation') {\n if (!payload.token || typeof payload.token !== 'string') {\n errors.push('token is required in payload for nvm:card-delegation')\n }\n }\n }\n\n // Validate extensions (must be present, even if empty)\n if (t.extensions === undefined) {\n errors.push('extensions is required (can be empty object)')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport const b64EncodeX402AccessToken = (accessToken: AgentX402AccessToken): string => {\n return Buffer.from(JSON.stringify(accessToken)).toString('base64')\n}\n\nexport const b64DecodeX402AccessToken = (encoded: string): AgentX402AccessToken => {\n return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'))\n}\n"],"names":["keccak256","toBytes","NeverminedTypedDataTypes","SessionKey","name","type","SessionKeys","Authorization","generateAgentX402AccessToken","options","subscriber","orderSessionKey","redeemSessionKey","publicClient","planId","schemeVersion","agentId","resource","httpVerb","validUntil","redeemSessionKeyHash","orderSessionKeyHash","message","from","address","sessionKeysProvider","sessionKeys","id","data","domain","version","chainId","chain","verifyingContract","eip712Data","types","primaryType","signature","signTypedData","network","x402Version","accepted","scheme","extra","payload","authorization","undefined","extensions","verifyAgentX402AccessToken","accessToken","erc4337Payload","subscriberAddress","isValid","verifyTypedData","SUPPORTED_SCHEMES","validateX402TokenStructure","token","errors","valid","t","push","includes","join","auth","startsWith","Array","isArray","length","b64EncodeX402AccessToken","Buffer","JSON","stringify","toString","b64DecodeX402AccessToken","encoded","parse"],"mappings":"AAAA,SAASA,SAAS,EAAgBC,OAAO,QAA6B,OAAM;AAsF5E,OAAO,MAAMC,2BAAgD;IAC3DC,YAAY;QACV;YAAEC,MAAM;YAAMC,MAAM;QAAS;QAC7B;YAAED,MAAM;YAAQC,MAAM;QAAS;KAChC;IACDC,aAAa;QAAC;YAAEF,MAAM;YAAeC,MAAM;QAAe;KAAE;IAC5DE,eAAe;QACb;YAAEH,MAAM;YAAQC,MAAM;QAAU;QAChC;YAAED,MAAM;YAAuBC,MAAM;QAAS;QAC9C;YAAED,MAAM;YAAeC,MAAM;QAAe;KAC7C;AACH,EAAC;AA0BD;;;;;CAKC,GACD,OAAO,MAAMG,+BAA+B,OAC1CC;IAEA,MAAM,EACJC,UAAU,EACVC,eAAe,EACfC,gBAAgB,EAChBC,YAAY,EACZC,MAAM,EACNC,gBAAgB,GAAG,EACnBC,OAAO,EACPC,QAAQ,EACRC,QAAQ,EACRC,UAAU,EACX,GAAGV;IAEJ,wBAAwB;IACxB,MAAMW,uBAAuBpB,UAAUC,QAAQW;IAC/C,MAAMS,sBAAsBrB,UAAUC,QAAQU;IAE9C,2CAA2C;IAC3C,MAAMW,UAAsC;QAC1CC,MAAMb,WAAWc,OAAO;QACxBC,qBAAqB;QACrBC,aAAa;YACX;gBACEC,IAAI;gBACJC,MAAMP;YACR;YACA;gBACEM,IAAI;gBACJC,MAAMR;YACR;SACD;IACH;IAEA,MAAMS,SAAoC;QACxCzB,MAAM;QACN0B,SAAS;QACTC,SAASlB,aAAamB,KAAK,EAAEL;QAC7BM,mBAAmBvB,WAAWc,OAAO;IACvC;IAEA,2BAA2B;IAC3B,MAAMU,aAAa;QACjBL;QAEAM,OAAOjC;QACPkC,aAAa;QACbd;IACF;IAEA,MAAMe,YAAY,MAAM3B,WAAW4B,aAAa,CAACJ;IAEjD,gDAAgD;IAChD,MAAMH,UAAUlB,aAAamB,KAAK,EAAEL;IACpC,MAAMY,UAAUR,UAAU,CAAC,OAAO,EAAEA,SAAS,GAAIlB,aAAamB,KAAK,EAAE5B;IAErE,OAAO;QACLoC,aAAa;QACb,GAAIvB,YAAY;YAAEA;QAAS,CAAC;QAC5BwB,UAAU;YACRC,QAAQ;YACRH;YACAzB;YACA6B,OAAO;gBACLb,SAASf;gBACT,GAAIC,WAAW;oBAAEA;gBAAQ,CAAC;gBAC1B,GAAIE,YAAY;oBAAEA;gBAAS,CAAC;YAC9B;QACF;QACA0B,SAAS;YACPP;YACAQ,eAAevB;QACjB;QACA,GAAIH,eAAe2B,aAAa;YAAE3B;QAAW,CAAC;QAC9C4B,YAAY,CAAC;IACf;AACF,EAAC;AAED;;;;;;CAMC,GACD,OAAO,MAAMC,6BAA6B,OACxCC,aACApC;IAEA,MAAMqC,iBAAiBD,YAAYL,OAAO;IAC1C,6DAA6D;IAC7D,MAAMO,oBAAoBD,eAAeL,aAAa,CAACtB,IAAI;IAE3D,MAAMM,SAAoC;QACxCzB,MAAM;QACN0B,SAAS;QACTC,SAASlB,aAAamB,KAAK,EAAEL;QAC7BM,mBAAmBkB;IACrB;IACA,MAAM,EAAEd,SAAS,EAAEQ,aAAa,EAAE,GAAGK;IACrC,MAAME,UAAU,MAAMvC,aAAawC,eAAe,CAAC;QACjD7B,SAAS2B;QACTd;QACAF,OAAOjC;QACP2B;QACAP,SAASuB;QACTT,aAAa;IACf;IACA,OAAOgB;AACT,EAAC;AAUD;;;;;CAKC,GACD,MAAME,oBAAkC;IAAC;IAAe;CAAsB;AAE9E,OAAO,MAAMC,6BAA6B,CAACC;IACzC,MAAMC,SAAmB,EAAE;IAE3B,IAAI,CAACD,SAAS,OAAOA,UAAU,UAAU;QACvC,OAAO;YAAEE,OAAO;YAAOD,QAAQ;gBAAC;aAA0B;QAAC;IAC7D;IAEA,MAAME,IAAIH;IAEV,uBAAuB;IACvB,IAAIG,EAAEnB,WAAW,KAAK,GAAG;QACvBiB,OAAOG,IAAI,CAAC;IACd;IAEA,2BAA2B;IAC3B,IAAI,CAACD,EAAElB,QAAQ,IAAI,OAAOkB,EAAElB,QAAQ,KAAK,UAAU;QACjDgB,OAAOG,IAAI,CAAC;IACd,OAAO;QACL,MAAMnB,WAAWkB,EAAElB,QAAQ;QAC3B,MAAMC,SAASD,SAASC,MAAM;QAE9B,IAAI,CAACY,kBAAkBO,QAAQ,CAACnB,SAAuB;YACrDe,OAAOG,IAAI,CAAC,CAAC,uBAAuB,EAAEN,kBAAkBQ,IAAI,CAAC,OAAO;QACtE;QAEA,IAAI,CAACrB,SAASF,OAAO,IAAI,OAAOE,SAASF,OAAO,KAAK,UAAU;YAC7DkB,OAAOG,IAAI,CAAC;QACd;QAEA,iBAAiB;QACjB,IAAI,CAACnB,SAASE,KAAK,IAAI,OAAOF,SAASE,KAAK,KAAK,UAAU;YACzDc,OAAOG,IAAI,CAAC;QACd,OAAO;YACL,MAAMjB,QAAQF,SAASE,KAAK;YAC5B,IAAI,CAACA,MAAMb,OAAO,IAAI,OAAOa,MAAMb,OAAO,KAAK,UAAU;gBACvD2B,OAAOG,IAAI,CAAC;YACd;QACF;QAEA,sCAAsC;QACtC,IAAIlB,WAAW,eAAe;YAC5B,IAAI,CAACD,SAAS3B,MAAM,IAAI,OAAO2B,SAAS3B,MAAM,KAAK,UAAU;gBAC3D2C,OAAOG,IAAI,CAAC;YACd;QACF;IACF;IAEA,mBAAmB;IACnB,IAAI,CAACD,EAAEf,OAAO,IAAI,OAAOe,EAAEf,OAAO,KAAK,UAAU;QAC/Ca,OAAOG,IAAI,CAAC;IACd,OAAO;QACL,MAAMnB,WAAWkB,EAAElB,QAAQ;QAC3B,MAAMC,SAASD,UAAUC;QACzB,MAAME,UAAUe,EAAEf,OAAO;QAEzB,IAAIF,WAAW,eAAe;YAC5B,IAAI,CAACE,QAAQP,SAAS,IAAI,OAAOO,QAAQP,SAAS,KAAK,UAAU;gBAC/DoB,OAAOG,IAAI,CAAC;YACd;YAEA,IAAI,CAAChB,QAAQC,aAAa,IAAI,OAAOD,QAAQC,aAAa,KAAK,UAAU;gBACvEY,OAAOG,IAAI,CAAC;YACd,OAAO;gBACL,MAAMG,OAAOnB,QAAQC,aAAa;gBAElC,IAAI,CAACkB,KAAKxC,IAAI,IAAI,OAAOwC,KAAKxC,IAAI,KAAK,UAAU;oBAC/CkC,OAAOG,IAAI,CAAC;gBACd,OAAO,IAAI,CAACG,KAAKxC,IAAI,CAACyC,UAAU,CAAC,OAAO;oBACtCP,OAAOG,IAAI,CAAC;gBACd;gBAEA,IAAI,CAACG,KAAKtC,mBAAmB,IAAI,OAAOsC,KAAKtC,mBAAmB,KAAK,UAAU;oBAC7EgC,OAAOG,IAAI,CAAC;gBACd;gBAEA,IAAI,CAACK,MAAMC,OAAO,CAACH,KAAKrC,WAAW,GAAG;oBACpC+B,OAAOG,IAAI,CAAC;gBACd;YACF;QACF,OAAO,IAAIlB,WAAW,uBAAuB;YAC3C,IAAI,CAACE,QAAQY,KAAK,IAAI,OAAOZ,QAAQY,KAAK,KAAK,UAAU;gBACvDC,OAAOG,IAAI,CAAC;YACd;QACF;IACF;IAEA,uDAAuD;IACvD,IAAID,EAAEZ,UAAU,KAAKD,WAAW;QAC9BW,OAAOG,IAAI,CAAC;IACd;IAEA,OAAO;QAAEF,OAAOD,OAAOU,MAAM,KAAK;QAAGV;IAAO;AAC9C,EAAC;AAED,OAAO,MAAMW,2BAA2B,CAACnB;IACvC,OAAOoB,OAAO9C,IAAI,CAAC+C,KAAKC,SAAS,CAACtB,cAAcuB,QAAQ,CAAC;AAC3D,EAAC;AAED,OAAO,MAAMC,2BAA2B,CAACC;IACvC,OAAOJ,KAAKK,KAAK,CAACN,OAAO9C,IAAI,CAACmD,SAAS,UAAUF,QAAQ,CAAC;AAC5D,EAAC"}
|
|
1
|
+
{"version":3,"sources":["../../src/models/AgentX402AccessToken.ts"],"sourcesContent":["import { keccak256, PublicClient, toBytes, TypedDataDefinition } from 'viem'\nimport { SmartAccount } from 'viem/account-abstraction'\n\n/**\n * x402 Resource information\n */\nexport type X402Resource = {\n url: string\n description?: string\n mimeType?: string\n}\n\n/**\n * Supported x402 payment schemes\n */\nexport type X402Scheme = 'nvm:erc4337' | 'nvm:card-delegation'\n\n/**\n * x402 Accepted scheme fields (common to all schemes)\n */\nexport type X402Accepted = {\n scheme: X402Scheme\n network: string\n planId?: string\n extra: {\n version: string\n agentId?: string\n httpVerb?: string\n }\n}\n\n/**\n * Payload specific to the nvm:erc4337 scheme\n */\nexport type X402Erc4337Payload = {\n signature: `0x${string}`\n authorization: {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n /**\n * Signed planId (#1678). Present on v2 tokens (minted after #1678) and\n * covered by the EIP-712 signature, so it is tamper-evident on its own.\n * OPTIONAL on the wire type only for backwards-compat: genuinely-old v1\n * tokens carry no `planId` here and verify against the legacy type list.\n */\n planId?: string\n }\n}\n\n/**\n * Payload specific to the nvm:card-delegation scheme\n */\nexport type X402CardDelegationPayload = {\n token: string\n}\n\n/**\n * x402 Access Token aligned with x402 v2 spec\n *\n * Key changes from previous version:\n * - `subscriberAddress` moved to `payload.authorization.from`\n * - `planId` is now in `accepted` (optional — required for erc4337, optional for card-delegation)\n * - `agentId` moved to `accepted.extra.agentId` (optional)\n * - `scheme` and `network` moved to `accepted`\n * - Added `resource` and `extensions` for x402 v2 alignment\n */\nexport type AgentX402AccessToken = {\n x402Version: 2\n resource?: X402Resource\n accepted: X402Accepted\n payload: X402Erc4337Payload | X402CardDelegationPayload\n validUntil?: number\n extensions: Record<string, unknown>\n}\n\nexport type NeverminedTypedDataDomain = {\n name: 'Nevermined'\n version: '1'\n chainId: number\n verifyingContract: `0x${string}`\n}\n\n/**\n * EIP-712 `Authorization` struct WITH a signed `planId` (#1678).\n *\n * `planId` is appended LAST so the change is purely additive to the EIP-712\n * encoding of the legacy (v1) struct. Signing the planId makes the token's plan\n * tamper-evident on its own — defense-in-depth atop the resource server's\n * `validateAcceptedMatchesRequirements` demand-match, which remains the primary\n * gate. See `NeverminedTypedDataTypesV1` for the legacy struct that pre-#1678\n * tokens were signed over; both shapes verify against the same signer.\n */\nexport type NeverminedTypedData = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n { name: 'planId'; type: 'string' },\n ]\n}\n\nexport const NeverminedTypedDataTypes: NeverminedTypedData = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n { name: 'planId', type: 'string' },\n ],\n}\n\n/**\n * Legacy (v1) EIP-712 `Authorization` struct — WITHOUT a signed `planId`.\n *\n * Retained so `verifyAgentX402AccessToken` can still validate genuinely-old\n * tokens minted before #1678 (their `authorization` carries no `planId`, and\n * EIP-712 hashes the type set, so they only verify against THIS type list).\n * Mint always produces the v2 (with-planId) shape going forward.\n */\nexport type NeverminedTypedDataV1 = {\n SessionKey: [{ name: 'id'; type: 'string' }, { name: 'data'; type: 'string' }]\n SessionKeys: [{ name: 'sessionKeys'; type: 'SessionKey[]' }]\n Authorization: [\n { name: 'from'; type: 'address' },\n { name: 'sessionKeysProvider'; type: 'string' },\n { name: 'sessionKeys'; type: 'SessionKey[]' },\n ]\n}\n\nexport const NeverminedTypedDataTypesV1: NeverminedTypedDataV1 = {\n SessionKey: [\n { name: 'id', type: 'string' },\n { name: 'data', type: 'string' },\n ],\n SessionKeys: [{ name: 'sessionKeys', type: 'SessionKey[]' }],\n Authorization: [\n { name: 'from', type: 'address' },\n { name: 'sessionKeysProvider', type: 'string' },\n { name: 'sessionKeys', type: 'SessionKey[]' },\n ],\n}\n\n/**\n * Legacy (v1) signed message shape — no `planId`. Mirrors `NeverminedTypedDataTypesV1`.\n * Only genuinely-old tokens carry this shape; mint never produces it.\n */\nexport type NeverminedTypedDataMessageV1 = {\n from: `0x${string}`\n sessionKeysProvider: string\n sessionKeys: { id: string; data: string }[]\n}\n\n/**\n * The v2 signed message shape — `planId` is REQUIRED. Mint always produces this\n * shape (#1678), so `planId` is non-optional here; the v1 variant above models\n * the legacy no-planId message. Mirrors `NeverminedTypedDataTypes`.\n */\nexport type NeverminedTypedDataMessage = NeverminedTypedDataMessageV1 & {\n /** Signed planId (#1678) — always present on v2 (minted) tokens. */\n planId: string\n}\n\n/**\n * Options for generating an x402 access token\n */\nexport type GenerateX402TokenOptions = {\n subscriber: SmartAccount\n orderSessionKey: string\n redeemSessionKey: string\n publicClient: PublicClient\n planId: string\n /** Scheme version (e.g., '1') - stored in accepted.extra.version */\n schemeVersion?: string\n agentId?: string\n resource?: X402Resource\n httpVerb?: string\n /** Token expiration timestamp in seconds (Unix epoch) */\n validUntil?: number\n}\n\n/**\n * Generate an x402 access token aligned with x402 v2 spec\n *\n * @param options - Token generation options\n * @returns x402 access token with EIP-712 signature\n */\nexport const generateAgentX402AccessToken = async (\n options: GenerateX402TokenOptions,\n): Promise<AgentX402AccessToken> => {\n const {\n subscriber,\n orderSessionKey,\n redeemSessionKey,\n publicClient,\n planId,\n schemeVersion = '1',\n agentId,\n resource,\n httpVerb,\n validUntil,\n } = options\n\n // A v2 token MUST carry a non-empty signed planId (#1678) — an empty/blank\n // planId would otherwise be signed into `authorization.planId` and could be\n // misread as a \"present but empty\" signed claim, blurring the v1/v2 boundary\n // that verification keys off genuine presence. erc4337 already requires a\n // planId upstream (`validateX402TokenStructure`), so this is a hard invariant.\n if (typeof planId !== 'string' || planId.trim() === '') {\n throw new Error(\n 'generateAgentX402AccessToken: planId is required and must be a non-empty string',\n )\n }\n\n // hash the session keys\n const redeemSessionKeyHash = keccak256(toBytes(redeemSessionKey))\n const orderSessionKeyHash = keccak256(toBytes(orderSessionKey))\n\n // generate the message with `from` address and the SIGNED planId (#1678).\n // Including `planId` here puts it inside the EIP-712 digest, so it cannot be\n // altered without invalidating the signature.\n const message: NeverminedTypedDataMessage = {\n from: subscriber.address,\n sessionKeysProvider: 'zerodev',\n sessionKeys: [\n {\n id: 'order',\n data: orderSessionKeyHash,\n },\n {\n id: 'redeem',\n data: redeemSessionKeyHash,\n },\n ],\n planId,\n }\n\n const domain: NeverminedTypedDataDomain = {\n name: 'Nevermined',\n version: '1',\n chainId: publicClient.chain?.id as number,\n verifyingContract: subscriber.address,\n }\n\n // generate the eip712 data\n const eip712Data = {\n domain,\n\n types: NeverminedTypedDataTypes,\n primaryType: 'Authorization',\n message,\n } satisfies TypedDataDefinition<NeverminedTypedData, 'Authorization'>\n\n const signature = await subscriber.signTypedData(eip712Data)\n\n // Get network in CAIP-2 format (eip155:chainId)\n const chainId = publicClient.chain?.id\n const network = chainId ? `eip155:${chainId}` : (publicClient.chain?.name as string)\n\n return {\n x402Version: 2,\n ...(resource && { resource }),\n accepted: {\n scheme: 'nvm:erc4337',\n network,\n planId,\n extra: {\n version: schemeVersion,\n ...(agentId && { agentId }),\n ...(httpVerb && { httpVerb }),\n },\n },\n payload: {\n signature,\n authorization: message,\n },\n ...(validUntil !== undefined && { validUntil }),\n extensions: {},\n }\n}\n\n/**\n * True when `authorization` carries a GENUINE signed planId (#1678) — a present,\n * non-empty string. This is the single v1/v2 discriminator: verification keys off\n * it to choose the matching EIP-712 type list, the handler keys off it to decide\n * whether the signed-vs-unsigned consistency guard fires. Keying off genuine\n * presence (not just `'planId' in authorization`) ensures a `planId: ''` / nullish\n * value can never be mistaken for a real signed claim.\n */\nexport const hasSignedPlanId = (\n authorization: X402Erc4337Payload['authorization'],\n): authorization is X402Erc4337Payload['authorization'] & { planId: string } => {\n return typeof authorization?.planId === 'string' && authorization.planId.trim() !== ''\n}\n\n/**\n * The signed-vs-unsigned planId consistency invariant (#1678), co-located with\n * `hasSignedPlanId` so signer, verifier, and the API handler share ONE\n * definition (no drift between where the planId is signed and where the guard\n * enforces it).\n *\n * For a v2 token (signed planId present) the tamperable unsigned `accepted.planId`\n * MUST exactly equal the signed `authorization.planId` — anything else is a\n * post-signing edit of the outer JSON. Returns `true` for v1 tokens (no signed\n * planId): there is no signed value to be consistent with, so the guard does not\n * apply (the caller handles the legacy fallback separately). The API handler maps\n * a `false` result to its forgery-gated rejection.\n */\nexport const isSignedPlanIdConsistent = (\n authorization: X402Erc4337Payload['authorization'],\n acceptedPlanId: string | null | undefined,\n): boolean => {\n if (!hasSignedPlanId(authorization)) return true\n return acceptedPlanId === authorization.planId\n}\n\n/**\n * Verify an x402 access token signature.\n *\n * EIP-712 hashes the type set, so a token signed over the v2 (with-planId)\n * struct cannot verify against the v1 type list and vice-versa. We therefore\n * detect which shape the token carries (genuine signed planId → v2) and verify\n * against the matching type list. This keeps genuinely-old v1 tokens valid\n * (#1678 backwards-compat) while v2 tokens are checked over the signed planId.\n *\n * Downgrade-safe: a v2 token was signed over the with-planId digest, so stripping\n * `authorization.planId` to force the v1 branch changes the digest and the\n * signature fails — an attacker cannot demote a signed token to dodge the planId.\n *\n * @param accessToken - The x402 access token to verify\n * @param publicClient - Viem public client\n * @returns true if signature is valid\n */\nexport const verifyAgentX402AccessToken = async (\n accessToken: AgentX402AccessToken,\n publicClient: PublicClient,\n): Promise<boolean> => {\n const erc4337Payload = accessToken.payload as X402Erc4337Payload\n // Extract subscriber address from payload.authorization.from\n const subscriberAddress = erc4337Payload.authorization.from\n\n const domain: NeverminedTypedDataDomain = {\n name: 'Nevermined',\n version: '1',\n chainId: publicClient.chain?.id as number,\n verifyingContract: subscriberAddress,\n }\n const { signature, authorization } = erc4337Payload\n const isValid = await publicClient.verifyTypedData({\n address: subscriberAddress,\n signature,\n // v2 (signed planId) verifies over the with-planId type list; legacy v1\n // tokens (no signed planId) verify over the original type list.\n types: hasSignedPlanId(authorization) ? NeverminedTypedDataTypes : NeverminedTypedDataTypesV1,\n domain,\n message: authorization,\n primaryType: 'Authorization',\n })\n return isValid\n}\n\n/**\n * Validation result for x402 token structure\n */\nexport type X402TokenValidationResult = {\n valid: boolean\n errors: string[]\n}\n\n/**\n * Validate the structure of an x402 access token\n *\n * @param token - The token to validate (unknown type for safety)\n * @returns Validation result with errors if any\n */\nconst SUPPORTED_SCHEMES: X402Scheme[] = ['nvm:erc4337', 'nvm:card-delegation']\n\nexport const validateX402TokenStructure = (token: unknown): X402TokenValidationResult => {\n const errors: string[] = []\n\n if (!token || typeof token !== 'object') {\n return { valid: false, errors: ['Token must be an object'] }\n }\n\n const t = token as Record<string, unknown>\n\n // Validate x402Version\n if (t.x402Version !== 2) {\n errors.push('x402Version must be 2')\n }\n\n // Validate accepted object\n if (!t.accepted || typeof t.accepted !== 'object') {\n errors.push('accepted is required')\n } else {\n const accepted = t.accepted as Record<string, unknown>\n const scheme = accepted.scheme as string\n\n if (!SUPPORTED_SCHEMES.includes(scheme as X402Scheme)) {\n errors.push(`scheme must be one of: ${SUPPORTED_SCHEMES.join(', ')}`)\n }\n\n if (!accepted.network || typeof accepted.network !== 'string') {\n errors.push('network is required in accepted')\n }\n\n // Validate extra\n if (!accepted.extra || typeof accepted.extra !== 'object') {\n errors.push('extra is required in accepted')\n } else {\n const extra = accepted.extra as Record<string, unknown>\n if (!extra.version || typeof extra.version !== 'string') {\n errors.push('version is required in accepted.extra')\n }\n }\n\n // Scheme-specific accepted validation\n if (scheme === 'nvm:erc4337') {\n if (!accepted.planId || typeof accepted.planId !== 'string') {\n errors.push('planId is required in accepted for nvm:erc4337')\n }\n }\n }\n\n // Validate payload\n if (!t.payload || typeof t.payload !== 'object') {\n errors.push('payload is required')\n } else {\n const accepted = t.accepted as Record<string, unknown> | undefined\n const scheme = accepted?.scheme as string | undefined\n const payload = t.payload as Record<string, unknown>\n\n if (scheme === 'nvm:erc4337') {\n if (!payload.signature || typeof payload.signature !== 'string') {\n errors.push('signature is required in payload')\n }\n\n if (!payload.authorization || typeof payload.authorization !== 'object') {\n errors.push('authorization is required in payload')\n } else {\n const auth = payload.authorization as Record<string, unknown>\n\n if (!auth.from || typeof auth.from !== 'string') {\n errors.push('from address is required in payload.authorization')\n } else if (!auth.from.startsWith('0x')) {\n errors.push('from must be a valid hex address')\n }\n\n if (!auth.sessionKeysProvider || typeof auth.sessionKeysProvider !== 'string') {\n errors.push('sessionKeysProvider is required in payload.authorization')\n }\n\n if (!Array.isArray(auth.sessionKeys)) {\n errors.push('sessionKeys array is required in payload.authorization')\n }\n }\n } else if (scheme === 'nvm:card-delegation') {\n if (!payload.token || typeof payload.token !== 'string') {\n errors.push('token is required in payload for nvm:card-delegation')\n }\n }\n }\n\n // Validate extensions (must be present, even if empty)\n if (t.extensions === undefined) {\n errors.push('extensions is required (can be empty object)')\n }\n\n return { valid: errors.length === 0, errors }\n}\n\nexport const b64EncodeX402AccessToken = (accessToken: AgentX402AccessToken): string => {\n return Buffer.from(JSON.stringify(accessToken)).toString('base64')\n}\n\nexport const b64DecodeX402AccessToken = (encoded: string): AgentX402AccessToken => {\n return JSON.parse(Buffer.from(encoded, 'base64').toString('utf-8'))\n}\n"],"names":["keccak256","toBytes","NeverminedTypedDataTypes","SessionKey","name","type","SessionKeys","Authorization","NeverminedTypedDataTypesV1","generateAgentX402AccessToken","options","subscriber","orderSessionKey","redeemSessionKey","publicClient","planId","schemeVersion","agentId","resource","httpVerb","validUntil","trim","Error","redeemSessionKeyHash","orderSessionKeyHash","message","from","address","sessionKeysProvider","sessionKeys","id","data","domain","version","chainId","chain","verifyingContract","eip712Data","types","primaryType","signature","signTypedData","network","x402Version","accepted","scheme","extra","payload","authorization","undefined","extensions","hasSignedPlanId","isSignedPlanIdConsistent","acceptedPlanId","verifyAgentX402AccessToken","accessToken","erc4337Payload","subscriberAddress","isValid","verifyTypedData","SUPPORTED_SCHEMES","validateX402TokenStructure","token","errors","valid","t","push","includes","join","auth","startsWith","Array","isArray","length","b64EncodeX402AccessToken","Buffer","JSON","stringify","toString","b64DecodeX402AccessToken","encoded","parse"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nevermined-io/core-kit",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
8
8
|
"scripts": {
|
|
9
|
-
"e2e": "NODE_OPTIONS='--loader ts-node/esm' mocha --config ./tests/integration/.mocharc.json",
|
|
10
9
|
"e2e:external": "nx e2e:external"
|
|
11
10
|
},
|
|
12
11
|
"exports": {
|
|
@@ -46,10 +45,14 @@
|
|
|
46
45
|
}
|
|
47
46
|
},
|
|
48
47
|
"e2e": {
|
|
49
|
-
"executor": "nx:
|
|
48
|
+
"executor": "@nx/jest:jest",
|
|
50
49
|
"options": {
|
|
51
|
-
"
|
|
52
|
-
"
|
|
50
|
+
"jestConfig": "packages/core-kit/jest.config.e2e.mjs",
|
|
51
|
+
"passWithNoTests": true,
|
|
52
|
+
"runInBand": true,
|
|
53
|
+
"testMatch": [
|
|
54
|
+
"**/*.e2e.spec.[jt]s?(x)"
|
|
55
|
+
]
|
|
53
56
|
},
|
|
54
57
|
"dependsOn": [
|
|
55
58
|
"^build",
|
|
@@ -62,10 +65,14 @@
|
|
|
62
65
|
]
|
|
63
66
|
},
|
|
64
67
|
"e2e:external": {
|
|
65
|
-
"executor": "nx:
|
|
68
|
+
"executor": "@nx/jest:jest",
|
|
66
69
|
"options": {
|
|
67
|
-
"
|
|
68
|
-
"
|
|
70
|
+
"jestConfig": "packages/core-kit/jest.config.e2e.mjs",
|
|
71
|
+
"passWithNoTests": true,
|
|
72
|
+
"runInBand": true,
|
|
73
|
+
"testMatch": [
|
|
74
|
+
"**/*.external.spec.[jt]s?(x)"
|
|
75
|
+
]
|
|
69
76
|
},
|
|
70
77
|
"dependsOn": [
|
|
71
78
|
"^build",
|