@introspectivelabs/x402-evm 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +16 -0
  2. package/dist/cjs/exact/client/index.d.ts +48 -0
  3. package/dist/cjs/exact/client/index.js +403 -0
  4. package/dist/cjs/exact/client/index.js.map +1 -0
  5. package/dist/cjs/exact/facilitator/index.d.ts +224 -0
  6. package/dist/cjs/exact/facilitator/index.js +355 -0
  7. package/dist/cjs/exact/facilitator/index.js.map +1 -0
  8. package/dist/cjs/exact/server/index.d.ts +47 -0
  9. package/dist/cjs/exact/server/index.js +86 -0
  10. package/dist/cjs/exact/server/index.js.map +1 -0
  11. package/dist/cjs/index.d.ts +71 -0
  12. package/dist/cjs/index.js +860 -0
  13. package/dist/cjs/index.js.map +1 -0
  14. package/dist/cjs/types-Dk5U6Xnw.d.ts +33 -0
  15. package/dist/cjs/userOperation-Dh1zucfd.d.ts +409 -0
  16. package/dist/esm/chunk-56L4QUDN.mjs +359 -0
  17. package/dist/esm/chunk-56L4QUDN.mjs.map +1 -0
  18. package/dist/esm/chunk-5HWFMQYG.mjs +328 -0
  19. package/dist/esm/chunk-5HWFMQYG.mjs.map +1 -0
  20. package/dist/esm/chunk-E3XDJP7M.mjs +53 -0
  21. package/dist/esm/chunk-E3XDJP7M.mjs.map +1 -0
  22. package/dist/esm/chunk-GGPRPAM4.mjs +13 -0
  23. package/dist/esm/chunk-GGPRPAM4.mjs.map +1 -0
  24. package/dist/esm/exact/client/index.d.mts +48 -0
  25. package/dist/esm/exact/client/index.mjs +18 -0
  26. package/dist/esm/exact/client/index.mjs.map +1 -0
  27. package/dist/esm/exact/facilitator/index.d.mts +224 -0
  28. package/dist/esm/exact/facilitator/index.mjs +9 -0
  29. package/dist/esm/exact/facilitator/index.mjs.map +1 -0
  30. package/dist/esm/exact/server/index.d.mts +47 -0
  31. package/dist/esm/exact/server/index.mjs +8 -0
  32. package/dist/esm/exact/server/index.mjs.map +1 -0
  33. package/dist/esm/index.d.mts +71 -0
  34. package/dist/esm/index.mjs +110 -0
  35. package/dist/esm/index.mjs.map +1 -0
  36. package/dist/esm/types-Dk5U6Xnw.d.mts +33 -0
  37. package/dist/esm/userOperation-B2UUp3K6.d.mts +409 -0
  38. package/package.json +107 -0
@@ -0,0 +1,409 @@
1
+ import { PublicClient, Transport, Chain, Hex } from 'viem';
2
+ import { SmartAccount } from 'viem/account-abstraction';
3
+ import { U as UserOperation07Json } from './types-Dk5U6Xnw.mjs';
4
+ import { SchemeNetworkClient, PaymentRequirements, PaymentPayload } from '@x402/core/types';
5
+
6
+ /**
7
+ * Configuration for bundler client operations
8
+ */
9
+ interface BundlerClientConfig {
10
+ /**
11
+ * Timeout for operations in milliseconds
12
+ *
13
+ * @default 30000
14
+ */
15
+ timeout?: number;
16
+ /**
17
+ * Number of retries for failed operations
18
+ *
19
+ * @default 0
20
+ */
21
+ retries?: number;
22
+ }
23
+ /**
24
+ * Gas estimation result from bundler
25
+ */
26
+ interface GasEstimate {
27
+ [key: string]: unknown;
28
+ callGasLimit?: string;
29
+ verificationGasLimit?: string;
30
+ preVerificationGas?: string;
31
+ maxFeePerGas?: string;
32
+ maxPriorityFeePerGas?: string;
33
+ paymasterVerificationGasLimit?: string;
34
+ paymasterPostOpGasLimit?: string;
35
+ }
36
+ /**
37
+ * Prepared user operation (unsigned)
38
+ * This matches the format returned by viem's prepareUserOperation,
39
+ * which uses bigint for numeric values.
40
+ */
41
+ interface PreparedUserOperation {
42
+ [key: string]: unknown;
43
+ sender: `0x${string}`;
44
+ nonce: bigint;
45
+ callData: `0x${string}`;
46
+ callGasLimit: bigint;
47
+ verificationGasLimit: bigint;
48
+ preVerificationGas: bigint;
49
+ maxFeePerGas: bigint;
50
+ maxPriorityFeePerGas: bigint;
51
+ paymaster?: `0x${string}`;
52
+ paymasterData?: `0x${string}`;
53
+ paymasterVerificationGasLimit?: bigint;
54
+ paymasterPostOpGasLimit?: bigint;
55
+ signature?: `0x${string}`;
56
+ }
57
+ /**
58
+ * Call configuration for preparing user operations
59
+ */
60
+ interface UserOperationCall {
61
+ /**
62
+ * Target contract address
63
+ */
64
+ to: `0x${string}`;
65
+ /**
66
+ * Value to send (in wei, for native ETH transfers)
67
+ */
68
+ value: bigint;
69
+ /**
70
+ * Call data (encoded function call)
71
+ */
72
+ data: `0x${string}`;
73
+ }
74
+ /**
75
+ * Abstract interface for bundler client operations.
76
+ * This allows different implementations (viem, custom, etc.)
77
+ */
78
+ interface BundlerClient {
79
+ /**
80
+ * Prepares an unsigned user operation for the given calls.
81
+ * This method should estimate gas and populate all required fields.
82
+ *
83
+ * @param calls - Array of calls to execute in the user operation
84
+ * @param entryPoint - The entry point address
85
+ * @returns Promise resolving to a prepared (unsigned) user operation
86
+ */
87
+ prepareUserOperation(calls: UserOperationCall[], entryPoint: `0x${string}`): Promise<PreparedUserOperation>;
88
+ /**
89
+ * Estimates gas for a user operation.
90
+ *
91
+ * @param userOp - The user operation to estimate gas for
92
+ * @param entryPoint - The entry point address
93
+ * @returns Promise resolving to gas estimates
94
+ */
95
+ estimateGas(userOp: UserOperation07Json, entryPoint: `0x${string}`): Promise<GasEstimate>;
96
+ /**
97
+ * Sends a user operation to the bundler.
98
+ *
99
+ * @param userOp - The signed user operation to send
100
+ * @param entryPoint - The entry point address
101
+ * @returns Promise resolving to the user operation hash
102
+ */
103
+ sendUserOperation(userOp: UserOperation07Json, entryPoint: `0x${string}`): Promise<string>;
104
+ }
105
+
106
+ /**
107
+ * Configuration for creating a viem-based bundler client
108
+ */
109
+ interface ViemBundlerClientConfig extends BundlerClientConfig {
110
+ /**
111
+ * Viem public client for blockchain interactions
112
+ */
113
+ publicClient: PublicClient<Transport, Chain>;
114
+ /**
115
+ * Smart account for user operation preparation (must be a SmartAccount, not a regular Account)
116
+ */
117
+ account: SmartAccount;
118
+ /**
119
+ * Chain configuration
120
+ */
121
+ chain: Chain;
122
+ /**
123
+ * Bundler RPC URL
124
+ */
125
+ bundlerUrl: string;
126
+ }
127
+ /**
128
+ * Viem-based implementation of BundlerClient.
129
+ * Uses viem's account-abstraction utilities for user operation handling.
130
+ */
131
+ declare class ViemBundlerClient implements BundlerClient {
132
+ private readonly bundlerClient;
133
+ private readonly account;
134
+ private readonly entryPoint;
135
+ /**
136
+ * Creates a new ViemBundlerClient instance.
137
+ *
138
+ * @param config - Configuration for the bundler client
139
+ */
140
+ constructor(config: ViemBundlerClientConfig);
141
+ /**
142
+ * Prepares an unsigned user operation for the given calls.
143
+ *
144
+ * @param calls - Array of calls to execute in the user operation
145
+ * @param _entryPoint - The entry point address (unused, viem uses the configured entry point)
146
+ * @returns Promise resolving to a prepared (unsigned) user operation
147
+ */
148
+ prepareUserOperation(calls: UserOperationCall[], _entryPoint: `0x${string}`): Promise<PreparedUserOperation>;
149
+ /**
150
+ * Estimates gas for a user operation.
151
+ * Note: This is typically done as part of prepareUserOperation,
152
+ * but is available as a separate method for flexibility.
153
+ *
154
+ * @param _userOp - The user operation to estimate gas for
155
+ * @param _entryPoint - The entry point address
156
+ * @returns Promise resolving to gas estimates
157
+ */
158
+ estimateGas(_userOp: UserOperation07Json, _entryPoint: `0x${string}`): Promise<GasEstimate>;
159
+ /**
160
+ * Sends a user operation to the bundler.
161
+ *
162
+ * @param userOp - The signed user operation to send
163
+ * @param _entryPoint - The entry point address (unused, viem uses the configured entry point)
164
+ * @returns Promise resolving to the user operation hash
165
+ */
166
+ sendUserOperation(userOp: UserOperation07Json, _entryPoint: `0x${string}`): Promise<string>;
167
+ }
168
+
169
+ /**
170
+ * Abstract interface for signing user operations.
171
+ * This allows different signer implementations (Safe, EOA, etc.)
172
+ */
173
+ interface UserOperationSigner {
174
+ /**
175
+ * The address of the signer
176
+ */
177
+ readonly address: `0x${string}`;
178
+ /**
179
+ * Signs a prepared (unsigned) user operation.
180
+ *
181
+ * @param userOp - The prepared user operation to sign
182
+ * @returns Promise resolving to the signature
183
+ */
184
+ signUserOperation(userOp: PreparedUserOperation): Promise<`0x${string}`>;
185
+ }
186
+
187
+ /**
188
+ * Base configuration properties shared by all configuration variants
189
+ */
190
+ interface ExactEvmSchemeERC4337ConfigBase {
191
+ /**
192
+ * Entry point address (EntryPoint v0.7)
193
+ * Optional - can be provided in payment requirements if not set here
194
+ */
195
+ entrypoint?: Hex;
196
+ /**
197
+ * Bundler URL (optional, can be provided in payment requirements)
198
+ */
199
+ bundlerUrl?: string;
200
+ }
201
+ /**
202
+ * Configuration variant when bundlerClient is explicitly provided.
203
+ * Account and publicClient are NOT needed when bundlerClient is used.
204
+ * Signer is required when using bundlerClient.
205
+ */
206
+ type ExactEvmSchemeERC4337ConfigWithBundler = ExactEvmSchemeERC4337ConfigBase & {
207
+ /**
208
+ * Bundler client for preparing and sending user operations.
209
+ */
210
+ bundlerClient: BundlerClient;
211
+ /**
212
+ * Signer for signing user operations (required when bundlerClient is provided).
213
+ */
214
+ signer: UserOperationSigner;
215
+ } & {
216
+ /**
217
+ * Account must not be provided when bundlerClient is used.
218
+ * Using `never` type prevents this property from being set.
219
+ */
220
+ account?: never;
221
+ /**
222
+ * Public client must not be provided when bundlerClient is used.
223
+ * The bundlerClient already has its own publicClient configured.
224
+ */
225
+ publicClient?: never;
226
+ };
227
+ /**
228
+ * Configuration variant when bundlerClient is not provided.
229
+ * Account is required for dynamic bundlerClient creation.
230
+ * Signer is optional - will be auto-created from account if not provided.
231
+ * PublicClient is optional - will create a default from network if not provided.
232
+ */
233
+ type ExactEvmSchemeERC4337ConfigWithAccount = ExactEvmSchemeERC4337ConfigBase & {
234
+ /**
235
+ * Bundler client is not provided - will be created dynamically from PaymentRequirements.
236
+ * Using `never` type prevents this property from being set.
237
+ */
238
+ bundlerClient?: never;
239
+ } & {
240
+ /**
241
+ * Smart account for user operation preparation.
242
+ * Required when bundlerClient is not provided.
243
+ */
244
+ account: SmartAccount;
245
+ /**
246
+ * Signer for signing user operations.
247
+ * Optional - will be auto-created from account using SafeAccountSigner if not provided.
248
+ * The account must support signUserOperation method for auto-creation to work.
249
+ */
250
+ signer?: UserOperationSigner;
251
+ /**
252
+ * Public client for blockchain interactions.
253
+ * Optional - will create a default from network if not provided.
254
+ */
255
+ publicClient?: PublicClient<Transport, Chain>;
256
+ };
257
+ /**
258
+ * Configuration for the ERC-4337 client scheme.
259
+ *
260
+ * This is a discriminated union that enforces type-safe combinations:
261
+ * - Either `bundlerClient` is provided (account and publicClient must NOT be provided)
262
+ * - Or `account` is provided when bundlerClient is not (for dynamic creation, publicClient optional)
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * // Minimal config (just account - signer auto-created)
267
+ * const scheme1 = new ExactEvmSchemeERC4337({
268
+ * account: myAccount,
269
+ * // signer will be auto-created from account
270
+ * // bundlerClient will be created dynamically from PaymentRequirements
271
+ * });
272
+ *
273
+ * // With account and custom signer
274
+ * const scheme2 = new ExactEvmSchemeERC4337({
275
+ * account: myAccount,
276
+ * signer: myCustomSigner,
277
+ * publicClient: myPublicClient, // Optional
278
+ * });
279
+ *
280
+ * // With explicit bundlerClient (backward compatible)
281
+ * const scheme3 = new ExactEvmSchemeERC4337({
282
+ * bundlerClient: myBundlerClient,
283
+ * signer: mySigner, // Required when bundlerClient is provided
284
+ * // account and publicClient must NOT be provided (bundlerClient has its own)
285
+ * });
286
+ * ```
287
+ */
288
+ type ExactEvmSchemeERC4337Config = ExactEvmSchemeERC4337ConfigWithBundler | ExactEvmSchemeERC4337ConfigWithAccount;
289
+ /**
290
+ * EVM client implementation for the Exact payment scheme using ERC-4337 UserOperations.
291
+ *
292
+ * This implementation creates payment payloads by building and signing UserOperations
293
+ * that execute ERC20 transfers. The UserOperations are prepared using a bundler client
294
+ * and signed using a user operation signer (e.g., Safe account, EOA).
295
+ *
296
+ * Supports minimal configuration: when bundlerClient is not provided and
297
+ * PaymentRequirements.extra.userOperation.supported is true, a ViemBundlerClient
298
+ * will be created dynamically from the payment requirements.
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * // Minimal config (just account - signer and bundlerClient auto-created)
303
+ * import { ExactEvmSchemeERC4337 } from '@introspectivelabs/x402-evm/exact/client';
304
+ * import { x402Client } from '@x402/core/client';
305
+ *
306
+ * const scheme = new ExactEvmSchemeERC4337({
307
+ * account: safeAccount, // SmartAccount - signer will be auto-created
308
+ * });
309
+ *
310
+ * // With custom signer
311
+ * const scheme2 = new ExactEvmSchemeERC4337({
312
+ * account: safeAccount,
313
+ * signer: customSigner, // Optional - overrides auto-creation
314
+ * });
315
+ *
316
+ * // Explicit config (backward compatible)
317
+ * import { ViemBundlerClient } from '@introspectivelabs/x402-evm/exact/client/bundler';
318
+ *
319
+ * const bundlerClient = new ViemBundlerClient({
320
+ * publicClient,
321
+ * account,
322
+ * chain,
323
+ * bundlerUrl: 'https://bundler.example.com',
324
+ * });
325
+ *
326
+ * const scheme3 = new ExactEvmSchemeERC4337({
327
+ * bundlerClient,
328
+ * signer: account, // Required when bundlerClient is provided
329
+ * });
330
+ *
331
+ * const client = new x402Client();
332
+ * client.register('eip155:84532', scheme);
333
+ * ```
334
+ */
335
+ declare class ExactEvmSchemeERC4337 implements SchemeNetworkClient {
336
+ readonly scheme = "exact";
337
+ private readonly bundlerClient?;
338
+ private readonly account?;
339
+ private readonly publicClient?;
340
+ private readonly signer;
341
+ private readonly entrypoint?;
342
+ private readonly bundlerUrl?;
343
+ /**
344
+ * Creates a new ExactEvmSchemeERC4337 instance.
345
+ *
346
+ * @param config - Configuration for the scheme (type-safe: either bundlerClient or account must be provided)
347
+ * @throws Error if bundlerClient is not provided and account is also not provided (runtime safety check)
348
+ * @throws Error if signer is not provided and account doesn't support signUserOperation
349
+ */
350
+ constructor(config: ExactEvmSchemeERC4337Config);
351
+ /**
352
+ * Creates a payment payload for the Exact scheme using ERC-4337 UserOperations.
353
+ *
354
+ * This method:
355
+ * 1. Extracts user operation capability from payment requirements
356
+ * 2. Creates bundlerClient dynamically if not provided (when userOperation.supported is true)
357
+ * 3. Builds ERC20 transfer call data
358
+ * 4. Prepares the user operation using the bundler client
359
+ * 5. Signs the user operation
360
+ * 6. Converts to JSON-RPC format
361
+ * 7. Returns the x402 payment payload
362
+ *
363
+ * @param x402Version - The x402 protocol version
364
+ * @param paymentRequirements - The payment requirements
365
+ * @returns Promise resolving to a payment payload
366
+ * @throws Error if user operation capability is not found or required fields are missing
367
+ */
368
+ createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "x402Version" | "payload">>;
369
+ }
370
+
371
+ /**
372
+ * Standard ERC20 transfer function ABI
373
+ */
374
+ declare const ERC20_TRANSFER_ABI: readonly [{
375
+ readonly type: "function";
376
+ readonly name: "transfer";
377
+ readonly stateMutability: "nonpayable";
378
+ readonly inputs: readonly [{
379
+ readonly name: "to";
380
+ readonly type: "address";
381
+ }, {
382
+ readonly name: "amount";
383
+ readonly type: "uint256";
384
+ }];
385
+ readonly outputs: readonly [{
386
+ readonly name: "success";
387
+ readonly type: "bool";
388
+ }];
389
+ }];
390
+ /**
391
+ * Builds ERC20 transfer call data.
392
+ *
393
+ * @param token - The ERC20 token contract address
394
+ * @param to - The recipient address
395
+ * @param amount - The amount to transfer (in token's smallest unit)
396
+ * @returns The encoded call data for the transfer function
397
+ */
398
+ declare function buildERC20TransferCallData(token: `0x${string}`, to: `0x${string}`, amount: bigint): `0x${string}`;
399
+
400
+ /**
401
+ * Converts a user operation with bigint values to JSON-RPC compatible format.
402
+ * This recursively converts all bigint values to hex strings.
403
+ *
404
+ * @param userOp - The user operation object (may contain bigints)
405
+ * @returns The user operation in JSON-RPC format (all bigints converted to hex)
406
+ */
407
+ declare function userOpToJson(userOp: Record<string, unknown>): UserOperation07Json;
408
+
409
+ export { type BundlerClient as B, ExactEvmSchemeERC4337 as E, type GasEstimate as G, type PreparedUserOperation as P, type UserOperationSigner as U, ViemBundlerClient as V, type ExactEvmSchemeERC4337Config as a, type BundlerClientConfig as b, type UserOperationCall as c, type ViemBundlerClientConfig as d, buildERC20TransferCallData as e, ERC20_TRANSFER_ABI as f, userOpToJson as u };
package/package.json ADDED
@@ -0,0 +1,107 @@
1
+ {
2
+ "name": "@introspectivelabs/x402-evm",
3
+ "version": "0.0.1",
4
+ "main": "./dist/cjs/index.js",
5
+ "module": "./dist/esm/index.js",
6
+ "types": "./dist/cjs/index.d.ts",
7
+ "keywords": [
8
+ "x402",
9
+ "payment",
10
+ "protocol",
11
+ "evm",
12
+ "ethereum"
13
+ ],
14
+ "license": "Apache-2.0",
15
+ "author": "Introspective Labs",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/Introspective-Labs/x402-modules.git",
19
+ "directory": "packages/evm"
20
+ },
21
+ "description": "x402 Payment Protocol for Smart Wallets EVM Implementation",
22
+ "publishConfig": {
23
+ "access": "public",
24
+ "registry": "https://registry.npmjs.org"
25
+ },
26
+ "devDependencies": {
27
+ "@eslint/js": "^9.24.0",
28
+ "@types/node": "^22.13.4",
29
+ "@typescript-eslint/eslint-plugin": "^8.29.1",
30
+ "@typescript-eslint/parser": "^8.29.1",
31
+ "eslint": "^9.24.0",
32
+ "eslint-plugin-import": "^2.31.0",
33
+ "eslint-plugin-jsdoc": "^50.6.9",
34
+ "eslint-plugin-prettier": "^5.2.6",
35
+ "prettier": "3.5.2",
36
+ "tsup": "^8.4.0",
37
+ "tsx": "^4.19.2",
38
+ "typescript": "^5.7.3",
39
+ "vite": "^6.2.6",
40
+ "vite-tsconfig-paths": "^5.1.4",
41
+ "vitest": "^3.0.5"
42
+ },
43
+ "peerDependencies": {
44
+ "@x402/core": "2.*",
45
+ "@x402/evm": "2.*",
46
+ "viem": "2.*",
47
+ "zod": "3.*"
48
+ },
49
+ "exports": {
50
+ ".": {
51
+ "import": {
52
+ "types": "./dist/esm/index.d.mts",
53
+ "default": "./dist/esm/index.mjs"
54
+ },
55
+ "require": {
56
+ "types": "./dist/cjs/index.d.ts",
57
+ "default": "./dist/cjs/index.js"
58
+ }
59
+ },
60
+ "./exact/client": {
61
+ "import": {
62
+ "types": "./dist/esm/exact/client/index.d.mts",
63
+ "default": "./dist/esm/exact/client/index.mjs"
64
+ },
65
+ "require": {
66
+ "types": "./dist/cjs/exact/client/index.d.ts",
67
+ "default": "./dist/cjs/exact/client/index.js"
68
+ }
69
+ },
70
+ "./exact/server": {
71
+ "import": {
72
+ "types": "./dist/esm/exact/server/index.d.mts",
73
+ "default": "./dist/esm/exact/server/index.mjs"
74
+ },
75
+ "require": {
76
+ "types": "./dist/cjs/exact/server/index.d.ts",
77
+ "default": "./dist/cjs/exact/server/index.js"
78
+ }
79
+ },
80
+ "./exact/facilitator": {
81
+ "import": {
82
+ "types": "./dist/esm/exact/facilitator/index.d.mts",
83
+ "default": "./dist/esm/exact/facilitator/index.mjs"
84
+ },
85
+ "require": {
86
+ "types": "./dist/cjs/exact/facilitator/index.d.ts",
87
+ "default": "./dist/cjs/exact/facilitator/index.js"
88
+ }
89
+ }
90
+ },
91
+ "files": [
92
+ "dist"
93
+ ],
94
+ "scripts": {
95
+ "start": "tsx --env-file=.env index.ts",
96
+ "build": "tsup",
97
+ "test": "vitest run",
98
+ "test:integration": "vitest run --config vitest.integration.config.ts",
99
+ "test:watch": "vitest",
100
+ "watch": "tsc --watch",
101
+ "format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
102
+ "format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"",
103
+ "lint": "eslint . --ext .ts --fix",
104
+ "lint:check": "eslint . --ext .ts",
105
+ "publish:dev": "pnpm dlx yalc publish --push"
106
+ }
107
+ }