@pimlico/alto 0.0.3 → 0.0.5

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 (247) hide show
  1. package/esm/cli/alto.js +0 -4
  2. package/esm/cli/alto.js.map +1 -1
  3. package/esm/cli/config/bundler.d.ts +2302 -22
  4. package/esm/cli/config/bundler.js +32 -4
  5. package/esm/cli/config/bundler.js.map +1 -1
  6. package/esm/cli/config/options.js +59 -4
  7. package/esm/cli/config/options.js.map +1 -1
  8. package/esm/cli/customTransport.js +5 -1
  9. package/esm/cli/customTransport.js.map +1 -1
  10. package/esm/cli/handler.js +39 -4
  11. package/esm/cli/handler.js.map +1 -1
  12. package/esm/cli/instrumentation.js +2 -2
  13. package/esm/cli/instrumentation.js.map +1 -1
  14. package/esm/cli/setupServer.d.ts +2 -1
  15. package/esm/cli/setupServer.js +51 -27
  16. package/esm/cli/setupServer.js.map +1 -1
  17. package/esm/executor/executor.d.ts +7 -14
  18. package/esm/executor/executor.js +139 -128
  19. package/esm/executor/executor.js.map +1 -1
  20. package/esm/executor/executorManager.d.ts +58 -4
  21. package/esm/executor/executorManager.js +206 -52
  22. package/esm/executor/executorManager.js.map +1 -1
  23. package/esm/executor/senderManager.d.ts +2 -1
  24. package/esm/executor/senderManager.js +3 -0
  25. package/esm/executor/senderManager.js.map +1 -1
  26. package/esm/executor/utilityWalletMonitor.d.ts +15 -0
  27. package/esm/executor/utilityWalletMonitor.js +38 -0
  28. package/esm/executor/utilityWalletMonitor.js.map +1 -0
  29. package/esm/executor/utils.d.ts +1 -2
  30. package/esm/executor/utils.js +49 -38
  31. package/esm/executor/utils.js.map +1 -1
  32. package/esm/handlers/compressionHandler.js.map +1 -0
  33. package/esm/handlers/eventManager.d.ts +21 -0
  34. package/esm/handlers/eventManager.js +166 -0
  35. package/esm/handlers/eventManager.js.map +1 -0
  36. package/{lib/utils → esm/handlers}/gasPriceManager.d.ts +19 -5
  37. package/esm/{utils → handlers}/gasPriceManager.js +58 -13
  38. package/esm/handlers/gasPriceManager.js.map +1 -0
  39. package/esm/handlers/index.d.ts +4 -0
  40. package/esm/handlers/index.js +4 -0
  41. package/esm/handlers/index.js.map +1 -0
  42. package/esm/mempool/index.d.ts +0 -1
  43. package/esm/mempool/index.js +0 -1
  44. package/esm/mempool/index.js.map +1 -1
  45. package/esm/mempool/mempool.d.ts +4 -2
  46. package/esm/mempool/mempool.js +70 -26
  47. package/esm/mempool/mempool.js.map +1 -1
  48. package/esm/mempool/reputationManager.js +7 -3
  49. package/esm/mempool/reputationManager.js.map +1 -1
  50. package/esm/rpc/EntryPointSimulationsV07.d.ts +7 -3
  51. package/esm/rpc/EntryPointSimulationsV07.js +12 -9
  52. package/esm/rpc/EntryPointSimulationsV07.js.map +1 -1
  53. package/esm/rpc/gasEstimation.d.ts +3 -3
  54. package/esm/rpc/gasEstimation.js +23 -14
  55. package/esm/rpc/gasEstimation.js.map +1 -1
  56. package/esm/rpc/nonceQueuer.d.ts +4 -1
  57. package/esm/rpc/nonceQueuer.js +9 -3
  58. package/esm/rpc/nonceQueuer.js.map +1 -1
  59. package/esm/rpc/rpcHandler.d.ts +53 -3
  60. package/esm/rpc/rpcHandler.js +150 -238
  61. package/esm/rpc/rpcHandler.js.map +1 -1
  62. package/esm/rpc/server.d.ts +2 -1
  63. package/esm/rpc/server.js +10 -1
  64. package/esm/rpc/server.js.map +1 -1
  65. package/esm/rpc/validation/SafeValidator.d.ts +5 -8
  66. package/esm/rpc/validation/SafeValidator.js +51 -208
  67. package/esm/rpc/validation/SafeValidator.js.map +1 -1
  68. package/esm/rpc/validation/TracerResultParserV07.js +6 -2
  69. package/esm/rpc/validation/TracerResultParserV07.js.map +1 -1
  70. package/esm/rpc/validation/UnsafeValidator.d.ts +7 -3
  71. package/esm/rpc/validation/UnsafeValidator.js +52 -48
  72. package/esm/rpc/validation/UnsafeValidator.js.map +1 -1
  73. package/esm/rpc/validation/tracer.js +1 -0
  74. package/esm/rpc/validation/tracer.js.map +1 -1
  75. package/esm/types/contracts/EntryPointSimulations.d.ts +0 -1
  76. package/esm/types/contracts/EntryPointSimulations.js +1941 -2
  77. package/esm/types/contracts/EntryPointSimulations.js.map +1 -1
  78. package/esm/types/contracts/PimlicoEntryPointSimulations.d.ts +1 -1
  79. package/esm/types/contracts/PimlicoEntryPointSimulations.js +1 -1
  80. package/esm/types/contracts/PimlicoEntryPointSimulations.js.map +1 -1
  81. package/esm/types/schemas.d.ts +1029 -333
  82. package/esm/types/schemas.js +94 -20
  83. package/esm/types/schemas.js.map +1 -1
  84. package/esm/types/utils.d.ts +1 -1
  85. package/esm/types/validation.js +7 -2
  86. package/esm/types/validation.js.map +1 -1
  87. package/esm/utils/bigInt.d.ts +1 -0
  88. package/esm/utils/bigInt.js +4 -0
  89. package/esm/utils/bigInt.js.map +1 -1
  90. package/esm/utils/helpers.d.ts +1 -0
  91. package/esm/utils/helpers.js +6 -0
  92. package/esm/utils/helpers.js.map +1 -1
  93. package/esm/utils/index.d.ts +0 -3
  94. package/esm/utils/index.js +0 -3
  95. package/esm/utils/index.js.map +1 -1
  96. package/esm/utils/metrics.d.ts +4 -0
  97. package/esm/utils/metrics.js +29 -1
  98. package/esm/utils/metrics.js.map +1 -1
  99. package/esm/utils/rpc-reply.d.ts +1 -1
  100. package/esm/utils/rpc-reply.js +2 -1
  101. package/esm/utils/rpc-reply.js.map +1 -1
  102. package/esm/utils/userop.d.ts +66 -6
  103. package/esm/utils/userop.js +182 -95
  104. package/esm/utils/userop.js.map +1 -1
  105. package/esm/utils/validation.d.ts +1 -1
  106. package/esm/utils/validation.js +9 -13
  107. package/esm/utils/validation.js.map +1 -1
  108. package/lib/cli/alto.js +0 -4
  109. package/lib/cli/alto.js.map +1 -1
  110. package/lib/cli/config/bundler.d.ts +2302 -22
  111. package/lib/cli/config/bundler.js +31 -3
  112. package/lib/cli/config/bundler.js.map +1 -1
  113. package/lib/cli/config/options.js +59 -4
  114. package/lib/cli/config/options.js.map +1 -1
  115. package/lib/cli/customTransport.js +5 -1
  116. package/lib/cli/customTransport.js.map +1 -1
  117. package/lib/cli/handler.js +38 -3
  118. package/lib/cli/handler.js.map +1 -1
  119. package/lib/cli/instrumentation.js +2 -2
  120. package/lib/cli/instrumentation.js.map +1 -1
  121. package/lib/cli/setupServer.d.ts +2 -1
  122. package/lib/cli/setupServer.js +52 -28
  123. package/lib/cli/setupServer.js.map +1 -1
  124. package/lib/executor/executor.d.ts +7 -14
  125. package/lib/executor/executor.js +138 -128
  126. package/lib/executor/executor.js.map +1 -1
  127. package/lib/executor/executorManager.d.ts +58 -4
  128. package/lib/executor/executorManager.js +204 -50
  129. package/lib/executor/executorManager.js.map +1 -1
  130. package/lib/executor/senderManager.d.ts +2 -1
  131. package/lib/executor/senderManager.js +3 -0
  132. package/lib/executor/senderManager.js.map +1 -1
  133. package/lib/executor/utilityWalletMonitor.d.ts +15 -0
  134. package/lib/executor/utilityWalletMonitor.js +42 -0
  135. package/lib/executor/utilityWalletMonitor.js.map +1 -0
  136. package/lib/executor/utils.d.ts +1 -2
  137. package/lib/executor/utils.js +48 -37
  138. package/lib/executor/utils.js.map +1 -1
  139. package/lib/handlers/compressionHandler.js.map +1 -0
  140. package/lib/handlers/eventManager.d.ts +21 -0
  141. package/lib/handlers/eventManager.js +196 -0
  142. package/lib/handlers/eventManager.js.map +1 -0
  143. package/{esm/utils → lib/handlers}/gasPriceManager.d.ts +19 -5
  144. package/lib/{utils → handlers}/gasPriceManager.js +58 -13
  145. package/lib/handlers/gasPriceManager.js.map +1 -0
  146. package/lib/handlers/index.d.ts +4 -0
  147. package/lib/handlers/index.js +20 -0
  148. package/lib/handlers/index.js.map +1 -0
  149. package/lib/mempool/index.d.ts +0 -1
  150. package/lib/mempool/index.js +0 -1
  151. package/lib/mempool/index.js.map +1 -1
  152. package/lib/mempool/mempool.d.ts +4 -2
  153. package/lib/mempool/mempool.js +70 -26
  154. package/lib/mempool/mempool.js.map +1 -1
  155. package/lib/mempool/reputationManager.js +7 -3
  156. package/lib/mempool/reputationManager.js.map +1 -1
  157. package/lib/rpc/EntryPointSimulationsV07.d.ts +7 -3
  158. package/lib/rpc/EntryPointSimulationsV07.js +13 -9
  159. package/lib/rpc/EntryPointSimulationsV07.js.map +1 -1
  160. package/lib/rpc/gasEstimation.d.ts +3 -3
  161. package/lib/rpc/gasEstimation.js +23 -14
  162. package/lib/rpc/gasEstimation.js.map +1 -1
  163. package/lib/rpc/nonceQueuer.d.ts +4 -1
  164. package/lib/rpc/nonceQueuer.js +9 -3
  165. package/lib/rpc/nonceQueuer.js.map +1 -1
  166. package/lib/rpc/rpcHandler.d.ts +53 -3
  167. package/lib/rpc/rpcHandler.js +147 -258
  168. package/lib/rpc/rpcHandler.js.map +1 -1
  169. package/lib/rpc/server.d.ts +2 -1
  170. package/lib/rpc/server.js +10 -1
  171. package/lib/rpc/server.js.map +1 -1
  172. package/lib/rpc/validation/SafeValidator.d.ts +5 -8
  173. package/lib/rpc/validation/SafeValidator.js +50 -207
  174. package/lib/rpc/validation/SafeValidator.js.map +1 -1
  175. package/lib/rpc/validation/TracerResultParserV07.js +6 -2
  176. package/lib/rpc/validation/TracerResultParserV07.js.map +1 -1
  177. package/lib/rpc/validation/UnsafeValidator.d.ts +7 -3
  178. package/lib/rpc/validation/UnsafeValidator.js +52 -48
  179. package/lib/rpc/validation/UnsafeValidator.js.map +1 -1
  180. package/lib/rpc/validation/tracer.js +1 -0
  181. package/lib/rpc/validation/tracer.js.map +1 -1
  182. package/lib/types/contracts/EntryPointSimulations.d.ts +0 -1
  183. package/lib/types/contracts/EntryPointSimulations.js +1942 -3
  184. package/lib/types/contracts/EntryPointSimulations.js.map +1 -1
  185. package/lib/types/contracts/PimlicoEntryPointSimulations.d.ts +1 -1
  186. package/lib/types/contracts/PimlicoEntryPointSimulations.js +2 -2
  187. package/lib/types/contracts/PimlicoEntryPointSimulations.js.map +1 -1
  188. package/lib/types/schemas.d.ts +1029 -333
  189. package/lib/types/schemas.js +93 -19
  190. package/lib/types/schemas.js.map +1 -1
  191. package/lib/types/utils.d.ts +1 -1
  192. package/lib/types/validation.js +7 -2
  193. package/lib/types/validation.js.map +1 -1
  194. package/lib/utils/bigInt.d.ts +1 -0
  195. package/lib/utils/bigInt.js +6 -1
  196. package/lib/utils/bigInt.js.map +1 -1
  197. package/lib/utils/helpers.d.ts +1 -0
  198. package/lib/utils/helpers.js +8 -1
  199. package/lib/utils/helpers.js.map +1 -1
  200. package/lib/utils/index.d.ts +0 -3
  201. package/lib/utils/index.js +0 -3
  202. package/lib/utils/index.js.map +1 -1
  203. package/lib/utils/metrics.d.ts +4 -0
  204. package/lib/utils/metrics.js +29 -1
  205. package/lib/utils/metrics.js.map +1 -1
  206. package/lib/utils/rpc-reply.d.ts +1 -1
  207. package/lib/utils/rpc-reply.js +2 -1
  208. package/lib/utils/rpc-reply.js.map +1 -1
  209. package/lib/utils/userop.d.ts +66 -6
  210. package/lib/utils/userop.js +184 -95
  211. package/lib/utils/userop.js.map +1 -1
  212. package/lib/utils/validation.d.ts +1 -1
  213. package/lib/utils/validation.js +9 -36
  214. package/lib/utils/validation.js.map +1 -1
  215. package/package.json +16 -14
  216. package/esm/executor/test/utils.d.ts +0 -13
  217. package/esm/executor/test/utils.js +0 -75
  218. package/esm/executor/test/utils.js.map +0 -1
  219. package/esm/mempool/nullMempool.d.ts +0 -15
  220. package/esm/mempool/nullMempool.js +0 -36
  221. package/esm/mempool/nullMempool.js.map +0 -1
  222. package/esm/types/test/validationTestErrors.d.ts +0 -3
  223. package/esm/types/test/validationTestErrors.js +0 -229
  224. package/esm/types/test/validationTestErrors.js.map +0 -1
  225. package/esm/utils/compressionHandler.js.map +0 -1
  226. package/esm/utils/gasPriceManager.js.map +0 -1
  227. package/esm/utils/test.d.ts +0 -17
  228. package/esm/utils/test.js +0 -130
  229. package/esm/utils/test.js.map +0 -1
  230. package/lib/executor/test/utils.d.ts +0 -13
  231. package/lib/executor/test/utils.js +0 -81
  232. package/lib/executor/test/utils.js.map +0 -1
  233. package/lib/mempool/nullMempool.d.ts +0 -15
  234. package/lib/mempool/nullMempool.js +0 -40
  235. package/lib/mempool/nullMempool.js.map +0 -1
  236. package/lib/types/test/validationTestErrors.d.ts +0 -3
  237. package/lib/types/test/validationTestErrors.js +0 -232
  238. package/lib/types/test/validationTestErrors.js.map +0 -1
  239. package/lib/utils/compressionHandler.js.map +0 -1
  240. package/lib/utils/gasPriceManager.js.map +0 -1
  241. package/lib/utils/test.d.ts +0 -17
  242. package/lib/utils/test.js +0 -161
  243. package/lib/utils/test.js.map +0 -1
  244. /package/esm/{utils → handlers}/compressionHandler.d.ts +0 -0
  245. /package/esm/{utils → handlers}/compressionHandler.js +0 -0
  246. /package/lib/{utils → handlers}/compressionHandler.d.ts +0 -0
  247. /package/lib/{utils → handlers}/compressionHandler.js +0 -0
@@ -1,9 +1,7 @@
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";
1
+ import { EntryPointV06Abi, EntryPointV07Abi, IOpInflatorAbi, RpcError, ValidationErrors, bundlerGetStakeStatusResponseSchema, deriveUserOperation } from "../types/index.js";
2
+ import { calcPreVerificationGas, calcVerificationGasAndCallGasLimit, getAAError, getNonceKeyAndValue, getUserOperationHash, isVersion06, isVersion07, maxBigInt, parseUserOperationReceipt, toUnpackedUserOperation } from "../utils/index.js";
3
+ import { TransactionNotFoundError, decodeFunctionData, getAbiItem, getAddress, getContract, slice, toFunctionSelector } from "viem";
4
+ import { base, baseSepolia, optimism } from "viem/chains";
7
5
  export class RpcHandler {
8
6
  entryPoints;
9
7
  publicClient;
@@ -27,7 +25,9 @@ export class RpcHandler {
27
25
  gasPriceManager;
28
26
  gasPriceMultipliers;
29
27
  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) {
28
+ eventManager;
29
+ enableInstantBundlingEndpoint;
30
+ constructor(entryPoints, publicClient, validator, mempool, executor, monitor, nonceQueuer, executorManager, reputationManager, usingTenderly, rpcMaxBlockRange, logger, metrics, enableDebugEndpoints, compressionHandler, legacyTransactions, gasPriceManager, gasPriceMultipliers, chainType, paymasterGasLimitMultiplier, eventManager, enableInstantBundlingEndpoint, dangerousSkipUserOperationValidation = false) {
31
31
  this.entryPoints = entryPoints;
32
32
  this.publicClient = publicClient;
33
33
  this.validator = validator;
@@ -51,6 +51,8 @@ export class RpcHandler {
51
51
  this.chainType = chainType;
52
52
  this.gasPriceManager = gasPriceManager;
53
53
  this.paymasterGasLimitMultiplier = paymasterGasLimitMultiplier;
54
+ this.enableInstantBundlingEndpoint = enableInstantBundlingEndpoint;
55
+ this.eventManager = eventManager;
54
56
  }
55
57
  async handleMethod(request, apiVersion) {
56
58
  // call the method with the params
@@ -141,6 +143,47 @@ export class RpcHandler {
141
143
  method,
142
144
  result: await this.pimlico_sendCompressedUserOperation(apiVersion, ...request.params)
143
145
  };
146
+ case "pimlico_sendUserOperationNow":
147
+ return {
148
+ method,
149
+ result: await this.pimlico_sendUserOperationNow(apiVersion, ...request.params)
150
+ };
151
+ }
152
+ }
153
+ ensureEntryPointIsSupported(entryPoint) {
154
+ if (!this.entryPoints.includes(entryPoint)) {
155
+ throw new Error(`EntryPoint ${entryPoint} not supported, supported EntryPoints: ${this.entryPoints.join(", ")}`);
156
+ }
157
+ }
158
+ ensureDebugEndpointsAreEnabled(methodName) {
159
+ if (!this.enableDebugEndpoints) {
160
+ throw new RpcError(`${methodName} is only available in development environment`);
161
+ }
162
+ }
163
+ async preMempoolChecks(opHash, userOperation, apiVersion, entryPoint) {
164
+ if (this.legacyTransactions &&
165
+ userOperation.maxFeePerGas !== userOperation.maxPriorityFeePerGas) {
166
+ const reason = "maxPriorityFeePerGas must equal maxFeePerGas on chains that don't support EIP-1559";
167
+ this.eventManager.emitFailedValidation(opHash, reason);
168
+ throw new RpcError(reason);
169
+ }
170
+ if (apiVersion !== "v1") {
171
+ await this.gasPriceManager.validateGasPrice({
172
+ maxFeePerGas: userOperation.maxFeePerGas,
173
+ maxPriorityFeePerGas: userOperation.maxPriorityFeePerGas
174
+ });
175
+ }
176
+ if (userOperation.verificationGasLimit < 10000n) {
177
+ const reason = "verificationGasLimit must be at least 10000";
178
+ this.eventManager.emitFailedValidation(opHash, reason);
179
+ throw new RpcError(reason);
180
+ }
181
+ this.logger.trace({ userOperation, entryPoint }, "beginning validation");
182
+ if (userOperation.preVerificationGas === 0n ||
183
+ userOperation.verificationGasLimit === 0n) {
184
+ const reason = "user operation gas limits must be larger than 0";
185
+ this.eventManager.emitFailedValidation(opHash, reason);
186
+ throw new RpcError(reason);
144
187
  }
145
188
  }
146
189
  eth_chainId() {
@@ -150,10 +193,7 @@ export class RpcHandler {
150
193
  return this.entryPoints;
151
194
  }
152
195
  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
- }
196
+ this.ensureEntryPointIsSupported(entryPoint);
157
197
  if (userOperation.maxFeePerGas === 0n) {
158
198
  throw new RpcError("user operation max fee per gas must be larger than 0 during gas estimation");
159
199
  }
@@ -163,14 +203,9 @@ export class RpcHandler {
163
203
  userOperation.preVerificationGas = 1000000n;
164
204
  userOperation.verificationGasLimit = 10000000n;
165
205
  userOperation.callGasLimit = 10000000n;
166
- if (this.chainId === chains.base.id) {
206
+ if (this.chainId === base.id) {
167
207
  userOperation.verificationGasLimit = 5000000n;
168
208
  }
169
- if (this.chainId === chains.celoAlfajores.id ||
170
- this.chainId === chains.celo.id) {
171
- userOperation.verificationGasLimit = 1000000n;
172
- userOperation.callGasLimit = 1000000n;
173
- }
174
209
  if (isVersion07(userOperation)) {
175
210
  userOperation.paymasterPostOpGasLimit = 2000000n;
176
211
  userOperation.paymasterVerificationGasLimit = 5000000n;
@@ -221,12 +256,10 @@ export class RpcHandler {
221
256
  paymasterPostOpGasLimit =
222
257
  (paymasterPostOpGasLimit * multiplier) / 100n;
223
258
  }
224
- if (this.chainId === chains.base.id ||
225
- this.chainId === chains.baseSepolia.id) {
259
+ if (this.chainId === base.id || this.chainId === baseSepolia.id) {
226
260
  callGasLimit += 10000n;
227
261
  }
228
- if (this.chainId === chains.base.id ||
229
- this.chainId === chains.optimism.id) {
262
+ if (this.chainId === base.id || this.chainId === optimism.id) {
230
263
  callGasLimit = maxBigInt(callGasLimit, 120000n);
231
264
  }
232
265
  if (userOperation.callData === "0x") {
@@ -256,10 +289,11 @@ export class RpcHandler {
256
289
  };
257
290
  }
258
291
  async eth_sendUserOperation(apiVersion, userOperation, entryPoint) {
292
+ const hash = getUserOperationHash(userOperation, entryPoint, this.chainId);
293
+ this.eventManager.emitReceived(hash);
259
294
  let status = "rejected";
260
295
  try {
261
296
  status = await this.addToMempoolIfValid(userOperation, entryPoint, apiVersion);
262
- const hash = getUserOperationHash(userOperation, entryPoint, this.chainId);
263
297
  return hash;
264
298
  }
265
299
  catch (error) {
@@ -323,27 +357,38 @@ export class RpcHandler {
323
357
  if (!tx.to) {
324
358
  return null;
325
359
  }
326
- let op = undefined;
360
+ let op;
327
361
  try {
328
362
  const decoded = decodeFunctionData({
329
- abi: EntryPointV06Abi,
363
+ abi: [...EntryPointV06Abi, ...EntryPointV07Abi],
330
364
  data: tx.input
331
365
  });
332
366
  if (decoded.functionName !== "handleOps") {
333
367
  return null;
334
368
  }
335
369
  const ops = decoded.args[0];
336
- op = ops.find((op) => op.sender === userOperationEvent.args.sender &&
370
+ const foundOp = ops.find((op) => op.sender === userOperationEvent.args.sender &&
337
371
  op.nonce === userOperationEvent.args.nonce);
372
+ if (foundOp === undefined) {
373
+ return null;
374
+ }
375
+ const handleOpsV07AbiItem = getAbiItem({
376
+ abi: EntryPointV07Abi,
377
+ name: "handleOps"
378
+ });
379
+ const handleOpsV07Selector = toFunctionSelector(handleOpsV07AbiItem);
380
+ if (slice(tx.input, 0, 4) === handleOpsV07Selector) {
381
+ op = toUnpackedUserOperation(foundOp);
382
+ }
383
+ else {
384
+ op = foundOp;
385
+ }
338
386
  }
339
387
  catch {
340
388
  return null;
341
389
  }
342
- if (op === undefined) {
343
- return null;
344
- }
345
390
  const result = {
346
- userOperation: isVersion06(op) ? op : toUnpackedUserOperation(op),
391
+ userOperation: op,
347
392
  entryPoint: getAddress(tx.to),
348
393
  transactionHash: txHash,
349
394
  blockHash: tx.blockHash ?? "0x",
@@ -351,211 +396,53 @@ export class RpcHandler {
351
396
  };
352
397
  return result;
353
398
  }
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;
399
+ eth_getUserOperationReceipt(userOperationHash) {
400
+ return this.executorManager.getUserOperationReceipt(userOperationHash);
492
401
  }
493
402
  debug_bundler_clearState() {
494
- if (!this.enableDebugEndpoints) {
495
- throw new RpcError("debug_bundler_clearState is only available in development environment");
496
- }
403
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_clearState");
497
404
  this.mempool.clear();
498
405
  this.reputationManager.clear();
499
406
  return "ok";
500
407
  }
501
408
  debug_bundler_clearMempool() {
502
- if (!this.enableDebugEndpoints) {
503
- throw new RpcError("debug_bundler_clearMempool is only available in development environment");
504
- }
409
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_clearMempool");
505
410
  this.mempool.clear();
506
411
  this.reputationManager.clearEntityCount();
507
412
  return "ok";
508
413
  }
509
414
  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
- }
415
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_dumpMempool");
416
+ this.ensureEntryPointIsSupported(entryPoint);
516
417
  return this.mempool
517
418
  .dumpOutstanding()
518
419
  .map((userOpInfo) => deriveUserOperation(userOpInfo.mempoolUserOperation));
519
420
  }
520
421
  async debug_bundler_sendBundleNow() {
521
- if (!this.enableDebugEndpoints) {
522
- throw new RpcError("debug_bundler_sendBundleNow is only available in development environment");
523
- }
422
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_sendBundleNow");
524
423
  const transactions = await this.executorManager.bundleNow();
525
424
  return transactions[0];
526
425
  }
527
426
  debug_bundler_setBundlingMode(bundlingMode) {
528
- if (!this.enableDebugEndpoints) {
529
- throw new RpcError("debug_bundler_setBundlingMode is only available in development environment");
530
- }
427
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_setBundlingMode");
531
428
  this.executorManager.setBundlingMode(bundlingMode);
532
429
  return "ok";
533
430
  }
534
431
  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
- }
432
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_setReputation");
433
+ this.ensureEntryPointIsSupported(entryPoint);
541
434
  return this.reputationManager.dumpReputations(entryPoint);
542
435
  }
543
436
  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
- }
437
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_getStakeStatus");
438
+ this.ensureEntryPointIsSupported(entryPoint);
550
439
  return bundlerGetStakeStatusResponseSchema.parse({
551
440
  method: "debug_bundler_getStakeStatus",
552
441
  result: await this.reputationManager.getStakeStatus(entryPoint, address)
553
442
  }).result;
554
443
  }
555
444
  debug_bundler_setReputation(args) {
556
- if (!this.enableDebugEndpoints) {
557
- throw new RpcError("debug_bundler_setReputation is only available in development environment");
558
- }
445
+ this.ensureDebugEndpointsAreEnabled("debug_bundler_setReputation");
559
446
  this.reputationManager.setReputation(args[1], args[0]);
560
447
  return "ok";
561
448
  }
@@ -563,57 +450,44 @@ export class RpcHandler {
563
450
  return this.monitor.getUserOperationStatus(userOperationHash);
564
451
  }
565
452
  async pimlico_getUserOperationGasPrice() {
566
- const gasPrice = await this.gasPriceManager.getGasPrice();
453
+ let { maxFeePerGas, maxPriorityFeePerGas } = await this.gasPriceManager.getGasPrice();
454
+ if (this.chainType === "hedera") {
455
+ maxFeePerGas /= 10n ** 9n;
456
+ maxPriorityFeePerGas /= 10n ** 9n;
457
+ }
567
458
  const { slow, standard, fast } = this.gasPriceMultipliers;
568
459
  return {
569
460
  slow: {
570
- maxFeePerGas: (gasPrice.maxFeePerGas * slow) / 100n,
571
- maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * slow) / 100n
461
+ maxFeePerGas: (maxFeePerGas * slow) / 100n,
462
+ maxPriorityFeePerGas: (maxPriorityFeePerGas * slow) / 100n
572
463
  },
573
464
  standard: {
574
- maxFeePerGas: (gasPrice.maxFeePerGas * standard) / 100n,
575
- maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * standard) / 100n
465
+ maxFeePerGas: (maxFeePerGas * standard) / 100n,
466
+ maxPriorityFeePerGas: (maxPriorityFeePerGas * standard) / 100n
576
467
  },
577
468
  fast: {
578
- maxFeePerGas: (gasPrice.maxFeePerGas * fast) / 100n,
579
- maxPriorityFeePerGas: (gasPrice.maxPriorityFeePerGas * fast) / 100n
469
+ maxFeePerGas: (maxFeePerGas * fast) / 100n,
470
+ maxPriorityFeePerGas: (maxPriorityFeePerGas * fast) / 100n
580
471
  }
581
472
  };
582
473
  }
583
474
  // check if we want to bundle userOperation. If yes, add to mempool
584
475
  async addToMempoolIfValid(op, entryPoint, apiVersion) {
476
+ this.ensureEntryPointIsSupported(entryPoint);
585
477
  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
- }
478
+ const opHash = getUserOperationHash(userOperation, entryPoint, this.chainId);
479
+ await this.preMempoolChecks(opHash, userOperation, apiVersion, entryPoint);
610
480
  const currentNonceValue = await this.getNonceValue(userOperation, entryPoint);
611
481
  const [, userOperationNonceValue] = getNonceKeyAndValue(userOperation.nonce);
612
482
  if (userOperationNonceValue < currentNonceValue) {
613
- throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
483
+ const reason = "UserOperation failed validation with reason: AA25 invalid account nonce";
484
+ this.eventManager.emitFailedValidation(opHash, reason, "AA25");
485
+ throw new RpcError(reason, ValidationErrors.InvalidFields);
614
486
  }
615
487
  if (userOperationNonceValue > currentNonceValue + 10n) {
616
- throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
488
+ const reason = "UserOperation failed validaiton with reason: AA25 invalid account nonce";
489
+ this.eventManager.emitFailedValidation(opHash, reason, "AA25");
490
+ throw new RpcError(reason, ValidationErrors.InvalidFields);
617
491
  }
618
492
  let queuedUserOperations = [];
619
493
  if (userOperationNonceValue > currentNonceValue &&
@@ -623,9 +497,10 @@ export class RpcHandler {
623
497
  if (userOperationNonceValue ===
624
498
  currentNonceValue + BigInt(queuedUserOperations.length)) {
625
499
  if (this.dangerousSkipUserOperationValidation) {
626
- const success = this.mempool.add(op, entryPoint);
500
+ const [success, errorReason] = this.mempool.add(op, entryPoint);
627
501
  if (!success) {
628
- throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
502
+ this.eventManager.emitFailedValidation(opHash, errorReason, getAAError(errorReason));
503
+ throw new RpcError(`UserOperation reverted during simulation with reason: ${errorReason}`, ValidationErrors.InvalidFields);
629
504
  }
630
505
  }
631
506
  else {
@@ -635,9 +510,10 @@ export class RpcHandler {
635
510
  const validationResult = await this.validator.validateUserOperation(apiVersion !== "v1", userOperation, queuedUserOperations, entryPoint);
636
511
  await this.reputationManager.checkReputation(userOperation, entryPoint, validationResult);
637
512
  await this.mempool.checkEntityMultipleRoleViolation(userOperation);
638
- const success = this.mempool.add(op, entryPoint, validationResult.referencedContracts);
513
+ const [success, errorReason] = this.mempool.add(op, entryPoint, validationResult.referencedContracts);
639
514
  if (!success) {
640
- throw new RpcError("UserOperation reverted during simulation with reason: AA25 invalid account nonce", ValidationErrors.InvalidFields);
515
+ this.eventManager.emitFailedValidation(opHash, errorReason, getAAError(errorReason));
516
+ throw new RpcError(`UserOperation reverted during simulation with reason: ${errorReason}`, ValidationErrors.InvalidFields);
641
517
  }
642
518
  return "added";
643
519
  }
@@ -645,10 +521,47 @@ export class RpcHandler {
645
521
  this.nonceQueuer.add(op, entryPoint);
646
522
  return "queued";
647
523
  }
524
+ async pimlico_sendUserOperationNow(apiVersion, userOperation, entryPoint) {
525
+ if (!this.enableInstantBundlingEndpoint) {
526
+ throw new RpcError("pimlico_sendUserOperationNow endpoint is not enabled", ValidationErrors.InvalidFields);
527
+ }
528
+ this.ensureEntryPointIsSupported(entryPoint);
529
+ const opHash = getUserOperationHash(userOperation, entryPoint, this.chainId);
530
+ await this.preMempoolChecks(opHash, userOperation, apiVersion, entryPoint);
531
+ const result = (await this.executor.bundle(entryPoint, [userOperation]))[0];
532
+ if (result.status === "failure") {
533
+ const { userOpHash, reason } = result.error;
534
+ this.monitor.setUserOperationStatus(userOpHash, {
535
+ status: "rejected",
536
+ transactionHash: null
537
+ });
538
+ this.logger.warn({
539
+ userOperation: JSON.stringify(result.error.userOperation, (_k, v) => (typeof v === "bigint" ? v.toString() : v)),
540
+ userOpHash,
541
+ reason
542
+ }, "user operation rejected");
543
+ this.metrics.userOperationsSubmitted
544
+ .labels({ status: "failed" })
545
+ .inc();
546
+ const { error } = result;
547
+ throw new RpcError(`userOperation reverted during simulation with reason: ${error.reason}`);
548
+ }
549
+ const res = result;
550
+ // wait for receipt
551
+ const receipt = await this.publicClient.waitForTransactionReceipt({
552
+ hash: res.value.transactionInfo.transactionHash,
553
+ pollingInterval: 100
554
+ });
555
+ const userOperationReceipt = parseUserOperationReceipt(opHash, receipt);
556
+ return userOperationReceipt;
557
+ }
648
558
  async pimlico_sendCompressedUserOperation(apiVersion, compressedCalldata, inflatorAddress, entryPoint) {
559
+ const receivedTimestamp = Date.now();
649
560
  let status = "rejected";
650
561
  try {
651
562
  const { inflatedOp, inflatorId } = await this.validateAndInflateCompressedUserOperation(inflatorAddress, compressedCalldata);
563
+ const hash = getUserOperationHash(inflatedOp, entryPoint, this.chainId);
564
+ this.eventManager.emitReceived(hash, receivedTimestamp);
652
565
  const compressedUserOp = {
653
566
  compressedCalldata,
654
567
  inflatedOp,
@@ -657,7 +570,6 @@ export class RpcHandler {
657
570
  };
658
571
  // check userOps inputs.
659
572
  status = await this.addToMempoolIfValid(compressedUserOp, entryPoint, apiVersion);
660
- const hash = getUserOperationHash(inflatedOp, entryPoint, this.chainId);
661
573
  return hash;
662
574
  }
663
575
  catch (error) {