diff --git a/.gitignore b/.gitignore index c320913b..87200589 100644 --- a/.gitignore +++ b/.gitignore @@ -1,16 +1,17 @@ ## Deps node_modules +## Private +.env + +## That one annoying file +.DS_Store + ## Generated cache /contracts artifacts logs.txt logs - -## Private -.env - -## That one annoying file -.DS_Store +docs mem-cache \ No newline at end of file diff --git a/README.md b/README.md index 4e1045ac..94af52e0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ node arb-bot -k 12ab... -r https://... --orderbook-address 0x1a2b... --arb-addre The app requires these arguments (all arguments can be set in env variables alternatively, more details below): - `-k` or `--key`, Private key of wallet that performs the transactions. Will override the 'BOT_WALLET_PRIVATEKEY' in env variables - `-r` or `--rpc`, RPC URL(s) that will be provider for interacting with evm, use different providers if more than 1 is specified to prevent banning. Will override the 'RPC_URL' in env variables -- `-m` or `--mode`, Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter`, Will override the 'MODE' in env variables +- `-m` or `--mode`, Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter` or `suniv2`, Will override the 'MODE' in env variables - `--orderbook-address`, Address of the deployed orderbook contract, Will override the 'ORDERBOOK_ADDRESS' in env variables - `--arb-address`, Address of the deployed arb contract, Will override the 'ARB_ADDRESS' in env variables - `--arb-contract-type`, Type of the Arb contract, can be either of `flash-loan-v2` or `flash-loan-v3` or `order-taker`, not availabe for `srouter` mode since it is a specialized mode, Will override the 'ARB_TYPE' in env variables @@ -61,6 +61,8 @@ Other optional arguments are: - `--flashbot-rpc`, Optional flashbot rpc url to submit transaction to, Will override the 'FLASHBOT_RPC' in env variables - `--interpreter-v2`, Flag for operating with interpreter V2, note that 'flash-loan-v2' is NOT compatible with interpreter v2. Will override the 'INTERPRETERV2' in env variables - `--no-bundle`, Flag for not bundling orders based on pairs and clear each order individually. Will override the 'NO_BUNDLE' in env variables +- `--hops`, Option to specify how many hops the binary search should do in srouter mode, default is 11 if left unspecified, Will override the 'HOPS' in env variables +- `--rp32`, Option to use sushi RouteProcessor v3.2, defaults to v3 if not passed, Will override the 'RP3_2' in env variables - `-V` or `--version`, output the version number - `-h` or `--help`, output usage information @@ -107,7 +109,7 @@ which will show: Options: -k, --key Private key of wallet that performs the transactions. Will override the 'BOT_WALLET_PRIVATEKEY' in env variables -r, --rpc RPC URL(s) that will be provider for interacting with evm, use different providers if more than 1 is specified to prevent banning. Will override the 'RPC_URL' in env variables - -m, --mode Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter`, Will override the 'MODE' in env variables + -m, --mode Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter` or `suniv2`, Will override the 'MODE' in env variables -o, --orders The path to a local json file containing the orders details, can be used in combination with --subgraph, Will override the 'ORDERS' in env variables -s, --subgraph Subgraph URL(s) to read orders details from, can be used in combination with --orders, Will override the 'SUBGRAPH' in env variables --orderbook-address
Address of the deployed orderbook contract, Will override the 'ORDERBOOK_ADDRESS' in env variables @@ -129,6 +131,8 @@ which will show: --use-public-rpcs Option to use public rpcs as fallback option for 'srouter' and 'router' mode, Will override the 'USE_PUBLIC_RPCS' in env variables --interpreter-v2 Flag for operating with interpreter V2, note that 'flash-loan-v2' is NOT compatible with interpreter v2. Will override the 'INTERPRETERV2' in env variables --no-bundle Flag for not bundling orders based on pairs and clear each order individually. Will override the 'NO_BUNDLE' in env variables + --hops Option to specify how many hops the binary search should do in srouter mode, default is 11 if left unspecified, Will override the 'HOPS' in env variables + --rp32 Option to use sushi RouteProcessor v3.2, defaults to v3 if not passed, Will override the 'RP3_2' in env variables -V, --version output the version number -h, --help display help for command
@@ -145,7 +149,7 @@ RPC_URL="https://polygon-mainnet.g.alchemy.com/v2/{API_KEY}, https://rpc.ankr.co # Option to submit transactions using the flashbot RPC. FLASHBOT_RPC="" -# bot running mode, one of "router", "0x", "curve", "crouter", "srouter" +# bot running mode, one of "router", "0x", "curve", "crouter", "srouter", "suniv2" MODE="router" # arb contract address @@ -213,6 +217,9 @@ NO_BUNDLE="false" # number of hops of binary search in srouter mode, if left unspecified will be 11 by default HOPS=11 + +# Option to use sushi RouteProcessorv3.2, default is v3 +RP3_2="true" ``` If both env variables and CLI argument are set, the CLI arguments will be prioritized and override the env variables. @@ -241,6 +248,8 @@ const configOptions = { timeout : 300, // seconds to wait for tx to mine before disregarding it interpreterv2 : true, // if interpreter v2 should be used, not compatible with flash-loan-v2 arb contract bundle : true, // if orders should be bundled based on token pair or be handled individually + hops : 6, // The amount of hops of binary search for sorouter mode + rp32 : true, // Option to use sushi RouteProcessorv3.2, default is v3 liquidityProviders : [ // list of liquidity providers for "router" mode to get quotes from (optional) "sushiswapv2", "uniswapv2" @@ -266,7 +275,7 @@ const sgFilters = { // fil const orderDetails = await RainArbBot.getOrderDetails(subgraphs, ordersJson, config.signer, sgFilters); // to run the clearing process and get the report object which holds the report of cleared orders -const mode = "srouter" // mode can be one of "router" or "0x" or "curve" or "crouter" or "srouter" +const mode = "srouter" // mode can be one of "router" or "0x" or "curve" or "crouter" or "srouter" or "suniv2" const reports = await RainArbBot.clear(mode, config, orderDetails, ...[clearOptions]) ```
diff --git a/arb-bot.js b/arb-bot.js index 9422be31..f3035f99 100755 --- a/arb-bot.js +++ b/arb-bot.js @@ -34,6 +34,7 @@ const ENV_OPTIONS = { timeout : process?.env?.TIMEOUT, flashbotRpc : process?.env?.FLASHBOT_RPC, hops : process?.env?.HOPS, + rp32 : process?.env?.RP3_2?.toLowerCase() === "true" ? true : false, rpc : process?.env?.RPC_URL ? Array.from(process?.env?.RPC_URL.matchAll(/[^,\s]+/g)).map(v => v[0]) : undefined, @@ -46,7 +47,7 @@ const getOptions = async argv => { const cmdOptions = new Command("node arb-bot") .option("-k, --key ", "Private key of wallet that performs the transactions. Will override the 'BOT_WALLET_PRIVATEKEY' in env variables") .option("-r, --rpc ", "RPC URL(s) that will be provider for interacting with evm, use different providers if more than 1 is specified to prevent banning. Will override the 'RPC_URL' in env variables") - .option("-m, --mode ", "Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter`, Will override the 'MODE' in env variables") + .option("-m, --mode ", "Running mode of the bot, must be one of: `0x` or `curve` or `router` or `crouter` or `srouter` or `suniv2`, Will override the 'MODE' in env variables") .option("-o, --orders ", "The path to a local json file containing the orders details, can be used in combination with --subgraph, Will override the 'ORDERS' in env variables") .option("-s, --subgraph ", "Subgraph URL(s) to read orders details from, can be used in combination with --orders, Will override the 'SUBGRAPH' in env variables") .option("--orderbook-address
", "Address of the deployed orderbook contract, Will override the 'ORDERBOOK_ADDRESS' in env variables") @@ -68,7 +69,8 @@ const getOptions = async argv => { .option("--use-public-rpcs", "Option to use public rpcs as fallback option for 'srouter' and 'router' mode, Will override the 'USE_PUBLIC_RPCS' in env variables") .option("--interpreter-v2", "Flag for operating with interpreter V2, note that 'flash-loan-v2' is NOT compatible with interpreter v2. Will override the 'INTERPRETERV2' in env variables") .option("--no-bundle", "Flag for not bundling orders based on pairs and clear each order individually. Will override the 'NO_BUNDLE' in env variables") - .option("--hops ", "Option to specify how many hops the binary search should o in srouter mode, default is 11 is left unspecified, Will override the 'HOPS' in env variables") + .option("--hops ", "Option to specify how many hops the binary search should do in srouter mode, default is 11 if left unspecified, Will override the 'HOPS' in env variables") + .option("--rp32", "Option to use sushi RouteProcessor v3.2, defaults to v3 if not passed, Will override the 'RP3_2' 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.", "- Use \"node arb-bot [options]\" command alias for running the app from its repository workspace", @@ -104,6 +106,7 @@ const getOptions = async argv => { cmdOptions.timeout = cmdOptions.timeout || ENV_OPTIONS.timeout; cmdOptions.interpreterv2 = cmdOptions.interpreterv2 || ENV_OPTIONS.interpreterv2; cmdOptions.hops = cmdOptions.hops || ENV_OPTIONS.hops; + cmdOptions.rp32 = cmdOptions.rp32 || ENV_OPTIONS.rp32; cmdOptions.bundle = cmdOptions.bundle ? ENV_OPTIONS.bundle : false; return cmdOptions; @@ -136,6 +139,7 @@ const arbRound = async options => { interpreterv2 : options.interpreterv2, bundle : options.bundle, hops : options.hops, + rp32 : options.rp32, liquidityProviders : options.lps ? Array.from(options.lps.matchAll(/[^,\s]+/g)).map(v => v[0]) : undefined, @@ -180,7 +184,7 @@ const main = async argv => { appGlobalLogger( true, - ...rpcs, + // ...rpcs, options.key, options.apiKey ); diff --git a/config.json b/config.json index 79b9e061..4476701e 100644 --- a/config.json +++ b/config.json @@ -4,6 +4,7 @@ "chainId": 137, "explorer": "https://polygonscan.com/", "routeProcessor3Address": "0x0a6e511Fe663827b9cA7e2D2542b20B37fC217A6", + "routeProcessor3_2Address": "0xE7eb31f23A5BefEEFf76dbD2ED6AdC822568a5d2", "uniV2Router02Address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "zeroEx": { "apiUrl": "https://polygon.api.0x.org/", @@ -214,6 +215,7 @@ "chainId": 1, "explorer": "https://etherscan.io/", "routeProcessor3Address": "0x827179dD56d07A7eeA32e3873493835da2866976", + "routeProcessor3_2Address": "0x5550D13389bB70F45fCeF58f19f6b6e87F6e747d", "uniV2Router02Address": "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F", "zeroEx": { "apiUrl": "https://api.0x.org/", @@ -551,6 +553,7 @@ "chainId": 43114, "explorer": "https://snowtrace.io/", "routeProcessor3Address": "0x717b7948AA264DeCf4D780aa6914482e5F46Da3e", + "routeProcessor3_2Address": "0x8f54301F315C56c112D492D9443047D4745dbe9e", "uniV2Router02Address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "zeroEx": { "apiUrl": "https://avalanche.api.0x.org/", @@ -643,6 +646,7 @@ "chainId": 42161, "explorer": "https://arbiscan.io/", "routeProcessor3Address": "0xfc506AaA1340b4dedFfd88bE278bEe058952D674", + "routeProcessor3_2Address": "0x09bD2A33c47746fF03b86BCe4E885D03C74a8E8C", "uniV2Router02Address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "zeroEx": { "apiUrl": "https://arbitrum.api.0x.org/", @@ -721,6 +725,7 @@ "chainId": 250, "explorer": "https://ftmscan.com/", "routeProcessor3Address": "0x2214A42d8e2A1d20635c2cb0664422c528B6A432", + "routeProcessor3_2Address": "0xFB70AD5a200d784E7901230E6875d91d5Fa6B68c", "uniV2Router02Address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "zeroEx": { "apiUrl": "https://fantom.api.0x.org/", @@ -810,6 +815,7 @@ "chainId": 56, "explorer": "https://bscscan.com/", "routeProcessor3Address": "0x400d75dAb26bBc18D163AEA3e83D9Ea68F6c1804", + "routeProcessor3_2Address": "0xd36990D74b947eC4Ad9f52Fe3D49d14AdDB51E44", "uniV2Router02Address": "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506", "zeroEx": { "apiUrl": "https://bsc.api.0x.org/", @@ -901,6 +907,7 @@ "chainId": 42220, "explorer": "https://celoscan.io/", "routeProcessor3Address": "0x2f686751b19a9d91cc3d57d90150Bc767f050066", + "routeProcessor3_2Address": "0xaB235da7f52d35fb4551AfBa11BFB56e18774A65", "uniV2Router02Address": "0x1421bDe4B10e8dd459b3BCb598810B1337D56842", "zeroEx": { "apiUrl": "https://celo.api.0x.org/", @@ -936,6 +943,7 @@ "chainId": 10, "explorer": "https://optimistic.etherscan.io/", "routeProcessor3Address": "0x4C5D5234f232BD2D76B96aA33F5AE4FCF0E4BFAb", + "routeProcessor3_2Address": "0xEb94EcA012eC0bbB254722FdDa2CE7475875A52B", "uniV2Router02Address": "", "zeroEx": { "apiUrl": "https://optimism.api.0x.org/", @@ -1007,5 +1015,42 @@ "address": "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6", "decimals": 18 } + }, + { + "network": "flare mainnet", + "chainId": 14, + "explorer": "https://flarescan.com/", + "routeProcessor3Address": "0x9B3F1D56D9004e6C69d8247d402F38DE5F87A27c", + "uniV2Router02Address": "0x088EeCB467B3968Da36c71F05023A1d3133B2B83", + "zeroEx": { + }, + "curve": { + "pools": [] + }, + "enosys":{ + "pools": [ + { + "address": "0x7520005032F43229F606d3ACeae97045b9D6F7ea", + "token0": "0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d", + "token1": "0x96B41289D90444B8adD57e6F265DB5aE8651DF29" + } + ] + }, + "nativeToken": { + "symbol": "FLR", + "address": "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + "decimals": 18 + }, + "nativeWrappedToken": { + "symbol": "WFLR", + "address": "0x1D80c49BbBCd1C0911346656B529DF9E5c2F783d", + "decimals": 18 + }, + "liquidityProviders": [ + + ], + "stableTokens": { + + } } ] \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-Bold-webfont.eot b/docs/html/fonts/OpenSans-Bold-webfont.eot deleted file mode 100644 index 5d20d916..00000000 Binary files a/docs/html/fonts/OpenSans-Bold-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Bold-webfont.svg b/docs/html/fonts/OpenSans-Bold-webfont.svg deleted file mode 100644 index 3ed7be4b..00000000 --- a/docs/html/fonts/OpenSans-Bold-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-Bold-webfont.woff b/docs/html/fonts/OpenSans-Bold-webfont.woff deleted file mode 100644 index 1205787b..00000000 Binary files a/docs/html/fonts/OpenSans-Bold-webfont.woff and /dev/null differ diff --git a/docs/html/fonts/OpenSans-BoldItalic-webfont.eot b/docs/html/fonts/OpenSans-BoldItalic-webfont.eot deleted file mode 100644 index 1f639a15..00000000 Binary files a/docs/html/fonts/OpenSans-BoldItalic-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-BoldItalic-webfont.svg b/docs/html/fonts/OpenSans-BoldItalic-webfont.svg deleted file mode 100644 index 6a2607b9..00000000 --- a/docs/html/fonts/OpenSans-BoldItalic-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-BoldItalic-webfont.woff b/docs/html/fonts/OpenSans-BoldItalic-webfont.woff deleted file mode 100644 index ed760c06..00000000 Binary files a/docs/html/fonts/OpenSans-BoldItalic-webfont.woff and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Italic-webfont.eot b/docs/html/fonts/OpenSans-Italic-webfont.eot deleted file mode 100644 index 0c8a0ae0..00000000 Binary files a/docs/html/fonts/OpenSans-Italic-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Italic-webfont.svg b/docs/html/fonts/OpenSans-Italic-webfont.svg deleted file mode 100644 index e1075dcc..00000000 --- a/docs/html/fonts/OpenSans-Italic-webfont.svg +++ /dev/null @@ -1,1830 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-Italic-webfont.woff b/docs/html/fonts/OpenSans-Italic-webfont.woff deleted file mode 100644 index ff652e64..00000000 Binary files a/docs/html/fonts/OpenSans-Italic-webfont.woff and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Light-webfont.eot b/docs/html/fonts/OpenSans-Light-webfont.eot deleted file mode 100644 index 14868406..00000000 Binary files a/docs/html/fonts/OpenSans-Light-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Light-webfont.svg b/docs/html/fonts/OpenSans-Light-webfont.svg deleted file mode 100644 index 11a472ca..00000000 --- a/docs/html/fonts/OpenSans-Light-webfont.svg +++ /dev/null @@ -1,1831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-Light-webfont.woff b/docs/html/fonts/OpenSans-Light-webfont.woff deleted file mode 100644 index e7860748..00000000 Binary files a/docs/html/fonts/OpenSans-Light-webfont.woff and /dev/null differ diff --git a/docs/html/fonts/OpenSans-LightItalic-webfont.eot b/docs/html/fonts/OpenSans-LightItalic-webfont.eot deleted file mode 100644 index 8f445929..00000000 Binary files a/docs/html/fonts/OpenSans-LightItalic-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-LightItalic-webfont.svg b/docs/html/fonts/OpenSans-LightItalic-webfont.svg deleted file mode 100644 index 431d7e35..00000000 --- a/docs/html/fonts/OpenSans-LightItalic-webfont.svg +++ /dev/null @@ -1,1835 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-LightItalic-webfont.woff b/docs/html/fonts/OpenSans-LightItalic-webfont.woff deleted file mode 100644 index 43e8b9e6..00000000 Binary files a/docs/html/fonts/OpenSans-LightItalic-webfont.woff and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Regular-webfont.eot b/docs/html/fonts/OpenSans-Regular-webfont.eot deleted file mode 100644 index 6bbc3cf5..00000000 Binary files a/docs/html/fonts/OpenSans-Regular-webfont.eot and /dev/null differ diff --git a/docs/html/fonts/OpenSans-Regular-webfont.svg b/docs/html/fonts/OpenSans-Regular-webfont.svg deleted file mode 100644 index 25a39523..00000000 --- a/docs/html/fonts/OpenSans-Regular-webfont.svg +++ /dev/null @@ -1,1831 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/docs/html/fonts/OpenSans-Regular-webfont.woff b/docs/html/fonts/OpenSans-Regular-webfont.woff deleted file mode 100644 index e231183d..00000000 Binary files a/docs/html/fonts/OpenSans-Regular-webfont.woff and /dev/null differ diff --git a/docs/html/global.html b/docs/html/global.html deleted file mode 100644 index b44a78d9..00000000 --- a/docs/html/global.html +++ /dev/null @@ -1,7841 +0,0 @@ - - - - - JSDoc: Global - - - - - - - - - - -
- -

Global

- - - - - - -
- -
- -

- - -
- -
-
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - - - - - - - - - -

Members

- - - -

(constant) DefaultQuery

- - - - -
- The default query used in the matchmaker bot to fetch the orders from subgraph -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(constant) clearOptions

- - - - -
- Options for clear() -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(constant) configOptions

- - - - -
- Options for getConfig() -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - -

(constant) fallbacks

- - - - -
- Chain specific fallback data -
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - -

Methods

- - - - - - - -

appGlobalLogger(scrub, …data)

- - - - - - -
- Method to shorten data fields of items that are logged and optionally hide sensitive data -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeAttributesDescription
scrub - - -boolean - - - - - - - - - - Option to scrub sensitive data
data - - -any - - - - - - - - - - <repeatable>
- -
The optinnal data to hide
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

bnFromFloat(float, decimals)

- - - - - - -
- convert float numbers to big number -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
float - - -any - - - - - - Any form of number
decimals - - -number - - - - - - 18 - - Decimals point of the number
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- ethers BigNumber with decimals point -
- - - - - - - - - - - - - - - -

build0xQueries(api, queries, tokenAddress, tokenDecimals, tokenSymbol)

- - - - - - -
- Builds initial 0x requests bodies from token addresses that is required -for getting token prices with least amount of hits possible and that is -to pair up tokens in a way that each show up only once in a request body -so that the number of requests will be: "number-of-tokens / 2" at best or -"(number-of-tokens / 2) + 1" at worst if the number of tokens is an odd digit. -This way the responses will include the "rate" for sell/buy tokens to native -network token which will be used to estimate the initial price of all possible -token pair combinations. -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
api - - -string - - - - The 0x API endpoint URL
queries - - -Array.<any> - - - - The array that keeps the 0x query text
tokenAddress - - -string - - - - The token address
tokenDecimals - - -number - - - - The token decimals
tokenSymbol - - -string - - - - The token symbol
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) bundleTakeOrders(ordersDetails, orderbook, arb, _eval, _shuffle, _interpreterv2, _bundle)

- - - - - - -
- Builds and bundles orders which their details are queried from a orderbook subgraph by checking the vault balances and evaling -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
ordersDetails - - -Array.<any> - - - - - - Orders details queried from subgraph
orderbook - - -ethers.Contract - - - - - - The Orderbook EthersJS contract instance with signer
arb - - -ethers.Contract - - - - - - The Arb EthersJS contract instance with signer
_eval - - -boolean - - - - - - true - - To eval() the orders and filter them based on the eval result
_shuffle - - -boolean - - - - - - true - - To shuffle the bundled order array at the end
_interpreterv2 - - -boolean - - - - - - false - - If should use eval2 of interpreter v2 for evaling
_bundle - - -boolean - - - - - - true - - = If orders should be bundled based on token pair
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- Array of bundled take orders -
- - - - - - - - - - - - - - - -

(async) clear(mode, config, ordersDetails, options)

- - - - - - -
- Method to find and take arbitrage trades for Rain Orderbook orders against some liquidity providers -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
mode - - -string - - - - The mode for clearing, either "0x" or "curve" or "router"
config - - -object - - - - The configuration object
ordersDetails - - -Array.<any> - - - - The order details queried from subgraph
options - - -clearOptions - - - - The options for clear, such as 'gasCoveragePercentage''
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -

createViemClient(chainId, rpcs, useFallbacs)

- - - - - - -
- Creates a viem client -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
chainId - - -number - - - - - - The chain id
rpcs - - -Array.<string> - - - - - - The RPC urls
useFallbacs - - -boolean - - - - - - false - - If fallback RPCs should be used as well or not
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) crouterClear(config, ordersDetails, gasCoveragePercentage)

- - - - - - -
- Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with router contract -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -object - - - - - - The configuration object
ordersDetails - - -Array.<any> - - - - - - The order details queried from subgraph
gasCoveragePercentage - - -string - - - - - - 100 - - (optional) The percentage of the gas cost to cover on each transaction -for it to be considered profitable and get submitted
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -

(async) curveClear(config, ordersDetails, gasCoveragePercentage)

- - - - - - -
- Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with curve -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -object - - - - - - The configuration object
ordersDetails - - -Array.<any> - - - - - - The order details queried from subgraph
gasCoveragePercentage - - -string - - - - - - 100 - - (optional) The percentage of the gas cost to cover on each transaction -for it to be considered profitable and get submitted
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -

estimateProfit(pairPrice, ethPrice, bundledOrder, gas, gasCoveragePercentage)

- - - - - - -
- Estimates the profit for a single bundled orders struct -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
pairPrice - - -string - - - - - - The price token pair
ethPrice - - -string - - - - - - Price of ETH to buy token
bundledOrder - - -object - - - - - - The bundled order object
gas - - -ethers.BigNumber - - - - - - The estimated gas cost in ETH
gasCoveragePercentage - - -string - - - - - - 100 - - Percentage of gas to cover, default is 100,i.e. full gas coverage
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The estimated profit -
- - - - - - - - - - - - - - - -

fromFixed18(bn, decimals)

- - - - - - -
- Convert a 18 fixed point BigNumber to a BigNumber with some other decimals point -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bn - - -BigNumber - - - - The BigNumber to convert
decimals - - -number - - - - The decimals point of convert the given BigNumber
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- A decimals point BigNumber -
- - - - - - - - - - - - - - - -

getActualClearAmount(arbAddress, receipt)

- - - - - - -
- Extracts the actual clear amount (received token value) from transaction receipt -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
arbAddress - - -string - - - - The arb contract address
receipt - - -any - - - - The transaction receipt
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The actual clear amount -
- - - - - - - - - - - - - - - -

getActualPrice(receipt, orderbook, arb, amount, buyDecimals)

- - - - - - -
- Calculates the actual clear price from transactioin event -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
receipt - - -any - - - - The transaction receipt
orderbook - - -string - - - - The Orderbook contract address
arb - - -string - - - - The Arb contract address
amount - - -string - - - - The clear amount
buyDecimals - - -number - - - - The buy token decimals
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The actual clear price or undefined if necessary info not found in transaction events -
- - - - - - - - - - - - - - - -

getAvailableSwaps(config)

- - - - - - -
- Returns array of available swaps pairs from specified curve pools in config file -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -any - - - - The config of a network from config.json file
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) getConfig(rpcUrl, walletPrivateKey, orderbookAddress, arbAddress, arbType, options)

- - - - - - -
- Get the configuration info of a network required for the bot -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
rpcUrl - - -string - - - - The RPC URL
walletPrivateKey - - -string - - - - The wallet private key
orderbookAddress - - -string - - - - The Rain Orderbook contract address deployed on the network
arbAddress - - -string - - - - The Rain Arb contract address deployed on the network
arbType - - -string - - - - The type of the Arb contract
options - - -configOptions - - - - (optional) Optional parameters, 0x API key, liquidity providers and monthly ratelimit
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The configuration object -
- - - - - - - - - - - - - - - -

getCurveSwaps(config)

- - - - - - -
- Returns array of available swaps pairs from specified curve pools in config file -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -any - - - - The config of a network from config.json file
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getDataFetcher(configOrViemClient, liquidityProviders)

- - - - - - -
- Instantiates a DataFetcher -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
configOrViemClient - - -any - - - - The network config data or a viem public client
liquidityProviders - - -Array.<LiquidityProviders> - - - - Array of Liquidity Providers
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) getEthPrice(config, targetTokenAddress, targetTokenDecimals, gasPrice, dataFetcher)

- - - - - - -
- Gets ETH price against a target token -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
config - - -any - - - - The network config data
targetTokenAddress - - -string - - - - The target token address
targetTokenDecimals - - -number - - - - The target token decimals
gasPrice - - -BigNumber - - - - The network gas price
dataFetcher - - -DataFetcher - - - - (optional) The DataFetcher instance
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getIncome(signer, receipt)

- - - - - - -
- Extracts the income (received token value) from transaction receipt -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
signer - - -ethers.Wallet - - - - The ethers wallet instance of the bot
receipt - - -any - - - - The transaction receipt
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The income value or undefined if cannot find any valid value -
- - - - - - - - - - - - - - - -

(async) getOrderDetails(sgs, json, signer, sgFilters)

- - - - - - -
- Get the order details from a source, i.e array of subgraphs and/or a local json file -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
sgs - - -Array.<string> - - - - The subgraph endpoint URL(s) to query for orders' details
json - - -string - - - - Path to a json file containing orders structs
signer - - -ethers.signer - - - - The ethers signer
sgFilters - - -any - - - - The filters for subgraph query
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- An array of order details -
- - - - - - - - - - - - - - - -

(async) getOrderDetailsFromJson(jsonContent)

- - - - - - -
- Get order details from an array of order struct -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
jsonContent - - -string - - - - Content of a JSON file containing orders struct
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

getOrderHash(order)

- - - - - - -
- Get the order hash from an order struct -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
order - - -any - - - - The order struct
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The order hash -
- - - - - - - - - - - - - - - -

getOrderStruct(orderDetails)

- - - - - - -
- Constructs Order struct from the result of sg default query -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
orderDetails - - -object - - - - The order details fetched from sg
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The order struct as js object -
- - - - - - - - - - - - - - - -

getQuery(orderHash, owner, interpreter)

- - - - - - -
- Method to get the subgraph query body with optional filters -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
orderHash - - -string - - - - The order hash to apply as filter
owner - - -string - - - - The order owner to apply as filter
interpreter - - -string - - - - The interpreter to apply as filter
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- the query string -
- - - - - - - - - - - - - - - -

(async) getRouteForTokens(chainId, sellAmount, fromTokenAddress, fromTokenDecimals, toTokenAddress, toTokenDecimals, receiverAddress, routeProcessorAddress, abiencoded)

- - - - - - -
- Gets the route for tokens -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
chainId - - -number - - - - The network chain id
sellAmount - - -ethers.BigNumber - - - - The sell amount, should be in onchain token value
fromTokenAddress - - -string - - - - The from token address
fromTokenDecimals - - -number - - - - The from token decimals
toTokenAddress - - -string - - - - The to token address
toTokenDecimals - - -number - - - - The to token decimals
receiverAddress - - -string - - - - The address of the receiver
routeProcessorAddress - - -string - - - - The address of the RouteProcessor contract
abiencoded - - -boolean - - - - If the result should be abi encoded or not
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) interpreterEval(interpreter, arbAddress, obAddress, order, inputIndex, outputIndex)

- - - - - - -
- Calls eval for a specific order to get its max output and ratio -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interpreter - - -ethers.Contract - - - - The interpreter ethersjs contract instance with signer
arbAddress - - -string - - - - Arb contract address
obAddress - - -string - - - - OrderBook contract address
order - - -object - - - - The order details fetched from sg
inputIndex - - -number - - - - The input token index
outputIndex - - -number - - - - The ouput token index
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The ratio and maxOuput as BigNumber -
- - - - - - - - - - - - - - - -

(async) interpreterV2Eval(interpreter, arbAddress, obAddress, order, inputIndex, outputIndex)

- - - - - - -
- Calls eval2 on interpreter v2 for a specific order to get its max output and ratio -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
interpreter - - -ethers.Contract - - - - The interpreter v2 ethersjs contract instance with signer
arbAddress - - -string - - - - Arb contract address
obAddress - - -string - - - - OrderBook contract address
order - - -object - - - - The order details fetched from sg
inputIndex - - -number - - - - The input token index
outputIndex - - -number - - - - The ouput token index
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The ratio and maxOuput as BigNumber -
- - - - - - - - - - - - - - - -

prepare(bundledOrders, availableSwaps, config, sort)

- - - - - - -
- Prepares the bundled orders by getting the best deals from Curve pools and sorting the -bundled orders based on the best deals -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bundledOrders - - -Array.<any> - - - - The bundled orders array
availableSwaps - - -Array.<any> - - - - The available swaps from Curve specofied pools
config - - -any - - - - The network config data
- - -ethers.Signer - - - - The ethersjs signer
sort - - -boolean - - - - (optional) Sort based on best deals or not
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

processLps(liquidityProviders, chainId)

- - - - - - -
- Resolves an array of case-insensitive names to LiquidityProviders, ignores the ones that are not valid -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
liquidityProviders - - -Array.<string> - - - - List of liquidity providers
chainId - - -number - - - - The chain id
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) promiseTimeout(promise, time, exception)

- - - - - - -
- Method to put a timeout on a promise, throws the exception if promise is not settled within the time -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
promise - - -Promise - - - - The Promise to put timeout on
time - - -number - - - - The time in milliseconds
exception - - -string -| - -number -| - -bigint -| - -symbol -| - -boolean - - - - The exception value to reject with if the promise is not settled within time
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- A new promise that gets settled with initial promise settlement or rejected with exception value -if the time runs out before the main promise settlement -
- - - - - - - - - - - - - - - -

(async) routerClear(config, ordersDetails, gasCoveragePercentage)

- - - - - - -
- Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with router contract -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -object - - - - - - The configuration object
ordersDetails - - -Array.<any> - - - - - - The order details queried from subgraph
gasCoveragePercentage - - -string - - - - - - 100 - - (optional) The percentage of the gas cost to cover on each transaction -for it to be considered profitable and get submitted
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -

setCurveSwaps(bundledOrders, availableSwaps, config, sort)

- - - - - - -
- Prepares the bundled orders by getting the best deals from Curve pools and sorting the -bundled orders based on the best deals -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bundledOrders - - -Array.<any> - - - - The bundled orders array
availableSwaps - - -Array.<any> - - - - The available swaps from Curve specofied pools
config - - -any - - - - The network config data
- - -ethers.Signer - - - - The ethersjs signer
sort - - -boolean - - - - (optional) Sort based on best deals or not
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) sleep(ms)

- - - - - - -
- Waits for provided miliseconds -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
ms - - -number - - - - Miliseconds to wait
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) srouterClear(config, ordersDetails, gasCoveragePercentage)

- - - - - - -
- Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with specialized router contract -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -object - - - - - - The configuration object
ordersDetails - - -Array.<any> - - - - - - The order details queried from subgraph
gasCoveragePercentage - - -string - - - - - - 100 - - (optional) The percentage of the gas cost to cover on each transaction -for it to be considered profitable and get submitted
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -

toFixed18(bn, decimals)

- - - - - - -
- Convert a BigNumber to a fixed 18 point BigNumber -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
bn - - -BigNumber - - - - The BigNumber to convert
decimals - - -number - - - - The decimals point of the given BigNumber
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- A 18 fixed point BigNumber -
- - - - - - - - - - - - - - - -

validateOrders(orders)

- - - - - - -
- Validates content of an array of orders -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
orders - - -Array.<any> - - - - Array of order struct
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

visualizeRoute(fromToken, toToken, legs)

- - - - - - -
- Method to visualize the routes, returns array of route strings sorted from highest to lowest percentage -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
fromToken - - -string - - - - The from token address
toToken - - -string - - - - The to token address
legs - - -Array.<any> - - - - The legs of the route
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -

(async) zeroExClear(config, ordersDetails, gasCoveragePercentage)

- - - - - - -
- Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with 0x -
- - - - - - - - - -
Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDefaultDescription
config - - -object - - - - - - The configuration object
ordersDetails - - -Array.<any> - - - - - - The order details queried from subgraph
gasCoveragePercentage - - -string - - - - - - 100 - - (optional) The percentage of the gas cost to cover on each transaction for it to be considered profitable and get submitted
- - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- The report of details of cleared orders -
- - - - - - - - - - - - - - - -
- -
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - \ No newline at end of file diff --git a/docs/html/index.html b/docs/html/index.html deleted file mode 100644 index 38d20757..00000000 --- a/docs/html/index.html +++ /dev/null @@ -1,65 +0,0 @@ - - - - - JSDoc: Home - - - - - - - - - - -
- -

Home

- - - - - - - - -

- - - - - - - - - - - - - - - - - - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - \ No newline at end of file diff --git a/docs/html/index.js.html b/docs/html/index.js.html deleted file mode 100644 index 51b4dd61..00000000 --- a/docs/html/index.js.html +++ /dev/null @@ -1,360 +0,0 @@ - - - - - JSDoc: Source: index.js - - - - - - - - - - -
- -

Source: index.js

- - - - - - -
-
-
const fs = require("fs");
-const path = require("path");
-const axios = require("axios");
-const { ethers } = require("ethers");
-const { getQuery } = require("./query");
-const { versions } = require("process");
-const CONFIG = require("../config.json");
-const { curveClear } = require("./modes/curve");
-const { zeroExClear } = require("./modes/zeroex");
-const { routerClear } = require("./modes/router");
-const { crouterClear } = require("./modes/crouter");
-const { srouterClear } = require("./modes/srouter");
-const { getOrderDetailsFromJson, appGlobalLogger } = require("./utils");
-
-
-/**
- * Options for getConfig()
- */
-const configOptions = {
-    /**
-     * The 0x API key
-     */
-    zeroExApiKey: undefined,
-    /**
-     * Seconds to wait for the transaction to mine before disregarding it
-     */
-    timeout: undefined,
-    /**
-     * List of liquidity providers for router contract tomoperate on
-     */
-    liquidityProviders: undefined,
-    /**
-     * Flashbot rpc url
-     */
-    flashbotRpc: undefined,
-    /**
-     * 0x monthly rate limit number, if not specified will not respect 0x monthly rate limit
-     */
-    monthlyRatelimit: undefined,
-    /**
-     * Hides sensitive data such as rpc url and wallet private key from apearing in logs
-     */
-    hideSensitiveData: true,
-    /**
-     * Option to shorten large data fields in logs
-     */
-    shortenLargeLogs: true,
-    /**
-     * Maximize profit for "srouter" mode, comes at the cost of RPC calls
-     */
-    maxProfit: false,
-    /**
-     * Maximize maxIORatio for "srouter" mode
-     */
-    maxRatio: false,
-    /**
-     * Option to fallback to public rpcs
-     */
-    usePublicRpcs: false,
-    /**
-     * Option for operating with interpreter v2
-     */
-    interpreterv2: false,
-    /**
-     * Flag for not bundling orders based on pairs and clear each order individually
-     */
-    bundle: true
-};
-
-/**
- * Options for clear()
- */
-const clearOptions = {
-    /**
-     * The percentage of the gas cost to cover on each transaction
-     * for it to be considered profitable and get submitted
-     */
-    gasCoveragePercentage: "100",
-    // /**
-    //  * Prioritize better deals to get cleared first, default is true
-    //  */
-    // prioritization: true
-};
-
-/**
- * Get the order details from a source, i.e array of subgraphs and/or a local json file
- *
- * @param {string[]} sgs - The subgraph endpoint URL(s) to query for orders' details
- * @param {string} json - Path to a json file containing orders structs
- * @param {ethers.signer} signer - The ethers signer
- * @param {any} sgFilters - The filters for subgraph query
- * @returns An array of order details
- */
-const getOrderDetails = async(sgs, json, signer, sgFilters) => {
-    const ordersDetails = [];
-    const isInvalidJson = typeof json !== "string" || !json;
-    const isInvalidSg = !Array.isArray(sgs) || sgs.length === 0;
-
-    if (isInvalidSg && isInvalidJson) throw "type of provided sources are invalid";
-    else {
-        let hasJson = false;
-        const promises = [];
-        if (!isInvalidJson) {
-            try {
-                const content = fs.readFileSync(path.resolve(json)).toString();
-                promises.push(getOrderDetailsFromJson(content, signer));
-                hasJson = true;
-            }
-            catch (error) {
-                console.log(error);
-            }
-        }
-        if (!isInvalidSg) {
-            sgs.forEach(v => {
-                if (v && typeof v === "string") promises.push(axios.post(
-                    v,
-                    {
-                        query: getQuery(
-                            sgFilters?.orderHash,
-                            sgFilters?.orderOwner,
-                            sgFilters?.orderInterpreter
-                        )
-                    },
-                    { headers: { "Content-Type": "application/json" } }
-                ));
-            });
-        }
-
-        const responses = await Promise.allSettled(promises);
-        if (responses.every(v => v.status === "rejected")) {
-            responses.forEach(v => console.log(v.reason));
-            throw "could not read anything from provided sources";
-        }
-        else {
-            for (let i = 0; i < responses.length; i++) {
-                if (i === 0) {
-                    if (responses[0].status === "fulfilled") {
-                        if (hasJson) ordersDetails.push(...responses[0].value);
-                        else ordersDetails.push(...responses[0].value.data.data.orders);
-                    }
-                    else console.log(responses[0].reason);
-                }
-                else {
-                    if (responses[i].status === "fulfilled") ordersDetails.push(
-                        ...responses[i].value.data.data.orders
-                    );
-                    else console.log(responses[i].reason);
-                }
-            }
-        }
-    }
-    return ordersDetails;
-};
-
-/**
- * Get the configuration info of a network required for the bot
- *
- * @param {string} rpcUrl - The RPC URL
- * @param {string} walletPrivateKey - The wallet private key
- * @param {string} orderbookAddress - The Rain Orderbook contract address deployed on the network
- * @param {string} arbAddress - The Rain Arb contract address deployed on the network
- * @param {string} arbType - The type of the Arb contract
- * @param {configOptions} options - (optional) Optional parameters, 0x API key, liquidity providers and monthly ratelimit
- * @returns The configuration object
- */
-const getConfig = async(
-    rpcUrl,
-    walletPrivateKey,
-    orderbookAddress,
-    arbAddress,
-    arbType,
-    options = configOptions
-) => {
-
-    // applied for API mode
-    if (!!options.hideSensitiveData || !!options.shortenLargeLogs) appGlobalLogger(
-        !!options.hideSensitiveData,
-        rpcUrl,
-        walletPrivateKey,
-        options?.zeroExApiKey
-    );
-
-    const AddressPattern = /^0x[a-fA-F0-9]{40}$/;
-    if (!/^(0x)?[a-fA-F0-9]{64}$/.test(walletPrivateKey)) throw "invalid wallet private key";
-    if (options.timeout !== undefined){
-        if (typeof options.timeout === "number") {
-            if (!Number.isInteger(options.timeout) || options.timeout == 0) throw "invalid timeout, must be an integer greater than 0";
-            else options.timeout = options.timeout * 1000;
-        }
-        else if (typeof options.timeout === "string") {
-            if (/^\d+$/.test(options.timeout)) options.timeout = Number(options.timeout) * 1000;
-            else throw "invalid timeout, must be an integer greater than 0";
-            if (options.timeout == 0) throw "invalid timeout, must be an integer greater than 0";
-        }
-        else throw "invalid timeout, must be an integer greater than 0";
-    }
-
-    const provider  = new ethers.providers.JsonRpcProvider(rpcUrl);
-    const signer    = new ethers.Wallet(walletPrivateKey, provider);
-    const chainId   = await signer.getChainId();
-    const config    = CONFIG.find(v => v.chainId === chainId);
-    if (!config) throw `Cannot find configuration for the network with chain id: ${chainId}`;
-
-    if (!AddressPattern.test(orderbookAddress)) throw "invalid orderbook contract address";
-    if (!AddressPattern.test(arbAddress)) throw "invalid arb contract address";
-
-    config.bundle = true;
-    if (options?.bundle !== undefined) config.bundle = !!options.bundle;
-
-    config.rpc              = rpcUrl;
-    config.signer           = signer;
-    config.orderbookAddress = orderbookAddress;
-    config.arbAddress       = arbAddress;
-    config.arbType          = arbType?.toLowerCase();
-    config.lps              = options?.liquidityProviders;
-    config.apiKey           = options?.zeroExApiKey;
-    config.monthlyRatelimit = options?.monthlyRatelimit;
-    config.timeout          = options?.timeout;
-    config.flashbotRpc      = options?.flashbotRpc;
-    config.maxProfit        = !!options?.maxProfit;
-    config.maxRatio         = !!options?.maxRatio;
-    config.usePublicRpcs    = !!options?.usePublicRpcs;
-    config.interpreterv2    = !!options?.interpreterv2;
-
-    return config;
-};
-
-/**
- * Method to find and take arbitrage trades for Rain Orderbook orders against some liquidity providers
- *
- * @param {string} mode - The mode for clearing, either "0x" or "curve" or "router"
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {clearOptions} options - The options for clear, such as 'gasCoveragePercentage''
- * @returns The report of details of cleared orders
- */
-const clear = async(
-    mode,
-    config,
-    ordersDetails,
-    options = clearOptions
-) => {
-    const _mode = mode.toLowerCase();
-    const version = versions.node;
-    const majorVersion = Number(version.slice(0, version.indexOf(".")));
-    // const prioritization = options.prioritization !== undefined
-    //     ? !!options.prioritization
-    //     : clearOptions.prioritization;
-    const gasCoveragePercentage = options.gasCoveragePercentage !== undefined
-        ? options.gasCoveragePercentage
-        : clearOptions.gasCoveragePercentage;
-
-    if (_mode !== "srouter") {
-        if (!config.arbType) throw "undefined arb contract type";
-        if (!/^flash-loan-v[23]$|^order-taker$/.test(config.arbType)) {
-            throw "invalid arb contract type, must be either of: 'flash-loan-v2' or 'flash-loan-v3' or 'order-taker'";
-        }
-    }
-    if (config.arbType === "flash-loan-v2" && config.interpreterv2) throw "interpreter v2 is not compatible with flash-loan-v2";
-
-    if (_mode === "0x") return await zeroExClear(
-        config,
-        ordersDetails,
-        gasCoveragePercentage,
-        // prioritization
-    );
-    else if (_mode === "curve") {
-        if (majorVersion >= 18) return await curveClear(
-            config,
-            ordersDetails,
-            gasCoveragePercentage,
-            // prioritization
-        );
-        else throw `NodeJS v18 or higher is required for running the app in "curve" mode, current version: ${version}`;
-    }
-    else if (_mode === "router") {
-        if (majorVersion >= 18) return await routerClear(
-            config,
-            ordersDetails,
-            gasCoveragePercentage,
-            // prioritization
-        );
-        else throw `NodeJS v18 or higher is required for running the app in "router" mode, current version: ${version}`;
-    }
-    else if (_mode === "crouter") {
-        if (majorVersion >= 18) return await crouterClear(
-            config,
-            ordersDetails,
-            gasCoveragePercentage,
-            // prioritization
-        );
-        else throw `NodeJS v18 or higher is required for running the app in "router" mode, current version: ${version}`;
-    }
-    else if (_mode === "srouter") {
-        if (majorVersion >= 18) return await srouterClear(
-            config,
-            ordersDetails,
-            gasCoveragePercentage,
-            // prioritization
-        );
-        else throw `NodeJS v18 or higher is required for running the app in "router" mode, current version: ${version}`;
-    }
-    else throw "unknown mode, must be either of '0x' or 'curve' or 'router' or 'srouter'";
-};
-
-module.exports = {
-    getOrderDetails,
-    getConfig,
-    clear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/modes_crouter.js.html b/docs/html/modes_crouter.js.html deleted file mode 100644 index fe907b98..00000000 --- a/docs/html/modes_crouter.js.html +++ /dev/null @@ -1,838 +0,0 @@ - - - - - JSDoc: Source: modes/crouter.js - - - - - - - - - - -
- -

Source: modes/crouter.js

- - - - - - -
-
-
const ethers = require("ethers");
-const { parseAbi } = require("viem");
-const { Router, Token } = require("sushiswap-router");
-const { arbAbis, orderbookAbi, routeProcessor3Abi, CURVE_POOLS_FNS, CURVE_ZAP_FNS } = require("../abis");
-const {
-    getIncome,
-    processLps,
-    getEthPrice,
-    getDataFetcher,
-    getActualPrice,
-    visualizeRoute,
-    promiseTimeout,
-    bundleTakeOrders,
-    createViemClient
-} = require("../utils");
-
-
-/**
- * Returns array of available swaps pairs from specified curve pools in config file
- * @param {any} config - The config of a network from config.json file
- */
-const getCurveSwaps = (config) => {
-    const swaps = [];
-    for (let i = 0; i < config.curve.pools.length; i++) {
-        const pool = config.curve.pools[i];
-        swaps.push({ address: pool.address, index: i });
-        if (pool.coins) {
-            swaps[swaps.length - 1].coins = [];
-            for (let j = 0; j < pool.coins.length; j++) {
-                for (let k = j + 1; k < pool.coins.length; k++) {
-                    const pair1 = pool.coins[j].symbol +
-                        "/" +
-                        pool.coins[k].symbol;
-                    const pair2 = pool.coins[k].symbol +
-                        "/" +
-                        pool.coins[j].symbol;
-                    if (!swaps[swaps.length - 1].coins.includes(pair1))
-                        swaps[swaps.length - 1].coins.push(pair1);
-                    if (!swaps[swaps.length - 1].coins.includes(pair2))
-                        swaps[swaps.length - 1].coins.push(pair2);
-                }
-            }
-        }
-        if (pool.underlyingCoins) {
-            swaps[swaps.length - 1].underlyingCoins = [];
-            for (let j = 0; j < pool.underlyingCoins.length; j++) {
-                for (let k = j + 1; k < pool.underlyingCoins.length; k++) {
-                    const pair1 = pool.underlyingCoins[j].symbol +
-                        "/" +
-                        pool.underlyingCoins[k].symbol;
-                    const pair2 = pool.underlyingCoins[k].symbol +
-                        "/" +
-                        pool.underlyingCoins[j].symbol;
-                    if (!swaps[swaps.length - 1].underlyingCoins.includes(pair1))
-                        swaps[swaps.length - 1].underlyingCoins.push(pair1);
-                    if (!swaps[swaps.length - 1].underlyingCoins.includes(pair2))
-                        swaps[swaps.length - 1].underlyingCoins.push(pair2);
-                }
-            }
-        }
-        if (pool.underlyingCoinsUnwrapped) {
-            swaps[swaps.length - 1].underlyingCoinsUnwrapped = [];
-            for (let j = 0; j < pool.underlyingCoinsUnwrapped.length; j++) {
-                for (let k = j + 1; k < pool.underlyingCoinsUnwrapped.length; k++) {
-                    const pair1 = pool.underlyingCoinsUnwrapped[j].symbol +
-                        "/" +
-                        pool.underlyingCoinsUnwrapped[k].symbol;
-                    const pair2 = pool.underlyingCoinsUnwrapped[k].symbol +
-                        "/" +
-                        pool.underlyingCoinsUnwrapped[j].symbol;
-                    if (!swaps[swaps.length - 1].underlyingCoinsUnwrapped.includes(pair1))
-                        swaps[swaps.length - 1].underlyingCoinsUnwrapped.push(pair1);
-                    if (!swaps[swaps.length - 1].underlyingCoinsUnwrapped.includes(pair2))
-                        swaps[swaps.length - 1].underlyingCoinsUnwrapped.push(pair2);
-                }
-            }
-        }
-    }
-    return swaps;
-};
-
-/**
- * Prepares the bundled orders by getting the best deals from Curve pools and sorting the
- * bundled orders based on the best deals
- *
- * @param {any[]} bundledOrders - The bundled orders array
- * @param {any[]} availableSwaps - The available swaps from Curve specofied pools
- * @param {any} config - The network config data
- * @param {ethers.Signer} - The ethersjs signer
- * @param {boolean} sort - (optional) Sort based on best deals or not
- */
-const setCurveSwaps = (bundledOrders, availableSwaps, config, signer) => {
-    for (let i = 0; i < bundledOrders.length; i++) {
-        const pairFormat = [];
-        const bOrder = bundledOrders[i];
-        const pair = bOrder.buyTokenSymbol + "/" + bOrder.sellTokenSymbol;
-        const pools = availableSwaps.filter(v => {
-            const _l = pairFormat.length;
-            if (v.coins?.includes(pair)) pairFormat.push("c");
-            else if (v.underlyingCoins?.includes(pair)) pairFormat.push("uc");
-            else if (v.underlyingCoinsUnwrapped?.includes(pair)) pairFormat.push("ucu");
-            return pairFormat.length > _l;
-        });
-        if (pools.length > 0) {
-            bOrder.curve = [];
-            pools.forEach((_pool, i) => {
-                const _curvePoolDetailsForPair = {};
-                const poolConfig = config.curve.pools[_pool.index];
-                _curvePoolDetailsForPair.poolContract = new ethers.Contract(
-                    _pool.address,
-                    CURVE_POOLS_FNS,
-                    signer
-                );
-                _curvePoolDetailsForPair.pairFormat = pairFormat[i];
-                _curvePoolDetailsForPair.buyTokenIndex = pairFormat[i] === "c"
-                    ? poolConfig.coins.findIndex(v => v.symbol === bOrder.buyTokenSymbol)
-                    : pairFormat[i] === "uc"
-                        ? poolConfig.underlyingCoins.findIndex(
-                            v => v.symbol === bOrder.buyTokenSymbol
-                        )
-                        : poolConfig.underlyingCoinsUnwrapped.findIndex(
-                            v => v.symbol === bOrder.buyTokenSymbol
-                        );
-                _curvePoolDetailsForPair.sellTokenIndex = pairFormat[i] === "c"
-                    ? poolConfig.coins.findIndex(v => v.symbol === bOrder.sellTokenSymbol)
-                    : pairFormat[i] === "uc"
-                        ? poolConfig.underlyingCoins.findIndex(
-                            v => v.symbol === bOrder.sellTokenSymbol
-                        )
-                        : poolConfig.underlyingCoinsUnwrapped.findIndex(
-                            v => v.symbol === bOrder.sellTokenSymbol
-                        );
-                bOrder.curve.push(_curvePoolDetailsForPair);
-            });
-        }
-    }
-    // bundledOrders = bundledOrders.filter(v => v.curve !== undefined);
-    return bundledOrders;
-};
-
-/**
- * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with router contract
- *
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction
- * for it to be considered profitable and get submitted
- * @returns The report of details of cleared orders
- */
-const crouterClear = async(
-    config,
-    ordersDetails,
-    gasCoveragePercentage = "100"
-) => {
-    if (
-        gasCoveragePercentage < 0 ||
-        !Number.isInteger(Number(gasCoveragePercentage))
-    ) throw "invalid gas coverage percentage, must be an integer greater than equal 0";
-
-    const lps               = processLps(config.lps, config.chainId);
-    const viemClient        = createViemClient(config.chainId, [config.rpc], !!config.usePublicRpc);
-    const dataFetcher       = getDataFetcher(viemClient, lps);
-    const signer            = config.signer;
-    const arbAddress        = config.arbAddress;
-    const orderbookAddress  = config.orderbookAddress;
-    const arbType           = config.arbType;
-    const flashbotSigner    = config.flashbotRpc
-        ? new ethers.Wallet(
-            signer.privateKey,
-            new ethers.providers.JsonRpcProvider(config.flashbotRpc)
-        )
-        : undefined;
-
-    // instantiating arb contract
-    const arb = new ethers.Contract(arbAddress, arbAbis[arbType], signer);
-
-    // instantiating orderbook contract
-    const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer);
-
-    console.log(
-        "------------------------- Starting The",
-        "\x1b[32mCURVE-ROUTER\x1b[0m",
-        "Mode -------------------------",
-        "\n"
-    );
-    console.log("\x1b[33m%s\x1b[0m", Date());
-    console.log("Arb Contract Address: " , arbAddress);
-    console.log("OrderBook Contract Address: " , orderbookAddress, "\n");
-
-    let bundledOrders = [];
-    if (ordersDetails.length) {
-        console.log(
-            "------------------------- Bundling Orders -------------------------", "\n"
-        );
-        bundledOrders = await bundleTakeOrders(
-            ordersDetails,
-            orderbook,
-            arb,
-            undefined,
-            config.rpc !== "test",
-            config.interpreterv2,
-            config.bundle
-        );
-        const availableSwaps = getCurveSwaps(config);
-        bundledOrders = setCurveSwaps(
-            bundledOrders,
-            availableSwaps,
-            config,
-            signer
-        );
-    }
-    else {
-        console.log("No orders found, exiting...", "\n");
-        return;
-    }
-
-    if (!bundledOrders.length) {
-        console.log("Could not find any order to clear for current market price, exiting...", "\n");
-        return;
-    }
-
-    const report = [];
-    for (let i = 0; i < bundledOrders.length; i++) {
-        try {
-            console.log(
-                `------------------------- Trying To Clear ${
-                    bundledOrders[i].buyTokenSymbol
-                }/${
-                    bundledOrders[i].sellTokenSymbol
-                } -------------------------`,
-                "\n"
-            );
-            console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`);
-            console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n");
-
-            console.log(">>> Updating vault balances...", "\n");
-            const newBalances = await Promise.allSettled(
-                bundledOrders[i].takeOrders.map(async(v) => {
-                    return ethers.utils.parseUnits(
-                        ethers.utils.formatUnits(
-                            await orderbook.vaultBalance(
-                                v.takeOrder.order.owner,
-                                bundledOrders[i].sellToken,
-                                v.takeOrder.order.validOutputs[
-                                    v.takeOrder.outputIOIndex
-                                ].vaultId
-                            ),
-                            bundledOrders[i].sellTokenDecimals
-                        )
-                    );
-                })
-            );
-            newBalances.forEach((v, j) => {
-                if (v.status === "fulfilled") {
-                    if (v.value.isZero()) {
-                        bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                    }
-                    else {
-                        if (v.value.lt(bundledOrders[i].takeOrders[j].quoteAmount)) {
-                            bundledOrders[i].takeOrders[j].quoteAmount = v.value;
-                        }
-                    }
-                }
-                else {
-                    console.log(`Could not get vault balance for order ${
-                        bundledOrders[i].takeOrders[j].id
-                    } due to:`);
-                    console.log(v.reason);
-                    bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                }
-            });
-            bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                v => !v.quoteAmount.isZero()
-            );
-
-            if (!bundledOrders[i].takeOrders.length) console.log(
-                "All orders of this token pair have empty vault balance, skipping...",
-                "\n"
-            );
-            else {
-                console.log(">>> Getting best market rate for this token pair", "\n");
-
-                let cumulativeAmountFixed = ethers.constants.Zero;
-                bundledOrders[i].takeOrders.forEach(v => {
-                    cumulativeAmountFixed = cumulativeAmountFixed.add(v.quoteAmount);
-                });
-                const cumulativeAmount = cumulativeAmountFixed.div(
-                    "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                );
-
-                const fromToken = new Token({
-                    chainId: config.chainId,
-                    decimals: bundledOrders[i].sellTokenDecimals,
-                    address: bundledOrders[i].sellToken,
-                    symbol: bundledOrders[i].sellTokenSymbol
-                });
-                const toToken = new Token({
-                    chainId: config.chainId,
-                    decimals: bundledOrders[i].buyTokenDecimals,
-                    address: bundledOrders[i].buyToken,
-                    symbol: bundledOrders[i].buyTokenSymbol
-                });
-
-                const gasPrice = await signer.provider.getGasPrice();
-                const pricePromises = [
-                    dataFetcher.fetchPoolsForToken(fromToken, toToken)
-                ];
-                if (bundledOrders[i].curve) pricePromises.push(viemClient.multicall({
-                    multicallAddress: viemClient.chain?.contracts?.multicall3?.address,
-                    allowFailure: true,
-                    contracts: bundledOrders[i].curve.map((curvePool) => {
-                        if (curvePool.pairFormat === "c") return {
-                            address: curvePool.poolContract.address,
-                            chainId: config.chainId,
-                            args: [
-                                curvePool.sellTokenIndex,
-                                curvePool.buyTokenIndex,
-                                cumulativeAmount.toBigInt()
-                            ],
-                            abi: parseAbi(CURVE_POOLS_FNS),
-                            functionName: "get_dy"
-                        };
-                        else return {
-                            address: curvePool.poolContract.address,
-                            chainId: config.chainId,
-                            args: [
-                                curvePool.sellTokenIndex,
-                                curvePool.buyTokenIndex,
-                                cumulativeAmount.toBigInt()
-                            ],
-                            abi: parseAbi(CURVE_POOLS_FNS),
-                            functionName: "get_dy_underlying"
-                        };
-                    })
-                }));
-
-                console.log(
-                    ">>> getting market rate for " +
-                    ethers.utils.formatUnits(cumulativeAmountFixed) +
-                    " " +
-                    bundledOrders[i].sellTokenSymbol
-                );
-
-                const _res = await Promise.allSettled(pricePromises);
-                let topCurveDealPoolIndex = -1;
-                if (_res[1] !== undefined && _res[1].status === "fulfilled") topCurveDealPoolIndex = _res[1].value.indexOf(
-                    (_res[1].value.filter(v => v.status === "success").sort(
-                        (a, b) => b.result > a.result ? 1 : b.result < a.result ? -1 : 0
-                    ))[0]
-                );
-                const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken);
-                const route = Router.findBestRoute(
-                    pcMap,
-                    config.chainId,
-                    fromToken,
-                    cumulativeAmount,
-                    toToken,
-                    gasPrice.toNumber(),
-                    // 30e9,
-                    // providers,
-                    // poolFilter
-                );
-
-                let rate;
-                let useCurve = false;
-                if (route.status == "NoWay" && topCurveDealPoolIndex === -1) throw "could not find any routes or quote form curve for this token pair";
-                else if (route.status !== "NoWay" && topCurveDealPoolIndex !== -1) {
-                    const curveAmountOut = ethers.BigNumber.from(
-                        _res[1].value[topCurveDealPoolIndex].result
-                    );
-                    console.log(
-                        "best rate from specified curve pools: " +
-                        ethers.utils.formatUnits(curveAmountOut, bundledOrders[i].buyTokenDecimals)+
-                        " " +
-                        bundledOrders[i].buyTokenSymbol
-                    );
-                    console.log(
-                        "best rate from router: " +
-                        ethers.utils.formatUnits(
-                            route.amountOutBN,
-                            bundledOrders[i].buyTokenDecimals
-                        ) +
-                        " " +
-                        bundledOrders[i].buyTokenSymbol
-                    );
-                    if (route.amountOutBN.lt(_res[1].value[topCurveDealPoolIndex].result)) {
-                        useCurve = true;
-                    }
-                    console.log(useCurve ? "choosing curve..." : "choosing router...");
-                    rate = useCurve
-                        ? ethers.BigNumber.from(_res[1].value[topCurveDealPoolIndex].result)
-                        : route.amountOutBN;
-                }
-                else if (route.status !== "NoWay" && topCurveDealPoolIndex === -1) {
-                    console.log("got no quote from curve");
-                    console.log(
-                        "best rate from router: " +
-                        ethers.utils.formatUnits(
-                            route.amountOutBN,
-                            bundledOrders[i].buyTokenDecimals
-                        ) +
-                        " " +
-                        bundledOrders[i].buyTokenSymbol
-                    );
-                    rate = route.amountOutBN;
-                }
-                else {
-                    console.log("found no route from router");
-                    console.log(
-                        "best rate from specified curve pools: " +
-                        ethers.utils.formatUnits(curveAmountOut, bundledOrders[i].buyTokenDecimals)+
-                        " " +
-                        bundledOrders[i].buyTokenSymbol
-                    );
-                    rate = ethers.BigNumber.from(_res[1].value[topCurveDealPoolIndex].result);
-                    useCurve = true;
-                }
-
-                const rateFixed = rate.mul("1" + "0".repeat(18 - bundledOrders[i].buyTokenDecimals));
-                const price = rateFixed.mul("1" + "0".repeat(18)).div(cumulativeAmountFixed);
-                console.log("");
-                console.log(
-                    "Current best price for this token pair:",
-                    `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`,
-                    "\n"
-                );
-
-                // filter take orders based on curent price and calculate final bundle quote amount
-                bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                    v => price.gte(v.ratio)
-                );
-                if (!bundledOrders[i].takeOrders.length) console.log(
-                    "All orders of this token pair have higher ratio than current market price, skipping...",
-                    "\n"
-                );
-                else {
-                    cumulativeAmountFixed = ethers.constants.Zero;
-                    bundledOrders[i].takeOrders.forEach(v => {
-                        cumulativeAmountFixed = cumulativeAmountFixed.add(v.quoteAmount);
-                    });
-                    const bundledQuoteAmount = cumulativeAmountFixed.div(
-                        "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                    );
-
-                    let exchangeData;
-                    if (!useCurve) {
-                        console.log(">>> Route portions: ", "\n");
-                        visualizeRoute(fromToken, toToken, route.legs).forEach(
-                            v => console.log("\x1b[36m%s\x1b[0m", v)
-                        );
-                        console.log("");
-                        const rpParams = Router.routeProcessor2Params(
-                            pcMap,
-                            route,
-                            fromToken,
-                            toToken,
-                            arb.address,
-                            config.routeProcessor3Address,
-                            // permits
-                            // "0.005"
-                        );
-                        const iface = new ethers.utils.Interface(routeProcessor3Abi);
-                        const fnData = iface.encodeFunctionData(
-                            "processRoute",
-                            [
-                                rpParams.tokenIn,
-                                // rpParams.amountIn,
-                                bundledQuoteAmount,
-                                rpParams.tokenOut,
-                                // rpParams.amountOutMin,
-                                // guaranteedAmount,
-                                ethers.BigNumber.from("0"),
-                                rpParams.to,
-                                rpParams.routeCode
-                            ]
-                        );
-                        exchangeData = ethers.utils.defaultAbiCoder.encode(
-                            ["address", "address", "bytes"],
-                            [
-                                config.routeProcessor3Address,
-                                config.routeProcessor3Address,
-                                fnData
-                            ]
-                        );
-                    }
-                    else {
-                        if (bundledOrders[i].curve[topCurveDealPoolIndex].pairFormat === "ucu") {
-                            if (config.curve.usdZapAddress) {
-                                iface = new ethers.utils.Interface(CURVE_ZAP_FNS[0]);
-                                fnData = iface.encodeFunctionData(
-                                    "exchange_underlying",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].poolContract.address,
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                                exchangeData = ethers.utils.defaultAbiCoder.encode(
-                                    ["address", "address", "bytes"],
-                                    [
-                                        config.curve.usdZapAddress,
-                                        config.curve.usdZapAddress,
-                                        fnData
-                                    ]
-                                );
-                            }
-                            else throw ">>> cannot find Zap contract address for this network, skipping...";
-                        }
-                        else {
-                            iface = new ethers.utils.Interface(CURVE_POOLS_FNS);
-                            if (bundledOrders[i].curve[topCurveDealPoolIndex].pairFormat === "c") {
-                                fnData = iface.encodeFunctionData(
-                                    "exchange",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                            }
-                            else {
-                                fnData = iface.encodeFunctionData(
-                                    "exchange_underlying",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topCurveDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                            }
-                            exchangeData = ethers.utils.defaultAbiCoder.encode(
-                                ["address", "address", "bytes"],
-                                [
-                                    bundledOrders[i].curve[
-                                        topCurveDealPoolIndex
-                                    ].poolContract.address,
-                                    bundledOrders[i].curve[
-                                        topCurveDealPoolIndex
-                                    ].poolContract.address,
-                                    fnData
-                                ]
-                            );
-                        }
-                    }
-
-                    const takeOrdersConfigStruct = {
-                        output: bundledOrders[i].buyToken,
-                        input: bundledOrders[i].sellToken,
-                        // for flash loan mode max and min input should be exactly the same as quoted sell
-                        // amount this makes sure the cleared order amount will exactly match the 0x quote
-                        minimumInput: bundledQuoteAmount,
-                        maximumInput: bundledQuoteAmount,
-                        maximumIORatio: ethers.constants.MaxUint256,
-                        orders: bundledOrders[i].takeOrders.map(v => v.takeOrder),
-                    };
-                    if (/^flash-loan-v3$|^order-taker$/.test(arbType)) {
-                        takeOrdersConfigStruct.data = "0x00";
-                        delete takeOrdersConfigStruct.output;
-                        delete takeOrdersConfigStruct.input;
-                        if (arbType === "flash-loan-v3") takeOrdersConfigStruct.data = "0x";
-                    }
-
-                    // building and submit the transaction
-                    try {
-                        if (arbType === "order-taker") takeOrdersConfigStruct.data = exchangeData;
-
-                        const ethPrice = gasCoveragePercentage === "0"
-                            ? "0"
-                            : await getEthPrice(
-                                config,
-                                bundledOrders[i].buyToken,
-                                bundledOrders[i].buyTokenDecimals,
-                                gasPrice,
-                                dataFetcher
-                            );
-                        if (ethPrice === undefined) console.log("can not get ETH price, skipping...", "\n");
-                        else {
-                            const rawtx = {
-                                data: arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            "0"
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            "0",
-                                            exchangeData
-                                        ]
-                                ),
-                                to: arb.address,
-                                gasPrice
-                            };
-                            console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                            let gasLimit = await signer.estimateGas(rawtx);
-                            gasLimit = gasLimit.mul("112").div("100");
-                            rawtx.gasLimit = gasLimit;
-                            const gasCost = gasLimit.mul(gasPrice);
-                            const gasCostInToken = ethers.utils.parseUnits(
-                                ethPrice
-                            ).mul(
-                                gasCost
-                            ).div(
-                                "1" + "0".repeat(
-                                    36 - bundledOrders[i].buyTokenDecimals
-                                )
-                            );
-                            if (gasCoveragePercentage !== "0") {
-                                const headroom = (
-                                    Number(gasCoveragePercentage) * 1.15
-                                ).toFixed();
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                await signer.estimateGas(rawtx);
-                            }
-
-                            try {
-                                console.log(">>> Trying to submit the transaction for this token pair...", "\n");
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                                const tx = flashbotSigner !== undefined
-                                    ? await flashbotSigner.sendTransaction(rawtx)
-                                    : await signer.sendTransaction(rawtx);
-                                console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n");
-                                console.log(
-                                    ">>> Transaction submitted successfully to the network, waiting for transaction to mine...",
-                                    "\n"
-                                );
-
-                                const receipt = config.timeout
-                                    ? await promiseTimeout(
-                                        tx.wait(),
-                                        config.timeout,
-                                        `Transaction failed to mine after ${config.timeout}ms`
-                                    )
-                                    : await tx.wait();
-                                const income = getIncome(signer, receipt);
-                                const clearActualPrice = getActualPrice(
-                                    receipt,
-                                    orderbookAddress,
-                                    arbAddress,
-                                    cumulativeAmountFixed,
-                                    bundledOrders[i].buyTokenDecimals
-                                );
-                                const actualGasCost = ethers.BigNumber.from(
-                                    receipt.effectiveGasPrice
-                                ).mul(receipt.gasUsed);
-                                const actualGasCostInToken = ethers.utils.parseUnits(
-                                    ethPrice
-                                ).mul(
-                                    actualGasCost
-                                ).div(
-                                    "1" + "0".repeat(
-                                        36 - bundledOrders[i].buyTokenDecimals
-                                    )
-                                );
-                                const netProfit = income
-                                    ? income.sub(actualGasCostInToken)
-                                    : undefined;
-                                console.log(
-                                    "\x1b[34m%s\x1b[0m",
-                                    `${bundledOrders[i].takeOrders.length} orders cleared successfully of this token pair!`,
-                                    "\n"
-                                );
-                                console.log(
-                                    "\x1b[36m%s\x1b[0m",
-                                    `Clear Initial Price: ${ethers.utils.formatEther(price)}`
-                                );
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${
-                                    ethers.utils.formatUnits(
-                                        bundledQuoteAmount,
-                                        bundledOrders[i].sellTokenDecimals
-                                    )
-                                } ${bundledOrders[i].sellTokenSymbol}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${
-                                    ethers.utils.formatEther(actualGasCost)
-                                } ${
-                                    config.nativeToken.symbol
-                                }`, "\n");
-                                if (income) {
-                                    console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits(
-                                        income,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`);
-                                    console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits(
-                                        netProfit,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`, "\n");
-                                }
-
-                                report.push({
-                                    transactionHash: receipt.transactionHash,
-                                    tokenPair:
-                                        bundledOrders[i].buyTokenSymbol +
-                                        "/" +
-                                        bundledOrders[i].sellTokenSymbol,
-                                    buyToken: bundledOrders[i].buyToken,
-                                    buyTokenDecimals: bundledOrders[i].buyTokenDecimals,
-                                    sellToken: bundledOrders[i].sellToken,
-                                    sellTokenDecimals: bundledOrders[i].sellTokenDecimals,
-                                    clearedAmount: bundledQuoteAmount.toString(),
-                                    clearPrice: ethers.utils.formatEther(
-                                        price
-                                    ),
-                                    clearActualPrice,
-                                    gasUsed: receipt.gasUsed,
-                                    gasCost: actualGasCost,
-                                    income,
-                                    netProfit,
-                                    clearedOrders: bundledOrders[i].takeOrders.map(v => v.id),
-                                });
-                            }
-                            catch (error) {
-                                console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:");
-                                console.log(error, "\n");
-                            }
-                        }
-                    }
-                    catch (error) {
-                        if (error === "dryrun" || error === "nomatch") {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction dry run failed, skipping...");
-                        }
-                        else {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:");
-                            console.log(error, "\n");
-                            // reason, code, method, transaction, error, stack, message
-                        }
-                    }
-                }
-            }
-        }
-        catch (error) {
-            console.log("\x1b[31m%s\x1b[0m", ">>> Something went wrong, reason:", "\n");
-            console.log(error);
-        }
-    }
-    return report;
-};
-
-module.exports = {
-    crouterClear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/modes_curve.js.html b/docs/html/modes_curve.js.html deleted file mode 100644 index 84bed32a..00000000 --- a/docs/html/modes_curve.js.html +++ /dev/null @@ -1,725 +0,0 @@ - - - - - JSDoc: Source: modes/curve.js - - - - - - - - - - -
- -

Source: modes/curve.js

- - - - - - -
-
-
const ethers = require("ethers");
-const { parseAbi } = require("viem");
-const { arbAbis, orderbookAbi, CURVE_POOLS_FNS, CURVE_ZAP_FNS } = require("../abis");
-const {
-    getIncome,
-    processLps,
-    getEthPrice,
-    getDataFetcher,
-    getActualPrice,
-    promiseTimeout,
-    bundleTakeOrders,
-    createViemClient,
-} = require("../utils");
-
-/**
- * Returns array of available swaps pairs from specified curve pools in config file
- * @param {any} config - The config of a network from config.json file
- */
-const getAvailableSwaps = (config) => {
-    const swaps = [];
-    for (let i = 0; i < config.curve.pools.length; i++) {
-        const pool = config.curve.pools[i];
-        swaps.push({ address: pool.address, index: i });
-        if (pool.coins) {
-            swaps[swaps.length - 1].coins = [];
-            for (let j = 0; j < pool.coins.length; j++) {
-                for (let k = j + 1; k < pool.coins.length; k++) {
-                    const pair1 = pool.coins[j].symbol +
-                        "/" +
-                        pool.coins[k].symbol;
-                    const pair2 = pool.coins[k].symbol +
-                        "/" +
-                        pool.coins[j].symbol;
-                    if (!swaps[swaps.length - 1].coins.includes(pair1))
-                        swaps[swaps.length - 1].coins.push(pair1);
-                    if (!swaps[swaps.length - 1].coins.includes(pair2))
-                        swaps[swaps.length - 1].coins.push(pair2);
-                }
-            }
-        }
-        if (pool.underlyingCoins) {
-            swaps[swaps.length - 1].underlyingCoins = [];
-            for (let j = 0; j < pool.underlyingCoins.length; j++) {
-                for (let k = j + 1; k < pool.underlyingCoins.length; k++) {
-                    const pair1 = pool.underlyingCoins[j].symbol +
-                        "/" +
-                        pool.underlyingCoins[k].symbol;
-                    const pair2 = pool.underlyingCoins[k].symbol +
-                        "/" +
-                        pool.underlyingCoins[j].symbol;
-                    if (!swaps[swaps.length - 1].underlyingCoins.includes(pair1))
-                        swaps[swaps.length - 1].underlyingCoins.push(pair1);
-                    if (!swaps[swaps.length - 1].underlyingCoins.includes(pair2))
-                        swaps[swaps.length - 1].underlyingCoins.push(pair2);
-                }
-            }
-        }
-        if (pool.underlyingCoinsUnwrapped) {
-            swaps[swaps.length - 1].underlyingCoinsUnwrapped = [];
-            for (let j = 0; j < pool.underlyingCoinsUnwrapped.length; j++) {
-                for (let k = j + 1; k < pool.underlyingCoinsUnwrapped.length; k++) {
-                    const pair1 = pool.underlyingCoinsUnwrapped[j].symbol +
-                        "/" +
-                        pool.underlyingCoinsUnwrapped[k].symbol;
-                    const pair2 = pool.underlyingCoinsUnwrapped[k].symbol +
-                        "/" +
-                        pool.underlyingCoinsUnwrapped[j].symbol;
-                    if (!swaps[swaps.length - 1].underlyingCoinsUnwrapped.includes(pair1))
-                        swaps[swaps.length - 1].underlyingCoinsUnwrapped.push(pair1);
-                    if (!swaps[swaps.length - 1].underlyingCoinsUnwrapped.includes(pair2))
-                        swaps[swaps.length - 1].underlyingCoinsUnwrapped.push(pair2);
-                }
-            }
-        }
-    }
-    return swaps;
-};
-
-/**
- * Prepares the bundled orders by getting the best deals from Curve pools and sorting the
- * bundled orders based on the best deals
- *
- * @param {any[]} bundledOrders - The bundled orders array
- * @param {any[]} availableSwaps - The available swaps from Curve specofied pools
- * @param {any} config - The network config data
- * @param {ethers.Signer} - The ethersjs signer
- * @param {boolean} sort - (optional) Sort based on best deals or not
- */
-const prepare = (bundledOrders, availableSwaps, config, signer) => {
-    for (let i = 0; i < bundledOrders.length; i++) {
-        const pairFormat = [];
-        const bOrder = bundledOrders[i];
-        const pair = bOrder.buyTokenSymbol + "/" + bOrder.sellTokenSymbol;
-        const pools = availableSwaps.filter(v => {
-            const _l = pairFormat.length;
-            if (v.coins?.includes(pair)) pairFormat.push("c");
-            else if (v.underlyingCoins?.includes(pair)) pairFormat.push("uc");
-            else if (v.underlyingCoinsUnwrapped?.includes(pair)) pairFormat.push("ucu");
-            return pairFormat.length > _l;
-            // v.coins?.includes(pair) ||
-            // v.underlyingCoins?.includes(pair) ||
-            // v.underlyingCoinsUnwrapped?.includes(pair);
-        });
-        if (pools.length > 0) {
-            bOrder.curve = [];
-            pools.forEach((_pool, i) => {
-                const _curvePoolDetailsForPair = {};
-                const poolConfig = config.curve.pools[_pool.index];
-                _curvePoolDetailsForPair.poolContract = new ethers.Contract(
-                    _pool.address,
-                    CURVE_POOLS_FNS,
-                    signer
-                );
-                _curvePoolDetailsForPair.pairFormat = pairFormat[i];
-                _curvePoolDetailsForPair.buyTokenIndex = pairFormat[i] === "c"
-                    ? poolConfig.coins.findIndex(v => v.symbol === bOrder.buyTokenSymbol)
-                    : pairFormat[i] === "uc"
-                        ? poolConfig.underlyingCoins.findIndex(
-                            v => v.symbol === bOrder.buyTokenSymbol
-                        )
-                        : poolConfig.underlyingCoinsUnwrapped.findIndex(
-                            v => v.symbol === bOrder.buyTokenSymbol
-                        );
-                _curvePoolDetailsForPair.sellTokenIndex = pairFormat[i] === "c"
-                    ? poolConfig.coins.findIndex(v => v.symbol === bOrder.sellTokenSymbol)
-                    : pairFormat[i] === "uc"
-                        ? poolConfig.underlyingCoins.findIndex(
-                            v => v.symbol === bOrder.sellTokenSymbol
-                        )
-                        : poolConfig.underlyingCoinsUnwrapped.findIndex(
-                            v => v.symbol === bOrder.sellTokenSymbol
-                        );
-                bOrder.curve.push(_curvePoolDetailsForPair);
-            });
-            // try {
-            //     let rate;
-            //     // let cumulativeAmountFixed = ethers.constants.Zero;
-            //     // bOrder.takeOrders.forEach(v => {
-            //     //     cumulativeAmountFixed = cumulativeAmountFixed.add(v.quoteAmount);
-            //     // });
-            //     // const cumulativeAmount = cumulativeAmountFixed.div("1" + "0".repeat(18 - bOrder.sellTokenDecimals));
-            //     if (pairFormat === "c") {
-            //         rate = await bOrder.poolContract.get_dy(
-            //             bOrder.sellTokenIndex,
-            //             bOrder.buyTokenIndex,
-            //             // cumulativeAmount
-            //             "1" + "0".repeat(bOrder.sellTokenDecimals)
-            //         );
-            //     }
-            //     else {
-            //         rate = await bOrder.poolContract.get_dy_underlying(
-            //             bOrder.sellTokenIndex,
-            //             bOrder.buyTokenIndex,
-            //             // cumulativeAmount
-            //             "1" + "0".repeat(bOrder.sellTokenDecimals)
-            //         );
-            //     }
-            //     // const rateFixed = rate.mul("1" + "0".repeat(18 - bOrder.buyTokenDecimals));
-            //     // const price = rateFixed.mul("1" + "0".repeat(18)).div(cumulativeAmountFixed);
-            //     const price = rate.mul("1" + "0".repeat(18 - bOrder.buyTokenDecimals));
-            //     bOrder.initPrice = price;
-
-            //     console.log(`Current market price for ${pair}: ${ethers.utils.formatEther(price)}`);
-            //     console.log("Current ratio of the orders in this token pair:");
-            //     bOrder.takeOrders.forEach(v => {
-            //         console.log(ethers.utils.formatEther(v.ratio));
-            //     });
-            //     bOrder.takeOrders = bOrder.takeOrders.filter(
-            //         v => price.gte(v.ratio)
-            //     );
-            //     console.log("\n");
-            // }
-            // catch(error) {
-            //     console.log(`>>> could not get price for this ${pair} due to:`);
-            //     console.log(error);
-            // }
-        }
-    }
-    // console.log(
-    //     ">>> Filtering bundled orders with lower ratio than current market price...",
-    //     "\n"
-    // );
-    // bundledOrders = bundledOrders.filter(v => v.initPrice && v.takeOrders.length > 0);
-    // if (sort) {
-    //     console.log("\n", ">>> Sorting the bundled orders based on initial prices...");
-    //     bundledOrders.sort(
-    //         (a, b) => a.initPrice.gt(b.initPrice) ? -1 : a.initPrice.lt(b.initPrice) ? 1 : 0
-    //     );
-    // }
-    bundledOrders = bundledOrders.filter(v => v.curve !== undefined);
-    return bundledOrders;
-};
-
-/**
- * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with curve
- *
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction
- * for it to be considered profitable and get submitted
- * @returns The report of details of cleared orders
- */
-const curveClear = async(
-    config,
-    ordersDetails,
-    gasCoveragePercentage = "100"
-) => {
-    if (
-        gasCoveragePercentage < 0 ||
-        !Number.isInteger(Number(gasCoveragePercentage))
-    ) throw "invalid gas coverage percentage, must be an integer greater than equal 0";
-
-    const signer            = config.signer;
-    const arbAddress        = config.arbAddress;
-    const orderbookAddress  = config.orderbookAddress;
-    const arbType           = config.arbType;
-    const flashbotSigner    = config.flashbotRpc
-        ? new ethers.Wallet(
-            signer.privateKey,
-            new ethers.providers.JsonRpcProvider(config.flashbotRpc)
-        )
-        : undefined;
-
-    // instantiating arb contract
-    const arb = new ethers.Contract(arbAddress, arbAbis[arbType], signer);
-
-    // instantiating orderbook contract
-    const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer);
-
-    console.log(
-        "------------------------- Starting The",
-        "\x1b[32mCURVE.FI\x1b[0m",
-        "Mode -------------------------",
-        "\n"
-    );
-    console.log("\x1b[33m%s\x1b[0m", Date());
-    console.log("Arb Contract Address: " , arbAddress);
-    console.log("OrderBook Contract Address: " , orderbookAddress, "\n");
-
-    let bundledOrders = [];
-    if (ordersDetails.length) {
-        console.log(
-            "------------------------- Bundling Orders -------------------------", "\n"
-        );
-        bundledOrders = await bundleTakeOrders(
-            ordersDetails,
-            orderbook,
-            arb,
-            undefined,
-            config.rpc !== "test",
-            config.interpreterv2,
-            config.bundle
-        );
-        const availableSwaps = getAvailableSwaps(config);
-        bundledOrders = prepare(
-            bundledOrders,
-            availableSwaps,
-            config,
-            signer
-        );
-    }
-    else {
-        console.log("No orders found, exiting...", "\n");
-        return;
-    }
-
-    if (!bundledOrders.length) {
-        console.log("Could not find any order to clear for current market price, exiting...", "\n");
-        return;
-    }
-
-    const report = [];
-    const viemClient = createViemClient(config.chainId, [config.rpc], !!config.usePublicRpc);
-    const dataFetcher = getDataFetcher(viemClient, processLps(config.lps, config.chainId));
-    for (let i = 0; i < bundledOrders.length; i++) {
-        try {
-            console.log(
-                `------------------------- Trying To Clear ${
-                    bundledOrders[i].buyTokenSymbol
-                }/${
-                    bundledOrders[i].sellTokenSymbol
-                } -------------------------`,
-                "\n"
-            );
-            console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`);
-            console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n");
-
-            console.log(">>> Updating vault balances...", "\n");
-            const newBalances = await Promise.allSettled(
-                bundledOrders[i].takeOrders.map(async(v) => {
-                    return ethers.utils.parseUnits(
-                        ethers.utils.formatUnits(
-                            await orderbook.vaultBalance(
-                                v.takeOrder.order.owner,
-                                bundledOrders[i].sellToken,
-                                v.takeOrder.order.validOutputs[
-                                    v.takeOrder.outputIOIndex
-                                ].vaultId
-                            ),
-                            bundledOrders[i].sellTokenDecimals
-                        )
-                    );
-                })
-            );
-            newBalances.forEach((v, j) => {
-                if (v.status === "fulfilled") {
-                    if (v.value.isZero()) {
-                        bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                    }
-                    else {
-                        if (v.value.lt(bundledOrders[i].takeOrders[j].quoteAmount)) {
-                            bundledOrders[i].takeOrders[j].quoteAmount = v.value;
-                        }
-                    }
-                }
-                else {
-                    console.log(`Could not get vault balance for order ${
-                        bundledOrders[i].takeOrders[j].id
-                    } due to:`);
-                    console.log(v.reason);
-                    bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                }
-            });
-            bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                v => !v.quoteAmount.isZero()
-            );
-
-
-            if (!bundledOrders[i].takeOrders.length) console.log(
-                "All orders of this token pair have empty vault balance, skipping...",
-                "\n"
-            );
-            else {
-                let cumulativeAmount = ethers.constants.Zero;
-                bundledOrders[i].takeOrders.forEach(v => {
-                    cumulativeAmount = cumulativeAmount.add(v.quoteAmount);
-                });
-
-                const bundledQuoteAmount = cumulativeAmount.div(
-                    "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                );
-
-                const takeOrdersConfigStruct = {
-                    output: bundledOrders[i].buyToken,
-                    input: bundledOrders[i].sellToken,
-                    // max and min input should be exactly the same as quoted sell amount
-                    // this makes sure the cleared order amount will exactly match the 0x quote
-                    minimumInput: bundledQuoteAmount,
-                    maximumInput: bundledQuoteAmount,
-                    maximumIORatio: ethers.constants.MaxUint256,
-                    orders: bundledOrders[i].takeOrders.map(v => v.takeOrder),
-                };
-                if (/^flash-loan-v3$|^order-taker$/.test(arbType)) {
-                    takeOrdersConfigStruct.data = "0x";
-                    delete takeOrdersConfigStruct.output;
-                    delete takeOrdersConfigStruct.input;
-                }
-
-                const _amountOuts = await viemClient.multicall({
-                    multicallAddress: viemClient.chain?.contracts?.multicall3?.address,
-                    allowFailure: true,
-                    contracts: bundledOrders[i].curve.map((curvePool) => {
-                        if (curvePool.pairFormat === "c") return {
-                            address: curvePool.poolContract.address,
-                            chainId: config.chainId,
-                            args: [
-                                curvePool.sellTokenIndex,
-                                curvePool.buyTokenIndex,
-                                bundledQuoteAmount.toBigInt()
-                            ],
-                            abi: parseAbi(CURVE_POOLS_FNS),
-                            functionName: "get_dy"
-                        };
-                        else return {
-                            address: curvePool.poolContract.address,
-                            chainId: config.chainId,
-                            args: [
-                                curvePool.sellTokenIndex,
-                                curvePool.buyTokenIndex,
-                                bundledQuoteAmount.toBigInt()
-                            ],
-                            abi: parseAbi(CURVE_POOLS_FNS),
-                            functionName: "get_dy_underlying"
-                        };
-                    })
-                });
-                const topDealPoolIndex = _amountOuts.indexOf(
-                    (_amountOuts.filter(v => v.status === "success").sort(
-                        (a, b) => b.result > a.result ? 1 : b.result < a.result ? -1 : 0
-                    ))[0]
-                );
-                if (topDealPoolIndex === -1) console.log("could not get deal from curve pools");
-                else {
-                    // submit the transaction
-                    try {
-                        let fnData;
-                        let exchangeData;
-                        let iface;
-                        if (bundledOrders[i].curve[topDealPoolIndex].pairFormat === "ucu") {
-                            if (config.curve.usdZapAddress) {
-                                iface = new ethers.utils.Interface(CURVE_ZAP_FNS[0]);
-                                fnData = iface.encodeFunctionData(
-                                    "exchange_underlying",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].poolContract.address,
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                                exchangeData = ethers.utils.defaultAbiCoder.encode(
-                                    ["address", "address", "bytes"],
-                                    [
-                                        config.curve.usdZapAddress,
-                                        config.curve.usdZapAddress,
-                                        fnData
-                                    ]
-                                );
-                            }
-                            else console.log(">>> cannot find Zap contract address for this network, skipping...");
-                        }
-                        else {
-                            iface = new ethers.utils.Interface(CURVE_POOLS_FNS);
-                            if (bundledOrders[i].curve[topDealPoolIndex].pairFormat === "c") {
-                                fnData = iface.encodeFunctionData(
-                                    "exchange",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                            }
-                            else {
-                                fnData = iface.encodeFunctionData(
-                                    "exchange_underlying",
-                                    [
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].sellTokenIndex.toString(),
-                                        bundledOrders[i].curve[
-                                            topDealPoolIndex
-                                        ].buyTokenIndex.toString(),
-                                        bundledQuoteAmount.toString(),
-                                        // guaranteedAmount.toString()
-                                        "0"
-                                    ]
-                                );
-                            }
-                            exchangeData = ethers.utils.defaultAbiCoder.encode(
-                                ["address", "address", "bytes"],
-                                [
-                                    bundledOrders[i].curve[topDealPoolIndex].poolContract.address,
-                                    bundledOrders[i].curve[topDealPoolIndex].poolContract.address,
-                                    fnData
-                                ]
-                            );
-                        }
-                        if (arbType === "order-taker") takeOrdersConfigStruct.data = exchangeData;
-
-                        const gasPrice = await signer.provider.getGasPrice();
-                        const ethPrice = gasCoveragePercentage === "0"
-                            ? "0"
-                            : await getEthPrice(
-                                config,
-                                bundledOrders[i].buyToken,
-                                bundledOrders[i].buyTokenDecimals,
-                                gasPrice,
-                                dataFetcher
-                            );
-                        if (ethPrice === undefined) console.log("can not get ETH price, skipping...", "\n");
-                        else {
-                            const rawtx = {
-                                data: arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            "0"
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            "0",
-                                            exchangeData
-                                        ]
-                                ),
-                                to: arb.address,
-                                gasPrice
-                            };
-                            console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                            let gasLimit = await signer.estimateGas(rawtx);
-                            gasLimit = gasLimit.mul("112").div("100");
-                            rawtx.gasLimit = gasLimit;
-                            const gasCost = gasLimit.mul(gasPrice);
-                            const gasCostInToken = ethers.utils.parseUnits(
-                                ethPrice
-                            ).mul(
-                                gasCost
-                            ).div(
-                                "1" + "0".repeat(
-                                    36 - bundledOrders[i].buyTokenDecimals
-                                )
-                            );
-                            if (gasCoveragePercentage !== "0") {
-                                const headroom = (
-                                    Number(gasCoveragePercentage) * 1.15
-                                ).toFixed();
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                await signer.estimateGas(rawtx);
-                            }
-
-                            try {
-                                console.log(">>> Trying to submit the transaction for this token pair...", "\n");
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                                const tx = flashbotSigner !== undefined
-                                    ? await flashbotSigner.sendTransaction(rawtx)
-                                    : await signer.sendTransaction(rawtx);
-                                console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n");
-                                console.log(
-                                    ">>> Transaction submitted successfully to the network, waiting for transaction to mine...",
-                                    "\n"
-                                );
-
-                                const receipt = config.timeout
-                                    ? await promiseTimeout(
-                                        tx.wait(),
-                                        config.timeout,
-                                        `Transaction failed to mine after ${config.timeout}ms`
-                                    )
-                                    : await tx.wait();
-                                const income = getIncome(signer, receipt);
-                                const clearActualPrice = getActualPrice(
-                                    receipt,
-                                    orderbookAddress,
-                                    arbAddress,
-                                    cumulativeAmount,
-                                    bundledOrders[i].buyTokenDecimals
-                                );
-                                const actualGasCost = ethers.BigNumber.from(
-                                    receipt.effectiveGasPrice
-                                ).mul(receipt.gasUsed);
-                                const actualGasCostInToken = ethers.utils.parseUnits(
-                                    ethPrice
-                                ).mul(
-                                    actualGasCost
-                                ).div(
-                                    "1" + "0".repeat(
-                                        36 - bundledOrders[i].buyTokenDecimals
-                                    )
-                                );
-                                const netProfit = income
-                                    ? income.sub(actualGasCostInToken)
-                                    : undefined;
-                                console.log(
-                                    "\x1b[34m%s\x1b[0m",
-                                    `${bundledOrders[i].takeOrders.length} orders cleared successfully of this token pair!`,
-                                    "\n"
-                                );
-                                // console.log(
-                                //     "\x1b[36m%s\x1b[0m",
-                                //     `Clear Initial Price: ${ethers.utils.formatEther(bundledOrders[i].initPrice)}`
-                                // );
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${
-                                    ethers.utils.formatUnits(
-                                        bundledQuoteAmount,
-                                        bundledOrders[i].sellTokenDecimals
-                                    )
-                                } ${bundledOrders[i].sellTokenSymbol}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${
-                                    ethers.utils.formatEther(actualGasCost)
-                                } ${
-                                    config.nativeToken.symbol
-                                }`, "\n");
-                                if (income) {
-                                    console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits(
-                                        income,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`);
-                                    console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits(
-                                        netProfit,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`, "\n");
-                                }
-
-                                report.push({
-                                    transactionHash: receipt.transactionHash,
-                                    tokenPair:
-                                        bundledOrders[i].buyTokenSymbol +
-                                        "/" +
-                                        bundledOrders[i].sellTokenSymbol,
-                                    buyToken: bundledOrders[i].buyToken,
-                                    buyTokenDecimals: bundledOrders[i].buyTokenDecimals,
-                                    sellToken: bundledOrders[i].sellToken,
-                                    sellTokenDecimals: bundledOrders[i].sellTokenDecimals,
-                                    clearedAmount: bundledQuoteAmount.toString(),
-                                    // clearPrice: ethers.utils.formatEther(
-                                    //     bundledOrders[i].initPrice
-                                    // ),
-                                    clearActualPrice,
-                                    gasUsed: receipt.gasUsed,
-                                    gasCost: actualGasCost,
-                                    income,
-                                    netProfit,
-                                    clearedOrders: bundledOrders[i].takeOrders.map(v => v.id),
-                                });
-                            }
-                            catch (error) {
-                                console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:");
-                                console.log(error, "\n");
-                            }
-                        }
-                    }
-                    catch (error) {
-                        if (error === "dryrun" || error === "nomatch") {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction dry run failed, skipping...");
-                        }
-                        else {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:");
-                            console.log(error, "\n");
-                        }
-                    }
-                }
-            }
-        }
-        catch (error) {
-            console.log("\x1b[31m%s\x1b[0m", ">>> Something went wrong, reason:", "\n");
-            console.log(error);
-        }
-    }
-    return report;
-};
-
-module.exports = {
-    curveClear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/modes_router.js.html b/docs/html/modes_router.js.html deleted file mode 100644 index a752ae64..00000000 --- a/docs/html/modes_router.js.html +++ /dev/null @@ -1,556 +0,0 @@ - - - - - JSDoc: Source: modes/router.js - - - - - - - - - - -
- -

Source: modes/router.js

- - - - - - -
-
-
const ethers = require("ethers");
-const { Router, Token } = require("sushiswap-router");
-const { arbAbis, orderbookAbi, routeProcessor3Abi } = require("../abis");
-const {
-    getIncome,
-    processLps,
-    getEthPrice,
-    getDataFetcher,
-    getActualPrice,
-    visualizeRoute,
-    promiseTimeout,
-    bundleTakeOrders
-} = require("../utils");
-
-
-/**
- * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with router contract
- *
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction
- * for it to be considered profitable and get submitted
- * @returns The report of details of cleared orders
- */
-const routerClear = async(
-    config,
-    ordersDetails,
-    gasCoveragePercentage = "100"
-) => {
-    if (
-        gasCoveragePercentage < 0 ||
-        !Number.isInteger(Number(gasCoveragePercentage))
-    ) throw "invalid gas coverage percentage, must be an integer greater than equal 0";
-
-    const lps               = processLps(config.lps, config.chainId);
-    const dataFetcher       = getDataFetcher(config, lps, !!config.usePublicRpc);
-    const signer            = config.signer;
-    const arbAddress        = config.arbAddress;
-    const orderbookAddress  = config.orderbookAddress;
-    const arbType           = config.arbType;
-    const flashbotSigner    = config.flashbotRpc
-        ? new ethers.Wallet(
-            signer.privateKey,
-            new ethers.providers.JsonRpcProvider(config.flashbotRpc)
-        )
-        : undefined;
-
-    // instantiating arb contract
-    const arb = new ethers.Contract(arbAddress, arbAbis[arbType], signer);
-
-    // instantiating orderbook contract
-    const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer);
-
-    console.log(
-        "------------------------- Starting The",
-        "\x1b[32mROUTER\x1b[0m",
-        "Mode -------------------------",
-        "\n"
-    );
-    console.log("\x1b[33m%s\x1b[0m", Date());
-    console.log("Arb Contract Address: " , arbAddress);
-    console.log("OrderBook Contract Address: " , orderbookAddress, "\n");
-
-    let bundledOrders = [];
-    if (ordersDetails.length) {
-        console.log(
-            "------------------------- Bundling Orders -------------------------", "\n"
-        );
-        bundledOrders = await bundleTakeOrders(
-            ordersDetails,
-            orderbook,
-            arb,
-            undefined,
-            config.rpc !== "test",
-            config.interpreterv2,
-            config.bundle
-        );
-    }
-    else {
-        console.log("No orders found, exiting...", "\n");
-        return;
-    }
-
-    if (!bundledOrders.length) {
-        console.log("Could not find any order to clear for current market price, exiting...", "\n");
-        return;
-    }
-
-    const report = [];
-    for (let i = 0; i < bundledOrders.length; i++) {
-        try {
-            console.log(
-                `------------------------- Trying To Clear ${
-                    bundledOrders[i].buyTokenSymbol
-                }/${
-                    bundledOrders[i].sellTokenSymbol
-                } -------------------------`,
-                "\n"
-            );
-            console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`);
-            console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n");
-
-            console.log(">>> Updating vault balances...", "\n");
-            const newBalances = await Promise.allSettled(
-                bundledOrders[i].takeOrders.map(async(v) => {
-                    return ethers.utils.parseUnits(
-                        ethers.utils.formatUnits(
-                            await orderbook.vaultBalance(
-                                v.takeOrder.order.owner,
-                                bundledOrders[i].sellToken,
-                                v.takeOrder.order.validOutputs[
-                                    v.takeOrder.outputIOIndex
-                                ].vaultId
-                            ),
-                            bundledOrders[i].sellTokenDecimals
-                        )
-                    );
-                })
-            );
-            newBalances.forEach((v, j) => {
-                if (v.status === "fulfilled") {
-                    if (v.value.isZero()) {
-                        bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                    }
-                    else {
-                        if (v.value.lt(bundledOrders[i].takeOrders[j].quoteAmount)) {
-                            bundledOrders[i].takeOrders[j].quoteAmount = v.value;
-                        }
-                    }
-                }
-                else {
-                    console.log(`Could not get vault balance for order ${
-                        bundledOrders[i].takeOrders[j].id
-                    } due to:`);
-                    console.log(v.reason);
-                    bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                }
-            });
-            bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                v => !v.quoteAmount.isZero()
-            );
-
-            if (!bundledOrders[i].takeOrders.length) console.log(
-                "All orders of this token pair have empty vault balance, skipping...",
-                "\n"
-            );
-            else {
-                console.log(">>> Getting best route for this token pair", "\n");
-
-                let cumulativeAmountFixed = ethers.constants.Zero;
-                bundledOrders[i].takeOrders.forEach(v => {
-                    cumulativeAmountFixed = cumulativeAmountFixed.add(v.quoteAmount);
-                });
-
-                console.log(
-                    ">>> getting market rate for " +
-                    ethers.utils.formatUnits(cumulativeAmountFixed) +
-                    " " +
-                    bundledOrders[i].sellTokenSymbol
-                );
-
-                const cumulativeAmount = cumulativeAmountFixed.div(
-                    "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                );
-
-                const fromToken = new Token({
-                    chainId: config.chainId,
-                    decimals: bundledOrders[i].sellTokenDecimals,
-                    address: bundledOrders[i].sellToken,
-                    symbol: bundledOrders[i].sellTokenSymbol
-                });
-                const toToken = new Token({
-                    chainId: config.chainId,
-                    decimals: bundledOrders[i].buyTokenDecimals,
-                    address: bundledOrders[i].buyToken,
-                    symbol: bundledOrders[i].buyTokenSymbol
-                });
-
-                // await fetchPoolsForTokenWrapper(dataFetcher, fromToken, toToken);
-                await dataFetcher.fetchPoolsForToken(fromToken, toToken);
-                const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken,toToken);
-                const gasPrice = await signer.provider.getGasPrice();
-                const route = Router.findBestRoute(
-                    pcMap,
-                    config.chainId,
-                    fromToken,
-                    cumulativeAmount,
-                    toToken,
-                    gasPrice.toNumber(),
-                    // 30e9,
-                    // providers,
-                    // poolFilter
-                );
-                if (route.status == "NoWay") throw "could not find any route for this token pair";
-
-                console.log(
-                    "best rate from router: " +
-                    ethers.utils.formatUnits(
-                        route.amountOutBN,
-                        bundledOrders[i].buyTokenDecimals
-                    ) +
-                    " " +
-                    bundledOrders[i].buyTokenSymbol
-                );
-
-                const rateFixed = route.amountOutBN.mul(
-                    "1" + "0".repeat(18 - bundledOrders[i].buyTokenDecimals)
-                );
-                const price = rateFixed.mul("1" + "0".repeat(18)).div(cumulativeAmountFixed);
-                console.log("");
-                console.log(
-                    "Current best route price for this token pair:",
-                    `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`,
-                    "\n"
-                );
-
-                // filter take orders based on curent price and calculate final bundle quote amount
-                bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                    v => price.gte(v.ratio)
-                );
-                if (!bundledOrders[i].takeOrders.length) console.log(
-                    "All orders of this token pair have higher ratio than current market price, skipping...",
-                    "\n"
-                );
-                else {
-                    cumulativeAmountFixed = ethers.constants.Zero;
-                    bundledOrders[i].takeOrders.forEach(v => {
-                        cumulativeAmountFixed = cumulativeAmountFixed.add(v.quoteAmount);
-                    });
-                    const bundledQuoteAmount = cumulativeAmountFixed.div(
-                        "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                    );
-
-                    // find best route with final qoute amount and get routeProcessor params
-                    // route = Router.findBestRoute(
-                    //     pcMap,
-                    //     config.chainId,
-                    //     fromToken,
-                    //     bundledQuoteAmount,
-                    //     toToken,
-                    //     gasPrice.toNumber(),
-                    //     // 30e9
-                    //     // providers,
-                    //     // poolFilter
-                    // );
-                    // if (route.status == "NoWay") throw "could not find any route for this token pair";
-                    console.log(">>> Route portions: ", "\n");
-                    visualizeRoute(fromToken, toToken, route.legs).forEach(
-                        v => console.log("\x1b[36m%s\x1b[0m", v)
-                    );
-                    console.log("");
-
-                    const rpParams = Router.routeProcessor2Params(
-                        pcMap,
-                        route,
-                        fromToken,
-                        toToken,
-                        arb.address,
-                        config.routeProcessor3Address,
-                        // permits
-                        // "0.005"
-                    );
-                    const takeOrdersConfigStruct = {
-                        output: bundledOrders[i].buyToken,
-                        input: bundledOrders[i].sellToken,
-                        // for flash loan mode max and min input should be exactly the same as quoted sell
-                        // amount this makes sure the cleared order amount will exactly match the 0x quote
-                        minimumInput: bundledQuoteAmount,
-                        maximumInput: bundledQuoteAmount,
-                        maximumIORatio: ethers.constants.MaxUint256,
-                        orders: bundledOrders[i].takeOrders.map(v => v.takeOrder),
-                    };
-                    if (/^flash-loan-v3$|^order-taker$/.test(arbType)) {
-                        takeOrdersConfigStruct.data = "0x00";
-                        delete takeOrdersConfigStruct.output;
-                        delete takeOrdersConfigStruct.input;
-                        if (arbType === "flash-loan-v3") takeOrdersConfigStruct.data = "0x";
-                    }
-
-                    // building and submit the transaction
-                    try {
-                        const iface = new ethers.utils.Interface(routeProcessor3Abi);
-                        const fnData = iface.encodeFunctionData(
-                            "processRoute",
-                            [
-                                rpParams.tokenIn,
-                                // rpParams.amountIn,
-                                bundledQuoteAmount,
-                                rpParams.tokenOut,
-                                // rpParams.amountOutMin,
-                                // guaranteedAmount,
-                                ethers.BigNumber.from("0"),
-                                rpParams.to,
-                                rpParams.routeCode
-                            ]
-                        );
-                        const exchangeData = ethers.utils.defaultAbiCoder.encode(
-                            ["address", "address", "bytes"],
-                            [
-                                config.routeProcessor3Address,
-                                config.routeProcessor3Address,
-                                fnData
-                            ]
-                        );
-                        if (arbType === "order-taker") takeOrdersConfigStruct.data = exchangeData;
-
-                        const ethPrice = gasCoveragePercentage === "0"
-                            ? "0"
-                            : await getEthPrice(
-                                config,
-                                bundledOrders[i].buyToken,
-                                bundledOrders[i].buyTokenDecimals,
-                                gasPrice,
-                                dataFetcher
-                            );
-                        if (ethPrice === undefined) console.log("can not get ETH price, skipping...", "\n");
-                        else {
-                            const rawtx = {
-                                data: arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            "0"
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            "0",
-                                            exchangeData
-                                        ]
-                                ),
-                                to: arb.address,
-                                gasPrice
-                            };
-                            console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                            let gasLimit = await signer.estimateGas(rawtx);
-                            gasLimit = gasLimit.mul("112").div("100");
-                            rawtx.gasLimit = gasLimit;
-                            const gasCost = gasLimit.mul(gasPrice);
-                            const gasCostInToken = ethers.utils.parseUnits(
-                                ethPrice
-                            ).mul(
-                                gasCost
-                            ).div(
-                                "1" + "0".repeat(
-                                    36 - bundledOrders[i].buyTokenDecimals
-                                )
-                            );
-                            if (gasCoveragePercentage !== "0") {
-                                const headroom = (
-                                    Number(gasCoveragePercentage) * 1.15
-                                ).toFixed();
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(headroom).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                await signer.estimateGas(rawtx);
-                            }
-
-                            try {
-                                console.log(">>> Trying to submit the transaction for this token pair...", "\n");
-                                rawtx.data = arb.interface.encodeFunctionData(
-                                    "arb",
-                                    arbType === "order-taker"
-                                        ? [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100")
-                                        ]
-                                        : [
-                                            takeOrdersConfigStruct,
-                                            gasCostInToken.mul(gasCoveragePercentage).div("100"),
-                                            exchangeData
-                                        ]
-                                );
-                                console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                                const tx = flashbotSigner !== undefined
-                                    ? await flashbotSigner.sendTransaction(rawtx)
-                                    : await signer.sendTransaction(rawtx);
-                                console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n");
-                                console.log(
-                                    ">>> Transaction submitted successfully to the network, waiting for transaction to mine...",
-                                    "\n"
-                                );
-                                const receipt = config.timeout
-                                    ? await promiseTimeout(
-                                        tx.wait(),
-                                        config.timeout,
-                                        `Transaction failed to mine after ${config.timeout}ms`
-                                    )
-                                    : await tx.wait();
-                                const income = getIncome(signer, receipt);
-                                const clearActualPrice = getActualPrice(
-                                    receipt,
-                                    orderbookAddress,
-                                    arbAddress,
-                                    cumulativeAmountFixed,
-                                    bundledOrders[i].buyTokenDecimals
-                                );
-                                const actualGasCost = ethers.BigNumber.from(
-                                    receipt.effectiveGasPrice
-                                ).mul(receipt.gasUsed);
-                                const actualGasCostInToken = ethers.utils.parseUnits(
-                                    ethPrice
-                                ).mul(
-                                    actualGasCost
-                                ).div(
-                                    "1" + "0".repeat(
-                                        36 - bundledOrders[i].buyTokenDecimals
-                                    )
-                                );
-                                const netProfit = income
-                                    ? income.sub(actualGasCostInToken)
-                                    : undefined;
-                                console.log(
-                                    "\x1b[34m%s\x1b[0m",
-                                    `${bundledOrders[i].takeOrders.length} orders cleared successfully of this token pair!`,
-                                    "\n"
-                                );
-                                console.log(
-                                    "\x1b[36m%s\x1b[0m",
-                                    `Clear Initial Price: ${ethers.utils.formatEther(price)}`
-                                );
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${
-                                    ethers.utils.formatUnits(
-                                        bundledQuoteAmount,
-                                        bundledOrders[i].sellTokenDecimals
-                                    )
-                                } ${bundledOrders[i].sellTokenSymbol}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${
-                                    ethers.utils.formatEther(actualGasCost)
-                                } ${
-                                    config.nativeToken.symbol
-                                }`, "\n");
-                                if (income) {
-                                    console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits(
-                                        income,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`);
-                                    console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits(
-                                        netProfit,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`, "\n");
-                                }
-
-                                report.push({
-                                    transactionHash: receipt.transactionHash,
-                                    tokenPair:
-                                        bundledOrders[i].buyTokenSymbol +
-                                        "/" +
-                                        bundledOrders[i].sellTokenSymbol,
-                                    buyToken: bundledOrders[i].buyToken,
-                                    buyTokenDecimals: bundledOrders[i].buyTokenDecimals,
-                                    sellToken: bundledOrders[i].sellToken,
-                                    sellTokenDecimals: bundledOrders[i].sellTokenDecimals,
-                                    clearedAmount: bundledQuoteAmount.toString(),
-                                    clearPrice: ethers.utils.formatEther(
-                                        price
-                                    ),
-                                    clearActualPrice,
-                                    gasUsed: receipt.gasUsed,
-                                    gasCost: actualGasCost,
-                                    income,
-                                    netProfit,
-                                    clearedOrders: bundledOrders[i].takeOrders.map(v => v.id),
-                                });
-                            }
-                            catch (error) {
-                                console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:");
-                                console.log(error, "\n");
-                            }
-                        }
-                    }
-                    catch (error) {
-                        if (error === "dryrun" || error === "nomatch") {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction dry run failed, skipping...");
-                        }
-                        else {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:");
-                            console.log(error, "\n");
-                            // reason, code, method, transaction, error, stack, message
-                        }
-                    }
-                }
-            }
-        }
-        catch (error) {
-            console.log("\x1b[31m%s\x1b[0m", ">>> Something went wrong, reason:", "\n");
-            console.log(error);
-        }
-    }
-    return report;
-};
-
-module.exports = {
-    routerClear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/modes_srouter.js.html b/docs/html/modes_srouter.js.html deleted file mode 100644 index 82691c5f..00000000 --- a/docs/html/modes_srouter.js.html +++ /dev/null @@ -1,481 +0,0 @@ - - - - - JSDoc: Source: modes/srouter.js - - - - - - - - - - -
- -

Source: modes/srouter.js

- - - - - - -
-
-
const ethers = require("ethers");
-const { arbAbis, orderbookAbi } = require("../abis");
-const { Router, Token } = require("sushiswap-router");
-const {
-    getIncome,
-    processLps,
-    getEthPrice,
-    getDataFetcher,
-    getActualPrice,
-    visualizeRoute,
-    promiseTimeout,
-    bundleTakeOrders,
-    getActualClearAmount
-} = require("../utils");
-
-
-/**
- * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with specialized router contract
- *
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction
- * for it to be considered profitable and get submitted
- * @returns The report of details of cleared orders
- */
-const srouterClear = async(
-    config,
-    ordersDetails,
-    gasCoveragePercentage = "100"
-) => {
-    if (
-        gasCoveragePercentage < 0 ||
-        !Number.isInteger(Number(gasCoveragePercentage))
-    ) throw "invalid gas coverage percentage, must be an integer greater than equal 0";
-
-    const lps               = processLps(config.lps, config.chainId);
-    const dataFetcher       = getDataFetcher(config, lps, !!config.usePublicRpc);
-    const signer            = config.signer;
-    const arbAddress        = config.arbAddress;
-    const orderbookAddress  = config.orderbookAddress;
-    const maxProfit         = config.maxProfit;
-    const maxRatio          = config.maxRatio;
-    const flashbotSigner    = config.flashbotRpc
-        ? new ethers.Wallet(
-            signer.privateKey,
-            new ethers.providers.JsonRpcProvider(config.flashbotRpc)
-        )
-        : undefined;
-
-    // instantiating arb contract
-    const arb = new ethers.Contract(arbAddress, arbAbis["srouter"], signer);
-
-    // instantiating orderbook contract
-    const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer);
-
-    console.log(
-        "------------------------- Starting The",
-        "\x1b[32mS-ROUTER\x1b[0m",
-        "Mode -------------------------",
-        "\n"
-    );
-    console.log("\x1b[33m%s\x1b[0m", Date());
-    console.log("Arb Contract Address: " , arbAddress);
-    console.log("OrderBook Contract Address: " , orderbookAddress, "\n");
-
-    let bundledOrders = [];
-    if (ordersDetails.length) {
-        console.log(
-            "------------------------- Bundling Orders -------------------------", "\n"
-        );
-        bundledOrders = await bundleTakeOrders(
-            ordersDetails,
-            orderbook,
-            arb,
-            maxProfit,
-            config.rpc !== "test",
-            config.interpreterv2,
-            config.bundle
-        );
-    }
-    else {
-        console.log("No orders found, exiting...", "\n");
-        return;
-    }
-
-    if (!bundledOrders.length) {
-        console.log("Could not find any order to clear for current market price, exiting...", "\n");
-        return;
-    }
-
-    const report = [];
-    for (let i = 0; i < bundledOrders.length; i++) {
-        try {
-            console.log(
-                `------------------------- Trying To Clear ${
-                    bundledOrders[i].buyTokenSymbol
-                }/${
-                    bundledOrders[i].sellTokenSymbol
-                } -------------------------`,
-                "\n"
-            );
-            console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`);
-            console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n");
-
-            if (!bundledOrders[i].takeOrders.length) throw "All orders of this token pair have empty vault balance, skipping...";
-
-            const fromToken = new Token({
-                chainId: config.chainId,
-                decimals: bundledOrders[i].sellTokenDecimals,
-                address: bundledOrders[i].sellToken,
-                symbol: bundledOrders[i].sellTokenSymbol
-            });
-            const toToken = new Token({
-                chainId: config.chainId,
-                decimals: bundledOrders[i].buyTokenDecimals,
-                address: bundledOrders[i].buyToken,
-                symbol: bundledOrders[i].buyTokenSymbol
-            });
-
-            const obSellTokenBalance = ethers.BigNumber.from(await signer.call({
-                data: "0x70a08231000000000000000000000000" + orderbookAddress.slice(2),
-                to: bundledOrders[i].sellToken
-            }));
-            const quoteChunks = obSellTokenBalance.div("5");
-
-            if (obSellTokenBalance.isZero()) throw `Orderbook has no ${
-                bundledOrders[i].sellTokenSymbol
-            } balance, skipping...`;
-
-            let ethPrice;
-            const gasPrice = await signer.provider.getGasPrice();
-            try {
-                if (gasCoveragePercentage !== "0") ethPrice = await getEthPrice(
-                    config,
-                    bundledOrders[i].buyToken,
-                    bundledOrders[i].buyTokenDecimals,
-                    gasPrice,
-                    dataFetcher
-                );
-                else ethPrice = "0";
-                if (ethPrice === undefined) throw "could not find a route for ETH price, skipping...";
-            }
-            catch {
-                throw "could not get ETH price, skipping...";
-            }
-            for (let j = 5; j > 0; j--) {
-                const maximumInput = j === 5 ? obSellTokenBalance : quoteChunks.mul(j);
-                const maximumInputFixed = maximumInput.mul(
-                    "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                );
-
-                console.log(`>>> Trying to arb with ${
-                    ethers.utils.formatEther(maximumInputFixed)
-                } ${
-                    bundledOrders[i].sellTokenSymbol
-                } as maximum input`);
-                console.log(">>> Getting best route", "\n");
-
-                // await fetchPoolsForTokenWrapper(dataFetcher, fromToken, toToken);
-                await dataFetcher.fetchPoolsForToken(fromToken, toToken);
-                const pcMap = dataFetcher.getCurrentPoolCodeMap(
-                    fromToken,
-                    toToken
-                );
-                const route = Router.findBestRoute(
-                    pcMap,
-                    config.chainId,
-                    fromToken,
-                    maximumInput,
-                    toToken,
-                    gasPrice.toNumber(),
-                    // 30e9,
-                    // providers,
-                    // poolFilter
-                );
-                if (route.status == "NoWay") console.log(
-                    "\x1b[31m%s\x1b[0m",
-                    `could not find any route for this token pair for ${
-                        ethers.utils.formatEther(maximumInputFixed)
-                    } ${
-                        bundledOrders[i].sellTokenSymbol
-                    }, trying with a lower amount...`
-                );
-                else {
-                    const rateFixed = route.amountOutBN.mul(
-                        "1" + "0".repeat(18 - bundledOrders[i].buyTokenDecimals)
-                    );
-                    const price = rateFixed.mul("1" + "0".repeat(18)).div(maximumInputFixed);
-
-                    // filter out orders that are not price match or failed eval when --max-profit is enabled
-                    // price check is at +2% as a headroom for current block vs tx block
-                    if (maxProfit) bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                        v => v.ratio !== undefined ? price.mul("102").div("100").gte(v.ratio) : false
-                    );
-
-                    console.log(
-                        "Current best route price for this token pair:",
-                        `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`,
-                        "\n"
-                    );
-                    console.log(">>> Route portions: ", "\n");
-                    visualizeRoute(fromToken, toToken, route.legs).forEach(
-                        v => console.log("\x1b[36m%s\x1b[0m", v)
-                    );
-                    console.log("");
-
-                    const rpParams = Router.routeProcessor2Params(
-                        pcMap,
-                        route,
-                        fromToken,
-                        toToken,
-                        arb.address,
-                        config.routeProcessor3Address,
-                        // permits
-                        // "0.005"
-                    );
-                    const takeOrdersConfigStruct = {
-                        minimumInput: ethers.constants.One,
-                        maximumInput,
-                        maximumIORatio: maxRatio ? ethers.constants.MaxUint256 : price,
-                        orders: bundledOrders[i].takeOrders.map(v => v.takeOrder),
-                        data: ethers.utils.defaultAbiCoder.encode(
-                            ["bytes"],
-                            [rpParams.routeCode]
-                        )
-                    };
-
-                    // building and submit the transaction
-                    try {
-                        const rawtx = {
-                            data: arb.interface.encodeFunctionData("arb", [takeOrdersConfigStruct, "0"]),
-                            to: arb.address,
-                            gasPrice
-                        };
-                        console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                        let gasLimit;
-                        try {
-                            gasLimit = await signer.estimateGas(rawtx);
-                        }
-                        catch {
-                            throw "nomatch";
-                        }
-                        gasLimit = gasLimit.mul("112").div("100");
-                        rawtx.gasLimit = gasLimit;
-                        const gasCost = gasLimit.mul(gasPrice);
-                        const gasCostInToken = ethers.utils.parseUnits(
-                            ethPrice
-                        ).mul(
-                            gasCost
-                        ).div(
-                            "1" + "0".repeat(
-                                36 - bundledOrders[i].buyTokenDecimals
-                            )
-                        );
-                        if (gasCoveragePercentage !== "0") {
-                            const headroom = (
-                                Number(gasCoveragePercentage) * 1.2
-                            ).toFixed();
-                            rawtx.data = arb.interface.encodeFunctionData(
-                                "arb",
-                                [
-                                    takeOrdersConfigStruct,
-                                    gasCostInToken.mul(headroom).div("100")
-                                ]
-                            );
-                            try {
-                                await signer.estimateGas(rawtx);
-                            }
-                            catch {
-                                throw "dryrun";
-                            }
-                        }
-
-                        // submit the tx only if dry runs with headroom is passed
-                        try {
-                            console.log(">>> Trying to submit the transaction...", "\n");
-                            rawtx.data = arb.interface.encodeFunctionData(
-                                "arb",
-                                [
-                                    takeOrdersConfigStruct,
-                                    gasCostInToken.mul(gasCoveragePercentage).div("100")
-                                ]
-                            );
-                            console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                            const tx = flashbotSigner !== undefined
-                                ? await flashbotSigner.sendTransaction(rawtx)
-                                : await signer.sendTransaction(rawtx);
-
-                            console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n");
-                            console.log(
-                                ">>> Transaction submitted successfully to the network, waiting for transaction to mine...",
-                                "\n"
-                            );
-                            const receipt = config.timeout
-                                ? await promiseTimeout(
-                                    tx.wait(),
-                                    config.timeout,
-                                    `Transaction failed to mine after ${config.timeout}ms`
-                                )
-                                : await tx.wait();
-                            if (receipt.status === 1) {
-                                const clearActualAmount = getActualClearAmount(
-                                    arbAddress,
-                                    orderbookAddress,
-                                    receipt
-                                );
-                                const income = getIncome(signer, receipt);
-                                const clearActualPrice = getActualPrice(
-                                    receipt,
-                                    orderbookAddress,
-                                    arbAddress,
-                                    clearActualAmount.mul("1" + "0".repeat(
-                                        18 - bundledOrders[i].sellTokenDecimals
-                                    )),
-                                    bundledOrders[i].buyTokenDecimals
-                                );
-                                const actualGasCost = ethers.BigNumber.from(
-                                    receipt.effectiveGasPrice
-                                ).mul(receipt.gasUsed);
-                                const actualGasCostInToken = ethers.utils.parseUnits(
-                                    ethPrice
-                                ).mul(
-                                    actualGasCost
-                                ).div(
-                                    "1" + "0".repeat(
-                                        36 - bundledOrders[i].buyTokenDecimals
-                                    )
-                                );
-                                const netProfit = income
-                                    ? income.sub(actualGasCostInToken)
-                                    : undefined;
-
-                                console.log(
-                                    "\x1b[36m%s\x1b[0m",
-                                    `Clear Initial Price: ${ethers.utils.formatEther(price)}`
-                                );
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${
-                                    ethers.utils.formatUnits(
-                                        clearActualAmount,
-                                        bundledOrders[i].sellTokenDecimals
-                                    )
-                                } ${bundledOrders[i].sellTokenSymbol}`);
-                                console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${
-                                    ethers.utils.formatEther(actualGasCost)
-                                } ${
-                                    config.nativeToken.symbol
-                                }`, "\n");
-                                if (income) {
-                                    console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits(
-                                        income,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`);
-                                    console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits(
-                                        netProfit,
-                                        bundledOrders[i].buyTokenDecimals
-                                    )} ${bundledOrders[i].buyTokenSymbol}`, "\n");
-                                }
-
-                                report.push({
-                                    transactionHash: receipt.transactionHash,
-                                    tokenPair:
-                                        bundledOrders[i].buyTokenSymbol +
-                                        "/" +
-                                        bundledOrders[i].sellTokenSymbol,
-                                    buyToken: bundledOrders[i].buyToken,
-                                    buyTokenDecimals: bundledOrders[i].buyTokenDecimals,
-                                    sellToken: bundledOrders[i].sellToken,
-                                    sellTokenDecimals: bundledOrders[i].sellTokenDecimals,
-                                    clearedAmount: clearActualAmount.toString(),
-                                    clearPrice: ethers.utils.formatEther(price),
-                                    clearActualPrice,
-                                    gasUsed: receipt.gasUsed,
-                                    gasCost: actualGasCost,
-                                    income,
-                                    netProfit,
-                                    clearedOrders: bundledOrders[i].takeOrders.map(
-                                        v => v.id
-                                    ),
-                                });
-                                j = 0;
-                            }
-                            else if (j > 1) console.log(
-                                `could not clear with ${ethers.utils.formatEther(
-                                    maximumInputFixed
-                                )} ${
-                                    bundledOrders[i].sellTokenSymbol
-                                } as max input, trying with lower amount...`
-                            );
-                            else console.log("could not arb this pair");
-                        }
-                        catch (error) {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:");
-                            console.log(error, "\n");
-                            throw "failed-exec";
-                        }
-                    }
-                    catch (error) {
-                        if (error !== "nomatch" && error !== "dryrun" && error !== "failed-exec") {
-                            console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:");
-                            console.log(error, "\n");
-                            // reason, code, method, transaction, error, stack, message
-                        }
-                        if (error === "failed-exec") throw "Transaction execution failed, skipping this pair...";
-                        if (j > 1) console.log(
-                            "\x1b[34m%s\x1b[0m",
-                            `could not clear with ${ethers.utils.formatEther(
-                                maximumInputFixed
-                            )} ${
-                                bundledOrders[i].sellTokenSymbol
-                            } as max input, trying with lower amount...`, "\n"
-                        );
-                        else console.log("\x1b[34m%s\x1b[0m", "could not arb this pair", "\n");
-                    }
-                }
-            }
-        }
-        catch (error) {
-            if (typeof error === "string") console.log("\x1b[31m%s\x1b[0m", error, "\n");
-            else {
-                console.log("\x1b[31m%s\x1b[0m", ">>> Something went wrong, reason:", "\n");
-                console.log(error);
-            }
-        }
-    }
-    return report;
-};
-
-module.exports = {
-    srouterClear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/modes_zeroex.js.html b/docs/html/modes_zeroex.js.html deleted file mode 100644 index 5d4ac39c..00000000 --- a/docs/html/modes_zeroex.js.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - JSDoc: Source: modes/zeroex.js - - - - - - - - - - -
- -

Source: modes/zeroex.js

- - - - - - -
-
-
const axios = require("axios");
-const ethers = require("ethers");
-const { arbAbis, orderbookAbi } = require("../abis");
-const { sleep, getIncome, getActualPrice, bundleTakeOrders, promiseTimeout } = require("../utils");
-
-
-const HEADERS = { headers: { "accept-encoding": "null" } };
-
-/**
- * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with 0x
- *
- * @param {object} config - The configuration object
- * @param {any[]} ordersDetails - The order details queried from subgraph
- * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction for it to be considered profitable and get submitted
- * @returns The report of details of cleared orders
- */
-const zeroExClear = async(
-    config,
-    ordersDetails,
-    gasCoveragePercentage = "100"
-) => {
-    if (
-        gasCoveragePercentage < 0 ||
-        !Number.isInteger(Number(gasCoveragePercentage))
-    ) throw "invalid gas coverage percentage, must be an integer greater than equal 0";
-
-    let rateLimit;
-    if (config.monthlyRatelimit !== undefined) {
-        const _val = Number(config.monthlyRatelimit);
-        if (Number.isInteger(_val) && _val > 0) rateLimit = Number((_val / 2592).toFixed()) / 1000;
-        else throw new Error("specified monthly ratelimit must be an integer greater than 0");
-    }
-
-    let hits = 0;
-    const start = Date.now();
-    const signer            = config.signer;
-    const api               = config.zeroEx.apiUrl;
-    const proxyAddress      = config.zeroEx.proxyAddress;
-    const arbAddress        = config.arbAddress;
-    const orderbookAddress  = config.orderbookAddress;
-    const arbType           = config.arbType;
-    // const nativeToken       = config.nativeWrappedToken;
-    const flashbotSigner    = config.flashbotRpc
-        ? new ethers.Wallet(
-            signer.privateKey,
-            new ethers.providers.JsonRpcProvider(config.flashbotRpc)
-        )
-        : undefined;
-
-    // set the api key in headers
-    if (config.apiKey) HEADERS.headers["0x-api-key"] = config.apiKey;
-    else throw "invalid 0x API key";
-
-    // instantiating arb contract
-    const arb = new ethers.Contract(arbAddress, arbAbis[arbType], signer);
-
-    // instantiating orderbook contract
-    const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer);
-
-    console.log(
-        "------------------------- Starting The",
-        "\x1b[32m0x\x1b[0m",
-        "Mode -------------------------",
-        "\n"
-    );
-    console.log("\x1b[33m%s\x1b[0m", Date());
-    console.log("Arb Contract Address: " , arbAddress);
-    console.log("OrderBook Contract Address: " , orderbookAddress, "\n");
-
-    // const initPriceQueries = [];
-    let bundledOrders = [];
-
-    if (ordersDetails.length) {
-        console.log(
-            "------------------------- Bundling Orders -------------------------", "\n"
-        );
-        bundledOrders = await bundleTakeOrders(
-            ordersDetails,
-            orderbook,
-            arb,
-            undefined,
-            config.rpc !== "test",
-            config.interpreterv2,
-            config.bundle
-        );
-        // for (let i = 0; i < bundledOrders.length; i++) {
-        //     build0xQueries(
-        //         api,
-        //         initPriceQueries,
-        //         bundledOrders[i].sellToken,
-        //         bundledOrders[i].sellTokenDecimals,
-        //         bundledOrders[i].sellTokenSymbol
-        //     );
-        //     build0xQueries(
-        //         api,
-        //         initPriceQueries,
-        //         bundledOrders[i].buyToken,
-        //         bundledOrders[i].buyTokenDecimals,
-        //         bundledOrders[i].buyTokenSymbol
-        //     );
-        // }
-    }
-    else {
-        console.log("No orders found, exiting...", "\n");
-        return;
-    }
-
-    if (!bundledOrders.length) {
-        console.log("Could not find any order with sufficient balance, exiting...", "\n");
-        return;
-    }
-
-    // console.log(
-    //     "------------------------- Getting Best Deals From 0x -------------------------",
-    //     "\n"
-    // );
-    // if (Array.isArray(initPriceQueries[initPriceQueries.length - 1])) {
-    //     initPriceQueries[initPriceQueries.length - 1] = {
-    //         quote: `${
-    //             api
-    //         }swap/v1/price?buyToken=${
-    //             nativeToken.address.toLowerCase()
-    //         }&sellToken=${
-    //             initPriceQueries[initPriceQueries.length - 1][0]
-    //         }&sellAmount=${
-    //             "1" + "0".repeat(initPriceQueries[initPriceQueries.length - 1][1])
-    //         }`,
-    //         tokens: [
-    //             nativeToken.symbol,
-    //             initPriceQueries[initPriceQueries.length - 1][2],
-    //             nativeToken.address.toLowerCase(),
-    //             initPriceQueries[initPriceQueries.length - 1][0],
-    //             nativeToken.decimals,
-    //             initPriceQueries[initPriceQueries.length - 1][1],
-    //         ]
-    //     };
-    // }
-    // hits += initPriceQueries.length;
-    // bundledOrders = await prepare(
-    //     initPriceQueries,
-    //     bundledOrders
-    // );
-
-    if (bundledOrders.length === 0) {
-        console.log("Could not find any order to clear for current market price, exiting...", "\n");
-        return;
-    }
-
-    const report = [];
-    for (let i = 0; i < bundledOrders.length; i++) {
-        await sleep(1000);
-        if (bundledOrders[i].takeOrders.length) {
-            try {
-                console.log(
-                    `------------------------- Trying To Clear ${
-                        bundledOrders[i].buyTokenSymbol
-                    }/${
-                        bundledOrders[i].sellTokenSymbol
-                    } -------------------------`,
-                    "\n"
-                );
-                console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`);
-                console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n");
-
-                console.log(">>> Updating vault balances...", "\n");
-                const newBalances = await Promise.allSettled(
-                    bundledOrders[i].takeOrders.map(async(v) => {
-                        return ethers.utils.parseUnits(
-                            ethers.utils.formatUnits(
-                                await orderbook.vaultBalance(
-                                    v.takeOrder.order.owner,
-                                    bundledOrders[i].sellToken,
-                                    v.takeOrder.order.validOutputs[
-                                        v.takeOrder.outputIOIndex
-                                    ].vaultId
-                                ),
-                                bundledOrders[i].sellTokenDecimals
-                            )
-                        );
-                    })
-                );
-                newBalances.forEach((v, j) => {
-                    if (v.status === "fulfilled") {
-                        if (v.value.isZero()) {
-                            bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                        }
-                        else {
-                            if (v.value.lt(bundledOrders[i].takeOrders[j].quoteAmount)) {
-                                bundledOrders[i].takeOrders[j].quoteAmount = v.value;
-                            }
-                        }
-                    }
-                    else {
-                        console.log(`Could not get vault balance for order ${
-                            bundledOrders[i].takeOrders[j].id
-                        } due to:`);
-                        console.log(v.reason);
-                        bundledOrders[i].takeOrders[j].quoteAmount = ethers.BigNumber.from("0");
-                    }
-                });
-                bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                    v => !v.quoteAmount.isZero()
-                );
-
-                if (bundledOrders[i].takeOrders.length) {
-                    console.log(">>> Getting current price for this token pair...", "\n");
-
-                    let cumulativeAmount = ethers.constants.Zero;
-                    bundledOrders[i].takeOrders.forEach(v => {
-                        cumulativeAmount = cumulativeAmount.add(v.quoteAmount);
-                    });
-                    const price = (await axios.get(
-                        `${
-                            api
-                        }swap/v1/price?buyToken=${
-                            bundledOrders[i].buyToken
-                        }&sellToken=${
-                            bundledOrders[i].sellToken
-                        }&sellAmount=${
-                            cumulativeAmount.div(
-                                "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                            ).div(2).toString()
-                        }`,
-                        HEADERS
-                    ))?.data?.price;
-                    hits++;
-                    await sleep(1000);
-                    const currentPrice = ethers.utils.parseUnits(price);
-
-                    console.log(`Quote amount: ${ethers.utils.formatUnits(
-                        cumulativeAmount.div(
-                            "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                        ).div(2),
-                        bundledOrders[i].sellTokenDecimals
-                    )} ${bundledOrders[i].sellTokenSymbol}`);
-                    console.log(`Current market price of this token pair: ${price}`);
-                    console.log("Current ratio of the orders in this token pair:");
-                    bundledOrders[i].takeOrders.forEach(v => {
-                        console.log(ethers.utils.formatEther(v.ratio));
-                    });
-
-                    console.log(
-                        "\n>>> Filtering the bundled orders of this token pair with lower ratio than current market price...",
-                        "\n"
-                    );
-
-                    bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter(
-                        v => currentPrice.gte(v.ratio)
-                    );
-
-                    if (bundledOrders[i].takeOrders.length) {
-                        cumulativeAmount = ethers.constants.Zero;
-                        bundledOrders[i].takeOrders.forEach(v => {
-                            cumulativeAmount = cumulativeAmount.add(v.quoteAmount);
-                        });
-
-                        const bundledQuoteAmount = cumulativeAmount.div(
-                            "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals)
-                        );
-
-                        console.log(">>> Getting quote for this token pair...", "\n");
-                        const response = await axios.get(
-                            `${
-                                api
-                            }swap/v1/quote?buyToken=${
-                                bundledOrders[i].buyToken
-                            }&sellToken=${
-                                bundledOrders[i].sellToken
-                            }&sellAmount=${
-                                bundledQuoteAmount.toString()
-                            }`,
-                            HEADERS
-                        );
-                        hits++;
-
-                        const txQuote = response?.data;
-                        if (txQuote) {
-                            // console.log("the full quote that will be submitted is:" + "\n" + JSON.stringify(txQuote, null, 2), "\n");
-                            const takeOrdersConfigStruct = {
-                                output: bundledOrders[i].buyToken,
-                                input: bundledOrders[i].sellToken,
-                                // max and min input should be exactly the same as quoted sell amount
-                                // this makes sure the cleared order amount will exactly match the 0x quote
-                                minimumInput: bundledQuoteAmount,
-                                maximumInput: bundledQuoteAmount,
-                                maximumIORatio: ethers.constants.MaxUint256,
-                                orders: bundledOrders[i].takeOrders.map(v => v.takeOrder),
-                            };
-                            if (/^flash-loan-v3$|^order-taker$/.test(arbType)) {
-                                takeOrdersConfigStruct.data = "0x";
-                                delete takeOrdersConfigStruct.output;
-                                delete takeOrdersConfigStruct.input;
-                            }
-
-                            // submit the transaction
-                            try {
-                                const exchangeData = ethers.utils.defaultAbiCoder.encode(
-                                    ["address", "address", "bytes"],
-                                    [txQuote.allowanceTarget, proxyAddress, txQuote.data]
-                                );
-                                if (arbType === "order-taker") takeOrdersConfigStruct.data = exchangeData;
-                                const rawtx = {
-                                    data: arb.interface.encodeFunctionData(
-                                        "arb",
-                                        arbType === "order-taker"
-                                            ? [
-                                                takeOrdersConfigStruct,
-                                                "0"
-                                            ]
-                                            : [
-                                                takeOrdersConfigStruct,
-                                                "0",
-                                                exchangeData
-                                            ]
-                                    ),
-                                    to: arb.address,
-                                    gasPrice: txQuote.gasPrice
-                                };
-                                console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                                let gasLimit = await signer.estimateGas(rawtx);
-                                gasLimit = gasLimit.mul("112").div("100");
-                                rawtx.gasLimit = gasLimit;
-                                const gasCost = gasLimit.mul(txQuote.gasPrice);
-                                const gasCostInToken = ethers.utils.parseUnits(
-                                    txQuote.buyTokenToEthRate
-                                ).mul(
-                                    gasCost
-                                ).div(
-                                    "1" + "0".repeat(
-                                        36 - bundledOrders[i].buyTokenDecimals
-                                    )
-                                );
-                                if (gasCoveragePercentage !== "0") {
-                                    const headroom = (
-                                        Number(gasCoveragePercentage) * 1.2
-                                    ).toFixed();
-                                    rawtx.data = arb.interface.encodeFunctionData(
-                                        "arb",
-                                        arbType === "order-taker"
-                                            ? [
-                                                takeOrdersConfigStruct,
-                                                gasCostInToken.mul(headroom).div("100")
-                                            ]
-                                            : [
-                                                takeOrdersConfigStruct,
-                                                gasCostInToken.mul(headroom).div("100"),
-                                                exchangeData
-                                            ]
-                                    );
-                                    await signer.estimateGas(rawtx);
-                                }
-
-                                try {
-                                    console.log(">>> Trying to submit the transaction for this token pair...", "\n");
-                                    rawtx.data = arb.interface.encodeFunctionData(
-                                        "arb",
-                                        arbType === "order-taker"
-                                            ? [
-                                                takeOrdersConfigStruct,
-                                                gasCostInToken.mul(gasCoveragePercentage).div("100")
-                                            ]
-                                            : [
-                                                takeOrdersConfigStruct,
-                                                gasCostInToken.mul(gasCoveragePercentage).div("100"),
-                                                exchangeData
-                                            ]
-                                    );
-                                    console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n");
-                                    const tx = flashbotSigner !== undefined
-                                        ? await flashbotSigner.sendTransaction(rawtx)
-                                        : await signer.sendTransaction(rawtx);
-
-                                    console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n");
-                                    console.log(
-                                        ">>> Transaction submitted successfully to the network, waiting for transaction to mine...",
-                                        "\n"
-                                    );
-                                    const receipt = config.timeout
-                                        ? await promiseTimeout(
-                                            tx.wait(),
-                                            config.timeout,
-                                            `Transaction failed to mine after ${config.timeout}ms`
-                                        )
-                                        : await tx.wait();
-                                    const income = getIncome(signer, receipt);
-                                    const clearActualPrice = getActualPrice(
-                                        receipt,
-                                        orderbookAddress,
-                                        arbAddress,
-                                        cumulativeAmount,
-                                        bundledOrders[i].buyTokenDecimals
-                                    );
-                                    const actualGasCost = ethers.BigNumber.from(
-                                        receipt.effectiveGasPrice
-                                    ).mul(receipt.gasUsed);
-                                    const actualGasCostInToken = ethers.utils.parseUnits(
-                                        txQuote.buyTokenToEthRate
-                                    ).mul(
-                                        actualGasCost
-                                    ).div(
-                                        "1" + "0".repeat(
-                                            36 - bundledOrders[i].buyTokenDecimals
-                                        )
-                                    );
-                                    const netProfit = income
-                                        ? income.sub(actualGasCostInToken)
-                                        : undefined;
-                                    console.log(
-                                        "\x1b[34m%s\x1b[0m",
-                                        `${bundledOrders[i].takeOrders.length} orders cleared successfully!`,
-                                        "\n"
-                                    );
-                                    console.log("\x1b[36m%s\x1b[0m", `Clear Quote Price: ${txQuote.price}`);
-                                    console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`);
-                                    console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${
-                                        ethers.utils.formatUnits(
-                                            bundledQuoteAmount,
-                                            bundledOrders[i].sellTokenDecimals
-                                        )
-                                    } ${bundledOrders[i].sellTokenSymbol}`);
-                                    console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${
-                                        ethers.utils.formatEther(actualGasCost)
-                                    } ${
-                                        config.nativeToken.symbol
-                                    }`, "\n");
-                                    if (income) {
-                                        console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits(
-                                            income,
-                                            bundledOrders[i].buyTokenDecimals
-                                        )} ${bundledOrders[i].buyTokenSymbol}`);
-                                        console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits(
-                                            netProfit,
-                                            bundledOrders[i].buyTokenDecimals
-                                        )} ${bundledOrders[i].buyTokenSymbol}`, "\n");
-                                    }
-
-                                    report.push({
-                                        transactionHash: receipt.transactionHash,
-                                        tokenPair:
-                                            bundledOrders[i].buyTokenSymbol +
-                                            "/" +
-                                            bundledOrders[i].sellTokenSymbol,
-                                        buyToken: bundledOrders[i].buyToken,
-                                        buyTokenDecimals: bundledOrders[i].buyTokenDecimals,
-                                        sellToken: bundledOrders[i].sellToken,
-                                        sellTokenDecimals: bundledOrders[i].sellTokenDecimals,
-                                        clearedAmount: bundledQuoteAmount.toString(),
-                                        clearPrice: txQuote.price,
-                                        clearGuaranteedPrice: txQuote.guaranteedPrice,
-                                        clearActualPrice,
-                                        gasUsed: receipt.gasUsed,
-                                        gasCost: actualGasCost,
-                                        income,
-                                        netProfit,
-                                        clearedOrders: bundledOrders[i].takeOrders.map(
-                                            v => v.id
-                                        ),
-                                    });
-                                }
-                                catch (error) {
-                                    console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:");
-                                    console.log(error, "\n");
-                                }
-                            }
-                            catch (error) {
-                                if (error === "dryrun" || error === "nomatch") {
-                                    console.log("\x1b[31m%s\x1b[0m", ">>> Transaction dry run failed, skipping...");
-                                }
-                                else {
-                                    console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:");
-                                    console.log(error, "\n");
-                                }
-                            }
-                        }
-                        else console.log("\x1b[31m%s\x1b[0m", "Failed to get quote from 0x", "\n");
-                    }
-                    else console.log(
-                        "All orders of this token pair have higher ratio than current market price, checking next token pair...",
-                        "\n"
-                    );
-                }
-                else console.log("All orders of this token pair have empty vault balance, skipping...", "\n");
-            }
-            catch (error) {
-                console.log("\x1b[31m%s\x1b[0m", ">>> Failed to get quote from 0x due to:", "\n");
-                console.log(error.message);
-                console.log("data:");
-                console.log(JSON.stringify(error.response.data, null, 2), "\n");
-            }
-        }
-    }
-    console.log("---------------------------------------------------------------------------", "\n");
-
-    // wait to stay within montly ratelimit
-    if (rateLimit) {
-        const rateLimitDuration = Number((((hits / rateLimit) * 1000) + 1).toFixed());
-        const duration = Date.now() - start;
-        console.log(`Executed in ${duration} miliseconds with ${hits} 0x api calls`);
-        const msToWait = rateLimitDuration - duration;
-        if (msToWait > 0) {
-            console.log(`Waiting ${msToWait} more miliseconds to stay within monthly rate limit...`);
-            await sleep(msToWait);
-        }
-        console.log("---------------------------------------------------------------------------", "\n");
-    }
-    return report;
-};
-
-module.exports = {
-    zeroExClear
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/query.js.html b/docs/html/query.js.html deleted file mode 100644 index 01bd8864..00000000 --- a/docs/html/query.js.html +++ /dev/null @@ -1,155 +0,0 @@ - - - - - JSDoc: Source: query.js - - - - - - - - - - -
- -

Source: query.js

- - - - - - -
-
-
/**
- * The default query used in the matchmaker bot to fetch the orders from subgraph
- */
-const DefaultQuery = `{
-    orders(
-        where: {orderActive: true}
-    ) {
-        id
-        handleIO 
-        expression
-        interpreter
-        interpreterStore
-        owner {
-            id
-        }
-        validInputs(orderBy: index, orderDirection: asc) {
-            index
-            token {
-                id
-                decimals
-                symbol
-            }
-            tokenVault {
-                balance
-            }
-            vault {
-                id
-            }
-        }
-        validOutputs(orderBy: index, orderDirection: asc) {
-            index
-            token {
-                id
-                decimals
-                symbol
-            }
-            tokenVault {
-                balance
-            }
-            vault {
-                id
-            }
-        }
-    }
-}`;
-
-/**
- * Method to get the subgraph query body with optional filters
- * @param {string} orderHash - The order hash to apply as filter
- * @param {string} owner - The order owner to apply as filter
- * @param {string} interpreter - The interpreter to apply as filter
- * @returns the query string
- */
-const getQuery = (orderHash, owner, interpreter) => {
-    const ownerFilter = owner ? `, owner :"${owner.toLowerCase()}"` : "";
-    const orderHashFilter = orderHash ? `, id :"${orderHash.toLowerCase()}"` : "";
-    const interpreterFilter = interpreter ? `, interpreter :"${interpreter.toLowerCase()}"` : "";
-    return `{
-        orders(
-            where: {orderActive: true${orderHashFilter}${ownerFilter}${interpreterFilter}}
-        ) {
-            id
-            handleIO 
-            expression
-            interpreter
-            interpreterStore
-            owner {
-                id
-            }
-            validInputs(orderBy: index, orderDirection: asc) {
-                index
-                token {
-                    id
-                    decimals
-                    symbol
-                }
-                tokenVault {
-                    balance
-                }
-                vault {
-                    id
-                }
-            }
-            validOutputs(orderBy: index, orderDirection: asc) {
-                index
-                token {
-                    id
-                    decimals
-                    symbol
-                }
-                tokenVault {
-                    balance
-                }
-                vault {
-                    id
-                }
-            }
-        }
-    }`;
-};
-
-module.exports = {
-    DefaultQuery,
-    getQuery
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/docs/html/scripts/linenumber.js b/docs/html/scripts/linenumber.js deleted file mode 100644 index 4354785c..00000000 --- a/docs/html/scripts/linenumber.js +++ /dev/null @@ -1,25 +0,0 @@ -/*global document */ -(() => { - const source = document.getElementsByClassName('prettyprint source linenums'); - let i = 0; - let lineNumber = 0; - let lineId; - let lines; - let totalLines; - let anchorHash; - - if (source && source[0]) { - anchorHash = document.location.hash.substring(1); - lines = source[0].getElementsByTagName('li'); - totalLines = lines.length; - - for (; i < totalLines; i++) { - lineNumber++; - lineId = `line${lineNumber}`; - lines[i].id = lineId; - if (lineId === anchorHash) { - lines[i].className += ' selected'; - } - } - } -})(); diff --git a/docs/html/scripts/prettify/Apache-License-2.0.txt b/docs/html/scripts/prettify/Apache-License-2.0.txt deleted file mode 100644 index d6456956..00000000 --- a/docs/html/scripts/prettify/Apache-License-2.0.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/docs/html/scripts/prettify/lang-css.js b/docs/html/scripts/prettify/lang-css.js deleted file mode 100644 index 041e1f59..00000000 --- a/docs/html/scripts/prettify/lang-css.js +++ /dev/null @@ -1,2 +0,0 @@ -PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", -/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/html/scripts/prettify/prettify.js b/docs/html/scripts/prettify/prettify.js deleted file mode 100644 index eef5ad7e..00000000 --- a/docs/html/scripts/prettify/prettify.js +++ /dev/null @@ -1,28 +0,0 @@ -var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; -(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= -[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), -l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, -q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, -q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, -"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), -a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} -for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], -"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], -H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], -J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ -I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), -["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", -/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), -["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", -hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= -!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p th:last-child { border-right: 1px solid #ddd; } - -.ancestors, .attribs { color: #999; } -.ancestors a, .attribs a -{ - color: #999 !important; - text-decoration: none; -} - -.clear -{ - clear: both; -} - -.important -{ - font-weight: bold; - color: #950B02; -} - -.yes-def { - text-indent: -1000px; -} - -.type-signature { - color: #aaa; -} - -.name, .signature { - font-family: Consolas, Monaco, 'Andale Mono', monospace; -} - -.details { margin-top: 14px; border-left: 2px solid #DDD; } -.details dt { width: 120px; float: left; padding-left: 10px; padding-top: 6px; } -.details dd { margin-left: 70px; } -.details ul { margin: 0; } -.details ul { list-style-type: none; } -.details li { margin-left: 30px; padding-top: 6px; } -.details pre.prettyprint { margin: 0 } -.details .object-value { padding-top: 0; } - -.description { - margin-bottom: 1em; - margin-top: 1em; -} - -.code-caption -{ - font-style: italic; - font-size: 107%; - margin: 0; -} - -.source -{ - border: 1px solid #ddd; - width: 80%; - overflow: auto; -} - -.prettyprint.source { - width: inherit; -} - -.source code -{ - font-size: 100%; - line-height: 18px; - display: block; - padding: 4px 12px; - margin: 0; - background-color: #fff; - color: #4D4E53; -} - -.prettyprint code span.line -{ - display: inline-block; -} - -.prettyprint.linenums -{ - padding-left: 70px; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.prettyprint.linenums ol -{ - padding-left: 0; -} - -.prettyprint.linenums li -{ - border-left: 3px #ddd solid; -} - -.prettyprint.linenums li.selected, -.prettyprint.linenums li.selected * -{ - background-color: lightyellow; -} - -.prettyprint.linenums li * -{ - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; -} - -.params .name, .props .name, .name code { - color: #4D4E53; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 100%; -} - -.params td.description > p:first-child, -.props td.description > p:first-child -{ - margin-top: 0; - padding-top: 0; -} - -.params td.description > p:last-child, -.props td.description > p:last-child -{ - margin-bottom: 0; - padding-bottom: 0; -} - -.disabled { - color: #454545; -} diff --git a/docs/html/styles/prettify-jsdoc.css b/docs/html/styles/prettify-jsdoc.css deleted file mode 100644 index 5a2526e3..00000000 --- a/docs/html/styles/prettify-jsdoc.css +++ /dev/null @@ -1,111 +0,0 @@ -/* JSDoc prettify.js theme */ - -/* plain text */ -.pln { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* string content */ -.str { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a keyword */ -.kwd { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a comment */ -.com { - font-weight: normal; - font-style: italic; -} - -/* a type name */ -.typ { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a literal value */ -.lit { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* punctuation */ -.pun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp open bracket */ -.opn { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* lisp close bracket */ -.clo { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a markup tag name */ -.tag { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute name */ -.atn { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a markup attribute value */ -.atv { - color: #006400; - font-weight: normal; - font-style: normal; -} - -/* a declaration */ -.dec { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* a variable name */ -.var { - color: #000000; - font-weight: normal; - font-style: normal; -} - -/* a function name */ -.fun { - color: #000000; - font-weight: bold; - font-style: normal; -} - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; -} diff --git a/docs/html/styles/prettify-tomorrow.css b/docs/html/styles/prettify-tomorrow.css deleted file mode 100644 index b6f92a78..00000000 --- a/docs/html/styles/prettify-tomorrow.css +++ /dev/null @@ -1,132 +0,0 @@ -/* Tomorrow Theme */ -/* Original theme - https://github.com/chriskempson/tomorrow-theme */ -/* Pretty printing styles. Used with prettify.js. */ -/* SPAN elements with the classes below are added by prettyprint. */ -/* plain text */ -.pln { - color: #4d4d4c; } - -@media screen { - /* string content */ - .str { - color: #718c00; } - - /* a keyword */ - .kwd { - color: #8959a8; } - - /* a comment */ - .com { - color: #8e908c; } - - /* a type name */ - .typ { - color: #4271ae; } - - /* a literal value */ - .lit { - color: #f5871f; } - - /* punctuation */ - .pun { - color: #4d4d4c; } - - /* lisp open bracket */ - .opn { - color: #4d4d4c; } - - /* lisp close bracket */ - .clo { - color: #4d4d4c; } - - /* a markup tag name */ - .tag { - color: #c82829; } - - /* a markup attribute name */ - .atn { - color: #f5871f; } - - /* a markup attribute value */ - .atv { - color: #3e999f; } - - /* a declaration */ - .dec { - color: #f5871f; } - - /* a variable name */ - .var { - color: #c82829; } - - /* a function name */ - .fun { - color: #4271ae; } } -/* Use higher contrast and text-weight for printable form. */ -@media print, projection { - .str { - color: #060; } - - .kwd { - color: #006; - font-weight: bold; } - - .com { - color: #600; - font-style: italic; } - - .typ { - color: #404; - font-weight: bold; } - - .lit { - color: #044; } - - .pun, .opn, .clo { - color: #440; } - - .tag { - color: #006; - font-weight: bold; } - - .atn { - color: #404; } - - .atv { - color: #060; } } -/* Style */ -/* -pre.prettyprint { - background: white; - font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 12px; - line-height: 1.5; - border: 1px solid #ccc; - padding: 10px; } -*/ - -/* Specify class=linenums on a pre to get line numbering */ -ol.linenums { - margin-top: 0; - margin-bottom: 0; } - -/* IE indents via margin-left */ -li.L0, -li.L1, -li.L2, -li.L3, -li.L4, -li.L5, -li.L6, -li.L7, -li.L8, -li.L9 { - /* */ } - -/* Alternate shading for lines */ -li.L1, -li.L3, -li.L5, -li.L7, -li.L9 { - /* */ } diff --git a/docs/html/utils.js.html b/docs/html/utils.js.html deleted file mode 100644 index 1f31d590..00000000 --- a/docs/html/utils.js.html +++ /dev/null @@ -1,1659 +0,0 @@ - - - - - JSDoc: Source: utils.js - - - - - - - - - - -
- -

Source: utils.js

- - - - - - -
-
-
const { ethers, BigNumber } = require("ethers");
-const { createPublicClient, http, fallback } = require("viem");
-const { erc20Abi, interpreterAbi, interpreterV2Abi } = require("./abis");
-const { DataFetcher, Router, LiquidityProviders, ChainId, Token, viemConfig } = require("sushiswap-router");
-
-
-/**
- * Chain specific fallback data
- */
-const fallbacks = {
-    [ChainId.ARBITRUM_NOVA]: {
-        transport: http("https://nova.arbitrum.io/rpc"),
-        liquidityProviders: [
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.ARBITRUM]: {
-        transport: [
-            http("https://lb.drpc.org/ogrpc?network=arbitrum&dkey=Ak765fp4zUm6uVwKu4annC8M80dnCZkR7pAEsm6XXi_w"),
-            http("https://rpc.ankr.com/arbitrum"),
-            http("https://arbitrum-one.public.blastapi.io"),
-            http("https://endpoints.omniatech.io/v1/arbitrum/one/public"),
-            http("https://arb1.croswap.com/rpc"),
-            http("https://1rpc.io/arb"),
-            http("https://arbitrum.blockpi.network/v1/rpc/public"),
-            http("https://arb-mainnet-public.unifra.io"),
-        ],
-        liquidityProviders: [
-            "dfyn",
-            "elk",
-            "sushiswapv3",
-            "uniswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.AVALANCHE]: {
-        transport: [
-            http("https://api.avax.network/ext/bc/C/rpc"),
-            http("https://rpc.ankr.com/avalanche")
-        ],
-        liquidityProviders: [
-            "elk",
-            "traderjoe",
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.BOBA]: {
-        transport: [
-            http("https://mainnet.boba.network"),
-            http("https://lightning-replica.boba.network")
-        ],
-        liquidityProviders: [
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.BOBA_AVAX]: {
-        transport: [
-            http("https://avax.boba.network"),
-            http("https://replica.avax.boba.network")
-        ],
-        liquidityProviders: [
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.BOBA_BNB]: {
-        transport: [
-            http("https://bnb.boba.network"),
-            http("https://replica.bnb.boba.network")
-        ],
-        liquidityProviders: [
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.BSC]: {
-        transport: [
-            http("https://rpc.ankr.com/bsc"),
-            http("https://lb.drpc.org/ogrpc?network=bsc&dkey=Ak765fp4zUm6uVwKu4annC8M80dnCZkR7pAEsm6XXi_w"),
-            http("https://bsc-dataseed.binance.org"),
-            http("https://bsc-dataseed1.binance.org"),
-            http("https://bsc-dataseed2.binance.org"),
-        ],
-        liquidityProviders: [
-            "apeswap",
-            "biswap",
-            "elk",
-            "jetswap",
-            "pancakeswap",
-            "sushiswapv3",
-            "sushiswapv2",
-            "uniswapv3"
-        ]
-    },
-    [ChainId.BTTC]: {
-        transport: http("https://rpc.bittorrentchain.io"),
-    },
-    [ChainId.CELO]: {
-        transport: http("https://forno.celo.org"),
-        liquidityProviders: [
-            "ubeswap",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.ETHEREUM]: {
-        transport: [
-            http("https://lb.drpc.org/ogrpc?network=ethereum&dkey=Ak765fp4zUm6uVwKu4annC8M80dnCZkR7pAEsm6XXi_w"),
-            http("https://eth.llamarpc.com"),
-            // http('https://eth.rpc.blxrbdn.com'),
-            // http('https://virginia.rpc.blxrbdn.com'),
-            // http('https://singapore.rpc.blxrbdn.com'),
-            // http('https://uk.rpc.blxrbdn.com'),
-            http("https://1rpc.io/eth"),
-            http("https://ethereum.publicnode.com"),
-            http("https://cloudflare-eth.com"),
-        ],
-        liquidityProviders: [
-            "apeswap",
-            "curveswap",
-            "elk",
-            "pancakeswap",
-            "sushiswapv3",
-            "sushiswapv2",
-            "uniswapv2",
-            "uniswapv3"
-        ]
-    },
-    [ChainId.FANTOM]: {
-        transport: [
-            http("https://rpc.ankr.com/fantom"),
-            http("https://rpc.fantom.network"),
-            http("https://rpc2.fantom.network"),
-        ],
-        liquidityProviders: [
-            "dfyn",
-            "elk",
-            "jetswap",
-            "spookyswap",
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.FUSE]: {
-        transport: http("https://rpc.fuse.io"),
-        liquidityProviders: [
-            "elk",
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.GNOSIS]: {
-        transport: http("https://rpc.ankr.com/gnosis"),
-        liquidityProviders: [
-            "elk",
-            "honeyswap",
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.HARMONY]: {
-        transport: [
-            http("https://api.harmony.one"),
-            http("https://rpc.ankr.com/harmony")
-        ],
-        liquidityProviders: [
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.KAVA]: {
-        transport: [
-            http("https://evm.kava.io"),
-            http("https://evm2.kava.io"),
-        ],
-        liquidityProviders: [
-            "elk"
-        ]
-    },
-    [ChainId.MOONBEAM]: {
-        transport: [
-            http("https://rpc.api.moonbeam.network"),
-            http("https://rpc.ankr.com/moonbeam")
-        ],
-        liquidityProviders: [
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.MOONRIVER]: {
-        transport: http("https://rpc.api.moonriver.moonbeam.network"),
-        liquidityProviders: [
-            "elk",
-            "sushiswapv3",
-            "sushiswapv2"
-        ]
-    },
-    [ChainId.OPTIMISM]: {
-        transport: [
-            http("https://lb.drpc.org/ogrpc?network=optimism&dkey=Ak765fp4zUm6uVwKu4annC8M80dnCZkR7pAEsm6XXi_w"),
-            http("https://rpc.ankr.com/optimism"),
-            http("https://optimism-mainnet.public.blastapi.io"),
-            http("https://1rpc.io/op"),
-            http("https://optimism.blockpi.network/v1/rpc/public"),
-            http("https://mainnet.optimism.io"),
-        ],
-        liquidityProviders: [
-            "elk",
-            "sushiswapv3",
-            "uniswapv3"
-        ]
-    },
-    [ChainId.POLYGON]: {
-        transport: [
-            http("https://polygon.llamarpc.com"),
-            // http('https://polygon.rpc.blxrbdn.com'),
-            http("https://polygon-mainnet.public.blastapi.io"),
-            http("https://polygon.blockpi.network/v1/rpc/public"),
-            http("https://polygon-rpc.com"),
-            http("https://rpc.ankr.com/polygon"),
-            http("https://matic-mainnet.chainstacklabs.com"),
-            http("https://polygon-bor.publicnode.com"),
-            http("https://rpc-mainnet.matic.quiknode.pro"),
-            http("https://rpc-mainnet.maticvigil.com"),
-            // ...polygon.rpcUrls.default.http.map((url) => http(url)),
-        ],
-        liquidityProviders: [
-            "apeswap",
-            "dfyn",
-            "elk",
-            "jetswap",
-            "quickswap",
-            "sushiswapv3",
-            "sushiswapv2",
-            "uniswapv3"
-        ]
-    },
-    [ChainId.POLYGON_ZKEVM]: {
-        transport: [
-            http("https://zkevm-rpc.com"),
-            http("https://rpc.ankr.com/polygon_zkevm"),
-            http("https://rpc.polygon-zkevm.gateway.fm"),
-        ],
-        liquidityProviders: [
-            "dovishv3",
-            "sushiswapv3"
-        ]
-    },
-    [ChainId.THUNDERCORE]: {
-        transport: [
-            http("https://mainnet-rpc.thundercore.com"),
-            http("https://mainnet-rpc.thundercore.io"),
-            http("https://mainnet-rpc.thundertoken.net"),
-        ],
-        liquidityProviders: [
-            "laserswap",
-            "sushiswapv3"
-        ]
-    },
-};
-
-/**
- * convert float numbers to big number
- *
- * @param {any} float - Any form of number
- * @param {number} decimals - Decimals point of the number
- * @returns ethers BigNumber with decimals point
- */
-const bnFromFloat = (float, decimals = 18) => {
-    if (typeof float == "string") {
-        if (float.startsWith("0x")) {
-            const num = BigInt(float).toString();
-            return BigNumber.from(num.padEnd(num.length + decimals), "0");
-        }
-        else {
-            if (float.includes(".")) {
-                const offset = decimals - float.slice(float.indexOf(".") + 1).length;
-                float = offset < 0 ? float.slice(0, offset) : float;
-            }
-            return ethers.utils.parseUnits(float, decimals);
-        }
-    }
-    else {
-        try {
-            float = float.toString();
-            return bnFromFloat(float, decimals);
-        }
-        catch {
-            return undefined;
-        }
-
-    }
-};
-
-/**
- * Convert a BigNumber to a fixed 18 point BigNumber
- *
- * @param {BigNumber} bn - The BigNumber to convert
- * @param {number} decimals - The decimals point of the given BigNumber
- * @returns A 18 fixed point BigNumber
- */
-const toFixed18 = (bn, decimals) => {
-    const num = bn.toBigInt().toString();
-    return BigNumber.from(
-        num + "0".repeat(18 - decimals)
-    );
-};
-
-/**
- * Convert a 18 fixed point BigNumber to a  BigNumber with some other decimals point
- *
- * @param {BigNumber} bn - The BigNumber to convert
- * @param {number} decimals - The decimals point of convert the given BigNumber
- * @returns A decimals point BigNumber
- */
-const fromFixed18 = (bn, decimals) => {
-    if (decimals != 18) {
-        const num = bn.toBigInt().toString();
-        return BigNumber.from(
-            num.slice(0, decimals - 18)
-        );
-    }
-    else return bn;
-};
-
-/**
- * Calls eval for a specific order to get its max output and ratio
- *
- * @param {ethers.Contract} interpreter - The interpreter ethersjs contract instance with signer
- * @param {string} arbAddress - Arb contract address
- * @param {string} obAddress - OrderBook contract address
- * @param {object} order - The order details fetched from sg
- * @param {number} inputIndex - The input token index
- * @param {number} outputIndex - The ouput token index
- * @returns The ratio and maxOuput as BigNumber
-*/
-const interpreterEval = async(
-    interpreter,
-    arbAddress,
-    obAddress,
-    order,
-    inputIndex,
-    outputIndex,
-    inputBalance,
-    outputBalance
-) => {
-    try {
-        const { stack: [ maxOutput, ratio ] } = await interpreter.eval(
-            order.interpreterStore,
-            order.owner.id,
-            order.expression + "00000002",
-            // construct the context for eval
-            [
-                [
-                    // base column
-                    arbAddress,
-                    obAddress
-                ],
-                [
-                    // calling context column
-                    order.id,
-                    order.owner.id,
-                    arbAddress
-                ],
-                [
-                    // calculateIO context column
-                ],
-                [
-                    // input context column
-                    order.validInputs[inputIndex].token.id,
-                    order.validInputs[inputIndex].token.decimals,
-                    order.validInputs[inputIndex].vault.id.split("-")[0],
-                    inputBalance,
-                    "0"
-                ],
-                [
-                    // output context column
-                    order.validOutputs[outputIndex].token.id,
-                    order.validOutputs[outputIndex].token.decimals,
-                    order.validOutputs[outputIndex].vault.id.split("-")[0],
-                    outputBalance,
-                    "0"
-                ],
-                [
-                    // empty context column
-                ],
-                [
-                    // signed context column
-                ]
-            ]
-        );
-        return { ratio, maxOutput };
-    }
-    catch {
-        return {
-            ratio: undefined,
-            maxOutput: undefined
-        };
-    }
-};
-
-/**
- * Calls eval2 on interpreter v2 for a specific order to get its max output and ratio
- *
- * @param {ethers.Contract} interpreter - The interpreter v2 ethersjs contract instance with signer
- * @param {string} arbAddress - Arb contract address
- * @param {string} obAddress - OrderBook contract address
- * @param {object} order - The order details fetched from sg
- * @param {number} inputIndex - The input token index
- * @param {number} outputIndex - The ouput token index
- * @returns The ratio and maxOuput as BigNumber
-*/
-const interpreterV2Eval = async(
-    interpreter,
-    arbAddress,
-    obAddress,
-    order,
-    inputIndex,
-    outputIndex,
-    inputBalance,
-    outputBalance
-) => {
-    try {
-        const { stack: [ ratio, maxOutput ] } = await interpreter.eval2(
-            order.interpreterStore,
-            order.owner.id,
-            order.expression + "00000002",
-            // construct the context for eval
-            [
-                [
-                    // base column
-                    arbAddress,
-                    obAddress
-                ],
-                [
-                    // calling context column
-                    order.id,
-                    order.owner.id,
-                    arbAddress
-                ],
-                [
-                    // calculateIO context column
-                ],
-                [
-                    // input context column
-                    order.validInputs[inputIndex].token.id,
-                    order.validInputs[inputIndex].token.decimals,
-                    order.validInputs[inputIndex].vault.id.split("-")[0],
-                    inputBalance,
-                    "0"
-                ],
-                [
-                    // output context column
-                    order.validOutputs[outputIndex].token.id,
-                    order.validOutputs[outputIndex].token.decimals,
-                    order.validOutputs[outputIndex].vault.id.split("-")[0],
-                    outputBalance,
-                    "0"
-                ],
-                [
-                    // empty context column
-                ],
-                [
-                    // signed context column
-                ]
-            ],
-            // empty inputs
-            []
-        );
-        return { ratio, maxOutput };
-    }
-    catch {
-        return {
-            ratio: undefined,
-            maxOutput: undefined
-        };
-    }
-};
-
-/**
- * Constructs Order struct from the result of sg default query
- *
- * @param {object} orderDetails - The order details fetched from sg
- * @returns The order struct as js object
- */
-const getOrderStruct = (orderDetails) => {
-    return {
-        owner: orderDetails.owner.id,
-        handleIO: orderDetails.handleIO,
-        evaluable: {
-            interpreter: orderDetails.interpreter,
-            store: orderDetails.interpreterStore,
-            expression: orderDetails.expression
-        },
-        validInputs: orderDetails.validInputs.map(v => {
-            return {
-                token: v.token.id,
-                decimals: Number(v.token.decimals),
-                vaultId: v.vault.id.split("-")[0]
-            };
-        }),
-        validOutputs: orderDetails.validOutputs.map(v => {
-            return {
-                token: v.token.id,
-                decimals: Number(v.token.decimals),
-                vaultId: v.vault.id.split("-")[0]
-            };
-        })
-    };
-};
-
-/**
- * Waits for provided miliseconds
- * @param {number} ms - Miliseconds to wait
- */
-const sleep = async(ms, msg = "") => {
-    let _timeoutReference;
-    return new Promise(
-        resolve => _timeoutReference = setTimeout(() => resolve(msg), ms),
-    ).finally(
-        () => clearTimeout(_timeoutReference)
-    );
-};
-
-/**
- * Extracts the income (received token value) from transaction receipt
- *
- * @param {ethers.Wallet} signer - The ethers wallet instance of the bot
- * @param {any} receipt - The transaction receipt
- * @returns The income value or undefined if cannot find any valid value
- */
-const getIncome = (signer, receipt) => {
-    const erc20Interface = new ethers.utils.Interface(erc20Abi);
-    if (receipt.events) return receipt.events.filter(
-        v => v.topics[2] && ethers.BigNumber.from(v.topics[2]).eq(signer.address)
-    ).map(v => {
-        try{
-            return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-        }
-        catch {
-            return undefined;
-        }
-    })[0]?.value;
-    else if (receipt.logs) return receipt.logs.filter(
-        v => v.topics[2] && ethers.BigNumber.from(v.topics[2]).eq(signer.address)
-    ).map(v => {
-        try{
-            return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-        }
-        catch {
-            return undefined;
-        }
-    })[0]?.value;
-    else return undefined;
-};
-
-/**
- * Extracts the actual clear amount (received token value) from transaction receipt
- *
- * @param {string} arbAddress - The arb contract address
- * @param {any} receipt - The transaction receipt
- * @returns The actual clear amount
- */
-const getActualClearAmount = (arbAddress, obAddress, receipt) => {
-    const erc20Interface = new ethers.utils.Interface(erc20Abi);
-    if (receipt.logs) return receipt.logs.map(v => {
-        try{
-            return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-        }
-        catch {
-            return undefined;
-        }
-    }).filter(v =>
-        v !== undefined &&
-        BigNumber.from(v.to).eq(arbAddress) &&
-        BigNumber.from(v.from).eq(obAddress)
-    )[0]?.value;
-    else if (receipt.events) receipt.events.map(v => {
-        try{
-            return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-        }
-        catch {
-            return undefined;
-        }
-    }).filter(v =>
-        v !== undefined &&
-        BigNumber.from(v.to).eq(arbAddress) &&
-        BigNumber.from(v.from).eq(obAddress)
-    )[0]?.value;
-    else return undefined;
-};
-
-/**
- * Calculates the actual clear price from transactioin event
- *
- * @param {any} receipt - The transaction receipt
- * @param {string} orderbook - The Orderbook contract address
- * @param {string} arb - The Arb contract address
- * @param {string} amount - The clear amount
- * @param {number} buyDecimals - The buy token decimals
- * @returns The actual clear price or undefined if necessary info not found in transaction events
- */
-const getActualPrice = (receipt, orderbook, arb, amount, buyDecimals) => {
-    const erc20Interface = new ethers.utils.Interface(erc20Abi);
-    const eventObj = receipt.events
-        ? receipt.events.map(v => {
-            try{
-                return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-            }
-            catch {
-                return undefined;
-            }
-        }).filter(v => v &&
-            !ethers.BigNumber.from(v.from).eq(orderbook) &&
-            ethers.BigNumber.from(v.to).eq(arb)
-        )
-        : receipt.logs?.map(v => {
-            try{
-                return erc20Interface.decodeEventLog("Transfer", v.data, v.topics);
-            }
-            catch {
-                return undefined;
-            }
-        }).filter(v => v &&
-            !ethers.BigNumber.from(v.from).eq(orderbook) &&
-            ethers.BigNumber.from(v.to).eq(arb)
-        );
-    if (eventObj[0] && eventObj[0]?.value) return ethers.utils.formatUnits(
-        eventObj[0].value
-            .mul("1" + "0".repeat(36 - buyDecimals))
-            .div(amount)
-    );
-    else return undefined;
-};
-
-/**
- * Estimates the profit for a single bundled orders struct
- *
- * @param {string} pairPrice - The price token pair
- * @param {string} ethPrice - Price of ETH to buy token
- * @param {object} bundledOrder - The bundled order object
- * @param {ethers.BigNumber} gas - The estimated gas cost in ETH
- * @param {string} gasCoveragePercentage - Percentage of gas to cover, default is 100,i.e. full gas coverage
- * @returns The estimated profit
- */
-const estimateProfit = (pairPrice, ethPrice, bundledOrder, gas, gasCoveragePercentage = "100") => {
-    let income = ethers.constants.Zero;
-    const price = ethers.utils.parseUnits(pairPrice);
-    const gasCost = ethers.utils.parseEther(ethPrice)
-        .mul(gas)
-        .div(ethers.utils.parseUnits("1"))
-        .mul(gasCoveragePercentage)
-        .div("100");
-    for (const takeOrder of bundledOrder.takeOrders) {
-        income = price
-            .sub(takeOrder.ratio)
-            .mul(takeOrder.quoteAmount)
-            .div(ethers.utils.parseUnits("1"))
-            .add(income);
-    }
-    return income.sub(gasCost);
-};
-
-/**
- * Builds and bundles orders which their details are queried from a orderbook subgraph by checking the vault balances and evaling
- *
- * @param {any[]} ordersDetails - Orders details queried from subgraph
- * @param {ethers.Contract} orderbook - The Orderbook EthersJS contract instance with signer
- * @param {ethers.Contract} arb - The Arb EthersJS contract instance with signer
- * @param {boolean} _eval - To eval() the orders and filter them based on the eval result
- * @param {boolean} _shuffle - To shuffle the bundled order array at the end
- * @param {boolean} _interpreterv2 - If should use eval2 of interpreter v2 for evaling
- * @param {boolean} _bundle = If orders should be bundled based on token pair
- * @returns Array of bundled take orders
- */
-const bundleTakeOrders = async(
-    ordersDetails,
-    orderbook,
-    arb,
-    _eval = true,
-    _shuffle = true,
-    _interpreterv2 = false,
-    _bundle = true
-) => {
-    const bundledOrders = [];
-    const obAsSigner = new ethers.VoidSigner(
-        orderbook.address,
-        orderbook.signer.provider
-    );
-
-    const vaultsCache = [];
-    for (let i = 0; i < ordersDetails.length; i++) {
-        const order = ordersDetails[i];
-        for (let j = 0; j < order.validOutputs.length; j++) {
-            const _output = order.validOutputs[j];
-            let quoteAmount, ratio, maxOutput;
-            let _outputBalance, _outputBalanceFixed;
-            let _hasVaultBalances = false;
-            if (_eval) {
-                if (_output?.tokenVault?.balance) {
-                    _hasVaultBalances = true;
-                }
-                if (_hasVaultBalances) {
-                    _outputBalance = _output.tokenVault.balance;
-                    _outputBalanceFixed = ethers.utils.parseUnits(
-                        ethers.utils.formatUnits(
-                            _output.tokenVault.balance,
-                            _output.token.decimals
-                        )
-                    );
-                    if (!vaultsCache.find(e =>
-                        e.owner === order.owner.id &&
-                        e.token === _output.token.id &&
-                        e.vaultId === _output.vault.id.split("-")[0]
-                    )) vaultsCache.push({
-                        owner: order.owner.id,
-                        token: _output.token.id,
-                        vaultId: _output.vault.id.split("-")[0],
-                        balance: _output.tokenVault.balance
-                    });
-                }
-                else {
-                    let _ov = vaultsCache.find(e =>
-                        e.owner === order.owner.id &&
-                        e.token === _output.token.id &&
-                        e.vaultId === _output.vault.id.split("-")[0]
-                    );
-                    if (!_ov) {
-                        const balance = await orderbook.vaultBalance(
-                            order.owner.id,
-                            _output.token.id,
-                            _output.vault.id.split("-")[0]
-                        );
-                        _ov = {
-                            owner: order.owner.id,
-                            token: _output.token.id,
-                            vaultId: _output.vault.id.split("-")[0],
-                            balance
-                        };
-                        vaultsCache.push(_ov);
-                    }
-                    _outputBalance = _ov.balance;
-                    _outputBalanceFixed = ethers.utils.parseUnits(
-                        ethers.utils.formatUnits(
-                            _outputBalance,
-                            _output.token.decimals
-                        )
-                    );
-                }
-                quoteAmount = _outputBalanceFixed;
-            }
-
-            if (quoteAmount === undefined || !quoteAmount.isZero()) {
-                for (let k = 0; k < order.validInputs.length; k ++) {
-                    if (_output.token.id !== order.validInputs[k].token.id) {
-                        const _input = order.validInputs[k];
-
-                        if (_eval) {
-                            let _inputBalance;
-                            if (_hasVaultBalances) {
-                                _inputBalance = _input.tokenVault.balance;
-                                if (!vaultsCache.find(e =>
-                                    e.owner === order.owner.id &&
-                                    e.token === _input.token.id &&
-                                    e.vaultId === _input.vault.id.split("-")[0]
-                                )) vaultsCache.push({
-                                    owner: order.owner.id,
-                                    token: _input.token.id,
-                                    vaultId: _input.vault.id.split("-")[0],
-                                    balance: _input.tokenVault.balance
-                                });
-                            }
-                            else {
-                                let _iv = vaultsCache.find(e =>
-                                    e.owner === order.owner.id &&
-                                    e.token === _input.token.id &&
-                                    e.vaultId === _input.vault.id.split("-")[0]
-                                );
-                                if (!_iv) {
-                                    const balance = await orderbook.vaultBalance(
-                                        order.owner.id,
-                                        _input.token.id,
-                                        _input.vault.id.split("-")[0]
-                                    );
-                                    _iv = {
-                                        owner: order.owner.id,
-                                        token: _input.token.id,
-                                        vaultId: _input.vault.id.split("-")[0],
-                                        balance
-                                    };
-                                    vaultsCache.push(_iv);
-                                }
-                                _inputBalance = _iv.balance;
-                            }
-                            ({ maxOutput, ratio } = _interpreterv2
-                                ? await interpreterV2Eval(
-                                    new ethers.Contract(
-                                        order.interpreter,
-                                        interpreterV2Abi,
-                                        obAsSigner
-                                    ),
-                                    arb.address,
-                                    orderbook.address,
-                                    order,
-                                    k,
-                                    j ,
-                                    _inputBalance.toString() ,
-                                    _outputBalance.toString()
-                                )
-                                : await interpreterEval(
-                                    new ethers.Contract(
-                                        order.interpreter,
-                                        interpreterAbi,
-                                        obAsSigner
-                                    ),
-                                    arb.address,
-                                    orderbook.address,
-                                    order,
-                                    k,
-                                    j ,
-                                    _inputBalance.toString() ,
-                                    _outputBalance.toString()
-                                )
-                            );
-
-                            if (maxOutput && ratio && maxOutput.lt(quoteAmount)) {
-                                quoteAmount = maxOutput;
-                            }
-                        }
-
-                        if (!_eval || (!quoteAmount.isZero() && ratio !== undefined)) {
-                            const pair = bundledOrders.find(v =>
-                                v.sellToken === _output.token.id &&
-                                v.buyToken === _input.token.id
-                            );
-                            if (pair && _bundle) pair.takeOrders.push({
-                                id: order.id,
-                                ratio,
-                                quoteAmount,
-                                takeOrder: {
-                                    order: getOrderStruct(order),
-                                    inputIOIndex: k,
-                                    outputIOIndex: j,
-                                    signedContext: []
-                                }
-                            });
-                            else bundledOrders.push({
-                                buyToken: _input.token.id,
-                                buyTokenSymbol: _input.token.symbol,
-                                buyTokenDecimals: _input.token.decimals,
-                                sellToken: _output.token.id,
-                                sellTokenSymbol: _output.token.symbol,
-                                sellTokenDecimals: _output.token.decimals,
-                                takeOrders: [{
-                                    id: order.id,
-                                    ratio,
-                                    quoteAmount,
-                                    takeOrder: {
-                                        order: getOrderStruct(order),
-                                        inputIOIndex: k,
-                                        outputIOIndex: j,
-                                        signedContext: []
-                                    }
-                                }]
-                            });
-                        }
-                    }
-                }
-            }
-        }
-    }
-    // sort ascending based on ratio if orders are evaled
-    if (_eval) bundledOrders.forEach(v => v.takeOrders.sort(
-        (a, b) => a.ratio && b.ratio
-            ? a.ratio.gt(b.ratio) ? 1 : a.ratio.lt(b.ratio) ? -1 : 0
-            : 0
-    ));
-    if (_shuffle) {
-        // shuffle take orders for each pair
-        if (!_eval) bundledOrders.forEach(v => shuffleArray(v.takeOrders));
-
-        // shuffle bundled orders pairs
-        shuffleArray(bundledOrders);
-    }
-    return bundledOrders;
-};
-
-/**
- * Creates a viem client
- * @param {number} chainId - The chain id
- * @param {string[]} rpcs - The RPC urls
- * @param {boolean} useFallbacs - If fallback RPCs should be used as well or not
- */
-const createViemClient = (chainId, rpcs, useFallbacs = false) => {
-    const transport = rpcs.includes("test") || rpcs.length === 0
-        ? fallback(fallbacks[chainId].transport, {rank: true})
-        : useFallbacs
-            ? fallback(
-                [...rpcs.map(v => http(v)), ...fallbacks[chainId].transport],
-                { rank: true }
-            )
-            : fallback(rpcs.map(v => http(v)));
-
-    return createPublicClient({
-        chain: viemConfig[chainId]?.chain,
-        transport
-        // batch: {
-        //     multicall: {
-        //         batchSize: 512
-        //     },
-        // },
-        // pollingInterval: 8_000,
-    });
-};
-
-/**
- * Instantiates a DataFetcher
- * @param {any} configOrViemClient - The network config data or a viem public client
- * @param {LiquidityProviders[]} liquidityProviders - Array of Liquidity Providers
- */
-const getDataFetcher = (configOrViemClient, liquidityProviders = [], useFallbacks = false) => {
-    try {
-        const dataFetcher = new DataFetcher(
-            ("transport" in configOrViemClient
-                ? configOrViemClient.chain.id
-                : configOrViemClient.chainId
-            ),
-            ("transport" in configOrViemClient
-                ? configOrViemClient
-                : createViemClient(
-                    configOrViemClient.chainId,
-                    [configOrViemClient.rpc],
-                    useFallbacks
-                )
-            )
-        );
-
-        // start and immediately stop data fetching as we only want data fetching on demand
-        dataFetcher.startDataFetching(
-            !liquidityProviders.length ? undefined : liquidityProviders
-        );
-        dataFetcher.stopDataFetching();
-        return dataFetcher;
-    }
-    catch(error) {
-        throw "cannot instantiate DataFetcher for this network";
-    }
-};
-
-/**
- * Gets ETH price against a target token
- *
- * @param {any} config - The network config data
- * @param {string} targetTokenAddress - The target token address
- * @param {number} targetTokenDecimals - The target token decimals
- * @param {BigNumber} gasPrice - The network gas price
- * @param {DataFetcher} dataFetcher - (optional) The DataFetcher instance
- */
-const getEthPrice = async(
-    config,
-    targetTokenAddress,
-    targetTokenDecimals,
-    gasPrice,
-    dataFetcher = undefined
-) => {
-    const amountIn = BigNumber.from(
-        "1" + "0".repeat(config.nativeWrappedToken.decimals)
-    );
-    const fromToken = new Token({
-        chainId: config.chainId,
-        decimals: config.nativeWrappedToken.decimals,
-        address: config.nativeWrappedToken.address,
-        symbol: config.nativeWrappedToken.symbol
-    });
-    const toToken = new Token({
-        chainId: config.chainId,
-        decimals: targetTokenDecimals,
-        address: targetTokenAddress
-    });
-    if (!dataFetcher) dataFetcher = getDataFetcher(config);
-    await dataFetcher.fetchPoolsForToken(fromToken, toToken);
-    const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken);
-    const route = Router.findBestRoute(
-        pcMap,
-        config.chainId,
-        fromToken,
-        amountIn,
-        toToken,
-        gasPrice.toNumber()
-        // 30e9,
-        // providers,
-        // poolFilter
-    );
-    if (route.status == "NoWay") return undefined;
-    else return ethers.utils.formatUnits(route.amountOutBN, targetTokenDecimals);
-};
-
-// /**
-//  * A wrapper for DataFetcher fetchPoolsForToken() to avoid any errors for liquidity providers that are not available for target chain
-//  *
-//  * @param {DataFetcher} dataFetcher - DataFetcher instance
-//  * @param {Token} fromToken - The from token
-//  * @param {Token} toToken - The to token
-//  * @param {string[]} excludePools - Set of pools to exclude
-//  */
-// const fetchPoolsForTokenWrapper = async(dataFetcher, fromToken, toToken, excludePools) => {
-//     // ensure that we only fetch the native wrap pools if the
-//     // token is the native currency and wrapped native currency
-//     if (fromToken.wrapped.equals(toToken.wrapped)) {
-//         const provider = dataFetcher.providers.find(
-//             (p) => p.getType() === LiquidityProviders.NativeWrap
-//         );
-//         if (provider) {
-//             try {
-//                 await provider.fetchPoolsForToken(
-//                     fromToken.wrapped,
-//                     toToken.wrapped,
-//                     excludePools
-//                 );
-//             }
-//             catch {}
-//         }
-//     }
-//     else {
-//         const [token0, token1] =
-//             fromToken.wrapped.equals(toToken.wrapped) ||
-//             fromToken.wrapped.sortsBefore(toToken.wrapped)
-//                 ? [fromToken.wrapped, toToken.wrapped]
-//                 : [toToken.wrapped, fromToken.wrapped];
-//         await Promise.allSettled(
-//             dataFetcher.providers.map((p) => {
-//                 try {
-//                     return p.fetchPoolsForToken(token0, token1, excludePools);
-//                 }
-//                 catch {
-//                     return;
-//                 }
-//             })
-//         );
-//     }
-// };
-
-/**
- * Resolves an array of case-insensitive names to LiquidityProviders, ignores the ones that are not valid
- *
- * @param {string[]} liquidityProviders - List of liquidity providers
- * @param {number} chainId - The chain id
- */
-const processLps = (liquidityProviders, chainId) => {
-    if (
-        !liquidityProviders ||
-        !Array.isArray(liquidityProviders) ||
-        !liquidityProviders.length ||
-        !liquidityProviders.every(v => typeof v === "string")
-    ) return undefined;
-    const _lps = [];
-    const LP = Object.values(LiquidityProviders);
-    for (let i = 0; i < liquidityProviders.length; i++) {
-        const index = LP.findIndex(
-            v => v.toLowerCase() === liquidityProviders[i].toLowerCase()
-                && !!fallbacks[chainId]?.liquidityProviders.includes(
-                    liquidityProviders[i].toLowerCase()
-                )
-        );
-        if (index > -1 && !_lps.includes(LP[index])) _lps.push(LP[index]);
-    }
-    return _lps.length ? _lps : undefined;
-};
-
-/**
- * Validates content of an array of orders
- *
- * @param {any[]} orders - Array of order struct
- */
-const validateOrders = (orders) => {
-    const addressPattern = /^0x[a-fA-F0-9]{40}$/;
-    const vaultIdPattern = /^0x[a-fA-F0-9]{64}$/;
-    return Array.isArray(orders)
-        && orders.every(v => typeof v.owner === "string"
-            && addressPattern.test(v.owner)
-            && typeof v.handleIO === "boolean"
-            && v.evaluable !== null
-            && typeof v.evaluable === "object"
-            && typeof v.evaluable.interpreter === "string"
-            && addressPattern.test(v.evaluable.interpreter)
-            && typeof v.evaluable.store === "string"
-            && addressPattern.test(v.evaluable.store)
-            && typeof v.evaluable.expression === "string"
-            && addressPattern.test(v.evaluable.expression)
-            && Array.isArray(v.validInputs)
-            && v.validInputs.length > 0
-            && Array.isArray(v.validOutputs)
-            && v.validOutputs.length > 0
-            && v.validInputs.every(e =>
-                typeof e.token === "string"
-                && addressPattern.test(e.token)
-                && typeof e.decimals === "number"
-                && e.decimals > 0
-                && typeof e.vaultId === "string"
-                && vaultIdPattern.test(e.vaultId)
-            )
-            && v.validOutputs.every(e =>
-                typeof e.token === "string"
-                && addressPattern.test(e.token)
-                && typeof e.decimals === "number"
-                && e.decimals > 0
-                && typeof e.vaultId === "string"
-                && vaultIdPattern.test(e.vaultId)
-            )
-        );
-};
-
-/**
- * Get the order hash from an order struct
- *
- * @param {any} order - The order struct
- * @returns The order hash
- */
-const getOrderHash = (order) => {
-    return ethers.utils.keccak256(
-        ethers.utils.defaultAbiCoder.encode(
-            [
-                "tuple("
-                    + "address,"
-                    + "bool,"
-                    + "tuple(address,address,address),"
-                    + "tuple[](address,uint8,uint256),"
-                    + "tuple[](address,uint8,uint256)" +
-                ")"
-            ],
-            [[
-                order.owner,
-                order.handleIO,
-                [
-                    order.evaluable.interpreter,
-                    order.evaluable.store,
-                    order.evaluable.expression
-                ],
-                order.validInputs.map(v => [
-                    v.token,
-                    v.decimals,
-                    v.vaultId
-                ]),
-                order.validOutputs.map(v => [
-                    v.token,
-                    v.decimals,
-                    v.vaultId
-                ])
-            ]]
-        )
-    );
-};
-
-/**
- * Get order details from an array of order struct
- *
- * @param {string} jsonContent - Content of a JSON file containing orders struct
- */
-const getOrderDetailsFromJson = async(jsonContent, signer) => {
-    const orders = JSON.parse(jsonContent);
-    if (!validateOrders(orders)) throw "invalid orders format";
-    const orderDetails = [];
-    for (let i = 0; i < orders.length; i++) {
-        const _inputSymbols = [];
-        const _outputSymbols = [];
-        for (let j = 0; j < orders[i].validInputs.length; j++) {
-            const erc20 = new ethers.Contract(orders[i].validInputs[j].token, erc20Abi, signer);
-            const symbol = await erc20.symbol();
-            _inputSymbols.push(symbol);
-        }
-        for (let j = 0; j < orders[i].validOutputs.length; j++) {
-            const erc20 = new ethers.Contract(orders[i].validOutputs[j].token, erc20Abi, signer);
-            const symbol = await erc20.symbol();
-            _outputSymbols.push(symbol);
-        }
-        orderDetails.push({
-            id: getOrderHash(orders[i]).toLowerCase(),
-            handleIO: orders[i].handleIO,
-            expression: orders[i].evaluable.expression.toLowerCase(),
-            interpreter: orders[i].evaluable.interpreter.toLowerCase(),
-            interpreterStore: orders[i].evaluable.store.toLowerCase(),
-            owner: {
-                id: orders[i].owner.toLowerCase()
-            },
-            validInputs: orders[i].validInputs.map((v, i) => {
-                const _input = {
-                    index: i,
-                    token: {
-                        id: v.token.toLowerCase(),
-                        decimals: v.decimals,
-                        symbol: _inputSymbols[i]
-                    },
-                    vault: {
-                        id: v.vaultId.toLowerCase() + "-" + orders[i].owner.toLowerCase()
-                    }
-                };
-                return _input;
-            }),
-            validOutputs: orders[i].validOutputs.map((v, i) => {
-                const _output = {
-                    index: i,
-                    token: {
-                        id: v.token.toLowerCase(),
-                        decimals: v.decimals,
-                        symbol: _outputSymbols[i]
-                    },
-                    vault: {
-                        id: v.vaultId.toLowerCase() + "-" + orders[i].owner.toLowerCase()
-                    }
-                };
-                return _output;
-            })
-        });
-    }
-    return orderDetails;
-};
-
-/**
- * Method to shorten data fields of items that are logged and optionally hide sensitive data
- *
- * @param {boolean} scrub - Option to scrub sensitive data
- * @param {...any} data - The optinnal data to hide
- */
-const appGlobalLogger = (scrub, ...data) => {
-    const largeDataPattern = /0x[a-fA-F0-9]{128,}/g;
-    const consoleMethods = ["log", "warn", "error", "info", "debug"];
-
-    // Stringifies an object
-    const objStringify = (obj) => {
-        const keys = Object.getOwnPropertyNames(obj);
-        for (let i = 0; i < keys.length; i++) {
-            if (
-                typeof obj[keys[i]] === "bigint"
-                || typeof obj[keys[i]] === "number"
-                || typeof obj[keys[i]] === "symbol"
-            ) obj[keys[i]] = obj[keys[i]].toString();
-            else if (typeof obj[keys[i]] === "object" && obj[keys[i]] !== null) {
-                obj[keys[i]] = objStringify(obj[keys[i]]);
-            }
-        }
-        return obj;
-    };
-
-    // Replaces a search value with replace value in an object's properties string content
-    const objStrReplacer = (logObj, searchee, replacer) => {
-        const objKeys = Object.getOwnPropertyNames(logObj);
-        for (let i = 0; i < objKeys.length; i++) {
-            if (typeof logObj[objKeys[i]] === "string" && logObj[objKeys[i]]) {
-                if (typeof searchee === "string") {
-                    // while (logObj[objKeys[i]].includes(searchee)) {
-                    logObj[objKeys[i]] = logObj[objKeys[i]].replaceAll(searchee, replacer);
-                    // }
-                }
-                else logObj[objKeys[i]] = logObj[objKeys[i]].replace(searchee, replacer);
-            }
-            else if (typeof logObj[objKeys[i]] === "object" && logObj[objKeys[i]] !== null) {
-                logObj[objKeys[i]] = objStrReplacer(logObj[objKeys[i]], searchee, replacer);
-            }
-        }
-        return logObj;
-    };
-
-    // filtering unscrubable data
-    const _data = data.filter(
-        v => v !== undefined && v !== null
-    ).map(
-        v => {
-            try {
-                let str;
-                if (typeof v !== "string") str = v.toString();
-                else str = v;
-                if (str) return str;
-                else return undefined;
-            }
-            catch { return undefined; }
-        }
-    ).filter(
-        v => v !== undefined
-    );
-
-    // intercepting the console with custom function to scrub and shorten loggings
-    consoleMethods.forEach(methodName => {
-        const orgConsole = console[methodName];
-        console[methodName] = function (...params) {
-            const modifiedParams = [];
-            const shortenedLogs = [];
-            for (let i = 0; i < params.length; i++) {
-                let logItem = params[i];
-                if (
-                    typeof logItem === "number" ||
-                    typeof logItem === "bigint" ||
-                    typeof logItem === "symbol"
-                ) logItem = logItem.toString();
-
-                if (typeof logItem === "string") {
-                    if (scrub) for (let j = 0; j < _data.length; j++) {
-                        // while (logItem.includes(_data[i]))
-                        logItem = logItem.replaceAll(
-                            _data[j],
-                            "**********"
-                        );
-                    }
-                    logItem = logItem.replace(
-                        largeDataPattern,
-                        largeData => {
-                            if (!shortenedLogs.includes(largeData)) {
-                                shortenedLogs.push(largeData);
-                                return largeData;
-                            }
-                            else return largeData.slice(0, 67) + "...";
-                        }
-                    );
-                }
-                else if (typeof logItem === "object" && logItem !== null) {
-                    logItem = objStringify(logItem);
-                    if (scrub) for (let j = 0; j < _data.length; j++) {
-                        logItem = objStrReplacer(logItem, _data[j], "**********");
-                    }
-                    logItem = objStrReplacer(
-                        logItem,
-                        largeDataPattern,
-                        largeData => {
-                            if (!shortenedLogs.includes(largeData)) {
-                                shortenedLogs.push(largeData);
-                                return largeData;
-                            }
-                            else return largeData.slice(0, 67) + "...";
-                        }
-                    );
-                }
-                modifiedParams.push(logItem);
-            }
-            orgConsole.apply(console, modifiedParams);
-        };
-    });
-};
-
-/**
- * Method to put a timeout on a promise, throws the exception if promise is not settled within the time
- *
- * @param {Promise} promise - The Promise to put timeout on
- * @param {number} time - The time in milliseconds
- * @param {string | number | bigint | symbol | boolean} exception - The exception value to reject with if the promise is not settled within time
- * @returns A new promise that gets settled with initial promise settlement or rejected with exception value
- * if the time runs out before the main promise settlement
- */
-const promiseTimeout = async(promise, time, exception) => {
-    let timer;
-    return Promise.race([
-        promise,
-        new Promise(
-            (_res, _rej) => timer = setTimeout(_rej, time, exception)
-        )
-    ]).finally(
-        () => clearTimeout(timer)
-    );
-};
-
-
-/**
- * Gets the route for tokens
- *
- * @param {number} chainId - The network chain id
- * @param {ethers.BigNumber} sellAmount - The sell amount, should be in onchain token value
- * @param {string} fromTokenAddress - The from token address
- * @param {number} fromTokenDecimals - The from token decimals
- * @param {string} toTokenAddress - The to token address
- * @param {number} toTokenDecimals - The to token decimals
- * @param {string} receiverAddress - The address of the receiver
- * @param {string} routeProcessorAddress - The address of the RouteProcessor contract
- * @param {boolean} abiencoded - If the result should be abi encoded or not
- */
-const getRouteForTokens = async(
-    chainId,
-    sellAmount,
-    fromTokenAddress,
-    fromTokenDecimals,
-    toTokenAddress,
-    toTokenDecimals,
-    receiverAddress,
-    routeProcessorAddress,
-    abiEncoded
-) => {
-    const amountIn = sellAmount;
-    const fromToken = new Token({
-        chainId: chainId,
-        decimals: fromTokenDecimals,
-        address: fromTokenAddress
-    });
-    const toToken = new Token({
-        chainId: chainId,
-        decimals: toTokenDecimals,
-        address: toTokenAddress
-    });
-    const dataFetcher = getDataFetcher({chainId});
-    await dataFetcher.fetchPoolsForToken(fromToken, toToken);
-    const pcMap = dataFetcher.getCurrentPoolCodeMap(fromToken, toToken);
-    const route = Router.findBestRoute(
-        pcMap,
-        chainId,
-        fromToken,
-        amountIn,
-        toToken,
-        30e9,
-        // providers,
-        // poolFilter
-    );
-    if (route.status == "NoWay") throw "NoWay";
-    else {
-        let routeText = "";
-        route.legs.forEach((v, i) => {
-            if (i === 0) routeText =
-                routeText +
-                v.tokenTo.symbol +
-                "/" +
-                v.tokenFrom.symbol +
-                "(" +
-                v.poolName +
-                ")";
-            else routeText =
-                routeText +
-                " + " +
-                v.tokenTo.symbol +
-                "/" +
-                v.tokenFrom.symbol +
-                "(" +
-                v.poolName +
-                ")";
-        });
-        console.log("Route portions: ", routeText, "\n");
-        const rpParams = Router.routeProcessor2Params(
-            pcMap,
-            route,
-            fromToken,
-            toToken,
-            receiverAddress,
-            routeProcessorAddress,
-            // permits
-            // "0.005"
-        );
-        if (abiEncoded) return ethers.utils.defaultAbiCoder.encode(
-            ["bytes"],
-            [rpParams.routeCode]
-        );
-        else return rpParams.routeCode;
-    }
-};
-
-/**
- * Method to visualize the routes, returns array of route strings sorted from highest to lowest percentage
- *
- * @param {string} fromToken - The from token address
- * @param {string} toToken - The to token address
- * @param {any[]} legs - The legs of the route
- */
-const visualizeRoute = (fromToken, toToken, legs) => {
-    return [
-        ...legs.filter(
-            v => v.tokenTo.address.toLowerCase() === toToken.address.toLowerCase() &&
-            v.tokenFrom.address.toLowerCase() === fromToken.address.toLowerCase() &&
-            v.tokenTo.symbol.toLowerCase() === toToken.symbol.toLowerCase() &&
-            v.tokenFrom.symbol.toLowerCase() === fromToken.symbol.toLowerCase()
-        ).map(v => [v]),
-
-        ...legs.filter(
-            v => v.tokenFrom.address.toLowerCase() === fromToken.address.toLowerCase() &&
-            v.tokenFrom.symbol.toLowerCase() === fromToken.symbol.toLowerCase() &&
-            (
-                v.tokenTo.address.toLowerCase() !== toToken.address.toLowerCase() ||
-                v.tokenTo.symbol.toLowerCase() !== toToken.symbol.toLowerCase()
-            )
-        ).map(v => {
-            const portoin = [v];
-            while(
-                portoin.at(-1).tokenTo.address.toLowerCase() !== toToken.address.toLowerCase() ||
-                portoin.at(-1).tokenTo.symbol.toLowerCase() !== toToken.symbol.toLowerCase()
-            ) {
-                portoin.push(
-                    legs.find(e =>
-                        e.tokenFrom.address.toLowerCase() ===
-                        portoin.at(-1).tokenTo.address.toLowerCase() &&
-                        e.tokenFrom.symbol.toLowerCase() ===
-                        portoin.at(-1).tokenTo.symbol.toLowerCase()
-                    )
-                );
-            }
-            return portoin;
-        })
-
-    ].sort(
-        (a, b) => b[0].absolutePortion - a[0].absolutePortion
-    ).map(
-        v => (v[0].absolutePortion * 100).toFixed(2).padStart(5, "0") + "%   --->   " +
-        v.map(
-            e => e.tokenTo.symbol + "/" + e.tokenFrom.symbol + " (" + e.poolName + ")"
-        ).join(
-            " >> "
-        )
-    );
-};
-
-/**
- * Builds initial 0x requests bodies from token addresses that is required
- * for getting token prices with least amount of hits possible and that is
- * to pair up tokens in a way that each show up only once in a request body
- * so that the number of requests will be: "number-of-tokens / 2" at best or
- * "(number-of-tokens / 2) + 1" at worst if the number of tokens is an odd digit.
- * This way the responses will include the "rate" for sell/buy tokens to native
- * network token which will be used to estimate the initial price of all possible
- * token pair combinations.
- *
- * @param {string} api - The 0x API endpoint URL
- * @param {any[]} queries - The array that keeps the 0x query text
- * @param {string} tokenAddress - The token address
- * @param {number} tokenDecimals - The token decimals
- * @param {string} tokenSymbol - The token symbol
- */
-const build0xQueries = (api, queries, tokenAddress, tokenDecimals, tokenSymbol) => {
-    tokenAddress = tokenAddress.toLowerCase();
-    if (queries.length === 0) queries.push([
-        tokenAddress,
-        tokenDecimals,
-        tokenSymbol
-    ]);
-    else if (!Array.isArray(queries[queries.length - 1])) {
-        if(!queries.find(v => v.quote.includes(tokenAddress))) queries.push([
-            tokenAddress,
-            tokenDecimals,
-            tokenSymbol
-        ]);
-    }
-    else {
-        if(
-            queries[queries.length - 1][0] !== tokenAddress &&
-            !queries.slice(0, -1).find(v => v.quote.includes(tokenAddress))
-        ) {
-            queries[queries.length - 1] = {
-                quote: `${
-                    api
-                }swap/v1/price?buyToken=${
-                    queries[queries.length - 1][0]
-                }&sellToken=${
-                    tokenAddress
-                }&sellAmount=${
-                    "1" + "0".repeat(tokenDecimals)
-                }`,
-                tokens: [
-                    queries[queries.length - 1][2],
-                    tokenSymbol,
-                    queries[queries.length - 1][0],
-                    tokenAddress,
-                    queries[queries.length - 1][1],
-                    tokenDecimals
-                ]
-            };
-        }
-    }
-};
-
-const shuffleArray = (array) => {
-    let currentIndex = array.length;
-    let randomIndex = 0;
-
-    // While there remain elements to shuffle.
-    while (currentIndex > 0) {
-
-        // Pick a remaining element.
-        randomIndex = Math.floor(Math.random() * currentIndex);
-        currentIndex--;
-
-        // And swap it with the current element.
-        [
-            array[currentIndex],
-            array[randomIndex]
-        ] = [
-            array[randomIndex],
-            array[currentIndex]
-        ];
-    }
-
-    return array;
-};
-
-module.exports = {
-    fallbacks,
-    bnFromFloat,
-    toFixed18,
-    fromFixed18,
-    interpreterEval,
-    getOrderStruct,
-    sleep,
-    getIncome,
-    getActualPrice,
-    estimateProfit,
-    bundleTakeOrders,
-    getDataFetcher,
-    getEthPrice,
-    processLps,
-    validateOrders,
-    getOrderHash,
-    getOrderDetailsFromJson,
-    appGlobalLogger,
-    promiseTimeout,
-    getActualClearAmount,
-    getRouteForTokens,
-    visualizeRoute,
-    build0xQueries,
-    shuffleArray,
-    createViemClient,
-    interpreterV2Eval
-};
-
-
- - - - -
- - - -
- -
- Documentation generated by JSDoc 4.0.2 on Sun Dec 10 2023 19:20:41 GMT+0000 (Coordinated Universal Time) -
- - - - - diff --git a/example.env b/example.env index 53106487..6ea4f7eb 100644 --- a/example.env +++ b/example.env @@ -11,7 +11,7 @@ RPC_URL="https://polygon-mainnet.g.alchemy.com/v2/{API_KEY}, https://rpc.ankr.co # Option to submit transactions using the flashbot RPC. FLASHBOT_RPC="" -# bot running mode, one of "router", "0x", "curve", "crouter", "srouter" +# bot running mode, one of "router", "0x", "curve", "crouter", "srouter", "suniv2" MODE="router" # arb contract address @@ -78,4 +78,7 @@ INTERPRETERV2="true" NO_BUNDLE="false" # number of hops of binary search in srouter mode, if left unspecified will be 11 by default -HOPS=11 \ No newline at end of file +HOPS=11 + +# Option to use sushi RouteProcessorv3.2, default is v3 +RP3_2="true" \ No newline at end of file diff --git a/src/index.js b/src/index.js index 98ae4bd4..fa1fa939 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ const { zeroExClear } = require("./modes/zeroex"); const { routerClear } = require("./modes/router"); const { crouterClear } = require("./modes/crouter"); const { srouterClear } = require("./modes/srouter"); +const { suniv2Clear } = require("./modes/suniv2"); const { getOrderDetailsFromJson, appGlobalLogger } = require("./utils"); @@ -68,7 +69,11 @@ const configOptions = { /** * The amount of hops of binary search for sorouter mode */ - hops: 11 + hops: 11, + /** + * Option to use sushi RouteProcessorv3.2, default is v3 + */ + rp32: false }; /** @@ -198,6 +203,7 @@ const getConfig = async( else throw "invalid timeout, must be an integer greater than 0"; } + console.log("\x1b[33m%s\x1b[0m", `current working rpc: ${rpcUrl}`); const provider = new ethers.providers.JsonRpcProvider(rpcUrl); const signer = new ethers.Wallet(walletPrivateKey, provider); const chainId = await signer.getChainId(); @@ -214,9 +220,9 @@ const getConfig = async( if (options.hops) { if (/^\d+$/.test(options.hops)) { hops = Number(options.hops); - if (v === 0) throw "invalid sleep value, must be an integer greater than 0"; + if (v === 0) throw "invalid hops value, must be an integer greater than 0"; } - else throw "invalid sleep value, must be an integer greater than 0"; + else throw "invalid hops value, must be an integer greater than 0"; } @@ -235,6 +241,7 @@ const getConfig = async( config.usePublicRpcs = !!options?.usePublicRpcs; config.interpreterv2 = !!options?.interpreterv2; config.hops = hops; + config.rp32 = !!options?.rp32; return config; }; @@ -257,14 +264,11 @@ const clear = async( const _mode = mode.toLowerCase(); const version = versions.node; const majorVersion = Number(version.slice(0, version.indexOf("."))); - // const prioritization = options.prioritization !== undefined - // ? !!options.prioritization - // : clearOptions.prioritization; const gasCoveragePercentage = options.gasCoveragePercentage !== undefined ? options.gasCoveragePercentage : clearOptions.gasCoveragePercentage; - if (_mode !== "srouter") { + if (_mode !== "srouter" && _mode !== "suniv2") { if (!config.arbType) throw "undefined arb contract type"; if (!/^flash-loan-v[23]$|^order-taker$/.test(config.arbType)) { throw "invalid arb contract type, must be either of: 'flash-loan-v2' or 'flash-loan-v3' or 'order-taker'"; @@ -314,6 +318,15 @@ const clear = async( ); else throw `NodeJS v18 or higher is required for running the app in "router" mode, current version: ${version}`; } + else if (_mode === "suniv2") { + if (majorVersion >= 18) return await suniv2Clear( + config, + ordersDetails, + gasCoveragePercentage, + // prioritization + ); + else throw `NodeJS v18 or higher is required for running the app in "router" mode, current version: ${version}`; + } else throw "unknown mode, must be either of '0x' or 'curve' or 'router' or 'srouter'"; }; diff --git a/src/modes/crouter.js b/src/modes/crouter.js index 5a581991..5979d5d9 100644 --- a/src/modes/crouter.js +++ b/src/modes/crouter.js @@ -158,7 +158,7 @@ const crouterClear = async( ) throw "invalid gas coverage percentage, must be an integer greater than equal 0"; const lps = processLps(config.lps, config.chainId); - const viemClient = createViemClient(config.chainId, [config.rpc], !!config.usePublicRpc); + const viemClient = createViemClient(config.chainId, [config.rpc],!!config.usePublicRpcs); const dataFetcher = getDataFetcher(viemClient, lps); const signer = config.signer; const arbAddress = config.arbAddress; @@ -455,7 +455,9 @@ const crouterClear = async( fromToken, toToken, arb.address, - config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, // permits // "0.005" ); @@ -477,8 +479,12 @@ const crouterClear = async( exchangeData = ethers.utils.defaultAbiCoder.encode( ["address", "address", "bytes"], [ - config.routeProcessor3Address, - config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, fnData ] ); @@ -615,7 +621,7 @@ const crouterClear = async( }; console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); let gasLimit = await signer.estimateGas(rawtx); - gasLimit = gasLimit.mul("112").div("100"); + gasLimit = gasLimit.mul("105").div("100"); rawtx.gasLimit = gasLimit; const gasCost = gasLimit.mul(gasPrice); const gasCostInToken = ethers.utils.parseUnits( @@ -629,7 +635,7 @@ const crouterClear = async( ); if (gasCoveragePercentage !== "0") { const headroom = ( - Number(gasCoveragePercentage) * 1.15 + Number(gasCoveragePercentage) * 1.05 ).toFixed(); rawtx.data = arb.interface.encodeFunctionData( "arb", @@ -663,15 +669,23 @@ const crouterClear = async( ] ); console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - const tx = flashbotSigner !== undefined - ? await flashbotSigner.sendTransaction(rawtx) - : await signer.sendTransaction(rawtx); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); console.log( ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", "\n" ); - + console.log(tx); const receipt = config.timeout ? await promiseTimeout( tx.wait(), @@ -679,6 +693,7 @@ const crouterClear = async( `Transaction failed to mine after ${config.timeout}ms` ) : await tx.wait(); + const income = getIncome(signer, receipt); const clearActualPrice = getActualPrice( receipt, diff --git a/src/modes/curve.js b/src/modes/curve.js index 252bc7fe..0fd29402 100644 --- a/src/modes/curve.js +++ b/src/modes/curve.js @@ -270,7 +270,7 @@ const curveClear = async( } const report = []; - const viemClient = createViemClient(config.chainId, [config.rpc], !!config.usePublicRpc); + const viemClient = createViemClient(config.chainId, [config.rpc], !!config.usePublicRpcs); const dataFetcher = getDataFetcher(viemClient, processLps(config.lps, config.chainId)); for (let i = 0; i < bundledOrders.length; i++) { try { @@ -503,7 +503,7 @@ const curveClear = async( }; console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); let gasLimit = await signer.estimateGas(rawtx); - gasLimit = gasLimit.mul("112").div("100"); + gasLimit = gasLimit.mul("105").div("100"); rawtx.gasLimit = gasLimit; const gasCost = gasLimit.mul(gasPrice); const gasCostInToken = ethers.utils.parseUnits( @@ -517,7 +517,7 @@ const curveClear = async( ); if (gasCoveragePercentage !== "0") { const headroom = ( - Number(gasCoveragePercentage) * 1.15 + Number(gasCoveragePercentage) * 1.05 ).toFixed(); rawtx.data = arb.interface.encodeFunctionData( "arb", @@ -551,15 +551,23 @@ const curveClear = async( ] ); console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - const tx = flashbotSigner !== undefined - ? await flashbotSigner.sendTransaction(rawtx) - : await signer.sendTransaction(rawtx); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); console.log( ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", "\n" ); - + console.log(tx); const receipt = config.timeout ? await promiseTimeout( tx.wait(), @@ -567,6 +575,7 @@ const curveClear = async( `Transaction failed to mine after ${config.timeout}ms` ) : await tx.wait(); + const income = getIncome(signer, receipt); const clearActualPrice = getActualPrice( receipt, diff --git a/src/modes/router.js b/src/modes/router.js index ab501c59..5c605e4c 100644 --- a/src/modes/router.js +++ b/src/modes/router.js @@ -33,7 +33,7 @@ const routerClear = async( ) throw "invalid gas coverage percentage, must be an integer greater than equal 0"; const lps = processLps(config.lps, config.chainId); - const dataFetcher = getDataFetcher(config, lps, !!config.usePublicRpc); + const dataFetcher = getDataFetcher(config, lps, !!config.usePublicRpcs); const signer = config.signer; const arbAddress = config.arbAddress; const orderbookAddress = config.orderbookAddress; @@ -256,7 +256,9 @@ const routerClear = async( fromToken, toToken, arb.address, - config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, // permits // "0.005" ); @@ -297,8 +299,12 @@ const routerClear = async( const exchangeData = ethers.utils.defaultAbiCoder.encode( ["address", "address", "bytes"], [ - config.routeProcessor3Address, - config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, + config.rp32 + ? config.routeProcessor3_2Address + : config.routeProcessor3Address, fnData ] ); @@ -334,7 +340,7 @@ const routerClear = async( }; console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); let gasLimit = await signer.estimateGas(rawtx); - gasLimit = gasLimit.mul("112").div("100"); + gasLimit = gasLimit.mul("105").div("100"); rawtx.gasLimit = gasLimit; const gasCost = gasLimit.mul(gasPrice); const gasCostInToken = ethers.utils.parseUnits( @@ -348,7 +354,7 @@ const routerClear = async( ); if (gasCoveragePercentage !== "0") { const headroom = ( - Number(gasCoveragePercentage) * 1.15 + Number(gasCoveragePercentage) * 1.05 ).toFixed(); rawtx.data = arb.interface.encodeFunctionData( "arb", @@ -382,14 +388,23 @@ const routerClear = async( ] ); console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - const tx = flashbotSigner !== undefined - ? await flashbotSigner.sendTransaction(rawtx) - : await signer.sendTransaction(rawtx); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); console.log( ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", "\n" ); + console.log(tx); const receipt = config.timeout ? await promiseTimeout( tx.wait(), @@ -397,6 +412,7 @@ const routerClear = async( `Transaction failed to mine after ${config.timeout}ms` ) : await tx.wait(); + const income = getIncome(signer, receipt); const clearActualPrice = getActualPrice( receipt, diff --git a/src/modes/srouter.js b/src/modes/srouter.js index 51f7f791..1031a326 100644 --- a/src/modes/srouter.js +++ b/src/modes/srouter.js @@ -34,7 +34,7 @@ const srouterClear = async( ) throw "invalid gas coverage percentage, must be an integer greater than equal 0"; const lps = processLps(config.lps, config.chainId); - const dataFetcher = getDataFetcher(config, lps, !!config.usePublicRpc); + const dataFetcher = getDataFetcher(config, lps, !!config.usePublicRpcs); const signer = config.signer; const arbAddress = config.arbAddress; const orderbookAddress = config.orderbookAddress; @@ -122,7 +122,6 @@ const srouterClear = async( data: "0x70a08231000000000000000000000000" + orderbookAddress.slice(2), to: bundledOrders[i].sellToken })); - // const quoteChunks = obSellTokenBalance.div("5"); if (obSellTokenBalance.isZero()) throw `Orderbook has no ${ bundledOrders[i].sellTokenSymbol @@ -144,290 +143,200 @@ const srouterClear = async( catch { throw "could not get ETH price, skipping..."; } - let maximumInput = obSellTokenBalance; - let succesOrFailure = true; - for (let j = 1; j < hops + 1; j++) { - // const maximumInput = j === 5 ? obSellTokenBalance : quoteChunks.mul(j); - const maximumInputFixed = maximumInput.mul( - "1" + "0".repeat(18 - bundledOrders[i].sellTokenDecimals) - ); - console.log(`>>> Trying to arb with ${ - ethers.utils.formatEther(maximumInputFixed) - } ${ - bundledOrders[i].sellTokenSymbol - } as maximum input`); - console.log(">>> Getting best route", "\n"); - - // await fetchPoolsForTokenWrapper(dataFetcher, fromToken, toToken); - await dataFetcher.fetchPoolsForToken(fromToken, toToken); - const pcMap = dataFetcher.getCurrentPoolCodeMap( - fromToken, - toToken - ); - const route = Router.findBestRoute( - pcMap, - config.chainId, - fromToken, - maximumInput, - toToken, - gasPrice.toNumber(), - // 30e9, - // providers, - // poolFilter - ); - if (route.status == "NoWay") { - succesOrFailure = false; - console.log( - "\x1b[31m%s\x1b[0m", - `could not find any route for this token pair for ${ - ethers.utils.formatEther(maximumInputFixed) - } ${ - bundledOrders[i].sellTokenSymbol - }, trying with a lower amount...` - ); + await dataFetcher.fetchPoolsForToken(fromToken, toToken); + + let rawtx, gasCostInToken, takeOrdersConfigStruct, price; + if (config.bundle) { + try { + ({ rawtx, gasCostInToken, takeOrdersConfigStruct, price } = await checkArb( + 0, + hops, + bundledOrders[i], + dataFetcher, + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, + )); + } catch { + rawtx = undefined; } - else { - const rateFixed = route.amountOutBN.mul( - "1" + "0".repeat(18 - bundledOrders[i].buyTokenDecimals) + } else { + const promises = []; + for (let j = 1; j < 4; j++) { + promises.push( + checkArb( + j, + hops, + bundledOrders[i], + dataFetcher, + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, + ) ); - const price = rateFixed.mul("1" + "0".repeat(18)).div(maximumInputFixed); + } + const allPromises = await Promise.allSettled(promises); - // filter out orders that are not price match or failed eval when --max-profit is enabled - // price check is at +2% as a headroom for current block vs tx block - if (maxProfit) bundledOrders[i].takeOrders = bundledOrders[i].takeOrders.filter( - v => v.ratio !== undefined ? price.mul("102").div("100").gte(v.ratio) : false + let choice; + for (let j = 0; j < allPromises.length; j++) { + if (allPromises[j].status === "fulfilled") { + if (!choice || choice.maximumInput.lt(allPromises[j].value.maximumInput)) { + choice = allPromises[j].value; + } + } + } + if (choice) { + ({ rawtx, gasCostInToken, takeOrdersConfigStruct, price } = choice); + } + } + + if (!rawtx) { + console.log("\x1b[31m%s\x1b[0m", "found no match for this pair..."); + } + else { + try { + console.log(">>> Trying to submit the transaction...", "\n"); + rawtx.data = arb.interface.encodeFunctionData( + "arb", + [ + takeOrdersConfigStruct, + gasCostInToken.mul(gasCoveragePercentage).div("100") + ] ); + console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); + console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); console.log( - "Current best route price for this token pair:", - `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`, + ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", "\n" ); - console.log(">>> Route portions: ", "\n"); - visualizeRoute(fromToken, toToken, route.legs).forEach( - v => console.log("\x1b[36m%s\x1b[0m", v) - ); - console.log(""); - - const rpParams = Router.routeProcessor2Params( - pcMap, - route, - fromToken, - toToken, - arb.address, - config.routeProcessor3Address, - // permits - // "0.005" - ); - const takeOrdersConfigStruct = { - minimumInput: ethers.constants.One, - maximumInput, - maximumIORatio: maxRatio ? ethers.constants.MaxUint256 : price, - orders: bundledOrders[i].takeOrders.map(v => v.takeOrder), - data: ethers.utils.defaultAbiCoder.encode( - ["bytes"], - [rpParams.routeCode] + console.log(tx); + const receipt = config.timeout + ? await promiseTimeout( + tx.wait(), + config.timeout, + `Transaction failed to mine after ${config.timeout}ms` ) - }; + : await tx.wait(); - // building and submit the transaction - try { - const rawtx = { - data: arb.interface.encodeFunctionData("arb", [takeOrdersConfigStruct, "0"]), - to: arb.address, - gasPrice - }; - console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - let gasLimit; - try { - gasLimit = await signer.estimateGas(rawtx); - } - catch { - throw "nomatch"; - } - gasLimit = gasLimit.mul("112").div("100"); - rawtx.gasLimit = gasLimit; - const gasCost = gasLimit.mul(gasPrice); - const gasCostInToken = ethers.utils.parseUnits( + if (receipt.status === 1) { + const clearActualAmount = getActualClearAmount( + arbAddress, + orderbookAddress, + receipt + ); + const income = getIncome(signer, receipt); + const clearActualPrice = getActualPrice( + receipt, + orderbookAddress, + arbAddress, + clearActualAmount.mul("1" + "0".repeat( + 18 - bundledOrders[i].sellTokenDecimals + )), + bundledOrders[i].buyTokenDecimals + ); + const actualGasCost = ethers.BigNumber.from( + receipt.effectiveGasPrice + ).mul(receipt.gasUsed); + const actualGasCostInToken = ethers.utils.parseUnits( ethPrice ).mul( - gasCost + actualGasCost ).div( "1" + "0".repeat( 36 - bundledOrders[i].buyTokenDecimals ) ); - if (gasCoveragePercentage !== "0") { - const headroom = ( - Number(gasCoveragePercentage) * 1.2 - ).toFixed(); - rawtx.data = arb.interface.encodeFunctionData( - "arb", - [ - takeOrdersConfigStruct, - gasCostInToken.mul(headroom).div("100") - ] - ); - try { - await signer.estimateGas(rawtx); - } - catch { - throw "dryrun"; - } - } - succesOrFailure = true; - if (j == 1 || j == hops) { - // submit the tx only if dry runs with headroom is passed - try { - console.log(">>> Trying to submit the transaction...", "\n"); - rawtx.data = arb.interface.encodeFunctionData( - "arb", - [ - takeOrdersConfigStruct, - gasCostInToken.mul(gasCoveragePercentage).div("100") - ] - ); - console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - const tx = flashbotSigner !== undefined - ? await flashbotSigner.sendTransaction(rawtx) - : await signer.sendTransaction(rawtx); - - console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); - console.log( - ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", - "\n" - ); - const receipt = config.timeout - ? await promiseTimeout( - tx.wait(), - config.timeout, - `Transaction failed to mine after ${config.timeout}ms` - ) - : await tx.wait(); - if (receipt.status === 1) { - const clearActualAmount = getActualClearAmount( - arbAddress, - orderbookAddress, - receipt - ); - const income = getIncome(signer, receipt); - const clearActualPrice = getActualPrice( - receipt, - orderbookAddress, - arbAddress, - clearActualAmount.mul("1" + "0".repeat( - 18 - bundledOrders[i].sellTokenDecimals - )), - bundledOrders[i].buyTokenDecimals - ); - const actualGasCost = ethers.BigNumber.from( - receipt.effectiveGasPrice - ).mul(receipt.gasUsed); - const actualGasCostInToken = ethers.utils.parseUnits( - ethPrice - ).mul( - actualGasCost - ).div( - "1" + "0".repeat( - 36 - bundledOrders[i].buyTokenDecimals - ) - ); - const netProfit = income - ? income.sub(actualGasCostInToken) - : undefined; - - console.log( - "\x1b[36m%s\x1b[0m", - `Clear Initial Price: ${ethers.utils.formatEther(price)}` - ); - console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`); - console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${ - ethers.utils.formatUnits( - clearActualAmount, - bundledOrders[i].sellTokenDecimals - ) - } ${bundledOrders[i].sellTokenSymbol}`); - console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${ - ethers.utils.formatEther(actualGasCost) - } ${ - config.nativeToken.symbol - }`, "\n"); - if (income) { - console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits( - income, - bundledOrders[i].buyTokenDecimals - )} ${bundledOrders[i].buyTokenSymbol}`); - console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits( - netProfit, - bundledOrders[i].buyTokenDecimals - )} ${bundledOrders[i].buyTokenSymbol}`, "\n"); - } - - report.push({ - transactionHash: receipt.transactionHash, - tokenPair: - bundledOrders[i].buyTokenSymbol + - "/" + - bundledOrders[i].sellTokenSymbol, - buyToken: bundledOrders[i].buyToken, - buyTokenDecimals: bundledOrders[i].buyTokenDecimals, - sellToken: bundledOrders[i].sellToken, - sellTokenDecimals: bundledOrders[i].sellTokenDecimals, - clearedAmount: clearActualAmount.toString(), - clearPrice: ethers.utils.formatEther(price), - clearActualPrice, - gasUsed: receipt.gasUsed, - gasCost: actualGasCost, - income, - netProfit, - clearedOrders: bundledOrders[i].takeOrders.map( - v => v.id - ), - }); - j = hops + 1; - } - else { - succesOrFailure = false; - if (j < hops) console.log( - `could not clear with ${ethers.utils.formatEther( - maximumInputFixed - )} ${ - bundledOrders[i].sellTokenSymbol - } as max input, trying with lower amount...` - ); - else console.log("could not arb this pair"); - } - } - catch (error) { - console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:"); - console.log(error, "\n"); - throw "failed-exec"; - } + const netProfit = income + ? income.sub(actualGasCostInToken) + : undefined; + + console.log( + "\x1b[36m%s\x1b[0m", + `Clear Initial Price: ${ethers.utils.formatEther(price)}` + ); + console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`); + console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${ + ethers.utils.formatUnits( + clearActualAmount, + bundledOrders[i].sellTokenDecimals + ) + } ${bundledOrders[i].sellTokenSymbol}`); + console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${ + ethers.utils.formatEther(actualGasCost) + } ${ + config.nativeToken.symbol + }`, "\n"); + if (income) { + console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits( + income, + bundledOrders[i].buyTokenDecimals + )} ${bundledOrders[i].buyTokenSymbol}`); + console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits( + netProfit, + bundledOrders[i].buyTokenDecimals + )} ${bundledOrders[i].buyTokenSymbol}`, "\n"); } + + report.push({ + transactionHash: receipt.transactionHash, + tokenPair: + bundledOrders[i].buyTokenSymbol + + "/" + + bundledOrders[i].sellTokenSymbol, + buyToken: bundledOrders[i].buyToken, + buyTokenDecimals: bundledOrders[i].buyTokenDecimals, + sellToken: bundledOrders[i].sellToken, + sellTokenDecimals: bundledOrders[i].sellTokenDecimals, + clearedAmount: clearActualAmount.toString(), + clearPrice: ethers.utils.formatEther(price), + clearActualPrice, + gasUsed: receipt.gasUsed, + gasCost: actualGasCost, + income, + netProfit, + clearedOrders: takeOrdersConfigStruct.orders.map( + v => v.id + ), + }); } - catch (error) { - succesOrFailure = false; - if (error !== "nomatch" && error !== "dryrun" && error !== "failed-exec") { - console.log("\x1b[31m%s\x1b[0m", ">>> Transaction failed due to:"); - console.log(error, "\n"); - // reason, code, method, transaction, error, stack, message - } - if (error === "failed-exec") throw "Transaction execution failed, skipping this pair..."; - if (j < hops) console.log( - "\x1b[34m%s\x1b[0m", - `could not clear with ${ethers.utils.formatEther( - maximumInputFixed - )} ${ - bundledOrders[i].sellTokenSymbol - } as max input, trying with lower amount...`, "\n" - ); - else console.log("\x1b[34m%s\x1b[0m", "could not arb this pair", "\n"); + else { + console.log("could not arb this pair, tx receipt: "); + console.log(receipt); } } - maximumInput = succesOrFailure - ? maximumInput.add(obSellTokenBalance.div(2 ** j)) - : maximumInput.sub(obSellTokenBalance.div(2 ** j)); + catch (error) { + console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:"); + console.log(error, "\n"); + } } } catch (error) { @@ -441,6 +350,212 @@ const srouterClear = async( return report; }; +async function checkArb( + mode, + hops, + bundledOrder, + dataFetcher, + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, +) { + let succesOrFailure = true; + let maximumInput = obSellTokenBalance; + const modeText = mode === 0 + ? "bundled orders" + : mode === 1 + ? "single order" + : mode === 2 + ? "double orders" + : "triple orders"; + for (let j = 1; j < hops + 1; j++) { + const maximumInputFixed = maximumInput.mul( + "1" + "0".repeat(18 - bundledOrder.sellTokenDecimals) + ); + + console.log(`>>> Trying to arb ${modeText} with ${ + ethers.utils.formatEther(maximumInputFixed) + } ${ + bundledOrder.sellTokenSymbol + } as maximum input`); + console.log(`>>> Getting best route ${modeText}`, "\n"); + + const pcMap = dataFetcher.getCurrentPoolCodeMap( + fromToken, + toToken + ); + const route = Router.findBestRoute( + pcMap, + config.chainId, + fromToken, + maximumInput, + toToken, + gasPrice.toNumber(), + // 30e9, + // providers, + // poolFilter + ); + if (route.status == "NoWay") { + succesOrFailure = false; + console.log( + "\x1b[31m%s\x1b[0m", + `could not find any route for ${modeText} for this token pair for ${ + ethers.utils.formatEther(maximumInputFixed) + } ${ + bundledOrder.sellTokenSymbol + }, trying with a lower amount...` + ); + } + else { + const rateFixed = route.amountOutBN.mul( + "1" + "0".repeat(18 - bundledOrder.buyTokenDecimals) + ); + const price = rateFixed.mul("1" + "0".repeat(18)).div(maximumInputFixed); + + // filter out orders that are not price match or failed eval when --max-profit is enabled + // price check is at +2% as a headroom for current block vs tx block + if (!mode && maxProfit) bundledOrder.takeOrders = bundledOrder.takeOrders.filter( + v => v.ratio !== undefined ? price.mul("102").div("100").gte(v.ratio) : false + ); + + if (bundledOrder.takeOrders.length === 0) { + maximumInput = maximumInput.sub(obSellTokenBalance.div(2 ** j)); + continue; + } + + console.log( + `Current best route price for ${modeText} for this token pair:`, + `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`, + "\n" + ); + console.log(`>>> Route portions for ${modeText}: `, "\n"); + visualizeRoute(fromToken, toToken, route.legs).forEach( + v => console.log("\x1b[36m%s\x1b[0m", v) + ); + console.log(""); + + const rpParams = Router.routeProcessor2Params( + pcMap, + route, + fromToken, + toToken, + arb.address, + config.rp32 ? config.routeProcessor3_2Address : config.routeProcessor3Address, + // permits + // "0.005" + ); + + const orders = mode === 0 + ? bundledOrder.takeOrders.map(v => v.takeOrder) + : mode === 1 + ? [bundledOrder.takeOrders[0].takeOrder] + : mode === 2 + ? [ + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder + ] + : [ + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder + ]; + + const takeOrdersConfigStruct = { + minimumInput: ethers.constants.One, + maximumInput, + maximumIORatio: maxRatio ? ethers.constants.MaxUint256 : price, + orders, + data: ethers.utils.defaultAbiCoder.encode( + ["bytes"], + [rpParams.routeCode] + ) + }; + + // building and submit the transaction + try { + const rawtx = { + data: arb.interface.encodeFunctionData("arb", [takeOrdersConfigStruct, "0"]), + to: arb.address, + gasPrice + }; + console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); + let gasLimit; + try { + gasLimit = await signer.estimateGas(rawtx); + } + catch { + throw "nomatch"; + } + gasLimit = gasLimit.mul("103").div("100"); + rawtx.gasLimit = gasLimit; + const gasCost = gasLimit.mul(gasPrice); + const gasCostInToken = ethers.utils.parseUnits( + ethPrice + ).mul( + gasCost + ).div( + "1" + "0".repeat( + 36 - bundledOrder.buyTokenDecimals + ) + ); + if (gasCoveragePercentage !== "0") { + const headroom = ( + Number(gasCoveragePercentage) * 1.05 + ).toFixed(); + rawtx.data = arb.interface.encodeFunctionData( + "arb", + [ + takeOrdersConfigStruct, + gasCostInToken.mul(headroom).div("100") + ] + ); + try { + await signer.estimateGas(rawtx); + } + catch { + throw "dryrun"; + } + } + succesOrFailure = true; + if (j == 1 || j == hops) { + return {rawtx, maximumInput, gasCostInToken, takeOrdersConfigStruct, price}; + } + } + catch (error) { + succesOrFailure = false; + if (error !== "nomatch" && error !== "dryrun") { + console.log("\x1b[31m%s\x1b[0m", `>>> Transaction for ${modeText} failed due to:`); + console.log(error, "\n"); + // reason, code, method, transaction, error, stack, message + } + if (j < hops) console.log( + "\x1b[34m%s\x1b[0m", + `could not clear ${modeText} with ${ethers.utils.formatEther( + maximumInputFixed + )} ${ + bundledOrder.sellTokenSymbol + } as max input, trying with lower amount...`, "\n" + ); + else { + console.log("\x1b[34m%s\x1b[0m", `could not arb this pair for ${modeText}`, "\n"); + } + } + } + maximumInput = succesOrFailure + ? maximumInput.add(obSellTokenBalance.div(2 ** j)) + : maximumInput.sub(obSellTokenBalance.div(2 ** j)); + } + return Promise.reject(); +} + module.exports = { srouterClear }; diff --git a/src/modes/suniv2.js b/src/modes/suniv2.js new file mode 100644 index 00000000..c9b5efaa --- /dev/null +++ b/src/modes/suniv2.js @@ -0,0 +1,541 @@ +const ethers = require("ethers"); +const { arbAbis, orderbookAbi } = require("../abis"); +const { Token } = require("sushiswap-router"); +const { + getIncome, + getActualPrice, + promiseTimeout, + bundleTakeOrders, + getActualClearAmount, + getAmountOutFlareSwap, + getUniV2Route +} = require("../utils"); + +/** + * Main function that gets order details from subgraph, bundles the ones that have balance and tries clearing them with specialized router contract specifically for flare mainnet + * + * @param {object} config - The configuration object + * @param {any[]} ordersDetails - The order details queried from subgraph + * @param {string} gasCoveragePercentage - (optional) The percentage of the gas cost to cover on each transaction + * for it to be considered profitable and get submitted + * @returns The report of details of cleared orders + */ +const suniv2Clear = async( + config, + ordersDetails, + gasCoveragePercentage = "100" +) => { + + if (!config.uniV2Router02Address) throw "no univ2Router contract address is specified for this network"; + if ( + gasCoveragePercentage < 0 || + !Number.isInteger(Number(gasCoveragePercentage)) + ) throw "invalid gas coverage percentage, must be an integer greater than equal 0"; + + const signer = config.signer; + const arbAddress = config.arbAddress; + const orderbookAddress = config.orderbookAddress; + const maxProfit = config.maxProfit; + const maxRatio = config.maxRatio; + const hops = config.hops; + const flashbotSigner = config.flashbotRpc + ? new ethers.Wallet( + signer.privateKey, + new ethers.providers.JsonRpcProvider(config.flashbotRpc) + ) + : undefined; + + // instantiating arb contract + const arb = new ethers.Contract(arbAddress, arbAbis["srouter"], signer); + + // instantiating orderbook contract + const orderbook = new ethers.Contract(orderbookAddress, orderbookAbi, signer); + + console.log( + "------------------------- Starting The", + "\x1b[32mS-ROUTER\x1b[0m", + "Mode -------------------------", + "\n" + ); + console.log("\x1b[33m%s\x1b[0m", Date()); + console.log("Arb Contract Address: " , arbAddress); + console.log("OrderBook Contract Address: " , orderbookAddress, "\n"); + + let bundledOrders = []; + + if (ordersDetails.length) { + console.log( + "------------------------- Bundling Orders -------------------------", "\n" + ); + bundledOrders = await bundleTakeOrders( + ordersDetails, + orderbook, + arb, + maxProfit, + config.rpc !== "test", + config.interpreterv2, + config.bundle + ); + } + else { + console.log("No orders found, exiting...", "\n"); + return; + } + + if (!bundledOrders.length) { + console.log("Could not find any order to clear for current market price, exiting...", "\n"); + return; + } + + const report = []; + for (let i = 0; i < bundledOrders.length; i++) { + try { + console.log( + `------------------------- Trying To Clear ${ + bundledOrders[i].buyTokenSymbol + }/${ + bundledOrders[i].sellTokenSymbol + } -------------------------`, + "\n" + ); + console.log(`Buy Token Address: ${bundledOrders[i].buyToken}`); + console.log(`Sell Token Address: ${bundledOrders[i].sellToken}`, "\n"); + + if (!bundledOrders[i].takeOrders.length) throw "All orders of this token pair have empty vault balance, skipping..."; + + const fromToken = new Token({ + chainId: config.chainId, + decimals: bundledOrders[i].sellTokenDecimals, + address: bundledOrders[i].sellToken, + symbol: bundledOrders[i].sellTokenSymbol + }); + const toToken = new Token({ + chainId: config.chainId, + decimals: bundledOrders[i].buyTokenDecimals, + address: bundledOrders[i].buyToken, + symbol: bundledOrders[i].buyTokenSymbol + }); + + const obSellTokenBalance = ethers.BigNumber.from(await signer.call({ + data: "0x70a08231000000000000000000000000" + orderbookAddress.slice(2), + to: bundledOrders[i].sellToken + })); + + if (obSellTokenBalance.isZero()) throw `Orderbook has no ${ + bundledOrders[i].sellTokenSymbol + } balance, skipping...`; + + let ethPrice; + const gasPrice = await signer.provider.getGasPrice(); + try { + if (gasCoveragePercentage !== "0") ethPrice = await getAmountOutFlareSwap( + signer, + config.uniV2Router02Address, + config.nativeWrappedToken.address, + "1" + "0".repeat(config.nativeWrappedToken.decimals), + bundledOrders[i].buyToken, + bundledOrders[i].buyTokenDecimals + ); + else ethPrice = "0"; + if (ethPrice === undefined) throw "could not find a route for ETH price, skipping..."; + } + catch { + throw "could not get ETH price, skipping..."; + } + + let rawtx, gasCostInToken, takeOrdersConfigStruct, price; + if (config.bundle) { + try { + ({ rawtx, gasCostInToken, takeOrdersConfigStruct, price } = await checkArb( + 0, + hops, + bundledOrders[i], + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, + )); + } catch { + rawtx = undefined; + } + } else { + const promises = []; + for (let j = 1; j < 4; j++) { + promises.push( + checkArb( + j, + hops, + bundledOrders[i], + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, + ) + ); + } + const allPromises = await Promise.allSettled(promises); + + let choice; + for (let j = 0; j < allPromises.length; j++) { + if (allPromises[j].status === "fulfilled") { + if (!choice || choice.maximumInput.lt(allPromises[j].value.maximumInput)) { + choice = allPromises[j].value; + } + } + } + if (choice) { + ({ rawtx, gasCostInToken, takeOrdersConfigStruct, price } = choice); + } + } + + if (!rawtx) { + console.log("\x1b[31m%s\x1b[0m", "found no match for this pair..."); + } + else { + // submit the tx only if dry runs with headroom is passed + try { + console.log(">>> Trying to submit the transaction...", "\n"); + rawtx.data = arb.interface.encodeFunctionData( + "arb", + [ + takeOrdersConfigStruct, + gasCostInToken.mul(gasCoveragePercentage).div("100") + ] + ); + console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); + + console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); + console.log( + ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", + "\n" + ); + console.log(tx); + const receipt = config.timeout + ? await promiseTimeout( + tx.wait(), + config.timeout, + `Transaction failed to mine after ${config.timeout}ms` + ) + : await tx.wait(); + + if (receipt.status === 1) { + const clearActualAmount = getActualClearAmount( + arbAddress, + orderbookAddress, + receipt + ); + const income = getIncome(signer, receipt); + const clearActualPrice = getActualPrice( + receipt, + orderbookAddress, + arbAddress, + clearActualAmount.mul("1" + "0".repeat( + 18 - bundledOrders[i].sellTokenDecimals + )), + bundledOrders[i].buyTokenDecimals + ); + const actualGasCost = ethers.BigNumber.from( + receipt.effectiveGasPrice + ).mul(receipt.gasUsed); + const actualGasCostInToken = ethers.utils.parseUnits( + ethPrice + ).mul( + actualGasCost + ).div( + "1" + "0".repeat( + 36 - bundledOrders[i].buyTokenDecimals + ) + ); + const netProfit = income + ? income.sub(actualGasCostInToken) + : undefined; + + console.log( + "\x1b[36m%s\x1b[0m", + `Clear Initial Price: ${ethers.utils.formatEther(price)}` + ); + console.log("\x1b[36m%s\x1b[0m", `Clear Actual Price: ${clearActualPrice}`); + console.log("\x1b[36m%s\x1b[0m", `Clear Amount: ${ + ethers.utils.formatUnits( + clearActualAmount, + bundledOrders[i].sellTokenDecimals + ) + } ${bundledOrders[i].sellTokenSymbol}`); + console.log("\x1b[36m%s\x1b[0m", `Consumed Gas: ${ + ethers.utils.formatEther(actualGasCost) + } ${ + config.nativeToken.symbol + }`, "\n"); + if (income) { + console.log("\x1b[35m%s\x1b[0m", `Gross Income: ${ethers.utils.formatUnits( + income, + bundledOrders[i].buyTokenDecimals + )} ${bundledOrders[i].buyTokenSymbol}`); + console.log("\x1b[35m%s\x1b[0m", `Net Profit: ${ethers.utils.formatUnits( + netProfit, + bundledOrders[i].buyTokenDecimals + )} ${bundledOrders[i].buyTokenSymbol}`, "\n"); + } + + report.push({ + transactionHash: receipt.transactionHash, + tokenPair: + bundledOrders[i].buyTokenSymbol + + "/" + + bundledOrders[i].sellTokenSymbol, + buyToken: bundledOrders[i].buyToken, + buyTokenDecimals: bundledOrders[i].buyTokenDecimals, + sellToken: bundledOrders[i].sellToken, + sellTokenDecimals: bundledOrders[i].sellTokenDecimals, + clearedAmount: clearActualAmount.toString(), + clearPrice: ethers.utils.formatEther(price), + clearActualPrice, + gasUsed: receipt.gasUsed, + gasCost: actualGasCost, + income, + netProfit, + clearedOrders: takeOrdersConfigStruct.orders.map( + v => v.id + ), + }); + } + else { + console.log("could not arb this pair, tx receipt: "); + console.log(receipt); + } + } + catch (error) { + console.log("\x1b[31m%s\x1b[0m", ">>> Transaction execution failed due to:"); + console.log(error, "\n"); + } + } + } + catch (error) { + if (typeof error === "string") console.log("\x1b[31m%s\x1b[0m", error, "\n"); + else { + console.log("\x1b[31m%s\x1b[0m", ">>> Something went wrong, reason:", "\n"); + console.log(error); + } + } + } + return report; +}; + +async function checkArb( + mode, + hops, + bundledOrder, + fromToken, + toToken, + signer, + obSellTokenBalance, + gasPrice, + gasCoveragePercentage, + maxProfit, + maxRatio, + arb, + ethPrice, + config, +) { + let succesOrFailure = true; + let maximumInput = obSellTokenBalance; + const modeText = mode === 0 + ? "bundled orders" + : mode === 1 + ? "single order" + : mode === 2 + ? "double orders" + : "triple orders"; + for (let j = 1; j < hops + 1; j++) { + const maximumInputFixed = maximumInput.mul( + "1" + "0".repeat(18 - bundledOrder.sellTokenDecimals) + ); + + console.log(`>>> Trying to arb ${modeText} with ${ + ethers.utils.formatEther(maximumInputFixed) + } ${ + bundledOrder.sellTokenSymbol + } as maximum input`); + console.log(`>>> Getting best route ${modeText}`, "\n"); + + const amountOut = await getAmountOutFlareSwap( + signer, + config.uniV2Router02Address, + fromToken.address, + "1" + "0".repeat(config.nativeWrappedToken.decimals), + toToken.address, + toToken.decimals + ); + if (amountOut === undefined) { + succesOrFailure = false; + console.log( + "\x1b[31m%s\x1b[0m", + `could not find any route for ${modeText} for this token pair for ${ + ethers.utils.formatEther(maximumInputFixed) + } ${ + bundledOrder.sellTokenSymbol + }, trying with a lower amount...` + ); + } + else { + const amountOutBN = ethers.utils.parseUnits(amountOut,toToken.decimals); + const rateFixed = amountOutBN.mul( + "1" + "0".repeat(18 - bundledOrder.buyTokenDecimals) + ); + const price = rateFixed.mul("1" + "0".repeat(18)).div(maximumInputFixed); + + // filter out orders that are not price match or failed eval when --max-profit is enabled + // price check is at +2% as a headroom for current block vs tx block + if (!mode && maxProfit) bundledOrder.takeOrders = bundledOrder.takeOrders.filter( + v => v.ratio !== undefined ? price.mul("102").div("100").gte(v.ratio) : false + ); + + if (bundledOrder.takeOrders.length === 0) { + maximumInput = maximumInput.sub(obSellTokenBalance.div(2 ** j)); + continue; + } + + console.log( + `Current best route price for ${modeText} for this token pair:`, + `\x1b[33m${ethers.utils.formatEther(price)}\x1b[0m`, + "\n" + ); + console.log(""); + + const routeCode = getUniV2Route( + config, + fromToken.address, + toToken.address, + arb.address + ); + const orders = mode === 0 + ? bundledOrder.takeOrders.map(v => v.takeOrder) + : mode === 1 + ? [bundledOrder.takeOrders[0].takeOrder] + : mode === 2 + ? [ + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder + ] + : [ + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder, + bundledOrder.takeOrders[0].takeOrder + ]; + + const takeOrdersConfigStruct = { + minimumInput: ethers.constants.One, + maximumInput, + maximumIORatio: maxRatio ? ethers.constants.MaxUint256 : price, + orders, + data: ethers.utils.defaultAbiCoder.encode( + ["bytes"], + [routeCode] + ) + }; + + // building and submit the transaction + try { + const rawtx = { + data: arb.interface.encodeFunctionData("arb", [takeOrdersConfigStruct, "0"]), + to: arb.address, + gasPrice + }; + console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); + let gasLimit; + try { + gasLimit = await signer.estimateGas(rawtx); + } + catch { + throw "nomatch"; + } + gasLimit = gasLimit.mul("103").div("100"); + rawtx.gasLimit = gasLimit; + const gasCost = gasLimit.mul(gasPrice); + const gasCostInToken = ethers.utils.parseUnits( + ethPrice + ).mul( + gasCost + ).div( + "1" + "0".repeat( + 36 - bundledOrder.buyTokenDecimals + ) + ); + if (gasCoveragePercentage !== "0") { + const headroom = ( + Number(gasCoveragePercentage) * 1.05 + ).toFixed(); + rawtx.data = arb.interface.encodeFunctionData( + "arb", + [ + takeOrdersConfigStruct, + gasCostInToken.mul(headroom).div("100") + ] + ); + try { + await signer.estimateGas(rawtx); + } + catch { + throw "dryrun"; + } + } + succesOrFailure = true; + if (j == 1 || j == hops) { + return {rawtx, maximumInput, gasCostInToken, takeOrdersConfigStruct, price}; + } + } + catch (error) { + succesOrFailure = false; + if (error !== "nomatch" && error !== "dryrun") { + console.log("\x1b[31m%s\x1b[0m", `>>> Transaction for ${modeText} failed due to:`); + console.log(error, "\n"); + // reason, code, method, transaction, error, stack, message + } + if (j < hops) console.log( + "\x1b[34m%s\x1b[0m", + `could not clear ${modeText} with ${ethers.utils.formatEther( + maximumInputFixed + )} ${ + bundledOrder.sellTokenSymbol + } as max input, trying with lower amount...`, "\n" + ); + else { + console.log("\x1b[34m%s\x1b[0m", `could not arb this pair for ${modeText}`, "\n"); + } + } + } + maximumInput = succesOrFailure + ? maximumInput.add(obSellTokenBalance.div(2 ** j)) + : maximumInput.sub(obSellTokenBalance.div(2 ** j)); + } + return Promise.reject(); +} + +module.exports = { + suniv2Clear +}; \ No newline at end of file diff --git a/src/modes/zeroex.js b/src/modes/zeroex.js index e3f93a2a..d69269d1 100644 --- a/src/modes/zeroex.js +++ b/src/modes/zeroex.js @@ -366,15 +366,24 @@ const zeroExClear = async( ] ); console.log("Block Number: " + await signer.provider.getBlockNumber(), "\n"); - const tx = flashbotSigner !== undefined - ? await flashbotSigner.sendTransaction(rawtx) - : await signer.sendTransaction(rawtx); + const tx = config.timeout + ? await promiseTimeout( + (flashbotSigner !== undefined + ? flashbotSigner.sendTransaction(rawtx) + : signer.sendTransaction(rawtx)), + config.timeout, + `Transaction failed to get submitted after ${config.timeout}ms` + ) + : flashbotSigner !== undefined + ? await flashbotSigner.sendTransaction(rawtx) + : await signer.sendTransaction(rawtx); console.log("\x1b[33m%s\x1b[0m", config.explorer + "tx/" + tx.hash, "\n"); console.log( ">>> Transaction submitted successfully to the network, waiting for transaction to mine...", "\n" ); + console.log(tx); const receipt = config.timeout ? await promiseTimeout( tx.wait(), @@ -382,6 +391,7 @@ const zeroExClear = async( `Transaction failed to mine after ${config.timeout}ms` ) : await tx.wait(); + const income = getIncome(signer, receipt); const clearActualPrice = getActualPrice( receipt, diff --git a/src/utils.js b/src/utils.js index 7e5aabb5..f5479c28 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,6 @@ const { ethers, BigNumber } = require("ethers"); const { createPublicClient, http, fallback } = require("viem"); -const { erc20Abi, interpreterAbi, interpreterV2Abi } = require("./abis"); +const { erc20Abi, interpreterAbi, interpreterV2Abi, uniswapV2Route02Abi } = require("./abis"); const { DataFetcher, Router, LiquidityProviders, ChainId, Token, viemConfig } = require("sushiswap-router"); @@ -962,7 +962,7 @@ const getEthPrice = async( dataFetcher = undefined ) => { if(targetTokenAddress.toLowerCase() == config.nativeWrappedToken.address.toLowerCase()){ - return "1" + "0".repeat(config.nativeWrappedToken.decimals); + return "1"; } const amountIn = BigNumber.from( "1" + "0".repeat(config.nativeWrappedToken.decimals) @@ -1223,7 +1223,7 @@ const getOrderDetailsFromJson = async(jsonContent, signer) => { * @param {...any} data - The optinnal data to hide */ const appGlobalLogger = (scrub, ...data) => { - const largeDataPattern = /0x[a-fA-F0-9]{128,}/g; + // const largeDataPattern = /0x[a-fA-F0-9]{128,}/g; const consoleMethods = ["log", "warn", "error", "info", "debug"]; // Stringifies an object @@ -1284,7 +1284,7 @@ const appGlobalLogger = (scrub, ...data) => { const orgConsole = console[methodName]; console[methodName] = function (...params) { const modifiedParams = []; - const shortenedLogs = []; + // const shortenedLogs = []; for (let i = 0; i < params.length; i++) { let logItem = params[i]; if ( @@ -1301,33 +1301,33 @@ const appGlobalLogger = (scrub, ...data) => { "**********" ); } - logItem = logItem.replace( - largeDataPattern, - largeData => { - if (!shortenedLogs.includes(largeData)) { - shortenedLogs.push(largeData); - return largeData; - } - else return largeData.slice(0, 67) + "..."; - } - ); + // logItem = logItem.replace( + // largeDataPattern, + // largeData => { + // if (!shortenedLogs.includes(largeData)) { + // shortenedLogs.push(largeData); + // return largeData; + // } + // else return largeData.slice(0, 67) + "..."; + // } + // ); } else if (typeof logItem === "object" && logItem !== null) { logItem = objStringify(logItem); if (scrub) for (let j = 0; j < _data.length; j++) { logItem = objStrReplacer(logItem, _data[j], "**********"); } - logItem = objStrReplacer( - logItem, - largeDataPattern, - largeData => { - if (!shortenedLogs.includes(largeData)) { - shortenedLogs.push(largeData); - return largeData; - } - else return largeData.slice(0, 67) + "..."; - } - ); + // logItem = objStrReplacer( + // logItem, + // largeDataPattern, + // largeData => { + // if (!shortenedLogs.includes(largeData)) { + // shortenedLogs.push(largeData); + // return largeData; + // } + // else return largeData.slice(0, 67) + "..."; + // } + // ); } modifiedParams.push(logItem); } @@ -1582,6 +1582,61 @@ const shuffleArray = (array) => { return array; }; +// Get UniswapV2 pool amount out for token +const getAmountOutFlareSwap = async( + signer, + uniswapV2Router, + fromToken, + amountIn, + toToken, + toTokenDecimals +) => { + const swapRouter = new ethers.Contract(uniswapV2Router, uniswapV2Route02Abi, signer); + const amountOutBN = await swapRouter.getAmountsOut(amountIn, [fromToken,toToken]); + if (amountOutBN[1]) return ethers.utils.formatUnits(amountOutBN[1], toTokenDecimals); + return undefined; +}; + +// Get UniswapV2 route for tokens. +const getUniV2Route = (config,fromTokenAddress,toTokenAddress,toAddress) => { + const pool = config.enosys.pools.filter(e => { + if( + ( + e.token0.toLowerCase() == fromTokenAddress.toLowerCase() && + e.token1.toLowerCase() == toTokenAddress.toLowerCase() + ) + || + ( + e.token0.toLowerCase() == toTokenAddress.toLowerCase() && + e.token1.toLowerCase() == fromTokenAddress.toLowerCase() + ) + ) return true; + else return false; + }); + if(pool.length == 0) throw "UniswapV2 LP pool not found"; + + return getUniV2RouteData(pool[0],fromTokenAddress,toAddress); + +}; + +const getUniV2RouteData = (uniV2Pool, fromTokenAddress, toAddress) => { + + const offeringToken = ethers.BigNumber.from(fromTokenAddress); + const token0 = ethers.BigNumber.from(uniV2Pool.token0); + const token1 = ethers.BigNumber.from(uniV2Pool.token1); + + const poolDirection = token0.lt(token1) ? + (offeringToken.eq(token0) ? "01" : "00") : + (offeringToken.eq(token1) ? "00" : "01"); + + return "0x02"+ + `${fromTokenAddress.toString().split("x")[1]}` + + "01ffff00" + + `${uniV2Pool.address.split("x")[1]}` + + `${poolDirection}` + + `${toAddress.toString().split("x")[1]}`; +}; + module.exports = { fallbacks, bnFromFloat, @@ -1608,5 +1663,8 @@ module.exports = { build0xQueries, shuffleArray, createViemClient, - interpreterV2Eval + interpreterV2Eval, + getAmountOutFlareSwap, + getUniV2Route, + getUniV2RouteData, }; \ No newline at end of file diff --git a/test/srouter.test.js b/test/srouter.test.js index dcc1a617..c99d3261 100644 --- a/test/srouter.test.js +++ b/test/srouter.test.js @@ -185,6 +185,7 @@ describe("Rain Arb Bot 'srouter' Mode Tests", async function () { config.lps = ["SushiSwapV2"]; config.interpreterv2 = false; config.hops = 5; + config.bundle = true; const reports = await clear("srouter", config, sgOrders); // should have cleared 2 toke pairs bundled orders @@ -306,6 +307,7 @@ describe("Rain Arb Bot 'srouter' Mode Tests", async function () { config.lps = ["SushiSwapV2"]; config.interpreterv2 = true; config.hops = 5; + config.bundle = true; const reports = await clear("srouter", config, sgOrders); // should have cleared 2 toke pairs bundled orders