diff --git a/lerna.json b/lerna.json index bed9b857..c09428df 100644 --- a/lerna.json +++ b/lerna.json @@ -4,7 +4,7 @@ ], "npmClient": "yarn", "useWorkspaces": true, - "version": "0.0.43", + "version": "0.0.44", "stream": "true", "command": { "version": { diff --git a/package.json b/package.json index 4541cb80..69a59d88 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "root", "private": true, - "version": "0.0.43", + "version": "0.0.44", "engines": { "node": ">=18.0.0" }, diff --git a/packages/api/package.json b/packages/api/package.json index e2bb606c..49afe62f 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -1,6 +1,6 @@ { "name": "api", - "version": "0.0.43", + "version": "0.0.44", "description": "The API module of Etherspot bundler client", "author": "Etherspot", "homepage": "https://https://github.com/etherspot/skandha#readme", @@ -35,12 +35,12 @@ "class-transformer": "0.5.1", "class-validator": "0.14.0", "ethers": "5.7.2", - "executor": "^0.0.43", + "executor": "^0.0.44", "fastify": "4.14.1", "pino": "8.11.0", "pino-pretty": "10.0.0", "reflect-metadata": "0.1.13", - "types": "^0.0.43" + "types": "^0.0.44" }, "devDependencies": { "@types/connect": "3.4.35" diff --git a/packages/api/src/app.ts b/packages/api/src/app.ts index 506e8705..dfedc702 100644 --- a/packages/api/src/app.ts +++ b/packages/api/src/app.ts @@ -9,6 +9,7 @@ import logger from "./logger"; import { BundlerRPCMethods, CustomRPCMethods, + HttpStatus, RedirectedRPCMethods, } from "./constants"; import { EthAPI, DebugAPI, Web3API, RedirectAPI } from "./modules"; @@ -139,9 +140,9 @@ export class ApiApp { if (this.redirectRpc && method in RedirectedRPCMethods) { const body = await redirectApi.redirect(method, params); if (body.error) { - return res.status(200).send({ ...body, id }); + return res.status(HttpStatus.OK).send({ ...body, id }); } - return res.status(200).send({ jsonrpc, id, ...body }); + return res.status(HttpStatus.OK).send({ jsonrpc, id, ...body }); } if (result === undefined) { @@ -197,6 +198,14 @@ export class ApiApp { newestBlock: params[2], }); break; + case CustomRPCMethods.skandha_config: + result = await skandhaApi.getConfig(); + // skip hexlify for this particular rpc + return res.status(HttpStatus.OK).send({ + jsonrpc, + id, + result, + }); default: throw new RpcError( `Method ${method} is not supported`, @@ -206,7 +215,7 @@ export class ApiApp { } result = deepHexlify(result); - return res.status(200).send({ + return res.status(HttpStatus.OK).send({ jsonrpc, id, result, diff --git a/packages/api/src/constants.ts b/packages/api/src/constants.ts index 2003e3d6..e4f87ece 100644 --- a/packages/api/src/constants.ts +++ b/packages/api/src/constants.ts @@ -1,6 +1,7 @@ export const CustomRPCMethods = { skandha_validateUserOperation: "skandha_validateUserOperation", skandha_getGasPrice: "skandha_getGasPrice", + skandha_config: "skandha_config", skandha_feeHistory: "skandha_feeHistory", }; @@ -60,3 +61,8 @@ export const RedirectedRPCMethods = { eth_maxPriorityFeePerGas: "eth_maxPriorityFeePerGas", eth_sendRawTransaction: "eth_sendRawTransaction", }; + +export enum HttpStatus { + OK = 200, + INTERNAL_SERVER_ERROR = 500, +} diff --git a/packages/api/src/modules/skandha.ts b/packages/api/src/modules/skandha.ts index 4f54aa82..979b475f 100644 --- a/packages/api/src/modules/skandha.ts +++ b/packages/api/src/modules/skandha.ts @@ -1,5 +1,6 @@ import { Eth } from "executor/lib/modules/eth"; import { + GetConfigResponse, GetFeeHistoryResponse, GetGasPriceResponse, } from "types/lib/api/interfaces"; @@ -46,4 +47,8 @@ export class SkandhaAPI { async getGasPrice(): Promise { return await this.skandhaModule.getGasPrice(); } + + async getConfig(): Promise { + return await this.skandhaModule.getConfig(); + } } diff --git a/packages/api/src/server.ts b/packages/api/src/server.ts index 2bef36f0..dea6c8ff 100644 --- a/packages/api/src/server.ts +++ b/packages/api/src/server.ts @@ -3,6 +3,7 @@ import cors from "@fastify/cors"; import RpcError from "types/lib/api/errors/rpc-error"; import { ServerConfig } from "types/lib/api/interfaces"; import logger from "./logger"; +import { HttpStatus } from "./constants"; export class Server { constructor(private app: FastifyInstance, private config: ServerConfig) { @@ -70,16 +71,18 @@ export class Server { data: err.data, code: err.code, }; - return res.status(200).send({ + return res.status(HttpStatus.OK).send({ jsonrpc: body.jsonrpc, id: body.id, error, }); } - return res.status(err.statusCode ?? 500).send({ - error: "Unexpected behaviour", - }); + return res + .status(err.statusCode ?? HttpStatus.INTERNAL_SERVER_ERROR) + .send({ + error: "Unexpected behaviour", + }); }); await this.app.listen({ diff --git a/packages/cli/package.json b/packages/cli/package.json index 011222ac..db9fe8c8 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "cli", - "version": "0.0.43", + "version": "0.0.44", "description": "> TODO: description", "author": "zincoshine ", "homepage": "https://https://github.com/etherspot/skandha#readme", @@ -31,13 +31,13 @@ "url": "https://https://github.com/etherspot/skandha/issues" }, "dependencies": { - "api": "^0.0.43", - "db": "^0.0.43", - "executor": "^0.0.43", + "api": "^0.0.44", + "db": "^0.0.44", + "executor": "^0.0.44", "find-up": "5.0.0", "got": "12.5.3", "js-yaml": "4.1.0", - "types": "^0.0.43", + "types": "^0.0.44", "yargs": "17.6.2" }, "devDependencies": { diff --git a/packages/cli/src/cmds/start/handler.ts b/packages/cli/src/cmds/start/handler.ts index 10868d05..dc263e37 100644 --- a/packages/cli/src/cmds/start/handler.ts +++ b/packages/cli/src/cmds/start/handler.ts @@ -29,6 +29,7 @@ export async function bundlerHandler( networks: configOptions.networks, testingMode, unsafeMode, + redirectRpc, }); } catch (err) { logger.debug("Config file not found. Proceeding with env vars..."); @@ -36,6 +37,7 @@ export async function bundlerHandler( networks: {}, testingMode, unsafeMode, + redirectRpc, }); } diff --git a/packages/db/package.json b/packages/db/package.json index 9217d128..066680ad 100644 --- a/packages/db/package.json +++ b/packages/db/package.json @@ -1,6 +1,6 @@ { "name": "db", - "version": "0.0.43", + "version": "0.0.44", "description": "The DB module of Etherspot bundler client", "author": "Etherspot", "homepage": "https://github.com/etherspot/etherspot-bundler#readme", @@ -37,6 +37,6 @@ "devDependencies": { "@types/rocksdb": "3.0.1", "prettier": "^2.8.4", - "types": "^0.0.43" + "types": "^0.0.44" } } diff --git a/packages/executor/package.json b/packages/executor/package.json index 1c9f483a..bba214f5 100644 --- a/packages/executor/package.json +++ b/packages/executor/package.json @@ -1,6 +1,6 @@ { "name": "executor", - "version": "0.0.43", + "version": "0.0.44", "description": "The Relayer module of Etherspot bundler client", "author": "Etherspot", "homepage": "https://https://github.com/etherspot/skandha#readme", @@ -33,7 +33,7 @@ "dependencies": { "async-mutex": "0.4.0", "ethers": "5.7.2", - "params": "^0.0.43", - "types": "^0.0.43" + "params": "^0.0.44", + "types": "^0.0.44" } } diff --git a/packages/executor/src/config.ts b/packages/executor/src/config.ts index 26b79943..750879b1 100644 --- a/packages/executor/src/config.ts +++ b/packages/executor/src/config.ts @@ -13,12 +13,14 @@ export class Config { networks: Networks; testingMode: boolean; unsafeMode: boolean; + redirectRpc: boolean; constructor(private config: ConfigOptions) { - this.supportedNetworks = this.parseSupportedNetworks(); - this.networks = this.parseNetworkConfigs(); this.testingMode = config.testingMode ?? false; this.unsafeMode = config.unsafeMode ?? false; + this.redirectRpc = config.redirectRpc ?? false; + this.supportedNetworks = this.parseSupportedNetworks(); + this.networks = this.parseNetworkConfigs(); } getNetworkProvider(network: NetworkName): providers.JsonRpcProvider | null { @@ -64,6 +66,9 @@ export class Config { } private parseSupportedNetworks(): NetworkName[] { + if (this.testingMode) { + return ["dev"]; + } const envNetworks = NETWORKS_ENV(); if (envNetworks) { return envNetworks.map((key) => key as NetworkName); diff --git a/packages/executor/src/executor.ts b/packages/executor/src/executor.ts index 6a8a73db..b012043f 100644 --- a/packages/executor/src/executor.ts +++ b/packages/executor/src/executor.ts @@ -103,7 +103,7 @@ export class Executor { this.skandha = new Skandha( this.network, this.provider, - this.networkConfig, + this.config, this.logger ); diff --git a/packages/executor/src/interfaces.ts b/packages/executor/src/interfaces.ts index dcadab03..86d7e0e0 100644 --- a/packages/executor/src/interfaces.ts +++ b/packages/executor/src/interfaces.ts @@ -142,6 +142,7 @@ export interface ConfigOptions { networks: Networks; testingMode?: boolean; unsafeMode: boolean; + redirectRpc: boolean; } export interface SlotMap { diff --git a/packages/executor/src/modules/eth.ts b/packages/executor/src/modules/eth.ts index 52133023..27e37640 100644 --- a/packages/executor/src/modules/eth.ts +++ b/packages/executor/src/modules/eth.ts @@ -160,22 +160,13 @@ export class Eth { //> // Binary search gas limits - let userOpToEstimate: UserOperationStruct = { + const userOpToEstimate: UserOperationStruct = { ...userOpComplemented, preVerificationGas, verificationGasLimit, callGasLimit, }; - // binary search vgl and cgl - try { - userOpToEstimate = await this.userOpValidationService.binarySearchVGL( - userOpToEstimate, - entryPoint - ); - // eslint-disable-next-line no-empty - } catch (err) {} - const gasFee = await getGasFee( this.networkName, this.provider, @@ -190,8 +181,8 @@ export class Eth { preVerificationGas, verificationGasLimit: userOpToEstimate.verificationGasLimit, verificationGas: userOpToEstimate.verificationGasLimit, - validAfter: BigNumber.from(validAfter), - validUntil: BigNumber.from(validUntil), + validAfter: validAfter ? BigNumber.from(validAfter) : undefined, + validUntil: validUntil ? BigNumber.from(validUntil) : undefined, callGasLimit: userOpToEstimate.callGasLimit, maxFeePerGas: gasFee.maxFeePerGas, maxPriorityFeePerGas: gasFee.maxPriorityFeePerGas, diff --git a/packages/executor/src/modules/skandha.ts b/packages/executor/src/modules/skandha.ts index acea2b68..dcfb51f9 100644 --- a/packages/executor/src/modules/skandha.ts +++ b/packages/executor/src/modules/skandha.ts @@ -1,6 +1,7 @@ import { BigNumber, BigNumberish, ethers } from "ethers"; import { NetworkName } from "types/lib"; import { + GetConfigResponse, GetFeeHistoryResponse, GetGasPriceResponse, } from "types/lib/api/interfaces"; @@ -11,22 +12,31 @@ import { getGasFee } from "params/lib"; import { IEntryPoint__factory } from "types/lib/executor/contracts"; import { UserOperationStruct } from "types/lib/executor/contracts/EntryPoint"; import { Logger, NetworkConfig } from "../interfaces"; +import { Config } from "../config"; // custom features of Skandha export class Skandha { + networkConfig: NetworkConfig; + constructor( private networkName: NetworkName, private provider: ethers.providers.JsonRpcProvider, - private config: NetworkConfig, + private config: Config, private logger: Logger - ) {} + ) { + const networkConfig = this.config.getNetworkConfig(this.networkName); + if (!networkConfig) { + throw new Error("No network config"); + } + this.networkConfig = networkConfig; + } async getGasPrice(): Promise { - const multiplier = this.config.gasPriceMarkup; + const multiplier = this.networkConfig.gasPriceMarkup; const gasFee = await getGasFee( this.networkName, this.provider, - this.config.etherscanApiKey + this.networkConfig.etherscanApiKey ); let { maxPriorityFeePerGas, maxFeePerGas } = gasFee; @@ -57,6 +67,52 @@ export class Skandha { }; } + async getConfig(): Promise { + const wallet = this.config.getRelayer(this.networkName); + const hasEtherscanApiKey = Boolean(this.networkConfig.etherscanApiKey); + const hasExecutionRpc = Boolean(this.networkConfig.rpcEndpointSubmit); + return { + flags: { + unsafeMode: this.config.unsafeMode, + testingMode: this.config.testingMode, + redirectRpc: this.config.redirectRpc, + }, + entryPoints: this.networkConfig.entryPoints, + beneficiary: this.networkConfig.beneficiary, + relayer: wallet ? await wallet.getAddress() : "", + minInclusionDenominator: BigNumber.from( + this.networkConfig.minInclusionDenominator + ).toNumber(), + throttlingSlack: BigNumber.from( + this.networkConfig.throttlingSlack + ).toNumber(), + banSlack: BigNumber.from(this.networkConfig.banSlack).toNumber(), + minSignerBalance: `${ethers.utils.formatEther( + this.networkConfig.minSignerBalance + )} eth`, + multicall: this.networkConfig.multicall, + estimationStaticBuffer: BigNumber.from( + this.networkConfig.estimationStaticBuffer + ).toNumber(), + validationGasLimit: BigNumber.from( + this.networkConfig.validationGasLimit + ).toNumber(), + receiptLookupRange: BigNumber.from( + this.networkConfig.receiptLookupRange + ).toNumber(), + etherscanApiKey: hasEtherscanApiKey, + conditionalTransactions: this.networkConfig.conditionalTransactions, + rpcEndpointSubmit: hasExecutionRpc, + gasPriceMarkup: BigNumber.from( + this.networkConfig.gasPriceMarkup + ).toNumber(), + enforceGasPrice: this.networkConfig.enforceGasPrice, + enforceGasPriceThreshold: BigNumber.from( + this.networkConfig.enforceGasPriceThreshold + ).toNumber(), + }; + } + /** * see eth_feeHistory * @param entryPoint Entry Point contract diff --git a/packages/params/package.json b/packages/params/package.json index 4080d181..d30b97ab 100644 --- a/packages/params/package.json +++ b/packages/params/package.json @@ -1,6 +1,6 @@ { "name": "params", - "version": "0.0.43", + "version": "0.0.44", "description": "Various bundler parameters", "author": "Etherspot", "homepage": "https://github.com/etherspot/skandha#readme", @@ -25,7 +25,7 @@ "@eth-optimism/sdk": "3.0.0", "@mantleio/sdk": "0.2.1", "ethers": "5.7.2", - "types": "^0.0.43" + "types": "^0.0.44" }, "scripts": { "clean": "rm -rf lib && rm -f *.tsbuildinfo", diff --git a/packages/types/package.json b/packages/types/package.json index 7952c6de..d19c365f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "types", - "version": "0.0.43", + "version": "0.0.44", "description": "The types of Etherspot bundler client", "author": "Etherspot", "homepage": "https://https://github.com/etherspot/skandha#readme", diff --git a/packages/types/src/api/interfaces.ts b/packages/types/src/api/interfaces.ts index cdb698ed..aff9fc3c 100644 --- a/packages/types/src/api/interfaces.ts +++ b/packages/types/src/api/interfaces.ts @@ -44,6 +44,31 @@ export type UserOperationReceipt = { receipt: providers.TransactionReceipt; }; +export type GetConfigResponse = { + flags: { + redirectRpc: boolean; + testingMode: boolean; + unsafeMode: boolean; + }; + entryPoints: string[]; + beneficiary: string; + relayer: string; + minInclusionDenominator: number; + throttlingSlack: number; + banSlack: number; + minSignerBalance: string; + multicall: string; + estimationStaticBuffer: number; + validationGasLimit: number; + receiptLookupRange: number; + etherscanApiKey: boolean; // true if set + conditionalTransactions: boolean; + rpcEndpointSubmit: boolean; // true if not empty string + gasPriceMarkup: number; + enforceGasPrice: boolean; + enforceGasPriceThreshold: number; +}; + export type SupportedEntryPoints = string[]; export type EthChainIdResponse = { chainId: number };