@aastar/sdk 0.18.0 → 0.20.2

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 (103) hide show
  1. package/LICENSE +180 -21
  2. package/dist/UserClient-YUHCJJJL.js +6 -0
  3. package/dist/UserClient-YUHCJJJL.js.map +1 -0
  4. package/dist/account.d.ts +1 -0
  5. package/dist/account.js +6 -0
  6. package/dist/account.js.map +1 -0
  7. package/dist/admin.d.ts +1 -0
  8. package/dist/admin.js +6 -0
  9. package/dist/admin.js.map +1 -0
  10. package/dist/airaccount.d.ts +2 -0
  11. package/dist/airaccount.js +4501 -0
  12. package/dist/airaccount.js.map +1 -0
  13. package/dist/channel.d.ts +1 -0
  14. package/dist/channel.js +6 -0
  15. package/dist/channel.js.map +1 -0
  16. package/dist/chunk-4DVUM4MC.js +106 -0
  17. package/dist/chunk-4DVUM4MC.js.map +1 -0
  18. package/dist/chunk-4KRQXOTI.js +4421 -0
  19. package/dist/chunk-4KRQXOTI.js.map +1 -0
  20. package/dist/chunk-DI3E6PMI.js +426 -0
  21. package/dist/chunk-DI3E6PMI.js.map +1 -0
  22. package/dist/chunk-DSZ372PH.js +333 -0
  23. package/dist/chunk-DSZ372PH.js.map +1 -0
  24. package/dist/chunk-HVAB4TTT.js +116 -0
  25. package/dist/chunk-HVAB4TTT.js.map +1 -0
  26. package/dist/chunk-MPOMWT2J.js +1140 -0
  27. package/dist/chunk-MPOMWT2J.js.map +1 -0
  28. package/dist/chunk-NZGXB2C5.js +115 -0
  29. package/dist/chunk-NZGXB2C5.js.map +1 -0
  30. package/dist/chunk-O3Y7II3B.js +578 -0
  31. package/dist/chunk-O3Y7II3B.js.map +1 -0
  32. package/dist/chunk-OSPRJZ5T.js +113 -0
  33. package/dist/chunk-OSPRJZ5T.js.map +1 -0
  34. package/dist/chunk-PCLPYRTX.js +229 -0
  35. package/dist/chunk-PCLPYRTX.js.map +1 -0
  36. package/dist/chunk-PZ5AY32C.js +9 -0
  37. package/dist/chunk-PZ5AY32C.js.map +1 -0
  38. package/dist/chunk-XFI3AK32.js +416 -0
  39. package/dist/chunk-XFI3AK32.js.map +1 -0
  40. package/dist/chunk-YHM77LIP.js +432 -0
  41. package/dist/chunk-YHM77LIP.js.map +1 -0
  42. package/dist/chunk-ZSSNU3UF.js +42091 -0
  43. package/dist/chunk-ZSSNU3UF.js.map +1 -0
  44. package/dist/contract-addresses-JE3X6DFY.js +4 -0
  45. package/dist/contract-addresses-JE3X6DFY.js.map +1 -0
  46. package/dist/core.d.ts +13 -0
  47. package/dist/core.js +5 -0
  48. package/dist/core.js.map +1 -0
  49. package/dist/dapp.d.ts +1 -0
  50. package/dist/dapp.js +283 -0
  51. package/dist/dapp.js.map +1 -0
  52. package/dist/dist-GHTBO7CD.js +6 -0
  53. package/dist/dist-GHTBO7CD.js.map +1 -0
  54. package/dist/enduser.d.ts +1 -0
  55. package/dist/enduser.js +7 -0
  56. package/dist/enduser.js.map +1 -0
  57. package/dist/identity.d.ts +1 -0
  58. package/dist/identity.js +6 -0
  59. package/dist/identity.js.map +1 -0
  60. package/dist/index.d.ts +601 -13
  61. package/dist/index.js +1639 -28
  62. package/dist/index.js.map +1 -0
  63. package/dist/index.node-55LOPHNQ.js +5 -0
  64. package/dist/index.node-55LOPHNQ.js.map +1 -0
  65. package/dist/lib-VRTYVDUO.js +1861 -0
  66. package/dist/lib-VRTYVDUO.js.map +1 -0
  67. package/dist/operator.d.ts +1 -0
  68. package/dist/operator.js +6 -0
  69. package/dist/operator.js.map +1 -0
  70. package/dist/paymaster.d.ts +1 -0
  71. package/dist/paymaster.js +6 -0
  72. package/dist/paymaster.js.map +1 -0
  73. package/dist/tokens.d.ts +1 -0
  74. package/dist/tokens.js +6 -0
  75. package/dist/tokens.js.map +1 -0
  76. package/dist/x402.d.ts +1 -0
  77. package/dist/x402.js +6 -0
  78. package/dist/x402.js.map +1 -0
  79. package/package.json +87 -18
  80. package/dist/clients/ExperimentClient.d.ts +0 -34
  81. package/dist/clients/ExperimentClient.js +0 -58
  82. package/dist/clients/admin.d.ts +0 -11
  83. package/dist/clients/admin.js +0 -20
  84. package/dist/clients/community.d.ts +0 -40
  85. package/dist/clients/community.js +0 -300
  86. package/dist/clients/endUser.d.ts +0 -77
  87. package/dist/clients/endUser.js +0 -298
  88. package/dist/clients/operator.d.ts +0 -66
  89. package/dist/clients/operator.js +0 -209
  90. package/dist/errors/decoder.d.ts +0 -6
  91. package/dist/errors/decoder.js +0 -44
  92. package/dist/utils/errorHandler.d.ts +0 -40
  93. package/dist/utils/errorHandler.js +0 -114
  94. package/dist/utils/funding.d.ts +0 -115
  95. package/dist/utils/funding.js +0 -188
  96. package/dist/utils/keys.d.ts +0 -61
  97. package/dist/utils/keys.js +0 -130
  98. package/dist/utils/roleData.d.ts +0 -66
  99. package/dist/utils/roleData.js +0 -128
  100. package/dist/utils/testScenarios.d.ts +0 -33
  101. package/dist/utils/testScenarios.js +0 -85
  102. package/dist/utils/userOp.d.ts +0 -89
  103. package/dist/utils/userOp.js +0 -231
@@ -0,0 +1,1140 @@
1
+ import { SuperPaymasterABI } from './chunk-ZSSNU3UF.js';
2
+ import { concat, pad, toHex, keccak256, encodeAbiParameters, toBytes, parseAbiParameters, parseAbi, encodeFunctionData } from 'viem';
3
+
4
+ var DEFAULT_VERIFICATION_GAS = 160000n;
5
+ var DEFAULT_POSTOP_GAS = 10000n;
6
+ function getSuperPaymasterMiddleware(config) {
7
+ return {
8
+ sponsorUserOperation: async (args) => {
9
+ const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS;
10
+ const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS;
11
+ const maxRate = config.maxRate ?? 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffn;
12
+ const paymasterAndData = concat([
13
+ config.paymasterAddress,
14
+ pad(toHex(verGas), { size: 16 }),
15
+ pad(toHex(postGas), { size: 16 }),
16
+ config.operator,
17
+ pad(toHex(maxRate), { size: 32 })
18
+ ]);
19
+ return {
20
+ paymasterAndData,
21
+ verificationGasLimit: verGas,
22
+ preVerificationGas: args.userOperation.preVerificationGas
23
+ };
24
+ }
25
+ };
26
+ }
27
+ async function checkEligibility(client, paymaster, user, operator) {
28
+ try {
29
+ const operatorData = await client.readContract({
30
+ address: paymaster,
31
+ abi: SuperPaymasterABI,
32
+ functionName: "operators",
33
+ args: [operator]
34
+ });
35
+ const token = operatorData[0];
36
+ const isConfigured = operatorData[2];
37
+ const isPaused = operatorData[3];
38
+ if (!isConfigured || isPaused) {
39
+ return { eligible: false };
40
+ }
41
+ const credit = await client.readContract({
42
+ address: paymaster,
43
+ abi: SuperPaymasterABI,
44
+ functionName: "getAvailableCredit",
45
+ args: [user, token]
46
+ });
47
+ return {
48
+ eligible: credit > 0n,
49
+ credit,
50
+ token
51
+ };
52
+ } catch (e) {
53
+ console.warn("Eligibility check failed:", e);
54
+ return { eligible: false };
55
+ }
56
+ }
57
+ var SuperPaymasterAdminClient = class {
58
+ client;
59
+ paymasterAddress;
60
+ constructor(client, paymasterAddress) {
61
+ this.client = client;
62
+ this.paymasterAddress = paymasterAddress;
63
+ }
64
+ async getOperator(operator) {
65
+ return this.client.readContract({
66
+ address: this.paymasterAddress,
67
+ abi: SuperPaymasterABI,
68
+ functionName: "operators",
69
+ args: [operator]
70
+ });
71
+ }
72
+ static async configureOperator(wallet, paymaster, token, treasury) {
73
+ return wallet.writeContract({
74
+ address: paymaster,
75
+ abi: SuperPaymasterABI,
76
+ functionName: "configureOperator",
77
+ args: [token, treasury],
78
+ chain: wallet.chain
79
+ });
80
+ }
81
+ static async setOperatorPaused(wallet, paymaster, operator, paused) {
82
+ return wallet.writeContract({
83
+ address: paymaster,
84
+ abi: SuperPaymasterABI,
85
+ functionName: "setOperatorPaused",
86
+ args: [operator, paused],
87
+ chain: wallet.chain
88
+ });
89
+ }
90
+ static async updateReputation(wallet, paymaster, operator, score) {
91
+ return wallet.writeContract({
92
+ address: paymaster,
93
+ abi: SuperPaymasterABI,
94
+ functionName: "updateReputation",
95
+ args: [operator, score],
96
+ chain: wallet.chain
97
+ });
98
+ }
99
+ static async setAPNTsToken(wallet, paymaster, token) {
100
+ return wallet.writeContract({
101
+ address: paymaster,
102
+ abi: SuperPaymasterABI,
103
+ functionName: "setAPNTsToken",
104
+ args: [token],
105
+ chain: wallet.chain
106
+ });
107
+ }
108
+ static async setXPNTsFactory(wallet, paymaster, factory) {
109
+ return wallet.writeContract({
110
+ address: paymaster,
111
+ abi: SuperPaymasterABI,
112
+ functionName: "setXPNTsFactory",
113
+ args: [factory],
114
+ chain: wallet.chain
115
+ });
116
+ }
117
+ };
118
+ var DEFAULT_VERIFICATION_GAS_V4 = 1500000n;
119
+ var DEFAULT_POSTOP_GAS_V4 = 300000n;
120
+ function getPaymasterV4Middleware(config) {
121
+ return {
122
+ sponsorUserOperation: async (args) => {
123
+ const verGas = config.verificationGasLimit ?? DEFAULT_VERIFICATION_GAS_V4;
124
+ const postGas = config.postOpGasLimit ?? DEFAULT_POSTOP_GAS_V4;
125
+ const paymasterAndData = concat([
126
+ config.paymasterAddress,
127
+ pad(toHex(verGas), { size: 16 }),
128
+ pad(toHex(postGas), { size: 16 }),
129
+ config.gasToken
130
+ ]);
131
+ return {
132
+ paymasterAndData,
133
+ verificationGasLimit: verGas,
134
+ preVerificationGas: args.userOperation.preVerificationGas
135
+ };
136
+ }
137
+ };
138
+ }
139
+ function buildPaymasterData(paymasterAddress, token, options) {
140
+ const validityWindow = options?.validityWindow ?? 3600;
141
+ const verGas = options?.verificationGasLimit ?? 200000n;
142
+ const postGas = options?.postOpGasLimit ?? 100000n;
143
+ const now = Math.floor(Date.now() / 1e3);
144
+ const validUntil = now + validityWindow;
145
+ const validAfter = now - 100;
146
+ return concat([
147
+ paymasterAddress,
148
+ pad(toHex(verGas), { size: 16 }),
149
+ pad(toHex(postGas), { size: 16 }),
150
+ token,
151
+ pad(toHex(validUntil), { size: 6 }),
152
+ pad(toHex(validAfter), { size: 6 })
153
+ ]);
154
+ }
155
+ function buildSuperPaymasterData(paymasterAddress, operator, options) {
156
+ const verGas = options?.verificationGasLimit ?? 80000n;
157
+ const postGas = options?.postOpGasLimit ?? 100000n;
158
+ const maxRate = options?.maxRate ?? (1n << 256n) - 1n;
159
+ return concat([
160
+ paymasterAddress,
161
+ pad(toHex(verGas), { size: 16 }),
162
+ pad(toHex(postGas), { size: 16 }),
163
+ operator,
164
+ pad(toHex(maxRate), { size: 32 })
165
+ // Optional rate commitment (rug pull protection)
166
+ ]);
167
+ }
168
+ function formatUserOpV07(userOp) {
169
+ const result = {
170
+ sender: userOp.sender,
171
+ nonce: toHex(userOp.nonce),
172
+ callData: userOp.callData,
173
+ preVerificationGas: toHex(userOp.preVerificationGas),
174
+ signature: userOp.signature
175
+ };
176
+ if (userOp.initCode && userOp.initCode !== "0x" && userOp.initCode.length > 2) {
177
+ result.initCode = userOp.initCode;
178
+ if (userOp.initCode.length > 42) {
179
+ result.factory = userOp.initCode.slice(0, 42);
180
+ result.factoryData = "0x" + userOp.initCode.slice(42);
181
+ } else {
182
+ result.factory = "0x0000000000000000000000000000000000000000";
183
+ result.factoryData = "0x";
184
+ }
185
+ }
186
+ if (userOp.accountGasLimits && userOp.accountGasLimits !== "0x") {
187
+ const packed = userOp.accountGasLimits.replace("0x", "").padStart(64, "0");
188
+ result.verificationGasLimit = "0x" + BigInt("0x" + packed.slice(0, 32)).toString(16);
189
+ result.callGasLimit = "0x" + BigInt("0x" + packed.slice(32, 64)).toString(16);
190
+ }
191
+ if (userOp.gasFees && userOp.gasFees !== "0x") {
192
+ const packed = userOp.gasFees.replace("0x", "").padStart(64, "0");
193
+ result.maxPriorityFeePerGas = "0x" + BigInt("0x" + packed.slice(0, 32)).toString(16);
194
+ result.maxFeePerGas = "0x" + BigInt("0x" + packed.slice(32, 64)).toString(16);
195
+ }
196
+ if (userOp.paymasterAndData && userOp.paymasterAndData !== "0x") {
197
+ const packed = userOp.paymasterAndData.replace("0x", "");
198
+ if (packed.length >= 104) {
199
+ result.paymaster = "0x" + packed.slice(0, 40);
200
+ result.paymasterVerificationGasLimit = "0x" + BigInt("0x" + packed.slice(40, 72)).toString(16);
201
+ result.paymasterPostOpGasLimit = "0x" + BigInt("0x" + packed.slice(72, 104)).toString(16);
202
+ result.paymasterData = "0x" + packed.slice(104);
203
+ }
204
+ }
205
+ return result;
206
+ }
207
+ function getUserOpHashV07(userOp, entryPoint, chainId) {
208
+ const hashedUserOp = keccak256(encodeAbiParameters(["address", "uint256", "bytes32", "bytes32", "bytes32", "uint256", "bytes32", "bytes32"].map((t) => ({ type: t })), [
209
+ userOp.sender,
210
+ userOp.nonce,
211
+ keccak256(toBytes(userOp.initCode)),
212
+ keccak256(toBytes(userOp.callData)),
213
+ userOp.accountGasLimits,
214
+ toHex(userOp.preVerificationGas),
215
+ userOp.gasFees,
216
+ keccak256(toBytes(userOp.paymasterAndData))
217
+ ]));
218
+ return keccak256(encodeAbiParameters(["bytes32", "address", "uint256"].map((t) => ({ type: t })), [hashedUserOp, entryPoint, chainId]));
219
+ }
220
+ function tuneGasLimit(estimate, nominalActual, targetEfficiency = 0.45) {
221
+ if (estimate === 0n)
222
+ return 0n;
223
+ const ceiling = nominalActual * 100n / BigInt(Math.floor(targetEfficiency * 100));
224
+ return estimate < ceiling ? estimate : ceiling;
225
+ }
226
+
227
+ // ../paymaster/dist/V4/BundlerCompat.js
228
+ var BundlerType;
229
+ (function(BundlerType2) {
230
+ BundlerType2["ALCHEMY"] = "alchemy";
231
+ BundlerType2["PIMLICO"] = "pimlico";
232
+ BundlerType2["STACKUP"] = "stackup";
233
+ BundlerType2["CANDIDE"] = "candide";
234
+ BundlerType2["UNKNOWN"] = "unknown";
235
+ })(BundlerType || (BundlerType = {}));
236
+ function detectBundlerType(bundlerUrl) {
237
+ const url = bundlerUrl.toLowerCase();
238
+ if (url.includes("alchemy.com"))
239
+ return BundlerType.ALCHEMY;
240
+ if (url.includes("pimlico.io"))
241
+ return BundlerType.PIMLICO;
242
+ if (url.includes("stackup"))
243
+ return BundlerType.STACKUP;
244
+ if (url.includes("candide.dev"))
245
+ return BundlerType.CANDIDE;
246
+ return BundlerType.UNKNOWN;
247
+ }
248
+
249
+ // ../paymaster/dist/V4/PaymasterClient.js
250
+ var PaymasterClient = class _PaymasterClient {
251
+ /**
252
+ * @private
253
+ * Static utility class, should not be instantiated.
254
+ */
255
+ constructor() {
256
+ }
257
+ static makePlaceholderSignature(byteLength) {
258
+ const clamped = Math.max(0, Math.min(byteLength, 1e4));
259
+ return `0x${"11".repeat(clamped)}`;
260
+ }
261
+ static estimatePreVerificationGasV07(userOp) {
262
+ const encoded = encodeAbiParameters(parseAbiParameters("(address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)"), [
263
+ [
264
+ userOp.sender,
265
+ userOp.nonce,
266
+ userOp.initCode,
267
+ userOp.callData,
268
+ userOp.accountGasLimits,
269
+ userOp.preVerificationGas,
270
+ userOp.gasFees,
271
+ userOp.paymasterAndData,
272
+ userOp.signature
273
+ ]
274
+ ]);
275
+ const bytes = toBytes(encoded);
276
+ let calldataCost = 0n;
277
+ for (const b of bytes)
278
+ calldataCost += b === 0 ? 4n : 16n;
279
+ return calldataCost + 26000n;
280
+ }
281
+ /**
282
+ * Get user's deposited balance on the Paymaster.
283
+ */
284
+ static async getDepositedBalance(publicClient, address, user, token) {
285
+ return publicClient.readContract({
286
+ address,
287
+ abi: [{
288
+ name: "balances",
289
+ type: "function",
290
+ inputs: [
291
+ { name: "user", type: "address" },
292
+ { name: "token", type: "address" }
293
+ ],
294
+ outputs: [{ name: "", type: "uint256" }],
295
+ stateMutability: "view"
296
+ }],
297
+ functionName: "balances",
298
+ args: [user, token]
299
+ });
300
+ }
301
+ /**
302
+ * Deposit tokens to Paymaster for a user (enables gasless transactions).
303
+ */
304
+ static async depositFor(wallet, address, user, token, amount) {
305
+ return wallet.writeContract({
306
+ address,
307
+ abi: parseAbi(["function depositFor(address user, address token, uint256 amount) external"]),
308
+ functionName: "depositFor",
309
+ args: [user, token, amount],
310
+ chain: wallet.chain
311
+ });
312
+ }
313
+ /**
314
+ * Approve the Paymaster (or any spender) to spend gas tokens.
315
+ */
316
+ static async approveGasToken(wallet, token, spender, amount) {
317
+ return wallet.writeContract({
318
+ address: token,
319
+ abi: parseAbi(["function approve(address spender, uint256 amount) external returns (bool)"]),
320
+ functionName: "approve",
321
+ args: [spender, amount],
322
+ chain: wallet.chain
323
+ });
324
+ }
325
+ /**
326
+ * Estimate Gas for a UserOperation.
327
+ */
328
+ static async estimateUserOperationGas(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, options) {
329
+ if (!options?.operator) {
330
+ try {
331
+ const cache = await client.readContract({
332
+ address: paymasterAddress,
333
+ abi: parseAbi(["function cachedPrice() view returns (uint208 price, uint48 updatedAt)"]),
334
+ functionName: "cachedPrice"
335
+ });
336
+ const cachedPrice = BigInt(cache?.price ?? cache?.[0] ?? 0);
337
+ const cachedUpdatedAt = BigInt(cache?.updatedAt ?? cache?.[1] ?? 0);
338
+ const now = BigInt(Math.floor(Date.now() / 1e3));
339
+ let stalenessThreshold = 0n;
340
+ try {
341
+ stalenessThreshold = await client.readContract({
342
+ address: paymasterAddress,
343
+ abi: parseAbi(["function priceStalenessThreshold() view returns (uint256)"]),
344
+ functionName: "priceStalenessThreshold"
345
+ });
346
+ } catch {
347
+ }
348
+ const isStale = cachedPrice === 0n || cachedUpdatedAt === 0n || stalenessThreshold > 0n && cachedUpdatedAt + stalenessThreshold < now;
349
+ if (isStale) {
350
+ const chainId2 = client.chain?.id || await client.getChainId();
351
+ const isTestnet2 = [11155111, 11155420, 31337].includes(chainId2);
352
+ if (isTestnet2) {
353
+ const updateHash = await wallet.writeContract({
354
+ address: paymasterAddress,
355
+ abi: parseAbi(["function updatePrice() external"]),
356
+ functionName: "updatePrice"
357
+ });
358
+ await client.waitForTransactionReceipt({ hash: updateHash });
359
+ console.log("[PaymasterClient] \u2705 cachedPrice refreshed via updatePrice()");
360
+ } else {
361
+ throw new Error(`Paymaster cachedPrice is stale on Mainnet (chainId: ${chainId2}). This requires Keeper to call updatePrice(). Please ensure Keeper is running.`);
362
+ }
363
+ }
364
+ } catch (e) {
365
+ if (e.message?.includes("requires Keeper"))
366
+ throw e;
367
+ console.log("[PaymasterClient] \u26A0\uFE0F Failed to check cachedPrice:", e.message?.slice(0, 50));
368
+ }
369
+ }
370
+ let paymasterAndData;
371
+ if (options?.operator) {
372
+ paymasterAndData = buildSuperPaymasterData(paymasterAddress, options.operator, {
373
+ verificationGasLimit: 300000n,
374
+ postOpGasLimit: 300000n
375
+ });
376
+ } else {
377
+ paymasterAndData = buildPaymasterData(paymasterAddress, token, {
378
+ validityWindow: options?.validityWindow,
379
+ verificationGasLimit: 250000n,
380
+ postOpGasLimit: 150000n
381
+ });
382
+ }
383
+ const chainId = client.chain?.id || await client.getChainId();
384
+ const isTestnet = [11155111, 11155420, 31337].includes(chainId);
385
+ const TESTNET_PRIORITY_FLOOR = 500000000n;
386
+ let maxFeePerGas = 0n;
387
+ let maxPriorityFeePerGas = 0n;
388
+ try {
389
+ const feeData = await client.estimateFeesPerGas();
390
+ maxFeePerGas = (feeData.maxFeePerGas ?? 0n) * 115n / 100n;
391
+ maxPriorityFeePerGas = (feeData.maxPriorityFeePerGas ?? 0n) * 115n / 100n;
392
+ } catch {
393
+ }
394
+ if (!maxFeePerGas) {
395
+ try {
396
+ const gasPrice = await client.getGasPrice();
397
+ maxFeePerGas = gasPrice * 120n / 100n;
398
+ } catch {
399
+ }
400
+ }
401
+ if (isTestnet) {
402
+ if (maxPriorityFeePerGas < TESTNET_PRIORITY_FLOOR)
403
+ maxPriorityFeePerGas = TESTNET_PRIORITY_FLOOR;
404
+ if (maxFeePerGas < TESTNET_PRIORITY_FLOOR * 2n)
405
+ maxFeePerGas = TESTNET_PRIORITY_FLOOR * 2n;
406
+ }
407
+ if (!maxFeePerGas)
408
+ maxFeePerGas = 1n;
409
+ if (maxFeePerGas < maxPriorityFeePerGas)
410
+ maxFeePerGas = maxPriorityFeePerGas + 1n;
411
+ const partialUserOp = {
412
+ sender: aaAddress,
413
+ nonce: 0n,
414
+ initCode: options?.factory && options?.factoryData ? concat([options.factory, options.factoryData]) : "0x",
415
+ callData,
416
+ accountGasLimits: concat([pad(toHex(250000n), { size: 16 }), pad(toHex(500000n), { size: 16 })]),
417
+ preVerificationGas: 0n,
418
+ gasFees: concat([pad(toHex(maxPriorityFeePerGas), { size: 16 }), pad(toHex(maxFeePerGas), { size: 16 })]),
419
+ paymasterAndData,
420
+ signature: _PaymasterClient.makePlaceholderSignature(65)
421
+ };
422
+ try {
423
+ const nonce = await client.readContract({
424
+ address: aaAddress,
425
+ abi: parseAbi(["function getNonce() view returns (uint256)"]),
426
+ functionName: "getNonce"
427
+ });
428
+ partialUserOp.nonce = BigInt(nonce);
429
+ } catch (e) {
430
+ }
431
+ partialUserOp.preVerificationGas = _PaymasterClient.estimatePreVerificationGasV07(partialUserOp) * 120n / 100n + 5000n;
432
+ const userOpHash = getUserOpHashV07(partialUserOp, entryPoint, BigInt(client.chain.id));
433
+ partialUserOp.signature = await wallet.account.signMessage({ message: { raw: userOpHash } });
434
+ const payload = {
435
+ jsonrpc: "2.0",
436
+ id: 1,
437
+ method: "eth_estimateUserOperationGas",
438
+ params: [formatUserOpV07(partialUserOp), entryPoint]
439
+ };
440
+ const response = await fetch(bundlerUrl, {
441
+ method: "POST",
442
+ headers: { "Content-Type": "application/json" },
443
+ body: JSON.stringify(payload, (_, v) => typeof v === "bigint" ? "0x" + v.toString(16) : v)
444
+ });
445
+ const result = await response.json();
446
+ if (bundlerUrl.includes("candide")) {
447
+ console.log("[PaymasterClient] Candide Request:", JSON.stringify(payload.params[0], null, 2));
448
+ console.log("[PaymasterClient] Candide Response:", JSON.stringify(result, null, 2));
449
+ }
450
+ const data = result.result;
451
+ console.log("[PaymasterClient] Gas Estimation Result:", JSON.stringify(data, null, 2));
452
+ if (result.error && (result.error.code === -32601 || result.error.message?.includes("Method not found"))) {
453
+ console.log("[PaymasterClient] EstimateUserOp failed (Method not found). Using Anvil defaults.");
454
+ return {
455
+ preVerificationGas: partialUserOp.preVerificationGas,
456
+ verificationGasLimit: 1000000n,
457
+ callGasLimit: 2000000n,
458
+ paymasterVerificationGasLimit: 100000n,
459
+ paymasterPostOpGasLimit: 100000n
460
+ };
461
+ }
462
+ if (result.error)
463
+ throw new Error(`Estimation Error: ${JSON.stringify(result.error)}`);
464
+ const estVGL = BigInt(data.verificationGasLimit);
465
+ const estPMVGL = data.paymasterVerificationGasLimit ? BigInt(data.paymasterVerificationGasLimit) : 100000n;
466
+ return {
467
+ preVerificationGas: BigInt(data.preVerificationGas) * 120n / 100n + 5000n,
468
+ verificationGasLimit: tuneGasLimit(estVGL, 35000n, 0.45),
469
+ callGasLimit: BigInt(data.callGasLimit) * 110n / 100n,
470
+ // Small 1.1x buffer
471
+ paymasterVerificationGasLimit: tuneGasLimit(estPMVGL, 35000n, 0.45),
472
+ paymasterPostOpGasLimit: data.paymasterPostOpGasLimit ? BigInt(data.paymasterPostOpGasLimit) : 100000n
473
+ };
474
+ }
475
+ /**
476
+ * High-level API to submit a gasless UserOperation.
477
+ * Automatically handles nonce fetching, gas estimation (if not provided), signing, and submission.
478
+ */
479
+ static async submitGaslessUserOperation(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, options) {
480
+ let gasLimits = {
481
+ preVerificationGas: options?.preVerificationGas,
482
+ verificationGasLimit: options?.verificationGasLimit,
483
+ callGasLimit: options?.callGasLimit,
484
+ paymasterVerificationGasLimit: options?.paymasterVerificationGasLimit,
485
+ paymasterPostOpGasLimit: options?.paymasterPostOpGasLimit ?? 200000n
486
+ };
487
+ if (options?.autoEstimate !== false && (!gasLimits.verificationGasLimit || !gasLimits.callGasLimit)) {
488
+ const est = await this.estimateUserOperationGas(client, wallet, aaAddress, entryPoint, paymasterAddress, token, bundlerUrl, callData, {
489
+ validityWindow: options?.validityWindow,
490
+ operator: options?.operator,
491
+ factory: options?.factory,
492
+ factoryData: options?.factoryData
493
+ });
494
+ gasLimits.preVerificationGas = options?.preVerificationGas ?? est.preVerificationGas;
495
+ gasLimits.verificationGasLimit = options?.verificationGasLimit ?? est.verificationGasLimit;
496
+ gasLimits.callGasLimit = options?.callGasLimit ?? est.callGasLimit;
497
+ gasLimits.paymasterVerificationGasLimit = options?.paymasterVerificationGasLimit ?? est.paymasterVerificationGasLimit;
498
+ if (!options?.paymasterPostOpGasLimit) {
499
+ const _base = est.paymasterPostOpGasLimit + 100000n;
500
+ gasLimits.paymasterPostOpGasLimit = _base > 200000n ? _base : 200000n;
501
+ }
502
+ }
503
+ const nonce = await client.readContract({
504
+ address: aaAddress,
505
+ abi: parseAbi(["function getNonce() view returns (uint256)"]),
506
+ functionName: "getNonce"
507
+ });
508
+ const chainId = client.chain?.id || await client.getChainId();
509
+ const isTestnet = [11155111, 11155420, 31337].includes(chainId);
510
+ const TESTNET_PRIORITY_FLOOR = 500000000n;
511
+ let maxFeePerGas = options?.maxFeePerGas;
512
+ let maxPriorityFeePerGas = options?.maxPriorityFeePerGas;
513
+ if (!maxFeePerGas || !maxPriorityFeePerGas) {
514
+ try {
515
+ const feeData = await client.estimateFeesPerGas();
516
+ maxFeePerGas = maxFeePerGas ?? (feeData.maxFeePerGas ?? 0n) * 115n / 100n;
517
+ maxPriorityFeePerGas = maxPriorityFeePerGas ?? (feeData.maxPriorityFeePerGas ?? 0n) * 115n / 100n;
518
+ } catch (e) {
519
+ maxFeePerGas = maxFeePerGas ?? void 0;
520
+ maxPriorityFeePerGas = maxPriorityFeePerGas ?? void 0;
521
+ }
522
+ }
523
+ if (!maxFeePerGas) {
524
+ try {
525
+ maxFeePerGas = await client.getGasPrice() * 150n / 100n;
526
+ } catch {
527
+ }
528
+ }
529
+ if (isTestnet) {
530
+ maxPriorityFeePerGas = maxPriorityFeePerGas ?? TESTNET_PRIORITY_FLOOR;
531
+ if (maxPriorityFeePerGas < TESTNET_PRIORITY_FLOOR)
532
+ maxPriorityFeePerGas = TESTNET_PRIORITY_FLOOR;
533
+ if (!maxFeePerGas || maxFeePerGas < TESTNET_PRIORITY_FLOOR * 2n)
534
+ maxFeePerGas = TESTNET_PRIORITY_FLOOR * 2n;
535
+ }
536
+ maxFeePerGas = maxFeePerGas ?? 1n;
537
+ maxPriorityFeePerGas = maxPriorityFeePerGas ?? 0n;
538
+ if (maxFeePerGas < maxPriorityFeePerGas)
539
+ maxFeePerGas = maxPriorityFeePerGas + 1n;
540
+ console.log(`[PaymasterClient] Gas Pricing: ${isTestnet ? "TESTNET (0.5 Gwei floor)" : "MAINNET (dynamic)"} | priority=${maxPriorityFeePerGas} maxFee=${maxFeePerGas}`);
541
+ let paymasterAndData;
542
+ if (options?.operator) {
543
+ paymasterAndData = buildSuperPaymasterData(paymasterAddress, options.operator, {
544
+ verificationGasLimit: gasLimits.paymasterVerificationGasLimit ?? gasLimits.verificationGasLimit ?? 150000n,
545
+ postOpGasLimit: gasLimits.paymasterPostOpGasLimit ?? 100000n
546
+ });
547
+ } else {
548
+ const pmVerGas = gasLimits.paymasterVerificationGasLimit ?? 75000n;
549
+ paymasterAndData = buildPaymasterData(paymasterAddress, token, {
550
+ validityWindow: options?.validityWindow,
551
+ verificationGasLimit: pmVerGas,
552
+ postOpGasLimit: gasLimits.paymasterPostOpGasLimit ?? 100000n
553
+ });
554
+ }
555
+ const initCode = options?.factory && options?.factoryData ? concat([options.factory, options.factoryData]) : "0x";
556
+ const accountGasLimits = concat([
557
+ pad(toHex(gasLimits.verificationGasLimit ?? 75000n), { size: 16 }),
558
+ pad(toHex(gasLimits.callGasLimit ?? 500000n), { size: 16 })
559
+ ]);
560
+ const gasFees = concat([
561
+ pad(toHex(maxPriorityFeePerGas), { size: 16 }),
562
+ pad(toHex(maxFeePerGas), { size: 16 })
563
+ ]);
564
+ const preVerificationGas = gasLimits.preVerificationGas ?? _PaymasterClient.estimatePreVerificationGasV07({
565
+ sender: aaAddress,
566
+ nonce: BigInt(nonce),
567
+ initCode,
568
+ callData,
569
+ accountGasLimits,
570
+ preVerificationGas: 0n,
571
+ gasFees,
572
+ paymasterAndData,
573
+ signature: _PaymasterClient.makePlaceholderSignature(65)
574
+ }) * 120n / 100n + 5000n;
575
+ const userOp = {
576
+ sender: aaAddress,
577
+ nonce: BigInt(nonce),
578
+ initCode,
579
+ callData,
580
+ accountGasLimits,
581
+ preVerificationGas,
582
+ gasFees,
583
+ paymasterAndData,
584
+ signature: "0x"
585
+ };
586
+ const userOpHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
587
+ const signature = await wallet.account.signMessage({ message: { raw: userOpHash } });
588
+ userOp.signature = signature;
589
+ const bundlerType = detectBundlerType(bundlerUrl);
590
+ console.log(`[PaymasterClient] Using ${bundlerType} Bundler`);
591
+ for (let attempt = 0; attempt < 5; attempt++) {
592
+ const response = await fetch(bundlerUrl, {
593
+ method: "POST",
594
+ headers: { "Content-Type": "application/json" },
595
+ body: JSON.stringify({
596
+ jsonrpc: "2.0",
597
+ id: 1,
598
+ method: "eth_sendUserOperation",
599
+ params: [formatUserOpV07(userOp), entryPoint]
600
+ }, (_, v) => typeof v === "bigint" ? "0x" + v.toString(16) : v)
601
+ });
602
+ const result = await response.json();
603
+ if (result.error && attempt < 4) {
604
+ const msg = result.error.message || "";
605
+ const errData = result.error.data || {};
606
+ if (result.error.code === -32602 || msg.includes("replacement underpriced")) {
607
+ console.log(`[PaymasterClient] \u26A0\uFE0F Replacement Underpriced. Bumping fees to replace pending UserOp...`);
608
+ let newMaxPriority = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(2, 34)) : 0n;
609
+ let newMaxFee = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(34)) : 0n;
610
+ if (errData.currentMaxPriorityFee && errData.currentMaxFee) {
611
+ const currentPriority = BigInt(errData.currentMaxPriorityFee);
612
+ const currentMax = BigInt(errData.currentMaxFee);
613
+ newMaxPriority = currentPriority * 110n / 100n;
614
+ newMaxFee = currentMax * 110n / 100n;
615
+ } else {
616
+ newMaxPriority = newMaxPriority * 115n / 100n;
617
+ newMaxFee = newMaxFee * 115n / 100n;
618
+ }
619
+ console.log(` -> New Priority: ${newMaxPriority}, New MaxFee: ${newMaxFee}`);
620
+ userOp.gasFees = concat([
621
+ pad(toHex(newMaxPriority), { size: 16 }),
622
+ pad(toHex(newMaxFee), { size: 16 })
623
+ ]);
624
+ const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
625
+ userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
626
+ continue;
627
+ }
628
+ const matchPriority = msg.match(/maxPriorityFeePerGas.*(?:at least|expected) (\d+)/i) || msg.match(/priority fee.*(?:at least|expected) (\d+)/i);
629
+ const matchMaxFee = msg.match(/maxFeePerGas.*(?:at least|expected) (\d+)/i);
630
+ if (matchPriority || matchMaxFee) {
631
+ console.log(`[PaymasterClient] \u26A0\uFE0F Fee Error: ${msg}. Retrying with higher fees...`);
632
+ let newMaxPriority = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(2, 34)) : 0n;
633
+ let newMaxFee = userOp.gasFees ? BigInt("0x" + userOp.gasFees.slice(34)) : 0n;
634
+ if (matchPriority && matchPriority[1]) {
635
+ const required = BigInt(matchPriority[1]);
636
+ if (required > newMaxPriority) {
637
+ console.log(` -> Bumping Priority Fee to ${required}`);
638
+ const delta = required - newMaxPriority;
639
+ newMaxPriority = required;
640
+ newMaxFee += delta;
641
+ }
642
+ }
643
+ if (matchMaxFee && matchMaxFee[1]) {
644
+ const required = BigInt(matchMaxFee[1]);
645
+ if (required > newMaxFee) {
646
+ console.log(` -> Bumping Max Fee to ${required}`);
647
+ newMaxFee = required;
648
+ }
649
+ }
650
+ if (newMaxFee < newMaxPriority)
651
+ newMaxFee = newMaxPriority + 1n;
652
+ userOp.gasFees = concat([
653
+ pad(toHex(newMaxPriority), { size: 16 }),
654
+ pad(toHex(newMaxFee), { size: 16 })
655
+ ]);
656
+ const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
657
+ userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
658
+ continue;
659
+ }
660
+ const matchPVG = msg.match(/preVerificationGas.*(?:at least|expected) (\d+)/i);
661
+ if (matchPVG && matchPVG[1]) {
662
+ const requiredPVG = BigInt(matchPVG[1]);
663
+ const currentPVG = BigInt(userOp.preVerificationGas);
664
+ if (requiredPVG > currentPVG) {
665
+ console.log(`[PaymasterClient] \u26A0\uFE0F PVG Error: ${msg}. Updating preVerificationGas...`);
666
+ const bufferedPVG = requiredPVG * 105n / 100n;
667
+ console.log(` -> Updating PVG from ${currentPVG} to ${bufferedPVG} (inc. buffer)`);
668
+ userOp.preVerificationGas = bufferedPVG;
669
+ const newHash = getUserOpHashV07(userOp, entryPoint, BigInt(client.chain.id));
670
+ userOp.signature = await wallet.account.signMessage({ message: { raw: newHash } });
671
+ continue;
672
+ }
673
+ }
674
+ }
675
+ if (result.error && (result.error.code === -32601 || result.error.message?.includes("Method not found"))) {
676
+ console.log("[PaymasterClient] SendUserOp failed (Method not found). Falling back to direct handleOps...");
677
+ const caller = wallet.account?.address ? wallet.account.address : wallet.account;
678
+ return await wallet.writeContract({
679
+ address: entryPoint,
680
+ abi: parseAbi(["function handleOps((address,uint256,bytes,bytes,bytes32,uint256,bytes32,bytes,bytes)[], address) external"]),
681
+ functionName: "handleOps",
682
+ args: [[userOp], caller],
683
+ chain: wallet.chain,
684
+ account: wallet.account
685
+ });
686
+ }
687
+ if (result.error)
688
+ throw new Error(`Bundler Error: ${JSON.stringify(result.error)}`);
689
+ console.log("[PaymasterClient] \u2705 Submitted via", bundlerType, "hash:", result.result);
690
+ return result.result;
691
+ }
692
+ throw new Error("Failed to submit UserOp after retries");
693
+ }
694
+ /**
695
+ * Helper to extract the actual Gas Token fee from a UserOperation receipt.
696
+ * Looks for the 'PostOpProcessed' event emitted by the Paymaster.
697
+ */
698
+ static getFeeFromReceipt(receipt, paymasterAddress) {
699
+ const TOPIC_POST_OP = "0x62544d7f48b11c32334310ebd306b47224fca220163218d4a7264322c52ae073";
700
+ for (const log of receipt.logs) {
701
+ if (log.address.toLowerCase() === paymasterAddress.toLowerCase() && log.topics[0] === TOPIC_POST_OP) {
702
+ const data = log.data.replace("0x", "");
703
+ if (data.length >= 192) {
704
+ const actualGasCostWei = BigInt("0x" + data.slice(0, 64));
705
+ const tokenCost = BigInt("0x" + data.slice(64, 128));
706
+ return { tokenCost, actualGasCostWei };
707
+ }
708
+ }
709
+ }
710
+ return null;
711
+ }
712
+ /**
713
+ * Get the fee for a specific transaction hash.
714
+ * Fetches the receipt (no scanning required) and decodes the log.
715
+ */
716
+ static async getTransactionFee(publicClient, txHash, paymasterAddress) {
717
+ const receipt = await publicClient.getTransactionReceipt({ hash: txHash });
718
+ return this.getFeeFromReceipt(receipt, paymasterAddress);
719
+ }
720
+ // ===========================================
721
+ // 🛠️ Semantic CallData Builders (For DX)
722
+ // ===========================================
723
+ /**
724
+ * Helper: Encode a standardized ERC-20 Transfer.
725
+ * Returns the raw function data: `transfer(to, amount)`
726
+ */
727
+ static encodeTokenTransfer(recipient, amount) {
728
+ return encodeFunctionData({
729
+ abi: parseAbi(["function transfer(address to, uint256 amount) external returns (bool)"]),
730
+ functionName: "transfer",
731
+ args: [recipient, amount]
732
+ });
733
+ }
734
+ /**
735
+ * Helper: Encode a SimpleAccount execution.
736
+ * Wraps the inner call into: `execute(target, value, data)`
737
+ * This is the payload signed by the user.
738
+ */
739
+ static encodeExecution(target, value, data) {
740
+ return encodeFunctionData({
741
+ abi: parseAbi(["function execute(address dest, uint256 value, bytes func) external"]),
742
+ functionName: "execute",
743
+ args: [target, value, data]
744
+ });
745
+ }
746
+ /**
747
+ * More robust version of waitForUserOperationReceipt.
748
+ * Catches timeouts and returns a cleaner result.
749
+ */
750
+ static async waitForUserOperation(bundlerClient, hash, timeout = 18e4) {
751
+ try {
752
+ return await bundlerClient.waitForUserOperationReceipt({ hash, timeout });
753
+ } catch (error) {
754
+ const errName = error.name || "";
755
+ const errMsg = error.message || "";
756
+ if (errName === "TimeoutError" || errName === "WaitForUserOperationReceiptTimeoutError" || /timed? out/i.test(errMsg)) {
757
+ return { timeout: true, hash };
758
+ }
759
+ throw error;
760
+ }
761
+ }
762
+ };
763
+ var PaymasterOperator = class {
764
+ /**
765
+ * Update the cached ETH/USD price from Chainlink Oracle.
766
+ * Must be called if cachedPrice is 0 (uninitialized).
767
+ */
768
+ static async updatePrice(wallet, address) {
769
+ return wallet.writeContract({
770
+ address,
771
+ abi: parseAbi(["function updatePrice() external"]),
772
+ functionName: "updatePrice",
773
+ chain: wallet.chain
774
+ });
775
+ }
776
+ /**
777
+ * Set the token price (in 8 decimals, e.g., 1e8 = $1 USD).
778
+ */
779
+ static async setTokenPrice(wallet, address, token, priceUSD) {
780
+ return wallet.writeContract({
781
+ address,
782
+ abi: parseAbi(["function setTokenPrice(address token, uint256 price) external"]),
783
+ functionName: "setTokenPrice",
784
+ args: [token, priceUSD],
785
+ chain: wallet.chain
786
+ });
787
+ }
788
+ static async getCachedPrice(publicClient, address) {
789
+ const result = await publicClient.readContract({
790
+ address,
791
+ abi: [{
792
+ name: "cachedPrice",
793
+ type: "function",
794
+ inputs: [],
795
+ outputs: [
796
+ { name: "price", type: "uint208" },
797
+ { name: "updatedAt", type: "uint48" }
798
+ ],
799
+ stateMutability: "view"
800
+ }],
801
+ functionName: "cachedPrice"
802
+ });
803
+ return { price: result[0], updatedAt: result[1] };
804
+ }
805
+ static async getTokenPrice(publicClient, address, token) {
806
+ return publicClient.readContract({
807
+ address,
808
+ abi: [{
809
+ name: "tokenPrices",
810
+ type: "function",
811
+ inputs: [{ name: "token", type: "address" }],
812
+ outputs: [{ name: "", type: "uint256" }],
813
+ stateMutability: "view"
814
+ }],
815
+ functionName: "tokenPrices",
816
+ args: [token]
817
+ });
818
+ }
819
+ static async getDepositedBalance(publicClient, address, user, token) {
820
+ return publicClient.readContract({
821
+ address,
822
+ abi: [{
823
+ name: "balances",
824
+ type: "function",
825
+ inputs: [
826
+ { name: "user", type: "address" },
827
+ { name: "token", type: "address" }
828
+ ],
829
+ outputs: [{ name: "", type: "uint256" }],
830
+ stateMutability: "view"
831
+ }],
832
+ functionName: "balances",
833
+ args: [user, token]
834
+ });
835
+ }
836
+ static async ensurePriceInitialized(wallet, publicClient, address) {
837
+ const { price } = await this.getCachedPrice(publicClient, address);
838
+ if (price === 0n) {
839
+ await this.updatePrice(wallet, address);
840
+ return true;
841
+ }
842
+ return false;
843
+ }
844
+ static async addStake(wallet, address, amount, unstakeDelaySec) {
845
+ return wallet.writeContract({
846
+ address,
847
+ abi: parseAbi(["function addStake(uint32 unstakeDelaySec) external payable"]),
848
+ functionName: "addStake",
849
+ args: [unstakeDelaySec],
850
+ value: amount,
851
+ chain: wallet.chain
852
+ });
853
+ }
854
+ static async addDeposit(wallet, address, amount) {
855
+ return wallet.writeContract({
856
+ address,
857
+ abi: parseAbi(["function addDeposit() external payable"]),
858
+ functionName: "addDeposit",
859
+ value: amount,
860
+ chain: wallet.chain
861
+ });
862
+ }
863
+ static async addGasToken(wallet, address, token) {
864
+ return wallet.writeContract({
865
+ address,
866
+ abi: ["function addGasToken(address token)"],
867
+ functionName: "addGasToken",
868
+ args: [token],
869
+ chain: wallet.chain
870
+ });
871
+ }
872
+ static async removeGasToken(wallet, address, token) {
873
+ return wallet.writeContract({
874
+ address,
875
+ abi: ["function removeGasToken(address token)"],
876
+ functionName: "removeGasToken",
877
+ args: [token],
878
+ chain: wallet.chain
879
+ });
880
+ }
881
+ static async setServiceFeeRate(wallet, address, rate) {
882
+ return wallet.writeContract({
883
+ address,
884
+ abi: ["function setServiceFeeRate(uint256 rate)"],
885
+ functionName: "setServiceFeeRate",
886
+ args: [rate],
887
+ chain: wallet.chain
888
+ });
889
+ }
890
+ static async setMaxGasCostCap(wallet, address, cap) {
891
+ return wallet.writeContract({
892
+ address,
893
+ abi: ["function setMaxGasCostCap(uint256 cap)"],
894
+ functionName: "setMaxGasCostCap",
895
+ args: [cap],
896
+ chain: wallet.chain
897
+ });
898
+ }
899
+ static async withdrawPNT(wallet, address, to, token, amount) {
900
+ return wallet.writeContract({
901
+ address,
902
+ abi: ["function withdrawPNT(address to, address token, uint256 amount)"],
903
+ functionName: "withdrawPNT",
904
+ args: [to, token, amount],
905
+ chain: wallet.chain
906
+ });
907
+ }
908
+ // --- Diagnostics & Automation ---
909
+ static async checkGaslessReadiness(publicClient, entryPoint, paymasterAddress, user, token) {
910
+ const issues = [];
911
+ const depositInfo = await publicClient.readContract({
912
+ address: entryPoint,
913
+ abi: parseAbi(["function getDepositInfo(address account) external view returns (uint256 deposit, bool staked, uint256 stake, uint32 unstakeDelaySec, uint48 withdrawTime)"]),
914
+ functionName: "getDepositInfo",
915
+ args: [paymasterAddress]
916
+ });
917
+ if (depositInfo[2] < 50000000000000000n)
918
+ issues.push("Paymaster stake in EntryPoint is less than 0.05 ETH");
919
+ if (depositInfo[3] < 86400)
920
+ issues.push("Paymaster unstake delay is less than 1 day");
921
+ if (depositInfo[0] < 100000000000000000n)
922
+ issues.push("Paymaster deposit in EntryPoint is less than 0.1 ETH");
923
+ const ethPrice = await publicClient.readContract({
924
+ address: paymasterAddress,
925
+ abi: parseAbi(["function cachedPrice() external view returns (uint208 price, uint48 updatedAt)"]),
926
+ functionName: "cachedPrice"
927
+ }).catch(() => [0n, 0n]);
928
+ if (ethPrice[0] === 0n)
929
+ issues.push("Paymaster ETH/USD price not initialized");
930
+ const [tokenPrice, userTokenBal, userPMDeposit] = await Promise.all([
931
+ this.getTokenPrice(publicClient, paymasterAddress, token),
932
+ publicClient.readContract({
933
+ address: token,
934
+ abi: parseAbi(["function balanceOf(address account) external view returns (uint256)"]),
935
+ functionName: "balanceOf",
936
+ args: [user]
937
+ }),
938
+ this.getDepositedBalance(publicClient, paymasterAddress, user, token)
939
+ ]);
940
+ if (tokenPrice === 0n)
941
+ issues.push("Token price not set in Paymaster");
942
+ if (userPMDeposit === 0n)
943
+ issues.push("User has no deposit in Paymaster");
944
+ return {
945
+ isReady: issues.length === 0,
946
+ issues,
947
+ details: {
948
+ paymasterStake: depositInfo[2],
949
+ paymasterDeposit: depositInfo[0],
950
+ ethUsdPrice: ethPrice.price,
951
+ tokenSupported: true,
952
+ tokenPrice,
953
+ userTokenBalance: userTokenBal,
954
+ userPaymasterDeposit: userPMDeposit
955
+ }
956
+ };
957
+ }
958
+ static async prepareGaslessEnvironment(operatorWallet, publicClient, entryPoint, paymasterAddress, token, options = {}) {
959
+ const report = await this.checkGaslessReadiness(publicClient, entryPoint, paymasterAddress, operatorWallet.account.address, token);
960
+ const results = [];
961
+ if (report.details.paymasterStake < (options.minStake || 50000000000000000n)) {
962
+ const hash = await this.addStake(operatorWallet, paymasterAddress, options.minStake || 50000000000000000n, 86400);
963
+ await publicClient.waitForTransactionReceipt({ hash });
964
+ results.push({ step: "Stake", hash, status: "Confirmed" });
965
+ }
966
+ if (report.details.paymasterDeposit < (options.minDeposit || 100000000000000000n)) {
967
+ const hash = await this.addDeposit(operatorWallet, paymasterAddress, options.minDeposit || 300000000000000000n);
968
+ await publicClient.waitForTransactionReceipt({ hash });
969
+ results.push({ step: "Deposit", hash, status: "Confirmed" });
970
+ }
971
+ if (report.details.ethUsdPrice === 0n) {
972
+ const hash = await this.updatePrice(operatorWallet, paymasterAddress);
973
+ await publicClient.waitForTransactionReceipt({ hash });
974
+ results.push({ step: "OraclePrice", hash, status: "Confirmed" });
975
+ }
976
+ if (report.details.tokenPrice === 0n) {
977
+ try {
978
+ const hash = await this.addGasToken(operatorWallet, paymasterAddress, token);
979
+ await publicClient.waitForTransactionReceipt({ hash });
980
+ results.push({ step: "AddGasToken", hash, status: "Confirmed" });
981
+ } catch (e) {
982
+ }
983
+ if (options.tokenPriceUSD) {
984
+ const hash = await this.setTokenPrice(operatorWallet, paymasterAddress, token, options.tokenPriceUSD);
985
+ await publicClient.waitForTransactionReceipt({ hash });
986
+ results.push({ step: "TokenPrice", hash, status: "Confirmed" });
987
+ }
988
+ }
989
+ return results;
990
+ }
991
+ };
992
+ var SuperPaymasterClient = class {
993
+ /**
994
+ * @private
995
+ * Static utility class, should not be instantiated.
996
+ */
997
+ constructor() {
998
+ }
999
+ /**
1000
+ * Submit a gasless transaction using SuperPaymaster.
1001
+ * Automatically handles gas estimation with a smart efficiency buffer.
1002
+ */
1003
+ static async submitGaslessTransaction(client, wallet, aaAddress, entryPoint, bundlerUrl, config) {
1004
+ const callData = encodeFunctionData({
1005
+ abi: parseAbi(["function execute(address dest, uint256 value, bytes func) external"]),
1006
+ functionName: "execute",
1007
+ args: [
1008
+ config.token,
1009
+ 0n,
1010
+ encodeFunctionData({
1011
+ abi: parseAbi(["function transfer(address to, uint256 amount) external returns (bool)"]),
1012
+ functionName: "transfer",
1013
+ args: [config.recipient, config.amount]
1014
+ })
1015
+ ]
1016
+ });
1017
+ console.log(`[SuperPaymasterClient] \u{1F3AF} Target Info:`);
1018
+ console.log(` - Paymaster: ${config.paymasterAddress}`);
1019
+ console.log(` - Token: ${config.token}`);
1020
+ console.log(` - Operator: ${config.operator}`);
1021
+ console.log("[SuperPaymasterClient] \u2601\uFE0F Estimating Gas usage...");
1022
+ const est = await PaymasterClient.estimateUserOperationGas(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
1023
+ operator: config.operator,
1024
+ factory: config.factory,
1025
+ factoryData: config.factoryData
1026
+ });
1027
+ console.log("[SuperPaymasterClient] \u2601\uFE0F Bundler Estimates:", est);
1028
+ const tunedVGL = tuneGasLimit(est.verificationGasLimit, 35000n, 0.45);
1029
+ const bundlerEstimateVGL = est.paymasterVerificationGasLimit || 100000n;
1030
+ const tunedPMVerificationGas = tuneGasLimit(bundlerEstimateVGL, 60000n, 0.45);
1031
+ const _postOpBase = est.paymasterPostOpGasLimit + 100000n;
1032
+ const tunedPostOp = _postOpBase > 200000n ? _postOpBase : 200000n;
1033
+ console.log(`[SuperPaymasterClient] \u{1F527} Tuned Limits: VGL=${tunedVGL}, PMVGL=${tunedPMVerificationGas}, PostOp=${tunedPostOp}`);
1034
+ return PaymasterClient.submitGaslessUserOperation(client, wallet, aaAddress, entryPoint, config.paymasterAddress, config.token, bundlerUrl, callData, {
1035
+ operator: config.operator,
1036
+ verificationGasLimit: tunedVGL,
1037
+ callGasLimit: est.callGasLimit,
1038
+ preVerificationGas: est.preVerificationGas,
1039
+ paymasterVerificationGasLimit: tunedPMVerificationGas,
1040
+ // EXPLICIT PM LIMIT
1041
+ paymasterPostOpGasLimit: tunedPostOp,
1042
+ autoEstimate: false,
1043
+ // We did it ourselves
1044
+ factory: config.factory,
1045
+ factoryData: config.factoryData
1046
+ });
1047
+ }
1048
+ };
1049
+
1050
+ // ../paymaster/dist/PaymasterManager.js
1051
+ var PaymasterManager = class _PaymasterManager {
1052
+ knownPaymasters;
1053
+ constructor(opts) {
1054
+ this.knownPaymasters = /* @__PURE__ */ new Map();
1055
+ if (opts?.knownPaymasters) {
1056
+ for (const [address, type] of Object.entries(opts.knownPaymasters)) {
1057
+ this.setKnownPaymaster(address, type);
1058
+ }
1059
+ }
1060
+ }
1061
+ /**
1062
+ * Register a known paymaster address → type mapping so that callers can
1063
+ * omit the explicit `type` and have it resolved from the address.
1064
+ */
1065
+ registerPaymaster(address, type) {
1066
+ this.setKnownPaymaster(address, type);
1067
+ }
1068
+ /**
1069
+ * Record an address → type mapping, throwing on a CONFLICTING re-registration.
1070
+ * Silently overwriting a v4 address with `super` (or vice-versa) would later
1071
+ * pack the wrong-length paymasterData for a `type`-less call, so a conflicting
1072
+ * re-registration is treated as a programmer error. Re-registering the SAME
1073
+ * type (including a case-variant of the address) is an idempotent no-op.
1074
+ */
1075
+ setKnownPaymaster(address, type) {
1076
+ const normalized = address.toLowerCase();
1077
+ const existing = this.knownPaymasters.get(normalized);
1078
+ if (existing && existing !== type) {
1079
+ throw new Error(`Paymaster ${address} is already registered as '${existing}'; refusing to re-register as '${type}'`);
1080
+ }
1081
+ this.knownPaymasters.set(normalized, type);
1082
+ }
1083
+ /**
1084
+ * Resolve a paymaster's type from a registered address. Returns undefined
1085
+ * if the address is not registered.
1086
+ */
1087
+ resolveType(address) {
1088
+ return this.knownPaymasters.get(address.toLowerCase());
1089
+ }
1090
+ /**
1091
+ * Build `paymasterAndData`, auto-selecting the correct byte layout for the
1092
+ * paymaster type. Dispatches to the existing per-type packers.
1093
+ */
1094
+ buildPaymasterData(params) {
1095
+ const type = params.type ?? this.resolveType(params.paymasterAddress);
1096
+ if (!type) {
1097
+ throw new Error(`PaymasterManager: cannot resolve paymaster type for ${params.paymasterAddress}. Pass an explicit \`type\` ('v4' | 'super') or register the address via registerPaymaster().`);
1098
+ }
1099
+ return _PaymasterManager.dispatch(type, params);
1100
+ }
1101
+ /**
1102
+ * Static helper: build `paymasterAndData` for an explicit type without an
1103
+ * instance. Useful when the caller already knows the type.
1104
+ */
1105
+ static buildPaymasterData(type, params) {
1106
+ return _PaymasterManager.dispatch(type, params);
1107
+ }
1108
+ static dispatch(type, params) {
1109
+ switch (type) {
1110
+ case "v4": {
1111
+ if (!params.token) {
1112
+ throw new Error("PaymasterManager: type 'v4' requires `token`.");
1113
+ }
1114
+ return buildPaymasterData(params.paymasterAddress, params.token, {
1115
+ validityWindow: params.validityWindow,
1116
+ verificationGasLimit: params.verificationGasLimit,
1117
+ postOpGasLimit: params.postOpGasLimit
1118
+ });
1119
+ }
1120
+ case "super": {
1121
+ if (!params.operator) {
1122
+ throw new Error("PaymasterManager: type 'super' requires `operator`.");
1123
+ }
1124
+ return buildSuperPaymasterData(params.paymasterAddress, params.operator, {
1125
+ verificationGasLimit: params.verificationGasLimit,
1126
+ postOpGasLimit: params.postOpGasLimit,
1127
+ maxRate: params.maxRate
1128
+ });
1129
+ }
1130
+ default: {
1131
+ const _never = type;
1132
+ throw new Error(`PaymasterManager: unsupported paymaster type '${_never}'.`);
1133
+ }
1134
+ }
1135
+ }
1136
+ };
1137
+
1138
+ export { PaymasterClient, PaymasterManager, PaymasterOperator, SuperPaymasterAdminClient, SuperPaymasterClient, buildPaymasterData, buildSuperPaymasterData, checkEligibility, formatUserOpV07, getPaymasterV4Middleware, getSuperPaymasterMiddleware, getUserOpHashV07, tuneGasLimit };
1139
+ //# sourceMappingURL=chunk-MPOMWT2J.js.map
1140
+ //# sourceMappingURL=chunk-MPOMWT2J.js.map