Skip to content

Commit

Permalink
add bundler instance for prool
Browse files Browse the repository at this point in the history
  • Loading branch information
plusminushalf committed Jun 5, 2024
1 parent 7e7eb4b commit f3ab2cd
Show file tree
Hide file tree
Showing 8 changed files with 147 additions and 5 deletions.
1 change: 0 additions & 1 deletion .github/workflows/canary.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
name: Release (Canary)
on:
push:
branches: [main]
workflow_dispatch:

jobs:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"clean": "rm -rf ./packages/alto/lib ./src/*.tsbuildinfo",
"clean-modules": "rm -rf ./packages/alto/node_modules node_modules",
"build": "pnpm -r run build",
"start": "node ./packages/alto/lib/cli/alto.js run",
"start": "pnpm run --filter @pimlico/alto start",
"dev": "pnpm -r run dev",
"test": "pnpm -r --workspace-concurrency 1 test --verbose=true",
"test:spec": "./packages/spec-tests/run-spec-tests.sh",
Expand Down
File renamed without changes.
116 changes: 116 additions & 0 deletions packages/alto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { type ResultPromise, execa } from "execa"
import { defineInstance } from "prool"

export type AltoParameters = {
rpcUrl: string
entrypoints: string[]
executorPrivateKey: string
host?: string
port?: number
path?: string
}

export function toFlagCase(key: string) {
return `--${key.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)}`
}

export function toArgs(options: {
[key: string]:
| Record<string, string>
| string
| boolean
| number
| bigint
| undefined
}) {
return Object.entries(options).flatMap(([key, value]) => {
if (value === undefined) {
return []
}

if (typeof value === "object" && value !== null) {
return Object.entries(value).flatMap(([subKey, subValue]) => {
if (subValue === undefined) {
return []
}
const flag = toFlagCase(key)
const value = `${subKey}: ${subValue}`
return [flag, value]
})
}

const flag = toFlagCase(key)

if (value === false) {
return []
}
if (value === true) {
return [flag]
}

const stringified = value.toString()
if (stringified === "") {
return [flag]
}

return [flag, stringified]
})
}

export const bundler = defineInstance((parameters: AltoParameters) => {
const { path = "./alto", ...args } = parameters

let process: ResultPromise<{ cleanup: true; reject: false }>

return {
_internal: {},
host: args.host || "localhost",
name: "alto",
port: args.port ?? 4337,
start: async ({ emitter, port = args.port, status }) => {
const { promise, resolve, reject } = Promise.withResolvers<void>()

const commandArgs = toArgs({
...args,
port,
entrypoints: args.entrypoints.join(",")
})

process = execa(path, commandArgs, {
cleanup: true,
reject: false
})

process.stdout.on("data", (data) => {
const message = data.toString()
emitter.emit("message", message)
emitter.emit("stdout", message)
if (message.includes("Listening on")) {
emitter.emit("listening")
resolve()
}
})
process.stderr.on("data", async (data) => {
const message = data.toString()
emitter.emit("message", message)
emitter.emit("stderr", message)
await stop()
reject(new Error(`Failed to start anvil: ${data.toString()}`))
})
process.on("close", () => process.removeAllListeners())
process.on("exit", (code, signal) => {
emitter.emit("exit", code, signal)

if (!code) {
process.removeAllListeners()
if (status === "starting") {
reject(new Error("Failed to start anvil: exited."))
}
}
})

return promise
},
stop: async () => {}
}
})
5 changes: 4 additions & 1 deletion packages/alto/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"lib/**/*.d.ts",
"lib/**/*.js",
"lib/**/*.js.map",
"./alto",
"*.d.ts",
"*.js"
],
Expand All @@ -22,7 +23,8 @@
"dev": "nodemon --exec DOTENV_CONFIG_PATH=$(pwd)/../.env ts-node -r tsconfig-paths/register cli/alto.ts run",
"test": "test -d test && mocha test/**/*.test.ts --exit || echo 'No test folder found. Skipping tests.'",
"lint": "eslint ./**/*.ts",
"lint:fix": "eslint ./**/*.ts --fix"
"lint:fix": "eslint ./**/*.ts --fix",
"start": "node ./lib/cli/alto.js run"
},
"exports": {
".": {
Expand All @@ -48,6 +50,7 @@
"abitype": "^0.8.0",
"async-mutex": "^0.4.0",
"dotenv": "^16.0.3",
"execa": "^9.1.0",
"fastify": "^4.25.2",
"fastify-cors": "3.0.3",
"opentelemetry-instrumentation-fetch-node": "^1.1.2",
Expand Down
1 change: 1 addition & 0 deletions packages/tests-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"dependencies": {
"@types/node": "^18.16.3",
"permissionless": "^0.1.25",
"prool": "^0.0.4",
"ts-node": "^10.9.2",
"viem": "^2.9.5",
"vitest": "^1.6.0",
Expand Down
21 changes: 19 additions & 2 deletions packages/tests-e2e/tests/eth_getUserOperationReceipt.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
import { test, describe, expect, beforeAll, beforeEach } from "vitest"
import {
ENTRYPOINT_ADDRESS_V06,
BundlerClient,
type BundlerClient,
ENTRYPOINT_ADDRESS_V07
} from "permissionless"
import {
beforeEachCleanUp,
getBundlerClient,
getSmartAccountClient
} from "../src/utils"
import { Address, Hex } from "viem"
import type { Address, Hex } from "viem"
import {
deployRevertingContract,
decodeRevert,
getRevertCall
} from "../src/revertingContract"
import { deployPaymaster } from "../src/testPaymaster"
import { bundler } from "@pimlico/alto"
import { createServer } from "prool"

describe.each([
{ entryPoint: ENTRYPOINT_ADDRESS_V06, version: "v0.6" },
Expand All @@ -29,6 +31,21 @@ describe.each([
revertingContract = await deployRevertingContract()
paymaster = await deployPaymaster(entryPoint)
bundlerClient = getBundlerClient(entryPoint)

const bundlerInstance = bundler({
rpcUrl: "http://127.0.0.1:8545",
entrypoints: [ENTRYPOINT_ADDRESS_V06, ENTRYPOINT_ADDRESS_V07],
executorPrivateKey:
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
})

bundlerInstance.on("message", console.log)

const bundlerServer = createServer({
instance: bundlerInstance
})

await bundlerServer.start()
})

beforeEach(async () => {
Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

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

0 comments on commit f3ab2cd

Please sign in to comment.