@pimlico/alto 0.0.0-staging.20240606T101741 → 0.0.0-staging.20240606T102147

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 (220) hide show
  1. package/esm/cli/alto.d.ts +6 -0
  2. package/esm/cli/alto.js +92 -0
  3. package/esm/cli/alto.js.map +1 -0
  4. package/esm/cli/config/bundler.d.ts +391 -0
  5. package/esm/cli/config/bundler.js +132 -0
  6. package/esm/cli/config/bundler.js.map +1 -0
  7. package/esm/cli/config/index.d.ts +3 -0
  8. package/esm/cli/config/index.js +3 -0
  9. package/esm/cli/config/index.js.map +1 -0
  10. package/esm/cli/config/options.d.ts +11 -0
  11. package/esm/cli/config/options.js +336 -0
  12. package/esm/cli/config/options.js.map +1 -0
  13. package/esm/cli/customTransport.d.ts +14 -0
  14. package/esm/cli/customTransport.js +53 -0
  15. package/esm/cli/customTransport.js.map +1 -0
  16. package/esm/cli/handler.d.ts +3 -0
  17. package/esm/cli/handler.js +116 -0
  18. package/esm/cli/handler.js.map +1 -0
  19. package/esm/cli/index.d.ts +4 -0
  20. package/esm/cli/index.js +4 -0
  21. package/esm/cli/index.js.map +1 -0
  22. package/esm/cli/instrumentation.d.ts +2 -0
  23. package/esm/cli/instrumentation.js +39 -0
  24. package/esm/cli/instrumentation.js.map +1 -0
  25. package/esm/cli/setupServer.d.ts +17 -0
  26. package/esm/cli/setupServer.js +155 -0
  27. package/esm/cli/setupServer.js.map +1 -0
  28. package/esm/cli/util.d.ts +22 -0
  29. package/esm/cli/util.js +30 -0
  30. package/esm/cli/util.js.map +1 -0
  31. package/esm/executor/executor.d.ts +54 -0
  32. package/esm/executor/executor.js +637 -0
  33. package/esm/executor/executor.js.map +1 -0
  34. package/esm/executor/executorManager.d.ts +34 -0
  35. package/esm/executor/executorManager.js +401 -0
  36. package/esm/executor/executorManager.js.map +1 -0
  37. package/esm/executor/index.d.ts +5 -0
  38. package/esm/executor/index.js +5 -0
  39. package/esm/executor/index.js.map +1 -0
  40. package/esm/executor/senderManager.d.ts +17 -0
  41. package/esm/executor/senderManager.js +160 -0
  42. package/esm/executor/senderManager.js.map +1 -0
  43. package/esm/executor/test/utils.d.ts +13 -0
  44. package/esm/executor/test/utils.js +75 -0
  45. package/esm/executor/test/utils.js.map +1 -0
  46. package/esm/executor/utils.d.ts +32 -0
  47. package/esm/executor/utils.js +239 -0
  48. package/esm/executor/utils.js.map +1 -0
  49. package/esm/index.d.ts +2 -0
  50. package/esm/index.js +2 -0
  51. package/esm/index.js.map +1 -0
  52. package/esm/mempool/index.d.ts +5 -0
  53. package/esm/mempool/index.js +5 -0
  54. package/esm/mempool/index.js.map +1 -0
  55. package/esm/mempool/mempool.d.ts +64 -0
  56. package/esm/mempool/mempool.js +489 -0
  57. package/esm/mempool/mempool.js.map +1 -0
  58. package/esm/mempool/monitoring.d.ts +10 -0
  59. package/esm/mempool/monitoring.js +34 -0
  60. package/esm/mempool/monitoring.js.map +1 -0
  61. package/esm/mempool/nullMempool.d.ts +15 -0
  62. package/esm/mempool/nullMempool.js +36 -0
  63. package/esm/mempool/nullMempool.js.map +1 -0
  64. package/esm/mempool/reputationManager.d.ts +115 -0
  65. package/esm/mempool/reputationManager.js +397 -0
  66. package/esm/mempool/reputationManager.js.map +1 -0
  67. package/esm/mempool/store.d.ts +22 -0
  68. package/esm/mempool/store.js +123 -0
  69. package/esm/mempool/store.js.map +1 -0
  70. package/esm/rpc/EntryPointSimulationsV07.d.ts +58 -0
  71. package/esm/rpc/EntryPointSimulationsV07.js +407 -0
  72. package/esm/rpc/EntryPointSimulationsV07.js.map +1 -0
  73. package/esm/rpc/ExecuteSimulator.d.ts +37 -0
  74. package/esm/rpc/ExecuteSimulator.js +48 -0
  75. package/esm/rpc/ExecuteSimulator.js.map +1 -0
  76. package/esm/rpc/gasEstimation.d.ts +17 -0
  77. package/esm/rpc/gasEstimation.js +410 -0
  78. package/esm/rpc/gasEstimation.js.map +1 -0
  79. package/esm/rpc/index.d.ts +5 -0
  80. package/esm/rpc/index.js +5 -0
  81. package/esm/rpc/index.js.map +1 -0
  82. package/esm/rpc/nonceQueuer.d.ts +25 -0
  83. package/esm/rpc/nonceQueuer.js +135 -0
  84. package/esm/rpc/nonceQueuer.js.map +1 -0
  85. package/esm/rpc/rpcHandler.d.ts +64 -0
  86. package/esm/rpc/rpcHandler.js +727 -0
  87. package/esm/rpc/rpcHandler.js.map +1 -0
  88. package/esm/rpc/server.d.ts +31 -0
  89. package/esm/rpc/server.js +238 -0
  90. package/esm/rpc/server.js.map +1 -0
  91. package/esm/rpc/validation/BundlerCollectorTracerV06.d.ts +102 -0
  92. package/esm/rpc/validation/BundlerCollectorTracerV06.js +255 -0
  93. package/esm/rpc/validation/BundlerCollectorTracerV06.js.map +1 -0
  94. package/esm/rpc/validation/BundlerCollectorTracerV07.d.ts +102 -0
  95. package/esm/rpc/validation/BundlerCollectorTracerV07.js +254 -0
  96. package/esm/rpc/validation/BundlerCollectorTracerV07.js.map +1 -0
  97. package/esm/rpc/validation/SafeValidator.d.ts +35 -0
  98. package/esm/rpc/validation/SafeValidator.js +487 -0
  99. package/esm/rpc/validation/SafeValidator.js.map +1 -0
  100. package/esm/rpc/validation/TracerResultParserV06.d.ts +13 -0
  101. package/esm/rpc/validation/TracerResultParserV06.js +578 -0
  102. package/esm/rpc/validation/TracerResultParserV06.js.map +1 -0
  103. package/esm/rpc/validation/TracerResultParserV07.d.ts +33 -0
  104. package/esm/rpc/validation/TracerResultParserV07.js +557 -0
  105. package/esm/rpc/validation/TracerResultParserV07.js.map +1 -0
  106. package/esm/rpc/validation/UnsafeValidator.d.ts +63 -0
  107. package/esm/rpc/validation/UnsafeValidator.js +257 -0
  108. package/esm/rpc/validation/UnsafeValidator.js.map +1 -0
  109. package/esm/rpc/validation/index.d.ts +3 -0
  110. package/esm/rpc/validation/index.js +3 -0
  111. package/esm/rpc/validation/index.js.map +1 -0
  112. package/esm/rpc/validation/tracer.d.ts +122 -0
  113. package/esm/rpc/validation/tracer.js +82 -0
  114. package/esm/rpc/validation/tracer.js.map +1 -0
  115. package/esm/types/contracts/BundleBulker.d.ts +120 -0
  116. package/esm/types/contracts/BundleBulker.js +157 -0
  117. package/esm/types/contracts/BundleBulker.js.map +1 -0
  118. package/esm/types/contracts/CallEngine.d.ts +28 -0
  119. package/esm/types/contracts/CallEngine.js +37 -0
  120. package/esm/types/contracts/CallEngine.js.map +1 -0
  121. package/esm/types/contracts/CodeHashGetter.d.ts +37 -0
  122. package/esm/types/contracts/CodeHashGetter.js +45 -0
  123. package/esm/types/contracts/CodeHashGetter.js.map +1 -0
  124. package/esm/types/contracts/EntryPoint.d.ts +1789 -0
  125. package/esm/types/contracts/EntryPoint.js +2304 -0
  126. package/esm/types/contracts/EntryPoint.js.map +1 -0
  127. package/esm/types/contracts/EntryPointSimulations.d.ts +153 -0
  128. package/esm/types/contracts/EntryPointSimulations.js +15 -0
  129. package/esm/types/contracts/EntryPointSimulations.js.map +1 -0
  130. package/esm/types/contracts/IOpInflator.d.ts +61 -0
  131. package/esm/types/contracts/IOpInflator.js +80 -0
  132. package/esm/types/contracts/IOpInflator.js.map +1 -0
  133. package/esm/types/contracts/IPaymaster.d.ts +3 -0
  134. package/esm/types/contracts/IPaymaster.js +117 -0
  135. package/esm/types/contracts/IPaymaster.js.map +1 -0
  136. package/esm/types/contracts/Inflator.d.ts +65 -0
  137. package/esm/types/contracts/Inflator.js +84 -0
  138. package/esm/types/contracts/Inflator.js.map +1 -0
  139. package/esm/types/contracts/PerOpInflator.d.ts +176 -0
  140. package/esm/types/contracts/PerOpInflator.js +229 -0
  141. package/esm/types/contracts/PerOpInflator.js.map +1 -0
  142. package/esm/types/contracts/PimlicoEntryPointSimulations.d.ts +23 -0
  143. package/esm/types/contracts/PimlicoEntryPointSimulations.js +33 -0
  144. package/esm/types/contracts/PimlicoEntryPointSimulations.js.map +1 -0
  145. package/esm/types/contracts/SenderCreator.d.ts +4 -0
  146. package/esm/types/contracts/SenderCreator.js +23 -0
  147. package/esm/types/contracts/SenderCreator.js.map +1 -0
  148. package/esm/types/contracts/SimpleAccountFactory.d.ts +57 -0
  149. package/esm/types/contracts/SimpleAccountFactory.js +76 -0
  150. package/esm/types/contracts/SimpleAccountFactory.js.map +1 -0
  151. package/esm/types/contracts/TestOpcodesAccount.d.ts +4 -0
  152. package/esm/types/contracts/TestOpcodesAccount.js +281 -0
  153. package/esm/types/contracts/TestOpcodesAccount.js.map +1 -0
  154. package/esm/types/contracts/TestOpcodesAccountFactory.d.ts +4 -0
  155. package/esm/types/contracts/TestOpcodesAccountFactory.js +23 -0
  156. package/esm/types/contracts/TestOpcodesAccountFactory.js.map +1 -0
  157. package/esm/types/contracts/TestStorageAccount.d.ts +4 -0
  158. package/esm/types/contracts/TestStorageAccount.js +313 -0
  159. package/esm/types/contracts/TestStorageAccount.js.map +1 -0
  160. package/esm/types/contracts/index.d.ts +17 -0
  161. package/esm/types/contracts/index.js +17 -0
  162. package/esm/types/contracts/index.js.map +1 -0
  163. package/esm/types/gasPrice.d.ts +110 -0
  164. package/esm/types/gasPrice.js +52 -0
  165. package/esm/types/gasPrice.js.map +1 -0
  166. package/esm/types/index.d.ts +11 -0
  167. package/esm/types/index.js +11 -0
  168. package/esm/types/index.js.map +1 -0
  169. package/esm/types/interfaces.d.ts +26 -0
  170. package/esm/types/interfaces.js +2 -0
  171. package/esm/types/interfaces.js.map +1 -0
  172. package/esm/types/mempool.d.ts +78 -0
  173. package/esm/types/mempool.js +16 -0
  174. package/esm/types/mempool.js.map +1 -0
  175. package/esm/types/schemas.d.ts +4791 -0
  176. package/esm/types/schemas.js +497 -0
  177. package/esm/types/schemas.js.map +1 -0
  178. package/esm/types/test/validationTestErrors.d.ts +3 -0
  179. package/esm/types/test/validationTestErrors.js +229 -0
  180. package/esm/types/test/validationTestErrors.js.map +1 -0
  181. package/esm/types/utils.d.ts +24 -0
  182. package/esm/types/utils.js +30 -0
  183. package/esm/types/utils.js.map +1 -0
  184. package/esm/types/validation.d.ts +14327 -0
  185. package/esm/types/validation.js +304 -0
  186. package/esm/types/validation.js.map +1 -0
  187. package/esm/utils/bigInt.d.ts +3 -0
  188. package/esm/utils/bigInt.js +9 -0
  189. package/esm/utils/bigInt.js.map +1 -0
  190. package/esm/utils/compressionHandler.d.ts +11 -0
  191. package/esm/utils/compressionHandler.js +39 -0
  192. package/esm/utils/compressionHandler.js.map +1 -0
  193. package/esm/utils/gasPriceManager.d.ts +34 -0
  194. package/esm/utils/gasPriceManager.js +338 -0
  195. package/esm/utils/gasPriceManager.js.map +1 -0
  196. package/esm/utils/helpers.d.ts +4 -0
  197. package/esm/utils/helpers.js +13 -0
  198. package/esm/utils/helpers.js.map +1 -0
  199. package/esm/utils/index.d.ts +11 -0
  200. package/esm/utils/index.js +10 -0
  201. package/esm/utils/index.js.map +1 -0
  202. package/esm/utils/logger.d.ts +6 -0
  203. package/esm/utils/logger.js +76 -0
  204. package/esm/utils/logger.js.map +1 -0
  205. package/esm/utils/metrics.d.ts +22 -0
  206. package/esm/utils/metrics.js +150 -0
  207. package/esm/utils/metrics.js.map +1 -0
  208. package/esm/utils/rpc-reply.d.ts +17 -0
  209. package/esm/utils/rpc-reply.js +41 -0
  210. package/esm/utils/rpc-reply.js.map +1 -0
  211. package/esm/utils/test.d.ts +17 -0
  212. package/esm/utils/test.js +130 -0
  213. package/esm/utils/test.js.map +1 -0
  214. package/esm/utils/userop.d.ts +49 -0
  215. package/esm/utils/userop.js +408 -0
  216. package/esm/utils/userop.js.map +1 -0
  217. package/esm/utils/validation.d.ts +65 -0
  218. package/esm/utils/validation.js +461 -0
  219. package/esm/utils/validation.js.map +1 -0
  220. package/package.json +4 -1
@@ -0,0 +1,727 @@
1
+ import { EntryPointV06Abi, EntryPointV07Abi, IOpInflatorAbi, RpcError, ValidationErrors, bundlerGetStakeStatusResponseSchema, deriveUserOperation, logSchema, receiptSchema } from "../types/index.js";
2
+ import { calcPreVerificationGas, calcVerificationGasAndCallGasLimit, getNonceKeyAndValue, getUserOperationHash, isVersion06, isVersion07, maxBigInt, toUnpackedUserOperation } from "../utils/index.js";
3
+ import { TransactionNotFoundError, TransactionReceiptNotFoundError, decodeFunctionData, getAbiItem, getAddress, getContract, encodeEventTopics, zeroAddress, decodeEventLog, parseAbi } from "viem";
4
+ import * as chains from "viem/chains";
5
+ import { z } from "zod";
6
+ import { fromZodError } from "zod-validation-error";
7
+ export class RpcHandler {
8
+ entryPoints;
9
+ publicClient;
10
+ validator;
11
+ mempool;
12
+ executor;
13
+ monitor;
14
+ nonceQueuer;
15
+ usingTenderly;
16
+ rpcMaxBlockRange;
17
+ logger;
18
+ metrics;
19
+ chainId;
20
+ chainType;
21
+ enableDebugEndpoints;
22
+ executorManager;
23
+ reputationManager;
24
+ compressionHandler;
25
+ legacyTransactions;
26
+ dangerousSkipUserOperationValidation;
27
+ gasPriceManager;
28
+ gasPriceMultipliers;
29
+ paymasterGasLimitMultiplier;
30
+ constructor(entryPoints, publicClient, validator, mempool, executor, monitor, nonceQueuer, executorManager, reputationManager, usingTenderly, rpcMaxBlockRange, logger, metrics, enableDebugEndpoints, compressionHandler, legacyTransactions, gasPriceManager, gasPriceMultipliers, chainType, paymasterGasLimitMultiplier, dangerousSkipUserOperationValidation = false) {
31
+ this.entryPoints = entryPoints;
32
+ this.publicClient = publicClient;
33
+ this.validator = validator;
34
+ this.mempool = mempool;
35
+ this.executor = executor;
36
+ this.monitor = monitor;
37
+ this.nonceQueuer = nonceQueuer;
38
+ this.usingTenderly = usingTenderly;
39
+ this.rpcMaxBlockRange = rpcMaxBlockRange;
40
+ this.logger = logger;
41
+ this.metrics = metrics;
42
+ this.enableDebugEndpoints = enableDebugEndpoints;
43
+ this.chainId = publicClient.chain.id;
44
+ this.executorManager = executorManager;
45
+ this.reputationManager = reputationManager;
46
+ this.compressionHandler = compressionHandler;
47
+ this.legacyTransactions = legacyTransactions;
48
+ this.dangerousSkipUserOperationValidation =
49
+ dangerousSkipUserOperationValidation;
50
+ this.gasPriceMultipliers = gasPriceMultipliers;
51
+ this.chainType = chainType;
52
+ this.gasPriceManager = gasPriceManager;
53
+ this.paymasterGasLimitMultiplier = paymasterGasLimitMultiplier;
54
+ }
55
+ async handleMethod(request, apiVersion) {
56
+ // call the method with the params
57
+ const method = request.method;
58
+ switch (method) {
59
+ case "eth_chainId":
60
+ return {
61
+ method,
62
+ result: this.eth_chainId(...request.params)
63
+ };
64
+ case "eth_supportedEntryPoints":
65
+ return {
66
+ method,
67
+ result: this.eth_supportedEntryPoints(...request.params)
68
+ };
69
+ case "eth_estimateUserOperationGas":
70
+ return {
71
+ method,
72
+ result: await this.eth_estimateUserOperationGas(apiVersion, request.params[0], request.params[1], request.params[2])
73
+ };
74
+ case "eth_sendUserOperation":
75
+ return {
76
+ method,
77
+ result: await this.eth_sendUserOperation(apiVersion, ...request.params)
78
+ };
79
+ case "eth_getUserOperationByHash":
80
+ return {
81
+ method,
82
+ result: await this.eth_getUserOperationByHash(...request.params)
83
+ };
84
+ case "eth_getUserOperationReceipt":
85
+ return {
86
+ method,
87
+ result: await this.eth_getUserOperationReceipt(...request.params)
88
+ };
89
+ case "debug_bundler_clearMempool":
90
+ return {
91
+ method,
92
+ result: this.debug_bundler_clearMempool(...request.params)
93
+ };
94
+ case "debug_bundler_clearState":
95
+ return {
96
+ method,
97
+ result: this.debug_bundler_clearState(...request.params)
98
+ };
99
+ case "debug_bundler_dumpMempool":
100
+ return {
101
+ method,
102
+ result: await this.debug_bundler_dumpMempool(...request.params)
103
+ };
104
+ case "debug_bundler_sendBundleNow":
105
+ return {
106
+ method,
107
+ result: await this.debug_bundler_sendBundleNow(...request.params)
108
+ };
109
+ case "debug_bundler_setBundlingMode":
110
+ return {
111
+ method,
112
+ result: this.debug_bundler_setBundlingMode(...request.params)
113
+ };
114
+ case "debug_bundler_setReputation":
115
+ return {
116
+ method,
117
+ result: this.debug_bundler_setReputation(request.params)
118
+ };
119
+ case "debug_bundler_dumpReputation":
120
+ return {
121
+ method,
122
+ result: this.debug_bundler_dumpReputation(...request.params)
123
+ };
124
+ case "debug_bundler_getStakeStatus":
125
+ return {
126
+ method,
127
+ result: await this.debug_bundler_getStakeStatus(...request.params)
128
+ };
129
+ case "pimlico_getUserOperationStatus":
130
+ return {
131
+ method,
132
+ result: this.pimlico_getUserOperationStatus(...request.params)
133
+ };
134
+ case "pimlico_getUserOperationGasPrice":
135
+ return {
136
+ method,
137
+ result: await this.pimlico_getUserOperationGasPrice(...request.params)
138
+ };
139
+ case "pimlico_sendCompressedUserOperation":
140
+ return {
141
+ method,
142
+ result: await this.pimlico_sendCompressedUserOperation(apiVersion, ...request.params)
143
+ };
144
+ }
145
+ }
146
+ eth_chainId() {
147
+ return BigInt(this.chainId);
148
+ }
149
+ eth_supportedEntryPoints() {
150
+ return this.entryPoints;
151
+ }
152
+ async eth_estimateUserOperationGas(apiVersion, userOperation, entryPoint, stateOverrides) {
153
+ // check if entryPoint is supported, if not throw
154
+ if (!this.entryPoints.includes(entryPoint)) {
155
+ throw new Error(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
156
+ }
157
+ if (userOperation.maxFeePerGas === 0n) {
158
+ throw new RpcError("user operation max fee per gas must be larger than 0 during gas estimation");
159
+ }
160
+ const preVerificationGas = ((await calcPreVerificationGas(this.publicClient, userOperation, entryPoint, this.chainId, this.chainType, this.gasPriceManager, false)) *
161
+ 110n) /
162
+ 100n;
163
+ userOperation.preVerificationGas = 1000000n;
164
+ userOperation.verificationGasLimit = 10000000n;
165
+ userOperation.callGasLimit = 10000000n;
166
+ if (this.chainId === chains.base.id) {
167
+ userOperation.verificationGasLimit = 5000000n;
168
+ }
169
+ if (this.chainId === chains.celoAlfajores.id ||
170
+ this.chainId === chains.celo.id) {
171
+ userOperation.verificationGasLimit = 1000000n;
172
+ userOperation.callGasLimit = 1000000n;
173
+ }
174
+ if (isVersion07(userOperation)) {
175
+ userOperation.paymasterPostOpGasLimit = 2000000n;
176
+ userOperation.paymasterVerificationGasLimit = 5000000n;
177
+ }
178
+ // This is necessary because entryPoint pays
179
+ // min(maxFeePerGas, baseFee + maxPriorityFeePerGas) for the verification
180
+ // Since we don't want our estimations to depend upon baseFee, we set
181
+ // maxFeePerGas to maxPriorityFeePerGas
182
+ userOperation.maxPriorityFeePerGas = userOperation.maxFeePerGas;
183
+ // Check if the nonce is valid
184
+ // If the nonce is less than the current nonce, the user operation has already been executed
185
+ // If the nonce is greater than the current nonce, we may have missing user operations in the mempool
186
+ const currentNonceValue = await this.getNonceValue(userOperation, entryPoint);
187
+ const [, userOperationNonceValue] = getNonceKeyAndValue(userOperation.nonce);
188
+ let queuedUserOperations = [];
189
+ if (userOperationNonceValue < currentNonceValue) {
190
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
191
+ }
192
+ if (userOperationNonceValue > currentNonceValue) {
193
+ // Nonce queues are supported only for v7 user operations
194
+ if (isVersion06(userOperation)) {
195
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
196
+ }
197
+ queuedUserOperations = await this.mempool.getQueuedUserOperations(userOperation, entryPoint, currentNonceValue);
198
+ if (userOperationNonceValue >
199
+ currentNonceValue + BigInt(queuedUserOperations.length)) {
200
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
201
+ }
202
+ }
203
+ const executionResult = await this.validator.getExecutionResult(userOperation, entryPoint, queuedUserOperations, stateOverrides);
204
+ let { verificationGasLimit, callGasLimit } = calcVerificationGasAndCallGasLimit(userOperation, executionResult.data.executionResult, this.chainId, executionResult.data.callDataResult);
205
+ let paymasterVerificationGasLimit = 0n;
206
+ let paymasterPostOpGasLimit = 0n;
207
+ if (isVersion07(userOperation) &&
208
+ userOperation.paymaster !== null &&
209
+ "paymasterVerificationGasLimit" in
210
+ executionResult.data.executionResult &&
211
+ "paymasterPostOpGasLimit" in executionResult.data.executionResult) {
212
+ paymasterVerificationGasLimit =
213
+ executionResult.data.executionResult
214
+ .paymasterVerificationGasLimit || 1n;
215
+ paymasterPostOpGasLimit =
216
+ executionResult.data.executionResult.paymasterPostOpGasLimit ||
217
+ 1n;
218
+ const multiplier = this.paymasterGasLimitMultiplier;
219
+ paymasterVerificationGasLimit =
220
+ (paymasterVerificationGasLimit * multiplier) / 100n;
221
+ paymasterPostOpGasLimit =
222
+ (paymasterPostOpGasLimit * multiplier) / 100n;
223
+ }
224
+ if (this.chainId === chains.base.id ||
225
+ this.chainId === chains.baseSepolia.id) {
226
+ callGasLimit += 10000n;
227
+ }
228
+ if (this.chainId === chains.base.id ||
229
+ this.chainId === chains.optimism.id) {
230
+ callGasLimit = maxBigInt(callGasLimit, 120000n);
231
+ }
232
+ if (userOperation.callData === "0x") {
233
+ callGasLimit = 0n;
234
+ }
235
+ if (isVersion07(userOperation)) {
236
+ return {
237
+ preVerificationGas,
238
+ verificationGasLimit,
239
+ callGasLimit,
240
+ paymasterVerificationGasLimit,
241
+ paymasterPostOpGasLimit
242
+ };
243
+ }
244
+ if (apiVersion === "v2") {
245
+ return {
246
+ preVerificationGas,
247
+ verificationGasLimit,
248
+ callGasLimit
249
+ };
250
+ }
251
+ return {
252
+ preVerificationGas,
253
+ verificationGas: verificationGasLimit,
254
+ verificationGasLimit,
255
+ callGasLimit
256
+ };
257
+ }
258
+ async eth_sendUserOperation(apiVersion, userOperation, entryPoint) {
259
+ let status = "rejected";
260
+ try {
261
+ status = await this.addToMempoolIfValid(userOperation, entryPoint, apiVersion);
262
+ const hash = getUserOperationHash(userOperation, entryPoint, this.chainId);
263
+ return hash;
264
+ }
265
+ catch (error) {
266
+ status = "rejected";
267
+ throw error;
268
+ }
269
+ finally {
270
+ this.metrics.userOperationsReceived
271
+ .labels({
272
+ status,
273
+ type: "regular"
274
+ })
275
+ .inc();
276
+ }
277
+ }
278
+ async eth_getUserOperationByHash(userOperationHash) {
279
+ const userOperationEventAbiItem = getAbiItem({
280
+ abi: EntryPointV06Abi,
281
+ name: "UserOperationEvent"
282
+ });
283
+ let fromBlock = undefined;
284
+ let toBlock = undefined;
285
+ if (this.rpcMaxBlockRange !== undefined) {
286
+ const latestBlock = await this.publicClient.getBlockNumber();
287
+ fromBlock = latestBlock - BigInt(this.rpcMaxBlockRange);
288
+ if (fromBlock < 0n) {
289
+ fromBlock = 0n;
290
+ }
291
+ toBlock = "latest";
292
+ }
293
+ const filterResult = await this.publicClient.getLogs({
294
+ address: this.entryPoints,
295
+ event: userOperationEventAbiItem,
296
+ fromBlock,
297
+ toBlock,
298
+ args: {
299
+ userOpHash: userOperationHash
300
+ }
301
+ });
302
+ if (filterResult.length === 0) {
303
+ return null;
304
+ }
305
+ const userOperationEvent = filterResult[0];
306
+ const txHash = userOperationEvent.transactionHash;
307
+ if (txHash === null) {
308
+ // transaction pending
309
+ return null;
310
+ }
311
+ const getTransaction = async (txHash) => {
312
+ try {
313
+ return await this.publicClient.getTransaction({ hash: txHash });
314
+ }
315
+ catch (e) {
316
+ if (e instanceof TransactionNotFoundError) {
317
+ return getTransaction(txHash);
318
+ }
319
+ throw e;
320
+ }
321
+ };
322
+ const tx = await getTransaction(txHash);
323
+ if (!tx.to) {
324
+ return null;
325
+ }
326
+ let op = undefined;
327
+ try {
328
+ const decoded = decodeFunctionData({
329
+ abi: EntryPointV06Abi,
330
+ data: tx.input
331
+ });
332
+ if (decoded.functionName !== "handleOps") {
333
+ return null;
334
+ }
335
+ const ops = decoded.args[0];
336
+ op = ops.find((op) => op.sender === userOperationEvent.args.sender &&
337
+ op.nonce === userOperationEvent.args.nonce);
338
+ }
339
+ catch {
340
+ return null;
341
+ }
342
+ if (op === undefined) {
343
+ return null;
344
+ }
345
+ const result = {
346
+ userOperation: isVersion06(op) ? op : toUnpackedUserOperation(op),
347
+ entryPoint: getAddress(tx.to),
348
+ transactionHash: txHash,
349
+ blockHash: tx.blockHash ?? "0x",
350
+ blockNumber: BigInt(tx.blockNumber ?? 0n)
351
+ };
352
+ return result;
353
+ }
354
+ async eth_getUserOperationReceipt(userOperationHash) {
355
+ const userOperationEventAbiItem = getAbiItem({
356
+ abi: EntryPointV06Abi,
357
+ name: "UserOperationEvent"
358
+ });
359
+ let fromBlock = undefined;
360
+ let toBlock = undefined;
361
+ if (this.rpcMaxBlockRange !== undefined) {
362
+ const latestBlock = await this.publicClient.getBlockNumber();
363
+ fromBlock = latestBlock - BigInt(this.rpcMaxBlockRange);
364
+ if (fromBlock < 0n) {
365
+ fromBlock = 0n;
366
+ }
367
+ toBlock = "latest";
368
+ }
369
+ const filterResult = await this.publicClient.getLogs({
370
+ address: this.entryPoints,
371
+ event: userOperationEventAbiItem,
372
+ fromBlock,
373
+ toBlock,
374
+ args: {
375
+ userOpHash: userOperationHash
376
+ }
377
+ });
378
+ if (filterResult.length === 0) {
379
+ return null;
380
+ }
381
+ const userOperationEvent = filterResult[0];
382
+ // throw if any of the members of userOperationEvent are undefined
383
+ if (userOperationEvent.args.actualGasCost === undefined ||
384
+ userOperationEvent.args.sender === undefined ||
385
+ userOperationEvent.args.nonce === undefined ||
386
+ userOperationEvent.args.userOpHash === undefined ||
387
+ userOperationEvent.args.success === undefined ||
388
+ userOperationEvent.args.paymaster === undefined ||
389
+ userOperationEvent.args.actualGasUsed === undefined) {
390
+ throw new Error("userOperationEvent has undefined members");
391
+ }
392
+ const txHash = userOperationEvent.transactionHash;
393
+ if (txHash === null) {
394
+ // transaction pending
395
+ return null;
396
+ }
397
+ const getTransactionReceipt = async (txHash) => {
398
+ while (true) {
399
+ try {
400
+ return await this.publicClient.getTransactionReceipt({
401
+ hash: txHash
402
+ });
403
+ }
404
+ catch (e) {
405
+ if (e instanceof TransactionReceiptNotFoundError) {
406
+ continue;
407
+ }
408
+ throw e;
409
+ }
410
+ }
411
+ };
412
+ const receipt = await getTransactionReceipt(txHash);
413
+ const logs = receipt.logs;
414
+ if (logs.some((log) => log.blockHash === null ||
415
+ log.blockNumber === null ||
416
+ log.transactionIndex === null ||
417
+ log.transactionHash === null ||
418
+ log.logIndex === null ||
419
+ log.topics.length === 0)) {
420
+ // transaction pending
421
+ return null;
422
+ }
423
+ const userOperationRevertReasonAbi = parseAbi([
424
+ "event UserOperationRevertReason(bytes32 indexed userOpHash, address indexed sender, uint256 nonce, bytes revertReason)"
425
+ ]);
426
+ const userOperationRevertReasonTopicEvent = encodeEventTopics({
427
+ abi: userOperationRevertReasonAbi
428
+ })[0];
429
+ let entryPoint = zeroAddress;
430
+ let revertReason = undefined;
431
+ let startIndex = -1;
432
+ let endIndex = -1;
433
+ logs.forEach((log, index) => {
434
+ if (log?.topics[0] === userOperationEvent.topics[0]) {
435
+ // process UserOperationEvent
436
+ if (log.topics[1] === userOperationEvent.topics[1]) {
437
+ // it's our userOpHash. save as end of logs array
438
+ endIndex = index;
439
+ entryPoint = log.address;
440
+ }
441
+ else if (endIndex === -1) {
442
+ // it's a different hash. remember it as beginning index, but only if we didn't find our end index yet.
443
+ startIndex = index;
444
+ }
445
+ }
446
+ if (log?.topics[0] === userOperationRevertReasonTopicEvent) {
447
+ // process UserOperationRevertReason
448
+ if (log.topics[1] === userOperationEvent.topics[1]) {
449
+ // it's our userOpHash. capture revert reason.
450
+ const decodedLog = decodeEventLog({
451
+ abi: userOperationRevertReasonAbi,
452
+ data: log.data,
453
+ topics: log.topics
454
+ });
455
+ revertReason = decodedLog.args.revertReason;
456
+ }
457
+ }
458
+ });
459
+ if (endIndex === -1) {
460
+ throw new Error("fatal: no UserOperationEvent in logs");
461
+ }
462
+ const filteredLogs = logs.slice(startIndex + 1, endIndex);
463
+ const logsParsing = z.array(logSchema).safeParse(filteredLogs);
464
+ if (!logsParsing.success) {
465
+ const err = fromZodError(logsParsing.error);
466
+ throw err;
467
+ }
468
+ const receiptParsing = receiptSchema.safeParse({
469
+ ...receipt,
470
+ status: receipt.status === "success" ? 1 : 0
471
+ });
472
+ if (!receiptParsing.success) {
473
+ const err = fromZodError(receiptParsing.error);
474
+ throw err;
475
+ }
476
+ let paymaster = userOperationEvent.args.paymaster;
477
+ paymaster = paymaster === zeroAddress ? undefined : paymaster;
478
+ const userOperationReceipt = {
479
+ userOpHash: userOperationHash,
480
+ entryPoint,
481
+ sender: userOperationEvent.args.sender,
482
+ nonce: userOperationEvent.args.nonce,
483
+ paymaster,
484
+ actualGasUsed: userOperationEvent.args.actualGasUsed,
485
+ actualGasCost: userOperationEvent.args.actualGasCost,
486
+ success: userOperationEvent.args.success,
487
+ reason: revertReason,
488
+ logs: logsParsing.data,
489
+ receipt: receiptParsing.data
490
+ };
491
+ return userOperationReceipt;
492
+ }
493
+ debug_bundler_clearState() {
494
+ if (!this.enableDebugEndpoints) {
495
+ throw new RpcError("debug_bundler_clearState is only available in development environment");
496
+ }
497
+ this.mempool.clear();
498
+ this.reputationManager.clear();
499
+ return "ok";
500
+ }
501
+ debug_bundler_clearMempool() {
502
+ if (!this.enableDebugEndpoints) {
503
+ throw new RpcError("debug_bundler_clearMempool is only available in development environment");
504
+ }
505
+ this.mempool.clear();
506
+ this.reputationManager.clearEntityCount();
507
+ return "ok";
508
+ }
509
+ async debug_bundler_dumpMempool(entryPoint) {
510
+ if (!this.enableDebugEndpoints) {
511
+ throw new RpcError("debug_bundler_dumpMempool is only available in development environment");
512
+ }
513
+ if (!this.entryPoints.includes(entryPoint)) {
514
+ throw new RpcError(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
515
+ }
516
+ return this.mempool
517
+ .dumpOutstanding()
518
+ .map((userOpInfo) => deriveUserOperation(userOpInfo.mempoolUserOperation));
519
+ }
520
+ async debug_bundler_sendBundleNow() {
521
+ if (!this.enableDebugEndpoints) {
522
+ throw new RpcError("debug_bundler_sendBundleNow is only available in development environment");
523
+ }
524
+ const transactions = await this.executorManager.bundleNow();
525
+ return transactions[0];
526
+ }
527
+ debug_bundler_setBundlingMode(bundlingMode) {
528
+ if (!this.enableDebugEndpoints) {
529
+ throw new RpcError("debug_bundler_setBundlingMode is only available in development environment");
530
+ }
531
+ this.executorManager.setBundlingMode(bundlingMode);
532
+ return "ok";
533
+ }
534
+ debug_bundler_dumpReputation(entryPoint) {
535
+ if (!this.enableDebugEndpoints) {
536
+ throw new RpcError("debug_bundler_setRe is only available in development environment");
537
+ }
538
+ if (!this.entryPoints.includes(entryPoint)) {
539
+ throw new RpcError(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
540
+ }
541
+ return this.reputationManager.dumpReputations(entryPoint);
542
+ }
543
+ async debug_bundler_getStakeStatus(address, entryPoint) {
544
+ if (!this.enableDebugEndpoints) {
545
+ throw new RpcError("debug_bundler_getStakeStatus is only available in development environment");
546
+ }
547
+ if (!this.entryPoints.includes(entryPoint)) {
548
+ throw new RpcError(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
549
+ }
550
+ return bundlerGetStakeStatusResponseSchema.parse({
551
+ method: "debug_bundler_getStakeStatus",
552
+ result: await this.reputationManager.getStakeStatus(entryPoint, address)
553
+ }).result;
554
+ }
555
+ debug_bundler_setReputation(args) {
556
+ if (!this.enableDebugEndpoints) {
557
+ throw new RpcError("debug_bundler_setReputation is only available in development environment");
558
+ }
559
+ this.reputationManager.setReputation(args[1], args[0]);
560
+ return "ok";
561
+ }
562
+ pimlico_getUserOperationStatus(userOperationHash) {
563
+ return this.monitor.getUserOperationStatus(userOperationHash);
564
+ }
565
+ async pimlico_getUserOperationGasPrice() {
566
+ const gasPrice = await this.gasPriceManager.getGasPrice();
567
+ const { slow, standard, fast } = this.gasPriceMultipliers;
568
+ return {
569
+ slow: {
570
+ maxFeePerGas: (gasPrice.maxFeePerGas * slow) / 100n,
571
+ maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * slow) / 100n
572
+ },
573
+ standard: {
574
+ maxFeePerGas: (gasPrice.maxFeePerGas * standard) / 100n,
575
+ maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * standard) / 100n
576
+ },
577
+ fast: {
578
+ maxFeePerGas: (gasPrice.maxFeePerGas * fast) / 100n,
579
+ maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * fast) / 100n
580
+ }
581
+ };
582
+ }
583
+ // check if we want to bundle userOperation. If yes, add to mempool
584
+ async addToMempoolIfValid(op, entryPoint, apiVersion) {
585
+ const userOperation = deriveUserOperation(op);
586
+ if (!this.entryPoints.includes(entryPoint)) {
587
+ throw new RpcError(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
588
+ }
589
+ if (this.chainId === chains.celoAlfajores.id ||
590
+ this.chainId === chains.celo.id) {
591
+ if (userOperation.maxFeePerGas !==
592
+ userOperation.maxPriorityFeePerGas) {
593
+ throw new RpcError("maxPriorityFeePerGas must equal maxFeePerGas on Celo chains");
594
+ }
595
+ }
596
+ if (apiVersion !== "v1") {
597
+ await this.gasPriceManager.validateGasPrice({
598
+ maxFeePerGas: userOperation.maxFeePerGas,
599
+ maxPriorityFeePerGas: userOperation.maxPriorityFeePerGas
600
+ });
601
+ }
602
+ if (userOperation.verificationGasLimit < 10000n) {
603
+ throw new RpcError("verificationGasLimit must be at least 10000");
604
+ }
605
+ this.logger.trace({ userOperation, entryPoint }, "beginning validation");
606
+ if (userOperation.preVerificationGas === 0n ||
607
+ userOperation.verificationGasLimit === 0n) {
608
+ throw new RpcError("user operation gas limits must be larger than 0");
609
+ }
610
+ const currentNonceValue = await this.getNonceValue(userOperation, entryPoint);
611
+ const [, userOperationNonceValue] = getNonceKeyAndValue(userOperation.nonce);
612
+ if (userOperationNonceValue < currentNonceValue) {
613
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
614
+ }
615
+ if (userOperationNonceValue > currentNonceValue + 10n) {
616
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
617
+ }
618
+ let queuedUserOperations = [];
619
+ if (userOperationNonceValue > currentNonceValue &&
620
+ isVersion07(userOperation)) {
621
+ queuedUserOperations = await this.mempool.getQueuedUserOperations(userOperation, entryPoint, currentNonceValue);
622
+ }
623
+ if (userOperationNonceValue ===
624
+ currentNonceValue + BigInt(queuedUserOperations.length)) {
625
+ if (this.dangerousSkipUserOperationValidation) {
626
+ const success = this.mempool.add(op, entryPoint);
627
+ if (!success) {
628
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
629
+ }
630
+ }
631
+ else {
632
+ if (apiVersion !== "v1") {
633
+ await this.validator.validatePreVerificationGas(userOperation, entryPoint);
634
+ }
635
+ const validationResult = await this.validator.validateUserOperation(apiVersion !== "v1", userOperation, queuedUserOperations, entryPoint);
636
+ await this.reputationManager.checkReputation(userOperation, entryPoint, validationResult);
637
+ await this.mempool.checkEntityMultipleRoleViolation(userOperation);
638
+ const success = this.mempool.add(op, entryPoint, validationResult.referencedContracts);
639
+ if (!success) {
640
+ throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
641
+ }
642
+ return "added";
643
+ }
644
+ }
645
+ this.nonceQueuer.add(op, entryPoint);
646
+ return "queued";
647
+ }
648
+ async pimlico_sendCompressedUserOperation(apiVersion, compressedCalldata, inflatorAddress, entryPoint) {
649
+ let status = "rejected";
650
+ try {
651
+ const { inflatedOp, inflatorId } = await this.validateAndInflateCompressedUserOperation(inflatorAddress, compressedCalldata);
652
+ const compressedUserOp = {
653
+ compressedCalldata,
654
+ inflatedOp,
655
+ inflatorAddress,
656
+ inflatorId
657
+ };
658
+ // check userOps inputs.
659
+ status = await this.addToMempoolIfValid(compressedUserOp, entryPoint, apiVersion);
660
+ const hash = getUserOperationHash(inflatedOp, entryPoint, this.chainId);
661
+ return hash;
662
+ }
663
+ catch (error) {
664
+ status = "rejected";
665
+ throw error;
666
+ }
667
+ finally {
668
+ this.metrics.userOperationsReceived
669
+ .labels({
670
+ status,
671
+ type: "compressed"
672
+ })
673
+ .inc();
674
+ }
675
+ }
676
+ async validateAndInflateCompressedUserOperation(inflatorAddress, compressedCalldata) {
677
+ // check if inflator is registered with our PerOpInflator.
678
+ if (this.compressionHandler === null) {
679
+ throw new RpcError("Endpoint not supported");
680
+ }
681
+ const inflatorId = await this.compressionHandler.getInflatorRegisteredId(inflatorAddress, this.publicClient);
682
+ if (inflatorId === 0) {
683
+ throw new RpcError(`Inflator ${inflatorAddress} is not registered`, ValidationErrors.InvalidFields);
684
+ }
685
+ // infalte + start to validate user op.
686
+ const inflatorContract = getContract({
687
+ address: inflatorAddress,
688
+ abi: IOpInflatorAbi,
689
+ client: {
690
+ public: this.publicClient
691
+ }
692
+ });
693
+ let inflatedOp;
694
+ try {
695
+ inflatedOp = await inflatorContract.read.inflate([
696
+ compressedCalldata
697
+ ]);
698
+ }
699
+ catch (e) {
700
+ throw new RpcError(`Inflator ${inflatorAddress} failed to inflate calldata ${compressedCalldata}, due to ${e}`, ValidationErrors.InvalidFields);
701
+ }
702
+ // check if perUseropIsRegisterd to target BundleBulker
703
+ const perOpInflatorId = this.compressionHandler.perOpInflatorId;
704
+ if (perOpInflatorId === 0) {
705
+ throw new RpcError(`PerUserOp ${this.compressionHandler.perOpInflatorAddress} has not been registered with BundelBulker`, ValidationErrors.InvalidFields);
706
+ }
707
+ return { inflatedOp, inflatorId };
708
+ }
709
+ async getNonceValue(userOperation, entryPoint) {
710
+ const entryPointContract = getContract({
711
+ address: entryPoint,
712
+ abi: isVersion06(userOperation)
713
+ ? EntryPointV06Abi
714
+ : EntryPointV07Abi,
715
+ client: {
716
+ public: this.publicClient
717
+ }
718
+ });
719
+ const [nonceKey] = getNonceKeyAndValue(userOperation.nonce);
720
+ const getNonceResult = await entryPointContract.read.getNonce([userOperation.sender, nonceKey], {
721
+ blockTag: "latest"
722
+ });
723
+ const [_, currentNonceValue] = getNonceKeyAndValue(getNonceResult);
724
+ return currentNonceValue;
725
+ }
726
+ }
727
+ //# sourceMappingURL=rpcHandler.js.map