Skip to content

Commit

Permalink
Merge branch 'main' into cleanup-executors
Browse files Browse the repository at this point in the history
  • Loading branch information
mouseless0x committed Feb 4, 2025
2 parents 106e1a9 + f4e6085 commit 21f837c
Show file tree
Hide file tree
Showing 11 changed files with 135 additions and 93 deletions.
53 changes: 32 additions & 21 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 15 additions & 7 deletions src/cli/alto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ import {
serverOptions
} from "./config"
import { registerCommandToYargs } from "./util"
import { TimeoutError, HttpRequestError, InternalRpcError } from "viem"
import {
TimeoutError,
HttpRequestError,
InternalRpcError,
} from "viem"

// Load environment variables from .env file
if (process.env.DOTENV_CONFIG_PATH) {
Expand All @@ -27,18 +31,22 @@ if (process.env.SENTRY_DSN) {
const SENTRY_IGNORE_ERRORS = [
InternalRpcError,
HttpRequestError,
TimeoutError
TimeoutError,
]

sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.ENVIRONMENT,
beforeSend(event, hint) {
if (
SENTRY_IGNORE_ERRORS.some(
(error) => hint.originalException instanceof error
)
) {
const errorType = event.exception?.values?.[0]?.type

const shouldIgnore = SENTRY_IGNORE_ERRORS.some(
(error) =>
hint.originalException instanceof error ||
errorType === error.name
)

if (shouldIgnore) {
return null
}

Expand Down
4 changes: 2 additions & 2 deletions src/cli/config/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ export const bundlerArgsSchema = z.object({
)}`
),
"enable-instant-bundling-endpoint": z.boolean(),
"enable-experimental-7702-endpoints": z.boolean()
"enable-experimental-7702-endpoints": z.boolean(),
"should-check-prefund": z.boolean()
})

export const executorArgsSchema = z.object({
Expand Down Expand Up @@ -177,7 +178,6 @@ export const logArgsSchema = z.object({
"redis-queue-endpoint": z.string().optional(),
"redis-event-manager-queue-name": z.string().optional(),
json: z.boolean(),
"network-name": z.string(),
"log-level": logLevel,
"public-client-log-level": logLevel.optional(),
"wallet-client-log-level": logLevel.optional(),
Expand Down
12 changes: 6 additions & 6 deletions src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,12 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
"Should the bundler enable the pimlico_experimental_sendUserOperation7702 and pimlico_experimental_estimateUserOperationGas7702 endpoint",
type: "boolean",
default: false
},
"should-check-prefund": {
description:
"Should the bundler check userOp's prefund before accepting it",
type: "boolean",
default: true
}
}

Expand Down Expand Up @@ -446,12 +452,6 @@ export const logOptions: CliCommandOptions<ILogArgsInput> = {
require: true,
default: false
},
"network-name": {
description: "Name of the network (used for metrics)",
type: "string",
require: true,
default: "localhost"
},
"log-level": {
description: "Default log level",
type: "string",
Expand Down
6 changes: 1 addition & 5 deletions src/cli/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export async function bundlerHandler(args_: IOptionsInput): Promise<void> {

const chain: Chain = {
id: chainId,
name: args.networkName,
name: 'chain-name', // isn't important, never used
nativeCurrency: {
name: "ETH",
symbol: "ETH",
Expand Down Expand Up @@ -157,10 +157,6 @@ export async function bundlerHandler(args_: IOptionsInput): Promise<void> {
await gasPriceManager.init()

const registry = new Registry()
registry.setDefaultLabels({
network: chain.name,
chainId
})
const metrics = createMetrics(registry)

await preFlightChecks(config)
Expand Down
3 changes: 1 addition & 2 deletions src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,6 @@
"lint:fix": "eslint src/**/*.ts --fix"
},
"dependencies": {
"bull": "^4.15.1",
"@fastify/cors": "^9.0.1",
"@fastify/websocket": "^10.0.1",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/core": "^1.25.1",
Expand All @@ -50,6 +48,7 @@
"@types/ws": "^8.5.10",
"abitype": "^0.8.0",
"async-mutex": "^0.4.0",
"bull": "^4.15.1",
"dotenv": "^16.0.3",
"fastify": "^4.25.2",
"ioredis": "^5.4.1",
Expand Down
4 changes: 3 additions & 1 deletion src/rpc/rpcHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -749,8 +749,10 @@ export class RpcHandler implements IRpcEndpoint {
})
}

const shouldCheckPrefund =
apiVersion !== "v1" || this.config.shouldCheckPrefund
const validationResult = await this.validator.validateUserOperation({
shouldCheckPrefund: apiVersion !== "v1",
shouldCheckPrefund,
userOperation,
queuedUserOperations,
entryPoint
Expand Down
48 changes: 21 additions & 27 deletions src/rpc/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
jsonRpcSchema
} from "@alto/types"
import type { Metrics } from "@alto/utils"
import cors from "@fastify/cors"
import websocket from "@fastify/websocket"
import * as sentry from "@sentry/node"
import Fastify, {
Expand All @@ -21,9 +20,10 @@ import type { Registry } from "prom-client"
import { toHex } from "viem"
import type * as WebSocket from "ws"
import { fromZodError } from "zod-validation-error"
import type { AltoConfig } from "../createConfig"
import rpcDecorators, { RpcStatus } from "../utils/fastify-rpc-decorators"
import RpcReply from "../utils/rpc-reply"
import type { IRpcEndpoint } from "./rpcHandler"
import type { AltoConfig } from "../createConfig"

// jsonBigIntOverride.ts
const originalJsonStringify = JSON.stringify
Expand Down Expand Up @@ -59,16 +59,6 @@ JSON.stringify = (
return originalJsonStringify(value, wrapperReplacer, space)
}

declare module "fastify" {
interface FastifyRequest {
rpcMethod: string
}

interface FastifyReply {
rpcStatus: "failed" | "success"
}
}

export class Server {
private config: AltoConfig
private fastify: FastifyInstance
Expand Down Expand Up @@ -101,20 +91,14 @@ export class Server {
disableRequestLogging: true
})

this.fastify.register(rpcDecorators)

this.fastify.register(websocket, {
options: {
maxPayload: config.websocketMaxPayloadSize
}
})

this.fastify.register(cors, {
origin: "*",
methods: ["POST", "GET", "OPTIONS"]
})

this.fastify.decorateRequest("rpcMethod", null)
this.fastify.decorateReply("rpcStatus", null)

this.fastify.addHook("onResponse", (request, reply) => {
const ignoredRoutes = ["/health", "/metrics"]
if (ignoredRoutes.includes(request.routeOptions.url)) {
Expand Down Expand Up @@ -221,7 +205,6 @@ export class Server {
}

private async rpc(request: FastifyRequest, reply: RpcReply): Promise<void> {
reply.rpcStatus = "failed" // default to failed
let requestId: number | null = null

const versionParsingResult = altoVersions.safeParse(
Expand Down Expand Up @@ -283,7 +266,6 @@ export class Server {
bundlerRequestParsing.error
)

//
if (
validationError.message.includes(
"Missing/invalid userOpHash"
Expand Down Expand Up @@ -331,8 +313,11 @@ export class Server {
result: result.result
}

await reply.status(200).send(jsonRpcResponse)
reply.rpcStatus = "success"
await reply
.setRpcStatus(RpcStatus.Success)
.status(200)
.send(jsonRpcResponse)

this.fastify.log.info(
{
data:
Expand All @@ -359,7 +344,10 @@ export class Server {
code: err.code
}
}
await reply.status(200).send(rpcError)
await reply
.setRpcStatus(RpcStatus.ClientError)
.status(200)
.send(rpcError)
this.fastify.log.info(rpcError, "error reply")
} else if (err instanceof Error) {
sentry.captureException(err)
Expand All @@ -371,7 +359,10 @@ export class Server {
}
}

await reply.status(500).send(rpcError)
await reply
.setRpcStatus(RpcStatus.ServerError)
.status(500)
.send(rpcError)
this.fastify.log.error(err, "error reply (non-rpc)")
} else {
const rpcError = {
Expand All @@ -382,7 +373,10 @@ export class Server {
}
}

await reply.status(500).send(rpcError)
await reply
.setRpcStatus(RpcStatus.ServerError)
.status(500)
.send(rpcError)
this.fastify.log.error(
{ err },
"error reply (unhandled error type)"
Expand Down
39 changes: 39 additions & 0 deletions src/utils/fastify-rpc-decorators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { FastifyPluginCallback, FastifyReply } from "fastify"

declare module "fastify" {
interface FastifyRequest {
rpcMethod: string
}

interface FastifyReply {
rpcStatus: RpcStatus
setRpcStatus(rpcStatus: RpcStatus): FastifyReply
}
}

export enum RpcStatus {
Unset = "unset",
ServerError = "server_error",
ClientError = "client_error",
Success = "success"
}

// define plugin using callbacks
const plugin: FastifyPluginCallback = (fastify, _, done) => {
fastify.decorateRequest("rpcMethod", null)
fastify.decorateReply("rpcStatus", RpcStatus.Unset)
fastify.decorateReply(
"setRpcStatus",
function (rpcStatus: RpcStatus): FastifyReply {
this.rpcStatus = rpcStatus
return this
}
)

done()
}

// Type assertion to allow symbol indexing
;(plugin as any)[Symbol.for("skip-override")] = true

export default plugin
Loading

0 comments on commit 21f837c

Please sign in to comment.