@introspectivelabs/x402-evm 0.1.0-beta.17 → 0.1.0-beta.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
- import { U as UserOperationSigner, P as PreparedUserOperation } from '../../userOpHash-Bzusu9T7.js';
2
- export { B as BundlerClient, f as BundlerClientConfig, j as ERC20_TRANSFER_ABI, b as ExactEvmSchemeEIP3009, c as ExactEvmSchemeEIP3009Config, E as ExactEvmSchemeERC4337, a as ExactEvmSchemeERC4337Config, G as GasEstimate, l as PackedUserOp, g as UserOperationCall, V as ViemBundlerClient, h as ViemBundlerClientConfig, i as buildERC20TransferCallData, k as computeUserOpHash, d as createP256SafeMessageSigner, e as createWebAuthnSafeMessageSigner, u as userOpToJson } from '../../userOpHash-Bzusu9T7.js';
1
+ import { U as UserOperationSigner, P as PreparedUserOperation } from '../../userOpHash-qINeS6ay.js';
2
+ export { B as BundlerClient, g as BundlerClientConfig, k as ERC20_TRANSFER_ABI, c as ExactEvmSchemeEIP3009, d as ExactEvmSchemeEIP3009Config, E as ExactEvmSchemeERC4337, a as ExactEvmSchemeERC4337Config, G as GasEstimate, m as PackedUserOp, b as PreparedPayment, h as UserOperationCall, V as ViemBundlerClient, i as ViemBundlerClientConfig, j as buildERC20TransferCallData, l as computeUserOpHash, e as createP256SafeMessageSigner, f as createWebAuthnSafeMessageSigner, u as userOpToJson } from '../../userOpHash-qINeS6ay.js';
3
3
  import { SmartAccount } from 'viem/account-abstraction';
4
4
  import 'viem';
5
- import '../../types-Dk5U6Xnw.js';
6
5
  import '../../types-lO5B0FRc.js';
7
6
  import '@x402/core/types';
7
+ import '../../types-Dk5U6Xnw.js';
8
8
 
9
9
  /**
10
10
  * Adapter to make a SmartAccount (e.g., Safe account) work as a UserOperationSigner.
@@ -53,15 +53,13 @@ var import_viem5 = require("viem");
53
53
  // src/exact/client/bundler/viem.ts
54
54
  var import_viem = require("viem");
55
55
  var import_account_abstraction = require("viem/account-abstraction");
56
+ function bigintToHex(n) {
57
+ return `0x${n.toString(16)}`;
58
+ }
56
59
  var ViemBundlerClient = class {
57
- /**
58
- * Creates a new ViemBundlerClient instance.
59
- *
60
- * @param config - Configuration for the bundler client
61
- */
62
60
  constructor(config) {
63
61
  this.account = config.account;
64
- this.entryPoint = "0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789";
62
+ this.usePaymaster = config.paymaster === true;
65
63
  this.bundlerClient = (0, import_account_abstraction.createBundlerClient)({
66
64
  client: config.publicClient,
67
65
  chain: config.chain,
@@ -70,13 +68,91 @@ var ViemBundlerClient = class {
70
68
  });
71
69
  }
72
70
  /**
73
- * Prepares an unsigned user operation for the given calls.
71
+ * Prepares an unsigned user operation using raw RPC calls.
74
72
  *
75
- * @param calls - Array of calls to execute in the user operation
76
- * @param _entryPoint - The entry point address (unused, viem uses the configured entry point)
77
- * @returns Promise resolving to a prepared (unsigned) user operation
73
+ * When paymaster is enabled, uses pm_sponsorUserOperation to get paymaster
74
+ * data and gas estimates in a single call (Pimlico-compatible).
75
+ * The returned UserOp has final paymaster data ready for hash computation and signing.
78
76
  */
79
- async prepareUserOperation(calls, _entryPoint) {
77
+ async prepareUserOperation(calls, entryPoint) {
78
+ if (!this.usePaymaster) {
79
+ return this.prepareWithoutPaymaster(calls);
80
+ }
81
+ const callData = await this.account.encodeCalls(
82
+ calls.map((call) => ({
83
+ to: call.to,
84
+ value: call.value,
85
+ data: call.data
86
+ }))
87
+ );
88
+ const nonce = await this.account.getNonce();
89
+ const sender = await this.account.getAddress();
90
+ const gasPriceResult = await this.bundlerClient.request({
91
+ method: "pimlico_getUserOperationGasPrice",
92
+ params: []
93
+ });
94
+ const maxFeePerGas = BigInt(gasPriceResult.fast.maxFeePerGas);
95
+ const maxPriorityFeePerGas = BigInt(gasPriceResult.fast.maxPriorityFeePerGas);
96
+ const stubSignature = await this.account.getStubSignature();
97
+ {
98
+ const userOpForEstimation = {
99
+ sender,
100
+ nonce: `0x${nonce.toString(16)}`,
101
+ callData,
102
+ signature: stubSignature,
103
+ callGasLimit: bigintToHex(500000n),
104
+ verificationGasLimit: bigintToHex(500000n),
105
+ preVerificationGas: bigintToHex(100000n),
106
+ maxFeePerGas: bigintToHex(maxFeePerGas),
107
+ maxPriorityFeePerGas: bigintToHex(maxPriorityFeePerGas)
108
+ };
109
+ const sponsorResult = await this.bundlerClient.request({
110
+ method: "pm_sponsorUserOperation",
111
+ params: [userOpForEstimation, entryPoint]
112
+ });
113
+ const callGasLimit = BigInt(sponsorResult.callGasLimit);
114
+ const verificationGasLimit = BigInt(sponsorResult.verificationGasLimit);
115
+ const preVerificationGas = BigInt(sponsorResult.preVerificationGas);
116
+ let paymaster;
117
+ let paymasterData;
118
+ let paymasterVerificationGasLimit;
119
+ let paymasterPostOpGasLimit;
120
+ if (sponsorResult.paymaster) {
121
+ paymaster = sponsorResult.paymaster;
122
+ paymasterData = sponsorResult.paymasterData ?? "0x";
123
+ paymasterVerificationGasLimit = BigInt(sponsorResult.paymasterVerificationGasLimit ?? "0x0");
124
+ paymasterPostOpGasLimit = BigInt(sponsorResult.paymasterPostOpGasLimit ?? "0x0");
125
+ } else if (sponsorResult.paymasterAndData && sponsorResult.paymasterAndData !== "0x") {
126
+ const packed = sponsorResult.paymasterAndData;
127
+ paymaster = `0x${packed.slice(2, 42)}`;
128
+ paymasterVerificationGasLimit = BigInt(`0x${packed.slice(42, 74)}`);
129
+ paymasterPostOpGasLimit = BigInt(`0x${packed.slice(74, 106)}`);
130
+ paymasterData = `0x${packed.slice(106)}`;
131
+ }
132
+ return {
133
+ sender,
134
+ nonce,
135
+ // Include factory/factoryData keys so that downstream signers (e.g. permissionless
136
+ // Safe signUserOperation) detect v0.7 format and correctly pack paymasterAndData
137
+ // from the separate v0.7 fields. Without these keys, permissionless defaults to
138
+ // paymasterAndData: "0x" causing SafeOp hash mismatch (AA24).
139
+ factory: void 0,
140
+ factoryData: void 0,
141
+ callData,
142
+ callGasLimit,
143
+ verificationGasLimit,
144
+ preVerificationGas,
145
+ maxFeePerGas,
146
+ maxPriorityFeePerGas,
147
+ ...paymaster ? { paymaster } : {},
148
+ ...paymasterData ? { paymasterData } : {},
149
+ ...paymasterVerificationGasLimit != null ? { paymasterVerificationGasLimit } : {},
150
+ ...paymasterPostOpGasLimit != null ? { paymasterPostOpGasLimit } : {},
151
+ signature: stubSignature
152
+ };
153
+ }
154
+ }
155
+ async prepareWithoutPaymaster(calls) {
80
156
  const prepared = await this.bundlerClient.prepareUserOperation({
81
157
  account: this.account,
82
158
  calls: calls.map((call) => ({
@@ -89,31 +165,20 @@ var ViemBundlerClient = class {
89
165
  return {
90
166
  sender: prepared.sender,
91
167
  nonce: prepared.nonce,
168
+ // Always include factory/factoryData keys for v0.7 format detection by signers
169
+ factory: p.factory ?? void 0,
170
+ factoryData: p.factoryData ?? void 0,
92
171
  callData: prepared.callData,
93
172
  callGasLimit: prepared.callGasLimit,
94
173
  verificationGasLimit: prepared.verificationGasLimit,
95
174
  preVerificationGas: prepared.preVerificationGas,
96
175
  maxFeePerGas: prepared.maxFeePerGas,
97
176
  maxPriorityFeePerGas: prepared.maxPriorityFeePerGas,
98
- // v0.7 factory fields (for account deployment)
99
- ...p.factory ? { factory: p.factory } : {},
100
- ...p.factoryData ? { factoryData: p.factoryData } : {},
101
- // v0.7 paymaster fields (separate, not paymasterAndData)
102
- ...p.paymaster ? { paymaster: p.paymaster } : {},
103
- ...p.paymasterData ? { paymasterData: p.paymasterData } : {},
104
- ...p.paymasterVerificationGasLimit != null ? { paymasterVerificationGasLimit: p.paymasterVerificationGasLimit } : {},
105
- ...p.paymasterPostOpGasLimit != null ? { paymasterPostOpGasLimit: p.paymasterPostOpGasLimit } : {},
106
177
  signature: prepared.signature
107
178
  };
108
179
  }
109
180
  /**
110
- * Estimates gas for a user operation.
111
- * Note: This is typically done as part of prepareUserOperation,
112
- * but is available as a separate method for flexibility.
113
- *
114
- * @param _userOp - The user operation to estimate gas for
115
- * @param _entryPoint - The entry point address
116
- * @returns Promise resolving to gas estimates
181
+ * @deprecated Gas estimation is done as part of prepareUserOperation
117
182
  */
118
183
  async estimateGas(_userOp, _entryPoint) {
119
184
  throw new Error(
@@ -121,26 +186,15 @@ var ViemBundlerClient = class {
121
186
  );
122
187
  }
123
188
  /**
124
- * Sends a user operation to the bundler.
189
+ * Sends a signed user operation to the bundler via raw eth_sendUserOperation RPC.
125
190
  *
126
- * @param userOp - The signed user operation to send
127
- * @param _entryPoint - The entry point address (unused, viem uses the configured entry point)
128
- * @returns Promise resolving to the user operation hash
191
+ * Bypasses viem's middleware to avoid re-calling paymaster RPCs which would
192
+ * change paymaster fields and invalidate the signature.
129
193
  */
130
- async sendUserOperation(userOp, _entryPoint) {
131
- const hash = await this.bundlerClient.sendUserOperation({
132
- account: this.account,
133
- sender: userOp.sender,
134
- nonce: BigInt(userOp.nonce),
135
- callData: userOp.callData,
136
- callGasLimit: BigInt(userOp.callGasLimit),
137
- verificationGasLimit: BigInt(userOp.verificationGasLimit),
138
- preVerificationGas: BigInt(userOp.preVerificationGas),
139
- maxFeePerGas: BigInt(userOp.maxFeePerGas),
140
- maxPriorityFeePerGas: BigInt(userOp.maxPriorityFeePerGas),
141
- // Combine paymaster and paymasterData into paymasterAndData
142
- paymasterAndData: userOp.paymaster && userOp.paymasterData ? userOp.paymaster + userOp.paymasterData.slice(2) : userOp.paymaster ? userOp.paymaster : "0x",
143
- signature: userOp.signature
194
+ async sendUserOperation(userOp, entryPoint) {
195
+ const hash = await this.bundlerClient.request({
196
+ method: "eth_sendUserOperation",
197
+ params: [userOp, entryPoint]
144
198
  });
145
199
  return hash;
146
200
  }
@@ -253,6 +307,7 @@ function userOpToJson(userOp) {
253
307
  const json = {};
254
308
  for (const [key, value] of Object.entries(userOp)) {
255
309
  if (key === "account") continue;
310
+ if (value === void 0) continue;
256
311
  if (typeof value === "bigint") {
257
312
  json[key] = toRpcHex(value);
258
313
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
@@ -443,7 +498,7 @@ function createDefaultPublicClient(network) {
443
498
  transport: (0, import_viem4.http)()
444
499
  });
445
500
  }
446
- var ExactEvmSchemeERC4337 = class {
501
+ var ExactEvmSchemeERC4337 = class _ExactEvmSchemeERC4337 {
447
502
  /**
448
503
  * Creates a new ExactEvmSchemeERC4337 instance.
449
504
  *
@@ -458,6 +513,7 @@ var ExactEvmSchemeERC4337 = class {
458
513
  this.publicClient = config.publicClient;
459
514
  this.entrypoint = config.entrypoint;
460
515
  this.bundlerUrl = config.bundlerUrl;
516
+ this.paymaster = config.paymaster;
461
517
  if (!this.bundlerClient && !this.account) {
462
518
  throw new Error(
463
519
  "Either bundlerClient or account must be provided. If bundlerClient is not provided, account (SmartAccount) is required for dynamic bundlerClient creation."
@@ -479,24 +535,14 @@ var ExactEvmSchemeERC4337 = class {
479
535
  }
480
536
  }
481
537
  /**
482
- * Creates a payment payload for the Exact scheme using ERC-4337 UserOperations.
483
- *
484
- * This method:
485
- * 1. Extracts user operation capability from payment requirements
486
- * 2. Creates bundlerClient dynamically if not provided (when userOperation.supported is true)
487
- * 3. Builds ERC20 transfer call data
488
- * 4. Prepares the user operation using the bundler client
489
- * 5. Signs the user operation
490
- * 6. Converts to JSON-RPC format
491
- * 7. Returns the x402 payment payload
492
- *
493
- * @param x402Version - The x402 protocol version
494
- * @param paymentRequirements - The payment requirements
495
- * @returns Promise resolving to a payment payload
496
- * @throws Error if user operation capability is not found or required fields are missing
538
+ * Prepares an unsigned payment payload (UserOp) without signing.
539
+ * Use with `completePaymentPayload()` to attach a signature from any surface.
497
540
  */
498
- async createPaymentPayload(x402Version, paymentRequirements) {
541
+ async preparePaymentPayload(x402Version, paymentRequirements) {
499
542
  const capability = extractUserOperationCapability(paymentRequirements);
543
+ const chain = resolveChain(paymentRequirements.network);
544
+ const configBundlerUrl = typeof this.bundlerUrl === "function" ? this.bundlerUrl(chain.id, paymentRequirements.network) : this.bundlerUrl;
545
+ const bundlerUrl = configBundlerUrl ?? capability?.bundlerUrl;
500
546
  let bundlerClient;
501
547
  if (this.bundlerClient) {
502
548
  bundlerClient = this.bundlerClient;
@@ -506,8 +552,7 @@ var ExactEvmSchemeERC4337 = class {
506
552
  "Account (SmartAccount) is required when bundlerClient is not provided. Either provide bundlerClient in config or account for dynamic creation."
507
553
  );
508
554
  }
509
- const bundlerUrl2 = this.bundlerUrl ?? capability?.bundlerUrl;
510
- if (!bundlerUrl2) {
555
+ if (!bundlerUrl) {
511
556
  throw new PaymentCreationError(
512
557
  "Bundler URL not provided",
513
558
  {
@@ -517,13 +562,14 @@ var ExactEvmSchemeERC4337 = class {
517
562
  }
518
563
  );
519
564
  }
520
- const chain = resolveChain(paymentRequirements.network);
521
565
  const publicClient = this.publicClient ?? createDefaultPublicClient(paymentRequirements.network);
566
+ const paymaster = this.paymaster ?? true;
522
567
  bundlerClient = new ViemBundlerClient({
523
568
  publicClient,
524
569
  account: this.account,
525
570
  chain,
526
- bundlerUrl: bundlerUrl2
571
+ bundlerUrl,
572
+ paymaster
527
573
  });
528
574
  }
529
575
  const entryPoint = this.entrypoint ?? capability?.entrypoint;
@@ -537,7 +583,6 @@ var ExactEvmSchemeERC4337 = class {
537
583
  }
538
584
  );
539
585
  }
540
- const bundlerUrl = this.bundlerUrl ?? capability?.bundlerUrl;
541
586
  if (!bundlerUrl) {
542
587
  throw new PaymentCreationError(
543
588
  "Bundler URL not provided",
@@ -563,7 +608,6 @@ var ExactEvmSchemeERC4337 = class {
563
608
  {
564
609
  to: token,
565
610
  value: BigInt(0),
566
- // ERC20 transfers don't send ETH
567
611
  data: callData
568
612
  }
569
613
  ],
@@ -582,9 +626,43 @@ var ExactEvmSchemeERC4337 = class {
582
626
  }
583
627
  );
584
628
  }
629
+ return {
630
+ unsignedUserOp,
631
+ bundlerClient,
632
+ entryPoint,
633
+ bundlerUrl,
634
+ x402Version,
635
+ network: paymentRequirements.network,
636
+ signer: this.signer
637
+ };
638
+ }
639
+ /**
640
+ * Assembles a signed payment payload from a prepared (unsigned) UserOp and a signature.
641
+ */
642
+ static completePaymentPayload(prepared, signature) {
643
+ const signedUserOp = { ...prepared.unsignedUserOp, signature };
644
+ const jsonUserOp = userOpToJson(signedUserOp);
645
+ const payload = {
646
+ type: "erc4337",
647
+ entryPoint: prepared.entryPoint,
648
+ bundlerRpcUrl: prepared.bundlerUrl,
649
+ userOperation: jsonUserOp
650
+ };
651
+ return {
652
+ x402Version: prepared.x402Version,
653
+ ...prepared.x402Version === 1 ? { scheme: "exact", network: prepared.network } : {},
654
+ payload
655
+ };
656
+ }
657
+ /**
658
+ * Creates a payment payload for the Exact scheme using ERC-4337 UserOperations.
659
+ * Convenience method that calls `preparePaymentPayload` + signs + `completePaymentPayload`.
660
+ */
661
+ async createPaymentPayload(x402Version, paymentRequirements) {
662
+ const prepared = await this.preparePaymentPayload(x402Version, paymentRequirements);
585
663
  let signature;
586
664
  try {
587
- signature = await this.signer.signUserOperation(unsignedUserOp);
665
+ signature = await this.signer.signUserOperation(prepared.unsignedUserOp);
588
666
  } catch (error) {
589
667
  const aaError = parseAAError(error);
590
668
  throw new PaymentCreationError(
@@ -598,23 +676,7 @@ var ExactEvmSchemeERC4337 = class {
598
676
  }
599
677
  );
600
678
  }
601
- const signedUserOp = {
602
- ...unsignedUserOp,
603
- signature
604
- };
605
- const jsonUserOp = userOpToJson(signedUserOp);
606
- const payload = {
607
- type: "erc4337",
608
- entryPoint,
609
- bundlerRpcUrl: bundlerUrl,
610
- userOperation: jsonUserOp
611
- };
612
- return {
613
- x402Version,
614
- // v1 requires scheme and network at top level
615
- ...x402Version === 1 ? { scheme: this.scheme, network: paymentRequirements.network } : {},
616
- payload
617
- };
679
+ return _ExactEvmSchemeERC4337.completePaymentPayload(prepared, signature);
618
680
  }
619
681
  };
620
682