diff --git a/README.md b/README.md index 0801a0d5..bfcaa812 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,7 @@ Other optional arguments are: - `-t` or `--topup-amount`, The initial topup amount of excess wallets, requirs `--mnemonic`. Will override the 'TOPUP_AMOUNT' in env variables - `--owner-profile`, Specifies the owner limit, example: --owner-profile 0x123456=12 . Will override the 'OWNER_PROFILE' in env variables - `--public-rpc`, Allows to use public RPCs as fallbacks, default is false. Will override the 'PUBLIC_RPC' in env variables +- `--gas-price-multiplier`, Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7%. Will override the 'GAS_PRICE_MULTIPLIER' in env variables - `-V` or `--version`, output the version number - `-h` or `--help`, output usage information @@ -256,6 +257,8 @@ PUBLIC_RPC= # Specifies the routing mode 'multi' or 'single' or 'full', default is 'single' ROUTE="single" +# Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7% +GAS_PRICE_MULTIPLIER= ``` If both env variables and CLI argument are set, the CLI arguments will be prioritized and override the env variables. diff --git a/example.env b/example.env index a024cfad..99db5906 100644 --- a/example.env +++ b/example.env @@ -85,6 +85,9 @@ PUBLIC_RPC= # Specifies the routing mode 'multi' or 'single' or 'full', default is 'single' ROUTE="single" +# Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7% +GAS_PRICE_MULTIPLIER= + # test rpcs vars TEST_POLYGON_RPC= diff --git a/src/cli.ts b/src/cli.ts index a3e73acf..340fecb4 100755 --- a/src/cli.ts +++ b/src/cli.ts @@ -62,6 +62,7 @@ const ENV_OPTIONS = { topupAmount: process?.env?.TOPUP_AMOUNT, botMinBalance: process?.env?.BOT_MIN_BALANCE, selfFundOrders: process?.env?.SELF_FUND_ORDERS, + gasPriceMultiplier: process?.env?.GAS_PRICE_MULTIPLIER, route: process?.env?.ROUTE, ownerProfile: process?.env?.OWNER_PROFILE ? Array.from(process?.env?.OWNER_PROFILE.matchAll(/[^,\s]+/g)).map((v) => v[0]) @@ -179,6 +180,10 @@ const getOptions = async (argv: any, version?: string) => { "--route ", "Specifies the routing mode 'multi' or 'single' or 'full', default is 'single'. Will override the 'ROUTE' in env variables", ) + .option( + "--gas-price-multiplier ", + "Option to multiply the gas price fetched from the rpc as percentage, default is 107, ie +7%. Will override the 'GAS_PRICE_MULTIPLIER' in env variables", + ) .description( [ "A NodeJS app to find and take arbitrage trades for Rain Orderbook orders against some DeFi liquidity providers, requires NodeJS v18 or higher.", @@ -216,6 +221,8 @@ const getOptions = async (argv: any, version?: string) => { cmdOptions.walletCount = cmdOptions.walletCount || getEnv(ENV_OPTIONS.walletCount); cmdOptions.topupAmount = cmdOptions.topupAmount || getEnv(ENV_OPTIONS.topupAmount); cmdOptions.selfFundOrders = cmdOptions.selfFundOrders || getEnv(ENV_OPTIONS.selfFundOrders); + cmdOptions.gasPriceMultiplier = + cmdOptions.gasPriceMultiplier || getEnv(ENV_OPTIONS.gasPriceMultiplier); cmdOptions.botMinBalance = cmdOptions.botMinBalance || getEnv(ENV_OPTIONS.botMinBalance); cmdOptions.ownerProfile = cmdOptions.ownerProfile || getEnv(ENV_OPTIONS.ownerProfile); cmdOptions.route = cmdOptions.route || getEnv(ENV_OPTIONS.route); @@ -384,6 +391,21 @@ export async function startup(argv: any, version?: string, tracer?: Tracer, ctx? if (!options.botMinBalance || !/^[0-9]+(.[0-9]+)?$/.test(options.botMinBalance)) { throw "expected a valid value for --bot-min-balance, it should be an number greater than 0"; } + if (options.gasPriceMultiplier) { + if (typeof options.gasPriceMultiplier === "number") { + if (options.gasPriceMultiplier <= 0 || !Number.isInteger(options.gasPriceMultiplier)) + throw "invalid gasPriceMultiplier value, must be an integer greater than zero"; + } else if ( + typeof options.gasPriceMultiplier === "string" && + /^[0-9]+$/.test(options.gasPriceMultiplier) + ) { + options.gasPriceMultiplier = Number(options.gasPriceMultiplier); + if (options.gasPriceMultiplier <= 0) + throw "invalid gasPriceMultiplier value, must be an integer greater than zero"; + } else throw "invalid gasPriceMultiplier value, must be an integer greater than zero"; + } else { + options.gasPriceMultiplier = 107; + } const poolUpdateInterval = _poolUpdateInterval * 60 * 1000; let ordersDetails: SgOrder[] = []; if (!process?.env?.CLI_STARTUP_TEST) { diff --git a/src/error.ts b/src/error.ts index 11063e47..7ae4bc30 100644 --- a/src/error.ts +++ b/src/error.ts @@ -2,6 +2,7 @@ import { BaseError, RpcRequestError, ExecutionRevertedError, + InsufficientFundsError, // InvalidInputRpcError, // TransactionRejectedRpcError, } from "viem"; @@ -49,6 +50,7 @@ export function containsNodeError(err: BaseError): boolean { // err instanceof TransactionRejectedRpcError || // err instanceof InvalidInputRpcError || err instanceof ExecutionRevertedError || + err instanceof InsufficientFundsError || (err instanceof RpcRequestError && err.code === ExecutionRevertedError.code) || ("cause" in err && containsNodeError(err.cause as any)) ); diff --git a/src/index.ts b/src/index.ts index e542ccee..3942c338 100644 --- a/src/index.ts +++ b/src/index.ts @@ -206,6 +206,7 @@ export async function getConfig( config.walletKey = walletKey; config.route = route; config.rpcRecords = rpcRecords; + config.gasPriceMultiplier = options.gasPriceMultiplier; // init accounts const { mainAccount, accounts } = await initAccounts(walletKey, config, options, tracer, ctx); diff --git a/src/processOrders.ts b/src/processOrders.ts index c6efb7a5..be4be8d5 100644 --- a/src/processOrders.ts +++ b/src/processOrders.ts @@ -439,7 +439,7 @@ export async function processPair(args: { let gasPrice; try { const gasPriceBigInt = await viemClient.getGasPrice(); - gasPrice = ethers.BigNumber.from(gasPriceBigInt).mul("107").div("100"); + gasPrice = ethers.BigNumber.from(gasPriceBigInt).mul(config.gasPriceMultiplier).div("100"); spanAttributes["details.gasPrice"] = gasPrice.toString(); } catch (e) { result.reason = ProcessPairHaltReason.FailedToGetGasPrice; @@ -579,6 +579,8 @@ export async function processPair(args: { if (e.noneNodeError) { spanAttributes["details.noneNodeError"] = true; result.error = e.noneNodeError; + } else { + spanAttributes["details.noneNodeError"] = false; } result.report = { status: ProcessPairReportStatus.NoOpportunity, diff --git a/src/types.ts b/src/types.ts index 537f06e2..b633ce50 100644 --- a/src/types.ts +++ b/src/types.ts @@ -46,6 +46,7 @@ export type CliOptions = { ownerProfile?: Record; publicRpc: boolean; route?: string; + gasPriceMultiplier: number; }; export type TokenDetails = { @@ -168,6 +169,7 @@ export type BotConfig = { walletKey: string; route?: "multi" | "single"; rpcRecords: Record; + gasPriceMultiplier: number; onFetchRequest?: (request: Request) => void; onFetchResponse?: (request: Response) => void; }; diff --git a/test/cli.test.js b/test/cli.test.js index dd21bf27..e3f06508 100644 --- a/test/cli.test.js +++ b/test/cli.test.js @@ -183,6 +183,8 @@ describe("Test cli", async function () { `0x${"2".repeat(40)}`, "--bot-min-balance", "0.123", + "--gas-price-multiplier", + "120", ]); const expected = { roundGap: 10000, @@ -201,9 +203,11 @@ describe("Test cli", async function () { cache: {}, }, }, + gasPriceMultiplier: 120, }, options: { botMinBalance: "0.123", + gasPriceMultiplier: 120, }, }; await sleep(1000); @@ -215,5 +219,7 @@ describe("Test cli", async function () { assert.equal(result.config.route, expected.config.route); assert.deepEqual(result.config.rpcRecords, expected.config.rpcRecords); assert.equal(result.options.botMinBalance, expected.options.botMinBalance); + assert.equal(result.options.gasPriceMultiplier, expected.options.gasPriceMultiplier); + assert.equal(result.config.gasPriceMultiplier, expected.config.gasPriceMultiplier); }); }); diff --git a/test/data.js b/test/data.js index b7ba410f..851a88db 100644 --- a/test/data.js +++ b/test/data.js @@ -65,6 +65,7 @@ const config = { decimals: token2.decimals, symbol: token2.symbol, }, + gasPriceMultiplier: 107, }; const vaultBalance1 = BigNumber.from("10000000000000000000"); diff --git a/test/e2e/e2e.test.js b/test/e2e/e2e.test.js index ae725205..1f40d6e1 100644 --- a/test/e2e/e2e.test.js +++ b/test/e2e/e2e.test.js @@ -249,6 +249,7 @@ for (let i = 0; i < testData.length; i++) { config.accounts = []; config.mainAccount = bot; config.quoteRpc = [mockServer.url + "/rpc"]; + config.gasPriceMultiplier = 107; orders = prepareOrdersForRound( await getOrderbookOwnersProfileMapFromSg(orders, viemClient, []), false, @@ -582,6 +583,7 @@ for (let i = 0; i < testData.length; i++) { config.accounts = []; config.mainAccount = bot; config.quoteRpc = [mockServer.url + "/rpc"]; + config.gasPriceMultiplier = 107; orders = prepareOrdersForRound( await getOrderbookOwnersProfileMapFromSg(orders, viemClient, []), false, @@ -933,6 +935,7 @@ for (let i = 0; i < testData.length; i++) { config.accounts = []; config.mainAccount = bot; config.quoteRpc = [mockServer.url + "/rpc"]; + config.gasPriceMultiplier = 107; orders = prepareOrdersForRound( await getOrderbookOwnersProfileMapFromSg(orders, viemClient, []), false,