diff --git a/.github/workflows/release-and-pypi-publish.yml b/.github/workflows/release-and-pypi-publish.yml index 0b8dd346e..14bfd7367 100644 --- a/.github/workflows/release-and-pypi-publish.yml +++ b/.github/workflows/release-and-pypi-publish.yml @@ -171,6 +171,7 @@ jobs: run: | pip install wheel python setup.py bdist_wheel + find dist -type f ! -name "*.whl" -exec rm -f {} + - name: Publish package to PyPI uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 529092709..e0a6f2122 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,57 @@ ## [Unreleased](https://github.com/bancorprotocol/fastlane-bot/tree/HEAD) -[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.3...HEAD) +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.8...HEAD) -- Cleanup of Unused Top-Level Files [\#47](https://github.com/bancorprotocol/fastlane-bot/issues/47) +- Bugfix: Remove DAI from `flashloan_tokens` [\#78](https://github.com/bancorprotocol/fastlane-bot/issues/78) +- Remove DAI from default `flashloan_tokens` to fix logging error message. [\#79](https://github.com/bancorprotocol/fastlane-bot/pull/79) ([mikewcasale](https://github.com/mikewcasale)) + +Closed issues + +- Broken Link To Github [\#64](https://github.com/bancorprotocol/fastlane-bot/issues/64) + +## [v2.7.8](https://github.com/bancorprotocol/fastlane-bot/tree/v2.7.8) (2023-08-10) + +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.7...v2.7.8) + +- Fix broken pypi automation [\#66](https://github.com/bancorprotocol/fastlane-bot/issues/66) + +Merged pull requests + +- Fix Github Link [\#65](https://github.com/bancorprotocol/fastlane-bot/pull/65) ([shmuel44](https://github.com/shmuel44)) + +## [v2.7.7](https://github.com/bancorprotocol/fastlane-bot/tree/v2.7.7) (2023-08-10) + +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.6...v2.7.7) + +- Update release-and-pypi-publish.yml [\#67](https://github.com/bancorprotocol/fastlane-bot/pull/67) ([mikewcasale](https://github.com/mikewcasale)) + +- Feature Request: Add `target_tokens` Setting to Narrow Search Space [\#62](https://github.com/bancorprotocol/fastlane-bot/issues/62) + +## [v2.7.6](https://github.com/bancorprotocol/fastlane-bot/tree/v2.7.6) (2023-08-09) + +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.5...v2.7.6) + +- Change the `--flashloan_tokens` flag type to list [\#57](https://github.com/bancorprotocol/fastlane-bot/issues/57) + +- 62 add target tokens setting to narrow search space [\#63](https://github.com/bancorprotocol/fastlane-bot/pull/63) ([mikewcasale](https://github.com/mikewcasale)) + +## [v2.7.5](https://github.com/bancorprotocol/fastlane-bot/tree/v2.7.5) (2023-08-09) + +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.4...v2.7.5) + +- Fix to ensure the @click flag for flashloan\_tokens is respected [\#58](https://github.com/bancorprotocol/fastlane-bot/pull/58) ([mikewcasale](https://github.com/mikewcasale)) Closed issues - Installation Issue with pyyaml==5.4.1 and Brownie [\#30](https://github.com/bancorprotocol/fastlane-bot/issues/30) +## [v2.7.4](https://github.com/bancorprotocol/fastlane-bot/tree/v2.7.4) (2023-08-07) + +[Full Changelog](https://github.com/bancorprotocol/fastlane-bot/compare/v2.7.3...v2.7.4) + +- Cleanup of Unused Top-Level Files [\#47](https://github.com/bancorprotocol/fastlane-bot/issues/47) + Merged pull requests - Creates a bash install script to handle the conda vs pip installation… [\#51](https://github.com/bancorprotocol/fastlane-bot/pull/51) ([mikewcasale](https://github.com/mikewcasale)) diff --git a/fastlane_bot/__init__.py b/fastlane_bot/__init__.py index a69fe3a05..5f4aac2c4 100644 --- a/fastlane_bot/__init__.py +++ b/fastlane_bot/__init__.py @@ -1,7 +1,7 @@ from .bot import CarbonBot as Bot, __VERSION__, __DATE__ from .config import Config, ConfigNetwork, ConfigDB, ConfigLogger, ConfigProvider -__version__ = '2.7.4' +__version__ = '2.7.9' diff --git a/fastlane_bot/events/interface.py b/fastlane_bot/events/interface.py index f4548a55b..15203b8b8 100644 --- a/fastlane_bot/events/interface.py +++ b/fastlane_bot/events/interface.py @@ -60,6 +60,26 @@ class QueryInterface: def cfg(self) -> Config: return self.ConfigObj + def filter_target_tokens(self, target_tokens: List[str]): + """ + Filter the pools to only include pools that are in the target pools list + + Parameters + ---------- + target_tokens: List[str] + The list of tokens to filter pools by. Pools must contain both tokens in the list to be included. + """ + initial_state = self.state.copy() + self.state = [ + pool + for pool in self.state + if pool["tkn0_key"] in target_tokens and pool["tkn1_key"] in target_tokens + ] + + self.cfg.logger.info( + f"Limiting pools by target_tokens. Removed {len(initial_state) - len(self.state)} non target-pools. {len(self.state)} pools remaining" + ) + def remove_unsupported_exchanges(self) -> None: initial_state = self.state.copy() self.state = [ @@ -479,8 +499,8 @@ def get_pool(self, **kwargs) -> Optional[PoolAndTokens]: ) pool.exchange_name except AttributeError: - if 'cid' in kwargs: - kwargs['cid'] = int(kwargs['cid']) + if "cid" in kwargs: + kwargs["cid"] = int(kwargs["cid"]) pool = next( ( pool diff --git a/main.py b/main.py index 1fc49b4af..fc7b7e48d 100644 --- a/main.py +++ b/main.py @@ -20,7 +20,11 @@ from fastlane_bot.config import Config from fastlane_bot.events.interface import QueryInterface from fastlane_bot.events.managers.manager import Manager -from fastlane_bot.events.utils import complex_handler, filter_latest_events +from fastlane_bot.events.utils import ( + complex_handler, + filter_latest_events, +) +from fastlane_bot.tools.cpc import T load_dotenv() @@ -52,7 +56,10 @@ ), ) @click.option( - "--flashloan_tokens", default=None, type=str, help="See flashloan_tokens in bot.py" + "--flashloan_tokens", + default=f"{T.WETH},{T.USDC},{T.USDT},{T.WBTC},{T.BNT},{T.NATIVE_ETH}", + type=str, + help="The --flashloan_tokens flag refers to those token denominations which the bot can take a flash loan in. By default, these are [WETH, DAI, USDC, USDT, WBTC, BNT, NATIVE_ETH]. If you override the default to TKN, the search space is decreased for all modes, including the b3_two_hop mode (assuming that --limit_bancor3_flashloan_tokens=True).", ) @click.option("--config", default=None, type=str, help="See config in config/*") @click.option("--n_jobs", default=-1, help="Number of parallel jobs to run") @@ -129,6 +136,12 @@ type=int, help="Set to the timeout in seconds. Set to None for no timeout.", ) +@click.option( + "--target_tokens", + default=None, + type=str, + help="A comma-separated string of tokens to target. Use None to target all tokens. Use `flashloan_tokens` to target only the flashloan tokens.", +) def main( cache_latest_only: bool, backdate_pools: bool, @@ -150,6 +163,7 @@ def main( limit_bancor3_flashloan_tokens: bool, default_min_profit_bnt: int, timeout: int, + target_tokens: str, ): """ The main entry point of the program. It sets up the configuration, initializes the web3 and Base objects, @@ -159,7 +173,7 @@ def main( cache_latest_only (bool): Whether to cache only the latest events or not. backdate_pools (bool): Whether to backdate pools or not. Set to False for quicker testing runs. arb_mode (str): The arbitrage mode to use. - flashloan_tokens (str): Tokens that the bot can use for flash loans. + flashloan_tokens (str): Comma seperated list of tokens that the bot can use for flash loans. config (str): The name of the configuration to use. n_jobs (int): The number of jobs to run in parallel. exchanges (str): A comma-separated string of exchanges to include. @@ -175,8 +189,11 @@ def main( limit_bancor3_flashloan_tokens (bool): Whether to limit the flashloan tokens to the ones supported by Bancor v3 or not. default_min_profit_bnt (int): The default minimum profit in BNT. timeout (int): The timeout in seconds. + target_tokens (str): A comma-separated string of tokens to target. Use None to target all tokens. Use `flashloan_tokens` to target only the flashloan tokens. """ + start_time = time.time() + # Set config loglevel = ( Config.LOGLEVEL_DEBUG @@ -203,6 +220,36 @@ def main( cfg.DEFAULT_MIN_PROFIT_BNT = Decimal(str(default_min_profit_bnt)) cfg.DEFAULT_MIN_PROFIT = Decimal(str(default_min_profit_bnt)) + # Log the flashloan tokens + flashloan_tokens = flashloan_tokens.split(",") + flashloan_tokens = [ + QueryInterface.cleanup_token_key(token) for token in flashloan_tokens + ] + cfg.logger.info( + f"Flashloan tokens are set as: {flashloan_tokens}, {type(flashloan_tokens)}" + ) + + if target_tokens: + if target_tokens == "flashloan_tokens": + target_tokens = flashloan_tokens + else: + target_tokens = target_tokens.split(",") + target_tokens = [ + QueryInterface.cleanup_token_key(token) for token in target_tokens + ] + + # Ensure that the target tokens are a subset of the flashloan tokens + for token in flashloan_tokens: + if token not in target_tokens: + cfg.logger.warning( + f"Falshloan token {token} not in target tokens. Adding it to target tokens." + ) + target_tokens.append(token) + + cfg.logger.info( + f"Target tokens are set as: {target_tokens}, {type(target_tokens)}" + ) + # Set external exchanges exchanges = exchanges.split(",") cfg.logger.info(f"Running data fetching for exchanges: {exchanges}") @@ -242,6 +289,10 @@ def main( cfg.logger.error("Error parsing the CSV file") raise + if timeout == 1: + cfg.logger.info("Timeout to test the bot flags") + return + # Initialize web3 static_pool_data["cid"] = [ cfg.w3.keccak(text=f"{row['descr']}").hex() @@ -288,6 +339,7 @@ def main( run_data_validator, randomizer, timeout, + target_tokens, ) @@ -306,6 +358,8 @@ def run( run_data_validator: bool, randomizer: int, timeout: int, + target_tokens: List[str] or None, + ) -> None: """ The main function that drives the logic of the program. It uses helper functions to handle specific tasks. @@ -325,6 +379,7 @@ def run( run_data_validator (bool): Whether to run the data validator or not. randomizer (bool): Whether to randomize the polling interval or not. timeout (int): The timeout for the polling interval. + target_tokens (List[str]): List of tokens that the bot will target for arbitrage. """ def get_event_filters( @@ -686,6 +741,10 @@ def update_pools_from_contracts( bot.db.remove_zero_liquidity_pools() bot.db.remove_unsupported_exchanges() + # Filter the target tokens + if target_tokens: + bot.db.filter_target_tokens(target_tokens) + # Run the bot bot.run( polling_interval=polling_interval, diff --git a/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.ipynb b/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.ipynb new file mode 100644 index 000000000..420bfc292 --- /dev/null +++ b/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.ipynb @@ -0,0 +1,192 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 4, + "id": "initial_id", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-06T13:29:46.610584Z", + "start_time": "2023-08-06T13:29:46.600527Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ConstantProductCurve v2.14 (23/May/2023)\n", + "CarbonBot v3-b2.2 (20/June/2023)\n", + "UniswapV2 v0.0.1 (2023-07-03)\n", + "UniswapV3 v0.0.1 (2023-07-03)\n", + "SushiswapV2 v0.0.1 (2023-07-03)\n", + "CarbonV1 v0.0.1 (2023-07-03)\n", + "BancorV3 v0.0.1 (2023-07-03)\n", + "Version = 3-b2.2 [requirements >= 3.0 is met]\n" + ] + } + ], + "source": [ + "# coding=utf-8\n", + "\"\"\"\n", + "This module contains the tests which ensure that the flashloan tokens click parameters are respected.\n", + "\"\"\"\n", + "from fastlane_bot import Bot\n", + "from fastlane_bot.tools.cpc import ConstantProductCurve as CPC\n", + "from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, SushiswapV2, CarbonV1, BancorV3\n", + "import subprocess, os, sys\n", + "import pytest\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CPC))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(Bot))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV2))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV3))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(SushiswapV2))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CarbonV1))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(BancorV3))\n", + "from fastlane_bot.testing import *\n", + "plt.rcParams['figure.figsize'] = [12,6]\n", + "from fastlane_bot import __VERSION__\n", + "require(\"3.0\", __VERSION__)" + ] + }, + { + "cell_type": "markdown", + "id": "dfafc69730cbead3", + "metadata": {}, + "source": [ + "# Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "1640a40ee6ae871c", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-06T13:29:46.610962Z", + "start_time": "2023-08-06T13:29:46.607946Z" + } + }, + "outputs": [], + "source": [ + "def find_main_py():\n", + " # Start at the directory of the current script\n", + " cwd = os.path.abspath(os.path.join(os.getcwd()))\n", + " \n", + " print(f\"Searching for main.py in {cwd}\")\n", + " while True:\n", + " # Check if main.py exists in the current directory\n", + " if \"main.py\" in os.listdir(cwd):\n", + " return cwd # Found the directory containing main.py\n", + " else:\n", + " # If not, go up one directory\n", + " new_cwd = os.path.dirname(cwd)\n", + "\n", + " # If we're already at the root directory, stop searching\n", + " if new_cwd == cwd:\n", + " raise FileNotFoundError(\"Could not find main.py in any parent directory\")\n", + "\n", + " cwd = new_cwd\n", + " \n", + " \n", + "def run_command(arb_mode, expected_log_line):\n", + " \n", + " # Find the correct path to main.py\n", + " main_script_path = find_main_py()\n", + " print(f\"Found main.py in {main_script_path}\")\n", + " main_script_path = main_script_path + \"/main.py\"\n", + "\n", + " # Run the command\n", + " cmd = [\n", + " \"python\",\n", + " main_script_path,\n", + " f\"--arb_mode={arb_mode}\",\n", + " \"--default_min_profit_bnt=60\",\n", + " \"--limit_bancor3_flashloan_tokens=False\",\n", + " \"--use_cached_events=True\",\n", + " \"--logging_path=fastlane_bot/data/\",\n", + " \"--timeout=1\",\n", + " \"--loglevel=DEBUG\",\n", + " \"--flashloan_tokens=BNT-FF1C,ETH-EEeE,ETH2X-FLI-USD\",\n", + " ]\n", + " subprocess.Popen(cmd)\n", + " \n", + " # Wait for the expected log line to appear\n", + " found = False\n", + " result = subprocess.run(cmd, text=True, capture_output=True, check=True, timeout=7)\n", + "\n", + " # Check if the expected log line is in the output\n", + " if expected_log_line in result.stderr or expected_log_line in result.stdout:\n", + " found = True\n", + "\n", + " if not found:\n", + " pytest.fail(\"Expected log line was not found within 1 minute\") # If we reach this point, the test has failed" + ] + }, + { + "cell_type": "markdown", + "id": "614f482aec4be2f8", + "metadata": {}, + "source": [ + "## Test flashloan_tokens is Respected" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "c6e198d0eeba3183", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-06T13:29:50.145382Z", + "start_time": "2023-08-06T13:29:46.612650Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Searching for main.py in /Users/mikewcasale/Documents/GitHub/fastlane-bot/resources/NBTest\n", + "Found main.py in /Users/mikewcasale/Documents/GitHub/fastlane-bot\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2023-08-06 06:29:49,894 [fastlane:INFO] - Using mainnet config\n", + "2023-08-06 06:29:49,894 [fastlane:INFO] - Flashloan tokens are set as: ['BNT-FF1C', 'ETH-EEeE', 'ETH2X_FLI-USD'], \n", + "2023-08-06 06:29:49,894 [fastlane:INFO] - Running data fetching for exchanges: ['carbon_v1', 'bancor_v3', 'uniswap_v3', 'uniswap_v2', 'sushiswap_v2']\n", + "2023-08-06 06:29:49,936 [fastlane:INFO] - Timeout to test the bot flags\n" + ] + } + ], + "source": [ + "expected_log_line = \"Flashloan tokens are set as: ['BNT-FF1C', 'ETH-EEeE', 'ETH2X_FLI-USD']\"\n", + "arb_mode = \"multi\"\n", + "run_command(arb_mode=arb_mode, expected_log_line=expected_log_line)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.py b/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.py new file mode 100644 index 000000000..53329eff1 --- /dev/null +++ b/resources/NBTest/NBTest_048_RespectFlashloanTokensClickParam.py @@ -0,0 +1,100 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.14.7 +# kernelspec: +# display_name: Python 3 (ipykernel) +# language: python +# name: python3 +# --- + +# coding=utf-8 +""" +This module contains the tests which ensure that the flashloan tokens click parameters are respected. +""" +from fastlane_bot import Bot +from fastlane_bot.tools.cpc import ConstantProductCurve as CPC +from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, SushiswapV2, CarbonV1, BancorV3 +import subprocess, os, sys +import pytest +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CPC)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(Bot)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(UniswapV2)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(UniswapV3)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(SushiswapV2)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CarbonV1)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(BancorV3)) +from fastlane_bot.testing import * +plt.rcParams['figure.figsize'] = [12,6] +from fastlane_bot import __VERSION__ +require("3.0", __VERSION__) + + +# # Setup + +# + +def find_main_py(): + # Start at the directory of the current script + cwd = os.path.abspath(os.path.join(os.getcwd())) + + print(f"Searching for main.py in {cwd}") + while True: + # Check if main.py exists in the current directory + if "main.py" in os.listdir(cwd): + return cwd # Found the directory containing main.py + else: + # If not, go up one directory + new_cwd = os.path.dirname(cwd) + + # If we're already at the root directory, stop searching + if new_cwd == cwd: + raise FileNotFoundError("Could not find main.py in any parent directory") + + cwd = new_cwd + + +def run_command(arb_mode, expected_log_line): + + # Find the correct path to main.py + main_script_path = find_main_py() + print(f"Found main.py in {main_script_path}") + main_script_path = main_script_path + "/main.py" + + # Run the command + cmd = [ + "python", + main_script_path, + f"--arb_mode={arb_mode}", + "--default_min_profit_bnt=60", + "--limit_bancor3_flashloan_tokens=False", + "--use_cached_events=True", + "--logging_path=fastlane_bot/data/", + "--timeout=1", + "--loglevel=DEBUG", + "--flashloan_tokens=BNT-FF1C,ETH-EEeE,ETH2X-FLI-USD", + ] + subprocess.Popen(cmd) + + # Wait for the expected log line to appear + found = False + result = subprocess.run(cmd, text=True, capture_output=True, check=True, timeout=7) + + # Check if the expected log line is in the output + if expected_log_line in result.stderr or expected_log_line in result.stdout: + found = True + + if not found: + pytest.fail("Expected log line was not found within 1 minute") # If we reach this point, the test has failed + + +# - + +# ## Test flashloan_tokens is Respected + +expected_log_line = "Flashloan tokens are set as: ['BNT-FF1C', 'ETH-EEeE', 'ETH2X_FLI-USD']" +arb_mode = "multi" +run_command(arb_mode=arb_mode, expected_log_line=expected_log_line) diff --git a/resources/NBTest/NBTest_902_ValidatorSlow.ipynb b/resources/NBTest/NBTest_902_ValidatorSlow.ipynb deleted file mode 100644 index 46d2b023d..000000000 --- a/resources/NBTest/NBTest_902_ValidatorSlow.ipynb +++ /dev/null @@ -1,1769 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 9, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ConstantProductCurve v2.14 (23/May/2023)\n", - "CarbonBot v3-b2.2 (20/June/2023)\n", - "UniswapV2 v0.0.1 (2023-07-03)\n", - "UniswapV3 v0.0.1 (2023-07-03)\n", - "SushiswapV2 v0.0.1 (2023-07-03)\n", - "CarbonV1 v0.0.1 (2023-07-03)\n", - "BancorV3 v0.0.1 (2023-07-03)\n", - "Version = 3-b2.2 [requirements >= 3.0 is met]\n" - ] - } - ], - "source": [ - "# coding=utf-8\n", - "\"\"\"\n", - "This module contains the tests for the exchanges classes\n", - "\"\"\"\n", - "from fastlane_bot import Bot, Config\n", - "from fastlane_bot.bot import CarbonBot\n", - "from fastlane_bot.tools.cpc import ConstantProductCurve\n", - "from fastlane_bot.tools.cpc import ConstantProductCurve as CPC\n", - "from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, SushiswapV2, CarbonV1, BancorV3\n", - "from fastlane_bot.events.interface import QueryInterface\n", - "from fastlane_bot.helpers.poolandtokens import PoolAndTokens\n", - "from fastlane_bot.helpers import TradeInstruction, TxReceiptHandler, TxRouteHandler, TxSubmitHandler, TxHelpers, TxHelper\n", - "from fastlane_bot.events.managers.manager import Manager\n", - "from fastlane_bot.events.interface import QueryInterface\n", - "from joblib import Parallel, delayed\n", - "import pytest\n", - "import math\n", - "import json\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CPC))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(Bot))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV2))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV3))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(SushiswapV2))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CarbonV1))\n", - "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(BancorV3))\n", - "from fastlane_bot.testing import *\n", - "from fastlane_bot.modes import triangle_single_bancor3\n", - "#plt.style.use('seaborn-dark')\n", - "plt.rcParams['figure.figsize'] = [12,6]\n", - "from fastlane_bot import __VERSION__\n", - "require(\"3.0\", __VERSION__)" - ], - "metadata": { - "collapsed": false, - "ExecuteTime": { - "end_time": "2023-08-06T12:29:53.196201Z", - "start_time": "2023-08-06T12:29:53.124133Z" - } - }, - "id": "56224b770915d14" - }, - { - "cell_type": "markdown", - "id": "4c4e2283", - "metadata": {}, - "source": [ - "# Multi Mode [NB039]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "a51e5ec2", - "metadata": { - "ExecuteTime": { - "end_time": "2023-08-06T12:29:54.497241Z", - "start_time": "2023-08-06T12:29:53.143Z" - } - }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "2023-08-06 05:29:54,070 [fastlane:INFO] - Time taken to add initial pools: 0.06647491455078125\n", - "2023-08-06 05:29:54,070 [fastlane:INFO] - Time taken to add initial pools: 0.06647491455078125\n", - "2023-08-06 05:29:54,073 [fastlane:INFO] - Initializing the bot...\n", - "2023-08-06 05:29:54,073 [fastlane:INFO] - Initializing the bot...\n", - "2023-08-06 05:29:54,191 [fastlane:INFO] - Removed 3242 unmapped uniswap_v2/sushi pools. 1897 uniswap_v2/sushi pools remaining\n", - "2023-08-06 05:29:54,191 [fastlane:INFO] - Removed 3242 unmapped uniswap_v2/sushi pools. 1897 uniswap_v2/sushi pools remaining\n", - "2023-08-06 05:29:54,192 [fastlane:INFO] - Unmapped uniswap_v2/sushi pools:\n", - "2023-08-06 05:29:54,192 [fastlane:INFO] - Unmapped uniswap_v2/sushi pools:\n", - "2023-08-06 05:29:54,379 [fastlane:INFO] - uniswap_v3: 0\n", - "2023-08-06 05:29:54,379 [fastlane:INFO] - uniswap_v3: 0\n", - "2023-08-06 05:29:54,380 [fastlane:INFO] - uniswap_v2: 3242\n", - "2023-08-06 05:29:54,380 [fastlane:INFO] - uniswap_v2: 3242\n", - "2023-08-06 05:29:54,380 [fastlane:INFO] - sushiswap_v2: 0\n", - "2023-08-06 05:29:54,380 [fastlane:INFO] - sushiswap_v2: 0\n", - "2023-08-06 05:29:54,382 [fastlane:INFO] - uniswap_v3: 636\n", - "2023-08-06 05:29:54,382 [fastlane:INFO] - uniswap_v3: 636\n", - "2023-08-06 05:29:54,382 [fastlane:INFO] - sushiswap_v2: 78\n", - "2023-08-06 05:29:54,382 [fastlane:INFO] - sushiswap_v2: 78\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - uniswap_v2: 0\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - uniswap_v2: 0\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - bancor_v2: 0\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - bancor_v2: 0\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - bancor_v3: 34\n", - "2023-08-06 05:29:54,383 [fastlane:INFO] - bancor_v3: 34\n", - "2023-08-06 05:29:54,384 [fastlane:INFO] - carbon_v1: 220\n", - "2023-08-06 05:29:54,384 [fastlane:INFO] - carbon_v1: 220\n", - "2023-08-06 05:29:54,415 [fastlane:INFO] - uniswap_v3_zero_liquidity_pools: 858\n", - "2023-08-06 05:29:54,415 [fastlane:INFO] - uniswap_v3_zero_liquidity_pools: 858\n", - "2023-08-06 05:29:54,415 [fastlane:INFO] - sushiswap_v2_zero_liquidity_pools: 34\n", - "2023-08-06 05:29:54,415 [fastlane:INFO] - sushiswap_v2_zero_liquidity_pools: 34\n", - "2023-08-06 05:29:54,416 [fastlane:INFO] - uniswap_v2_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,416 [fastlane:INFO] - uniswap_v2_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,416 [fastlane:INFO] - bancor_v2_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,416 [fastlane:INFO] - bancor_v2_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,417 [fastlane:INFO] - bancor_v3_zero_liquidity_pools: 37\n", - "2023-08-06 05:29:54,417 [fastlane:INFO] - bancor_v3_zero_liquidity_pools: 37\n", - "2023-08-06 05:29:54,417 [fastlane:INFO] - carbon_v1_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,417 [fastlane:INFO] - carbon_v1_zero_liquidity_pools: 0\n", - "2023-08-06 05:29:54,418 [fastlane:INFO] - Removed 0 unsupported exchanges. 968 pools remaining\n", - "2023-08-06 05:29:54,418 [fastlane:INFO] - Removed 0 unsupported exchanges. 968 pools remaining\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - Pools remaining per exchange:\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - Pools remaining per exchange:\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - carbon_v1: 220\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - carbon_v1: 220\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - sushiswap_v2: 78\n", - "2023-08-06 05:29:54,419 [fastlane:INFO] - sushiswap_v2: 78\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - uniswap_v2: 0\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - uniswap_v2: 0\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - bancor_v3: 34\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - bancor_v3: 34\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - uniswap_v3: 636\n", - "2023-08-06 05:29:54,420 [fastlane:INFO] - uniswap_v3: 636\n" - ] - } - ], - "source": [ - "C = cfg = Config.new(config=Config.CONFIG_MAINNET)\n", - "C.DEFAULT_MIN_PROFIT_BNT = 0.02\n", - "C.DEFAULT_MIN_PROFIT = 0.02\n", - "cfg.DEFAULT_MIN_PROFIT_BNT = 0.02\n", - "cfg.DEFAULT_MIN_PROFIT = 0.02\n", - "assert (C.NETWORK == C.NETWORK_MAINNET)\n", - "assert (C.PROVIDER == C.PROVIDER_ALCHEMY)\n", - "setup_bot = CarbonBot(ConfigObj=C)\n", - "pools = None\n", - "with open('fastlane_bot/data/tests/latest_pool_data_testing.json') as f:\n", - " pools = json.load(f)\n", - "pools = [pool for pool in pools]\n", - "pools[0]\n", - "static_pools = pools\n", - "state = pools\n", - "exchanges = list({ex['exchange_name'] for ex in state})\n", - "db = QueryInterface(state=state, ConfigObj=C, exchanges=exchanges)\n", - "setup_bot.db = db\n", - "\n", - "static_pool_data_filename = \"static_pool_data\"\n", - "\n", - "static_pool_data = pd.read_csv(f\"fastlane_bot/data/{static_pool_data_filename}.csv\", low_memory=False)\n", - " \n", - "uniswap_v2_event_mappings = pd.read_csv(\"fastlane_bot/data/uniswap_v2_event_mappings.csv\", low_memory=False)\n", - " \n", - "tokens = pd.read_csv(\"fastlane_bot/data/tokens.csv\", low_memory=False)\n", - " \n", - "exchanges = \"carbon_v1,bancor_v3,uniswap_v3,uniswap_v2,sushiswap_v2\"\n", - "\n", - "exchanges = exchanges.split(\",\")\n", - "\n", - "\n", - "alchemy_max_block_fetch = 20\n", - "static_pool_data[\"cid\"] = [\n", - " cfg.w3.keccak(text=f\"{row['descr']}\").hex()\n", - " for index, row in static_pool_data.iterrows()\n", - " ]\n", - "# Filter out pools that are not in the supported exchanges\n", - "static_pool_data = [\n", - " row for index, row in static_pool_data.iterrows()\n", - " if row[\"exchange_name\"] in exchanges\n", - "]\n", - "\n", - "static_pool_data = pd.DataFrame(static_pool_data)\n", - "static_pool_data['exchange_name'].unique()\n", - "# Initialize data fetch manager\n", - "mgr = Manager(\n", - " web3=cfg.w3,\n", - " cfg=cfg,\n", - " pool_data=static_pool_data.to_dict(orient=\"records\"),\n", - " SUPPORTED_EXCHANGES=exchanges,\n", - " alchemy_max_block_fetch=alchemy_max_block_fetch,\n", - " uniswap_v2_event_mappings=uniswap_v2_event_mappings,\n", - " tokens=tokens.to_dict(orient=\"records\"),\n", - ")\n", - "\n", - "# Add initial pools for each row in the static_pool_data\n", - "start_time = time.time()\n", - "Parallel(n_jobs=-1, backend=\"threading\")(\n", - " delayed(mgr.add_pool_to_exchange)(row) for row in mgr.pool_data\n", - ")\n", - "cfg.logger.info(f\"Time taken to add initial pools: {time.time() - start_time}\")\n", - "\n", - "# check if any duplicate cid's exist in the pool data\n", - "mgr.deduplicate_pool_data()\n", - "cids = [pool[\"cid\"] for pool in mgr.pool_data]\n", - "assert len(cids) == len(set(cids)), \"duplicate cid's exist in the pool data\"\n", - "def init_bot(mgr: Manager) -> CarbonBot:\n", - " \"\"\"\n", - " Initializes the bot.\n", - "\n", - " Parameters\n", - " ----------\n", - " mgr : Manager\n", - " The manager object.\n", - "\n", - " Returns\n", - " -------\n", - " CarbonBot\n", - " The bot object.\n", - " \"\"\"\n", - " mgr.cfg.logger.info(\"Initializing the bot...\")\n", - " bot = CarbonBot(ConfigObj=mgr.cfg)\n", - " bot.db = db\n", - " bot.db.mgr = mgr\n", - " assert isinstance(\n", - " bot.db, QueryInterface\n", - " ), \"QueryInterface not initialized correctly\"\n", - " return bot\n", - "bot = init_bot(mgr)\n", - "# add data cleanup steps from main.py\n", - "bot.db.handle_token_key_cleanup()\n", - "bot.db.remove_unmapped_uniswap_v2_pools()\n", - "bot.db.remove_zero_liquidity_pools()\n", - "bot.db.remove_unsupported_exchanges()\n", - "tokens = bot.db.get_tokens()\n", - "ADDRDEC = {t.key: (t.address, int(t.decimals)) for t in tokens if not math.isnan(t.decimals)}\n", - "flashloan_tokens = bot.setup_flashloan_tokens(None)\n", - "CCm = bot.setup_CCm(None)\n", - "pools = db.get_pool_data_with_tokens()\n", - "\n", - "arb_mode = \"multi\"" - ] - }, - { - "cell_type": "markdown", - "id": "a70cf16f", - "metadata": {}, - "source": [ - "## Test_MIN_PROFIT" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "c8f41237", - "metadata": { - "ExecuteTime": { - "end_time": "2023-08-06T12:29:54.497413Z", - "start_time": "2023-08-06T12:29:54.494079Z" - } - }, - "outputs": [], - "source": [ - "assert(cfg.DEFAULT_MIN_PROFIT_BNT <= 0.02), f\"[TestMultiMode], DEFAULT_MIN_PROFIT_BNT must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_BNT}\"\n", - "assert(C.DEFAULT_MIN_PROFIT_BNT <= 0.02), f\"[TestMultiMode], DEFAULT_MIN_PROFIT_BNT must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_BNT}\"" - ] - }, - { - "cell_type": "markdown", - "id": "eddfdea7", - "metadata": {}, - "source": [ - "## Test_validator_in_out" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "aaaf7423", - "metadata": { - "ExecuteTime": { - "end_time": "2023-08-06T12:29:54.500387Z", - "start_time": "2023-08-06T12:29:54.496715Z" - } - }, - "outputs": [], - "source": [ - "arb_finder = bot._get_arb_finder(\"multi\")\n", - "assert arb_finder.__name__ == \"FindArbitrageMultiPairwise\", f\"[TestMultiMode] Expected arb_finder class name name = FindArbitrageMultiPairwise, found {arb_finder.__name__}\"" - ] - }, - { - "cell_type": "markdown", - "id": "96ef3bf0", - "metadata": {}, - "source": [ - "## Test_validator_multi" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "db7ec9ec", - "metadata": { - "ExecuteTime": { - "end_time": "2023-08-06T12:29:54.788652Z", - "start_time": "2023-08-06T12:29:54.508442Z" - } - }, - "outputs": [], - "source": [ - "arb_finder = bot._get_arb_finder(\"multi\")\n", - "finder = arb_finder(\n", - " flashloan_tokens=flashloan_tokens,\n", - " CCm=CCm,\n", - " mode=\"bothin\",\n", - " result=bot.AO_CANDIDATES,\n", - " ConfigObj=bot.ConfigObj,\n", - " )\n", - "r = finder.find_arbitrage()\n", - "\n", - "arb_opp = r[0]\n", - "\n", - "validated = bot.validate_optimizer_trades(arb_opp=arb_opp, arb_mode=\"multi\", arb_finder=finder)\n", - "\n", - "\n", - "\n", - "assert arb_opp == validated" - ] - }, - { - "cell_type": "markdown", - "id": "5b195f52", - "metadata": {}, - "source": [ - "## Test_validator_single" - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "78d0dbc1", - "metadata": { - "ExecuteTime": { - "end_time": "2023-08-06T12:29:58.990699Z", - "start_time": "2023-08-06T12:29:54.793412Z" - } - }, - "outputs": [ - { - "data": { - "text/plain": "0it [00:00, ?it/s]", - "application/vnd.jupyter.widget-view+json": { - "version_major": 2, - "version_minor": 0, - "model_id": "56850cdfceff41aab83fda57bbd21b77" - } - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/plain": " 0%| | 0/2 [00:00 CarbonBot: - """ - Initializes the bot. - - Parameters - ---------- - mgr : Manager - The manager object. - - Returns - ------- - CarbonBot - The bot object. - """ - mgr.cfg.logger.info("Initializing the bot...") - bot = CarbonBot(ConfigObj=mgr.cfg) - bot.db = db - bot.db.mgr = mgr - assert isinstance( - bot.db, QueryInterface - ), "QueryInterface not initialized correctly" - return bot -bot = init_bot(mgr) -# add data cleanup steps from main.py -bot.db.handle_token_key_cleanup() -bot.db.remove_unmapped_uniswap_v2_pools() -bot.db.remove_zero_liquidity_pools() -bot.db.remove_unsupported_exchanges() -tokens = bot.db.get_tokens() -ADDRDEC = {t.key: (t.address, int(t.decimals)) for t in tokens if not math.isnan(t.decimals)} -flashloan_tokens = bot.setup_flashloan_tokens(None) -CCm = bot.setup_CCm(None) -pools = db.get_pool_data_with_tokens() - -arb_mode = "multi" -# - - -# ## Test_MIN_PROFIT - -assert(cfg.DEFAULT_MIN_PROFIT_BNT <= 0.02), f"[TestMultiMode], DEFAULT_MIN_PROFIT_BNT must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_BNT}" -assert(C.DEFAULT_MIN_PROFIT_BNT <= 0.02), f"[TestMultiMode], DEFAULT_MIN_PROFIT_BNT must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_BNT}" - -# ## Test_validator_in_out - -arb_finder = bot._get_arb_finder("multi") -assert arb_finder.__name__ == "FindArbitrageMultiPairwise", f"[TestMultiMode] Expected arb_finder class name name = FindArbitrageMultiPairwise, found {arb_finder.__name__}" - -# ## Test_validator_multi - -# + -arb_finder = bot._get_arb_finder("multi") -finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=bot.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) -r = finder.find_arbitrage() - -arb_opp = r[0] - -validated = bot.validate_optimizer_trades(arb_opp=arb_opp, arb_mode="multi", arb_finder=finder) - - - -assert arb_opp == validated -# - - -# ## Test_validator_single - -# + -arb_mode="single" -arb_finder = bot._get_arb_finder(arb_mode) -finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=bot.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) -r = finder.find_arbitrage() - -arb_opp = r[0] - -validated = bot.validate_optimizer_trades(arb_opp=arb_opp, arb_mode=arb_mode, arb_finder=finder) - - -assert arb_opp == validated -# - - -# ## Test_validator_bancor_v3 - -# + -arb_mode="bancor_v3" - -arb_finder = bot._get_arb_finder(arb_mode) -finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=bot.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) -r = finder.find_arbitrage() - -arb_opp = r[0] - -validated = bot.validate_optimizer_trades(arb_opp=arb_opp, arb_mode=arb_mode, arb_finder=finder) - - - -assert arb_opp == validated -# - - -# ## Test_validator_multi_triangle - -# + -arb_mode="multi_triangle" -arb_finder = bot._get_arb_finder(arb_mode) -finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=bot.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) -r = finder.find_arbitrage() - -arb_opp = r[0] - -validated = bot.validate_optimizer_trades(arb_opp=arb_opp, arb_mode=arb_mode, arb_finder=finder) - - - -assert arb_opp == validated diff --git a/resources/NBTest/NBTest_906_TargetTokens.ipynb b/resources/NBTest/NBTest_906_TargetTokens.ipynb new file mode 100644 index 000000000..290a360f7 --- /dev/null +++ b/resources/NBTest/NBTest_906_TargetTokens.ipynb @@ -0,0 +1,314 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 7, + "id": "initial_id", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-09T17:45:55.576598Z", + "start_time": "2023-08-09T17:45:55.569839Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ConstantProductCurve v2.14 (23/May/2023)\n", + "CarbonBot v3-b2.2 (20/June/2023)\n", + "UniswapV2 v0.0.1 (2023-07-03)\n", + "UniswapV3 v0.0.1 (2023-07-03)\n", + "SushiswapV2 v0.0.1 (2023-07-03)\n", + "CarbonV1 v0.0.1 (2023-07-03)\n", + "BancorV3 v0.0.1 (2023-07-03)\n", + "Version = 3-b2.2 [requirements >= 3.0 is met]\n" + ] + } + ], + "source": [ + "# coding=utf-8\n", + "\"\"\"\n", + "This module contains the tests which ensure the target_tokens parameter is respected.\n", + "\"\"\"\n", + "from fastlane_bot import Bot\n", + "from fastlane_bot.tools.cpc import ConstantProductCurve as CPC\n", + "from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, SushiswapV2, CarbonV1, BancorV3\n", + "import subprocess, os, sys\n", + "import pytest\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CPC))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(Bot))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV2))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(UniswapV3))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(SushiswapV2))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(CarbonV1))\n", + "print(\"{0.__name__} v{0.__VERSION__} ({0.__DATE__})\".format(BancorV3))\n", + "from fastlane_bot.testing import *\n", + "plt.rcParams['figure.figsize'] = [12,6]\n", + "from fastlane_bot import __VERSION__\n", + "require(\"3.0\", __VERSION__)" + ] + }, + { + "cell_type": "markdown", + "id": "dfafc69730cbead3", + "metadata": {}, + "source": [ + "# Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1640a40ee6ae871c", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-09T17:45:55.588072Z", + "start_time": "2023-08-09T17:45:55.575696Z" + } + }, + "outputs": [], + "source": [ + "from fastlane_bot.tools.cpc import T\n", + "\n", + "\n", + "def find_main_py():\n", + " # Start at the directory of the current script\n", + " cwd = os.path.abspath(os.path.join(os.getcwd()))\n", + " \n", + " with open(\"log.txt\", \"w\") as f:\n", + " f.write(f\"Searching for main.py in {cwd}\")\n", + " \n", + " print(f\"Searching for main.py in {cwd}\")\n", + " while True:\n", + " # Check if main.py exists in the current directory\n", + " if \"main.py\" in os.listdir(cwd):\n", + " return cwd # Found the directory containing main.py\n", + " else:\n", + " # If not, go up one directory\n", + " new_cwd = os.path.dirname(cwd)\n", + "\n", + " # If we're already at the root directory, stop searching\n", + " if new_cwd == cwd:\n", + " raise FileNotFoundError(\"Could not find main.py in any parent directory\")\n", + "\n", + " cwd = new_cwd\n", + " \n", + " \n", + "def run_command(mode):\n", + " \n", + " # Find the correct path to main.py\n", + " main_script_path = find_main_py()\n", + " print(f\"Found main.py in {main_script_path}\")\n", + " main_script_path = main_script_path + \"/main.py\"\n", + "\n", + " # Run the command\n", + " cmd = [\n", + " \"python\",\n", + " main_script_path,\n", + " f\"--arb_mode={mode}\",\n", + " \"--use_cached_events=True\",\n", + " \"--logging_path=fastlane_bot/data/\",\n", + " \"--timeout=45\",\n", + " f\"--target_tokens={T.WETH},{T.DAI}\"\n", + " ]\n", + " subprocess.Popen(cmd)\n", + " \n", + " # Wait for the expected log line to appear\n", + " expected_log_line = \"Limiting pools by target_tokens. Removed \"\n", + " found = False\n", + " result = subprocess.run(cmd, text=True, capture_output=True, check=True, timeout=120)\n", + "\n", + " # Check if the expected log line is in the output\n", + " if expected_log_line in result.stderr:\n", + " found = True\n", + "\n", + " if not found:\n", + " pytest.fail(\"Expected log line was not found within 1 minute\") # If we reach this point, the test has failed" + ] + }, + { + "cell_type": "markdown", + "id": "614f482aec4be2f8", + "metadata": {}, + "source": [ + "## Test Flashloan Tokens b3_two_hop" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "c6e198d0eeba3183", + "metadata": { + "ExecuteTime": { + "end_time": "2023-08-09T17:46:55.475498Z", + "start_time": "2023-08-09T17:45:55.578507Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Searching for main.py in /Users/mikewcasale/Documents/GitHub/fastlane-bot/resources/NBTest\n", + "Found main.py in /Users/mikewcasale/Documents/GitHub/fastlane-bot\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "Python-dotenv could not parse statement starting at line 3\n", + "Python-dotenv could not parse statement starting at line 4\n", + "Python-dotenv could not parse statement starting at line 5\n", + "Python-dotenv could not parse statement starting at line 6\n", + "2023-08-09 10:45:59,352 [fastlane:INFO] - Using mainnet config\n", + "2023-08-09 10:45:59,352 [fastlane:INFO] - Flashloan tokens are set as: ['WETH-6Cc2', 'DAI-1d0F', 'USDC-eB48', 'USDT-1ec7', 'WBTC-C599', 'BNT-FF1C', 'ETH-EEeE'], \n", + "2023-08-09 10:45:59,352 [fastlane:WARNING] - Falshloan token USDC-eB48 not in target tokens. Adding it to target tokens.\n", + "2023-08-09 10:45:59,352 [fastlane:WARNING] - Falshloan token USDT-1ec7 not in target tokens. Adding it to target tokens.\n", + "2023-08-09 10:45:59,352 [fastlane:WARNING] - Falshloan token WBTC-C599 not in target tokens. Adding it to target tokens.\n", + "2023-08-09 10:45:59,352 [fastlane:WARNING] - Falshloan token BNT-FF1C not in target tokens. Adding it to target tokens.\n", + "2023-08-09 10:45:59,352 [fastlane:WARNING] - Falshloan token ETH-EEeE not in target tokens. Adding it to target tokens.\n", + "2023-08-09 10:45:59,352 [fastlane:INFO] - Target tokens are set as: ['WETH-6Cc2', 'DAI-1d0F', 'USDC-eB48', 'USDT-1ec7', 'WBTC-C599', 'BNT-FF1C', 'ETH-EEeE'], \n", + "2023-08-09 10:45:59,352 [fastlane:INFO] - Running data fetching for exchanges: ['carbon_v1', 'bancor_v3', 'uniswap_v3', 'uniswap_v2', 'sushiswap_v2']\n", + "2023-08-09 10:45:59,631 [fastlane:INFO] - Time taken to add initial pools: 0.08833503723144531\n", + "2023-08-09 10:45:59,840 [fastlane:INFO] - Fetching events from 17876915 to 17878915... 0\n", + "2023-08-09 10:45:59,840 [fastlane:INFO] - Using cached events\n", + "2023-08-09 10:45:59,841 [fastlane:INFO] - Found 25 new events\n", + "2023-08-09 10:46:02,626 [fastlane:INFO] - Updating carbon pools w/ multicall...\n", + "2023-08-09 10:46:03,654 [fastlane:INFO] - Fetched 281 carbon strategies in 1.0274429321289062 seconds\n", + "2023-08-09 10:46:09,610 [fastlane:INFO] - Updated 281 carbon strategies info in 5.956198215484619 seconds\n", + "2023-08-09 10:46:27,709 [fastlane:INFO] - Initializing the bot...\n", + "2023-08-09 10:46:27,818 [fastlane:INFO] - State has changed...\n", + "2023-08-09 10:46:27,825 [fastlane:INFO] - Removed 122 unmapped uniswap_v2/sushi pools. 5078 uniswap_v2/sushi pools remaining\n", + "2023-08-09 10:46:27,825 [fastlane:INFO] - Unmapped uniswap_v2/sushi pools:\n", + "2023-08-09 10:46:28,146 [fastlane:INFO] - uniswap_v3: 0\n", + "2023-08-09 10:46:28,146 [fastlane:INFO] - uniswap_v2: 122\n", + "2023-08-09 10:46:28,146 [fastlane:INFO] - sushiswap_v2: 0\n", + "2023-08-09 10:46:40,251 [fastlane:INFO] - Fetching events from 17878916 to 17878919... 17878915\n", + "2023-08-09 10:46:40,251 [fastlane:INFO] - Using cached events\n", + "2023-08-09 10:46:40,251 [fastlane:INFO] - Found 25 new events\n", + "2023-08-09 10:46:42,744 [fastlane:INFO] - Initializing the bot...\n", + "2023-08-09 10:46:42,873 [fastlane:INFO] - Removed 122 unmapped uniswap_v2/sushi pools. 5078 uniswap_v2/sushi pools remaining\n", + "2023-08-09 10:46:42,873 [fastlane:INFO] - Unmapped uniswap_v2/sushi pools:\n", + "2023-08-09 10:46:43,219 [fastlane:INFO] - uniswap_v3: 0\n", + "2023-08-09 10:46:43,219 [fastlane:INFO] - uniswap_v2: 122\n", + "2023-08-09 10:46:43,219 [fastlane:INFO] - sushiswap_v2: 0\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - uniswap_v3: 11\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - sushiswap_v2: 2\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - uniswap_v2: 13\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - bancor_v2: 0\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - bancor_v3: 33\n", + "2023-08-09 10:46:43,221 [fastlane:INFO] - carbon_v1: 281\n", + "2023-08-09 10:46:43,238 [fastlane:INFO] - uniswap_v3_zero_liquidity_pools: 1483\n", + "2023-08-09 10:46:43,238 [fastlane:INFO] - sushiswap_v2_zero_liquidity_pools: 87\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - uniswap_v2_zero_liquidity_pools: 3130\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - bancor_v2_zero_liquidity_pools: 0\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - bancor_v3_zero_liquidity_pools: 38\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - carbon_v1_zero_liquidity_pools: 0\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - Removed 0 unsupported exchanges. 340 pools remaining\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - Pools remaining per exchange:\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - carbon_v1: 281\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - bancor_v3: 33\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - uniswap_v3: 11\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - uniswap_v2: 13\n", + "2023-08-09 10:46:43,239 [fastlane:INFO] - sushiswap_v2: 2\n", + "2023-08-09 10:46:43,240 [fastlane:INFO] - Limiting pools by target_tokens. Removed 194 non target-pools. 146 pools remaining\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "100%|██████████| 7/7 [00:00<00:00, 638263.65it/s]\n", + "100%|██████████| 5/5 [00:00<00:00, 262144.00it/s]\n", + "0it [00:00, ?it/s]\n", + "100%|██████████| 7/7 [00:00<00:00, 458752.00it/s]\n", + "0it [00:00, ?it/s]\n", + "100%|██████████| 69/69 [00:00<00:00, 2097152.00it/s]\n", + "100%|██████████| 26/26 [00:00<00:00, 1028791.55it/s]\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "100%|██████████| 5/5 [00:00<00:00, 388361.48it/s]\n", + "100%|██████████| 69/69 [00:00<00:00, 1982239.56it/s]\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "100%|██████████| 26/26 [00:00<00:00, 1380403.85it/s]\n", + "/Users/mikewcasale/Documents/GitHub/fastlane-bot/fastlane_bot/tools/optimizer/margpoptimizer.py:217: RuntimeWarning: divide by zero encountered in scalar divide\n", + " price = get(p, tokens_ix.get(tknb)) / get(p, tokens_ix.get(tknq))\n", + "/Users/mikewcasale/Documents/GitHub/fastlane-bot/fastlane_bot/tools/optimizer/margpoptimizer.py:61: RuntimeWarning: invalid value encountered in subtract\n", + " jac[:, j] = (func(x_plus, quiet=True) - y) / Dxj\n", + "0it [00:00, ?it/s]\n", + "0it [00:00, ?it/s]\n", + "2023-08-09 10:46:43,646 [fastlane:INFO] - No eligible arb opportunities.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: bad operand type for unary -: 'NoneType'\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: bad operand type for unary -: 'NoneType'\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: bad operand type for unary -: 'NoneType'\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: bad operand type for unary -: 'NoneType'\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: float division by zero\n", + "[FindArbitrageSinglePairwise] Exception: bad operand type for unary -: 'NoneType'\n" + ] + } + ], + "source": [ + "run_command(\"single\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.17" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/resources/NBTest/NBTest_906_TargetTokens.py b/resources/NBTest/NBTest_906_TargetTokens.py new file mode 100644 index 000000000..4a18adc45 --- /dev/null +++ b/resources/NBTest/NBTest_906_TargetTokens.py @@ -0,0 +1,101 @@ +# --- +# jupyter: +# jupytext: +# text_representation: +# extension: .py +# format_name: light +# format_version: '1.5' +# jupytext_version: 1.14.7 +# kernelspec: +# display_name: Python 3 (ipykernel) +# language: python +# name: python3 +# --- + +# coding=utf-8 +""" +This module contains the tests which ensure the target_tokens parameter is respected. +""" +from fastlane_bot import Bot +from fastlane_bot.tools.cpc import ConstantProductCurve as CPC +from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, SushiswapV2, CarbonV1, BancorV3 +import subprocess, os, sys +import pytest +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CPC)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(Bot)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(UniswapV2)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(UniswapV3)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(SushiswapV2)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(CarbonV1)) +print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(BancorV3)) +from fastlane_bot.testing import * +plt.rcParams['figure.figsize'] = [12,6] +from fastlane_bot import __VERSION__ +require("3.0", __VERSION__) + +# # Setup + +# + +from fastlane_bot.tools.cpc import T + + +def find_main_py(): + # Start at the directory of the current script + cwd = os.path.abspath(os.path.join(os.getcwd())) + + with open("log.txt", "w") as f: + f.write(f"Searching for main.py in {cwd}") + + print(f"Searching for main.py in {cwd}") + while True: + # Check if main.py exists in the current directory + if "main.py" in os.listdir(cwd): + return cwd # Found the directory containing main.py + else: + # If not, go up one directory + new_cwd = os.path.dirname(cwd) + + # If we're already at the root directory, stop searching + if new_cwd == cwd: + raise FileNotFoundError("Could not find main.py in any parent directory") + + cwd = new_cwd + + +def run_command(mode): + + # Find the correct path to main.py + main_script_path = find_main_py() + print(f"Found main.py in {main_script_path}") + main_script_path = main_script_path + "/main.py" + + # Run the command + cmd = [ + "python", + main_script_path, + f"--arb_mode={mode}", + "--use_cached_events=True", + "--logging_path=fastlane_bot/data/", + "--timeout=45", + f"--target_tokens={T.WETH},{T.DAI}" + ] + subprocess.Popen(cmd) + + # Wait for the expected log line to appear + expected_log_line = "Limiting pools by target_tokens. Removed " + found = False + result = subprocess.run(cmd, text=True, capture_output=True, check=True, timeout=120) + + # Check if the expected log line is in the output + if expected_log_line in result.stderr: + found = True + + if not found: + pytest.fail("Expected log line was not found within 1 minute") # If we reach this point, the test has failed + + +# - + +# ## Test Flashloan Tokens b3_two_hop + +run_command("single") diff --git a/setup.py b/setup.py index 084f0d1df..07c6ab6b0 100644 --- a/setup.py +++ b/setup.py @@ -72,7 +72,7 @@ """, long_description=long_description, long_description_content_type="text/markdown", - url="https://github.com/bancorprotocol/carbon-bot", + url="https://github.com/bancorprotocol/fastlane-bot", install_requires=open("requirements.txt").readlines(), extras_require=extras_require, tests_require=["pytest~=6.2.5", "pytest-mock~=3.10.0", "imgkit~=1.2.3"],