diff --git a/fastlane_bot/tests/test_039_TestMultiMode.py b/fastlane_bot/tests/test_039_TestMultiMode.py deleted file mode 100644 index dc47761d1..000000000 --- a/fastlane_bot/tests/test_039_TestMultiMode.py +++ /dev/null @@ -1,248 +0,0 @@ -# ------------------------------------------------------------ -# Auto generated test file `test_039_TestMultiMode.py` -# ------------------------------------------------------------ -# source file = NBTest_039_TestMultiMode.py -# test id = 039 -# test comment = TestMultiMode -# ------------------------------------------------------------ - - - -""" -This module contains the tests for the exchanges classes -""" -from fastlane_bot import Bot, Config -from fastlane_bot.bot import CarbonBot -from fastlane_bot.tools.cpc import ConstantProductCurve as CPC -from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, CarbonV1, BancorV3 -from fastlane_bot.events.interface import QueryInterface -from fastlane_bot.events.managers.manager import Manager -from fastlane_bot.events.interface import QueryInterface -from joblib import Parallel, delayed -import math -import json -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(CarbonV1)) -print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(BancorV3)) -from fastlane_bot.testing import * -#plt.style.use('seaborn-dark') -plt.rcParams['figure.figsize'] = [12,6] -from fastlane_bot import __VERSION__ -require("3.0", __VERSION__) - - - -C = cfg = Config.new(config=Config.CONFIG_MAINNET) -cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN = 0.00001 -assert (C.NETWORK == C.NETWORK_MAINNET) -assert (C.PROVIDER == C.PROVIDER_ALCHEMY) -setup_bot = CarbonBot(ConfigObj=C) -pools = None -with open('fastlane_bot/tests/_data/latest_pool_data_testing.json') as f: - pools = json.load(f) -pools = [pool for pool in pools] -pools[0] -static_pools = pools -state = pools -exchanges = list({ex['exchange_name'] for ex in state}) -db = QueryInterface(state=state, ConfigObj=C, exchanges=exchanges) -setup_bot.db = db - -static_pool_data_filename = "static_pool_data" - -static_pool_data = pd.read_csv(f"fastlane_bot/data/{static_pool_data_filename}.csv", low_memory=False) - -uniswap_v2_event_mappings = pd.read_csv("fastlane_bot/data/uniswap_v2_event_mappings.csv", low_memory=False) - -tokens = pd.read_csv("fastlane_bot/data/tokens.csv", low_memory=False) - -exchanges = "carbon_v1,bancor_v3,uniswap_v3,uniswap_v2,sushiswap_v2" - -exchanges = exchanges.split(",") - - -alchemy_max_block_fetch = 20 -static_pool_data["cid"] = [ - cfg.w3.keccak(text=f"{row['descr']}").hex() - for index, row in static_pool_data.iterrows() - ] -static_pool_data = [ - row for index, row in static_pool_data.iterrows() - if row["exchange_name"] in exchanges -] - -static_pool_data = pd.DataFrame(static_pool_data) -static_pool_data['exchange_name'].unique() -mgr = Manager( - web3=cfg.w3, - w3_async=cfg.w3_async, - cfg=cfg, - pool_data=static_pool_data.to_dict(orient="records"), - SUPPORTED_EXCHANGES=exchanges, - alchemy_max_block_fetch=alchemy_max_block_fetch, - uniswap_v2_event_mappings=uniswap_v2_event_mappings, - tokens=tokens.to_dict(orient="records"), -) - -start_time = time.time() -Parallel(n_jobs=-1, backend="threading")( - delayed(mgr.add_pool_to_exchange)(row) for row in mgr.pool_data -) -cfg.logger.info(f"Time taken to add initial pools: {time.time() - start_time}") - -mgr.deduplicate_pool_data() -cids = [pool["cid"] for pool in mgr.pool_data] -assert len(cids) == len(set(cids)), "duplicate cid's exist in the pool data" -def init_bot(mgr: Manager) -> 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) -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.address: (t.address, int(t.decimals)) for t in tokens if not math.isnan(t.decimals)} -flashloan_tokens = bot.RUN_FLASHLOAN_TOKENS -CCm = bot.get_curves() -pools = db.get_pool_data_with_tokens() - -arb_mode = "multi" - - -# ------------------------------------------------------------ -# Test 039 -# File test_039_TestMultiMode.py -# Segment Test_TAX_TOKENS -# ------------------------------------------------------------ -def test_test_tax_tokens(): -# ------------------------------------------------------------ - - assert any(token.address in cfg.TAX_TOKENS for token in tokens), f"[TestMultiMode], DB does not include any tax tokens" - - for curve in CCm: - for token in cfg.TAX_TOKENS: - assert token not in [curve.params['tknx_addr'], curve.params['tkny_addr']], f"[TestMultiMode], curve {curve} includes tax token {token}" - - -# ------------------------------------------------------------ -# Test 039 -# File test_039_TestMultiMode.py -# Segment Test_MIN_PROFIT -# ------------------------------------------------------------ -def test_test_min_profit(): -# ------------------------------------------------------------ - - assert(cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN <= 0.0001), f"[TestMultiMode], default_min_profit_gas_token must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN}" - - -# ------------------------------------------------------------ -# Test 039 -# File test_039_TestMultiMode.py -# Segment Test_get_arb_finder -# ------------------------------------------------------------ -def test_test_get_arb_finder(): -# ------------------------------------------------------------ - - 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 039 -# File test_039_TestMultiMode.py -# Segment Test_Combos_and_Tokens -# ------------------------------------------------------------ -def test_test_combos_and_tokens(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("multi") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=arb_finder.AO_TOKENS, - ConfigObj=bot.ConfigObj, - ) - all_tokens, combos = finder.find_arbitrage() - - # subjected to the length of `TAX_TOKENS` - assert type(all_tokens) == set, f"[NBTest 039 TestMultiMode] all_tokens is wrong data type. Expected set, found: {type(all_tokens)}" - assert type(combos) == list, f"[NBTest 039 TestMultiMode] combos is wrong data type. Expected list, found: {type(combos)}" - assert len(all_tokens) >= 234, f"[NBTest 039 TestMultiMode] Using wrong dataset, expected at least 234 tokens, found {len(all_tokens)}" - assert len(combos) >= 1398, f"[NBTest 039 TestMultiMode] Using wrong dataset, expected at least 1398 combos, found {len(combos)}" - # - - - -# ------------------------------------------------------------ -# Test 039 -# File test_039_TestMultiMode.py -# Segment Test_Expected_Output -# ------------------------------------------------------------ -def test_test_expected_output(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("multi") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=arb_finder.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) - - r = finder.find_arbitrage() - - multi_carbon_count = 0 - carbon_wrong_direction_count = 0 - for arb in r: - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = arb - if len(best_trade_instructions_dic) > 2: - multi_carbon_count += 1 - carbon_tkn_in = None - for trade in best_trade_instructions_dic: - if "-" in trade["cid"]: - if carbon_tkn_in is None: - carbon_tkn_in = trade["tknin"] - else: - if trade["tknin"] not in carbon_tkn_in: - carbon_wrong_direction_count += 1 - for ti in best_trade_instructions_dic: - for token in cfg.TAX_TOKENS: - assert token not in [ti['tknin'], ti['tknout']], f"[TestMultiMode], trade instruction {ti} includes tax token {token}" - - assert len(r) >= 27, f"[NBTest 039 TestMultiMode] Expected at least 27 arbs, found {len(r)}" - assert multi_carbon_count > 0, f"[NBTest 039 TestMultiMode] Not finding arbs with multiple Carbon curves." - assert carbon_wrong_direction_count == 0, f"[NBTest 039 TestMultiMode] Expected all Carbon curves to have the same tkn in and tkn out. Mixing is currently not supported." - # - - - \ No newline at end of file diff --git a/fastlane_bot/tests/test_042_TestBancorV3ModeTwoHop.py b/fastlane_bot/tests/test_042_TestBancorV3ModeTwoHop.py deleted file mode 100644 index 012c8b757..000000000 --- a/fastlane_bot/tests/test_042_TestBancorV3ModeTwoHop.py +++ /dev/null @@ -1,408 +0,0 @@ -# ------------------------------------------------------------ -# Auto generated test file `test_042_TestBancorV3ModeTwoHop.py` -# ------------------------------------------------------------ -# source file = NBTest_042_TestBancorV3ModeTwoHop.py -# test id = 042 -# test comment = TestBancorV3ModeTwoHop -# ------------------------------------------------------------ - - - -""" -This module contains the tests for the exchanges classes -""" -from fastlane_bot import Bot, Config -from fastlane_bot.bot import CarbonBot -from fastlane_bot.helpers import TxRouteHandler -from fastlane_bot.tools.cpc import ConstantProductCurve -from fastlane_bot.tools.cpc import ConstantProductCurve as CPC -from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, CarbonV1, BancorV3 -from fastlane_bot.events.interface import QueryInterface -from fastlane_bot.events.managers.manager import Manager -from fastlane_bot.events.interface import QueryInterface -from joblib import Parallel, delayed -import math -import json -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(CarbonV1)) -print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(BancorV3)) -from fastlane_bot.testing import * -#plt.style.use('seaborn-dark') -plt.rcParams['figure.figsize'] = [12,6] -from fastlane_bot import __VERSION__ -require("3.0", __VERSION__) - - - -C = cfg = Config.new(config=Config.CONFIG_MAINNET) -cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN = 0.00001 -assert (C.NETWORK == C.NETWORK_MAINNET) -assert (C.PROVIDER == C.PROVIDER_ALCHEMY) -setup_bot = CarbonBot(ConfigObj=C) -pools = None -with open('fastlane_bot/tests/_data/latest_pool_data_testing.json') as f: - pools = json.load(f) -pools = [pool for pool in pools] -pools[0] -static_pools = pools -state = pools -exchanges = list({ex['exchange_name'] for ex in state}) -db = QueryInterface(state=state, ConfigObj=C, exchanges=exchanges) -setup_bot.db = db - -static_pool_data_filename = "static_pool_data" - -static_pool_data = pd.read_csv(f"fastlane_bot/data/{static_pool_data_filename}.csv", low_memory=False) - -uniswap_v2_event_mappings = pd.read_csv("fastlane_bot/data/uniswap_v2_event_mappings.csv", low_memory=False) - -tokens = pd.read_csv("fastlane_bot/data/tokens.csv", low_memory=False) - -exchanges = "carbon_v1,bancor_v3,uniswap_v3,uniswap_v2,sushiswap_v2" - -exchanges = exchanges.split(",") - - -alchemy_max_block_fetch = 20 -static_pool_data["cid"] = [ - cfg.w3.keccak(text=f"{row['descr']}").hex() - for index, row in static_pool_data.iterrows() - ] -static_pool_data = [ - row for index, row in static_pool_data.iterrows() - if row["exchange_name"] in exchanges -] - -static_pool_data = pd.DataFrame(static_pool_data) -static_pool_data['exchange_name'].unique() -mgr = Manager( - web3=cfg.w3, - w3_async=cfg.w3_async, - cfg=cfg, - pool_data=static_pool_data.to_dict(orient="records"), - SUPPORTED_EXCHANGES=exchanges, - alchemy_max_block_fetch=alchemy_max_block_fetch, - uniswap_v2_event_mappings=uniswap_v2_event_mappings, - tokens=tokens.to_dict(orient="records"), -) - -start_time = time.time() -Parallel(n_jobs=-1, backend="threading")( - delayed(mgr.add_pool_to_exchange)(row) for row in mgr.pool_data -) -cfg.logger.info(f"Time taken to add initial pools: {time.time() - start_time}") - -mgr.deduplicate_pool_data() -cids = [pool["cid"] for pool in mgr.pool_data] -assert len(cids) == len(set(cids)), "duplicate cid's exist in the pool data" -def init_bot(mgr: Manager) -> 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) -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.address: (t.address, int(t.decimals)) for t in tokens if not math.isnan(t.decimals)} -flashloan_tokens = bot.RUN_FLASHLOAN_TOKENS -CCm = bot.get_curves() -pools = db.get_pool_data_with_tokens() - -arb_mode = "b3_two_hop" - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_min_profit -# ------------------------------------------------------------ -def test_test_min_profit(): -# ------------------------------------------------------------ - - assert(cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN <= 0.0001), f"[test_bancor_v3_two_hop], default_min_profit_gas_token must be <= 0.0001 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN}" - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_arb_mode_class -# ------------------------------------------------------------ -def test_test_arb_mode_class(): -# ------------------------------------------------------------ - - arb_finder = bot._get_arb_finder("b3_two_hop") - assert arb_finder.__name__ == "ArbitrageFinderTriangleBancor3TwoHop", f"[test_bancor_v3_two_hop] Wrong Arb Finder class, expected ArbitrageFinderTriangleBancor3TwoHop, got {arb_finder.__name__}" - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_Trade_Merge -# ------------------------------------------------------------ -def test_test_trade_merge(): -# ------------------------------------------------------------ - - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = r - ( - ordered_trade_instructions_dct, - tx_in_count, - ) = bot._simple_ordering_by_src_token( - best_trade_instructions_dic, best_src_token - ) - ordered_scaled_dcts = bot._basic_scaling( - ordered_trade_instructions_dct, best_src_token - ) - # Convert the trade instructions - ordered_trade_instructions_objects = bot._convert_trade_instructions( - ordered_scaled_dcts) - tx_route_handler = TxRouteHandler( - trade_instructions=ordered_trade_instructions_objects - ) - agg_trade_instructions = ( - tx_route_handler.aggregate_carbon_trades(ordered_trade_instructions_objects) - if bot._carbon_in_trade_route(ordered_trade_instructions_objects) - else ordered_trade_instructions_objects - ) - # Calculate the trade instructions - calculated_trade_instructions = tx_route_handler.calculate_trade_outputs( - agg_trade_instructions - ) - assert len(calculated_trade_instructions) == 3 - # Aggregate multiple Bancor V3 trades into a single trade - calculated_trade_instructions = TxRouteHandler.aggregate_bancor_v3_trades( - calculated_trade_instructions - ) - assert len(calculated_trade_instructions) == 2 - assert calculated_trade_instructions[0].tknin != "0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C" - assert calculated_trade_instructions[0].tknout != "0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C" - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_get_optimal_arb_trade_amts -# ------------------------------------------------------------ -def test_test_get_optimal_arb_trade_amts(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = r - ( - ordered_trade_instructions_dct, - tx_in_count, - ) = bot._simple_ordering_by_src_token( - best_trade_instructions_dic, best_src_token - ) - - - pool_cids = [curve['cid'] for curve in ordered_trade_instructions_dct] - first_check_pools = finder.get_exact_pools(pool_cids) - - assert first_check_pools[0].cid == pool_cids[0], f"[test_bancor_v3_two_hop] Validation, wrong first pool, expected CID: 0x7be3da0f8d0f70d8f7a84a08dd267beea4318ed1c9fb3d602b0f3a3c7bd1cf4a, got CID: {first_check_pools[0].cid}" - assert first_check_pools[1].cid == pool_cids[1], f"[test_bancor_v3_two_hop] Validation, wrong second pool, expected CID: 0x748ab2bef0d97e5a044268626e6c9c104bab818605d44f650fdeaa03a3c742d2, got CID: {first_check_pools[1].cid}" - assert first_check_pools[2].cid == pool_cids[2], f"[test_bancor_v3_two_hop] Validation, wrong third pool, expected CID: 0xb1d8cd62f75016872495dae3e19d96e364767e7d674488392029d15cdbcd7b34, got CID: {first_check_pools[2].cid}" - assert(len(first_check_pools) == 3), f"[test_bancor_v3_two_hop] Validation expected 3 pools, got {len(first_check_pools)}" - for pool in first_check_pools: - assert type(pool) == ConstantProductCurve, f"[test_bancor_v3_two_hop] Validation pool type mismatch, got {type(pool)} expected ConstantProductCurve" - assert pool.cid in pool_cids, f"[test_bancor_v3_two_hop] Validation missing pool.cid {pool.cid} in {pool_cids}" - - optimal_arb = finder.get_optimal_arb_trade_amts(pool_cids, 'DAI-1d0F') - assert type(optimal_arb) == float, f"[test_bancor_v3_two_hop] Optimal arb calculation type is {type(optimal_arb)} not float" - # - - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_max_arb_trade_in_constant_product -# ------------------------------------------------------------ -def test_test_max_arb_trade_in_constant_product(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = r - ( - ordered_trade_instructions_dct, - tx_in_count, - ) = bot._simple_ordering_by_src_token( - best_trade_instructions_dic, best_src_token - ) - - - pool_cids = [curve['cid'] for curve in ordered_trade_instructions_dct] - first_check_pools = finder.get_exact_pools(pool_cids) - flt='0x6B175474E89094C44Da98b954EedeAC495271d0F' - tkn0 = flt - tkn1 = finder.get_tkn(pool=first_check_pools[0], tkn_num=1) if finder.get_tkn(pool=first_check_pools[0], tkn_num=1) != flt else finder.get_tkn(pool=first_check_pools[0], tkn_num=0) - tkn2 = finder.get_tkn(pool=first_check_pools[1], tkn_num=0) if finder.get_tkn(pool=first_check_pools[1], tkn_num=0) == tkn1 else finder.get_tkn(pool=first_check_pools[1], tkn_num=1) - tkn3 = finder.get_tkn(pool=first_check_pools[1], tkn_num=0) if finder.get_tkn(pool=first_check_pools[1], tkn_num=0) != tkn1 else finder.get_tkn(pool=first_check_pools[1], tkn_num=1) - tkn5 = finder.get_tkn(pool=first_check_pools[2], tkn_num=1) if finder.get_tkn(pool=first_check_pools[2], tkn_num=1) == flt else finder.get_tkn(pool=first_check_pools[2], tkn_num=0) - p0t0 = first_check_pools[0].x if finder.get_tkn(pool=first_check_pools[0], tkn_num=0) == flt else first_check_pools[0].y - p0t1 = first_check_pools[0].y if finder.get_tkn(pool=first_check_pools[0], tkn_num=0) == flt else first_check_pools[0].x - p1t0 = first_check_pools[1].x if tkn1 == finder.get_tkn(pool=first_check_pools[1], tkn_num=0) else first_check_pools[1].y - p1t1 = first_check_pools[1].y if tkn1 == finder.get_tkn(pool=first_check_pools[1], tkn_num=0) else first_check_pools[1].x - p2t0 = first_check_pools[2].x if finder.get_tkn(pool=first_check_pools[2], tkn_num=0) != flt else first_check_pools[2].y - p2t1 = first_check_pools[2].y if finder.get_tkn(pool=first_check_pools[2], tkn_num=0) != flt else first_check_pools[2].x - fee0 = finder.get_fee_safe(first_check_pools[0].fee) - fee1 = finder.get_fee_safe(first_check_pools[1].fee) - fee2 = finder.get_fee_safe(first_check_pools[2].fee) - optimal_arb = finder.get_optimal_arb_trade_amts(pool_cids, '0x6B175474E89094C44Da98b954EedeAC495271d0F') - optimal_arb_low_level_check = finder.max_arb_trade_in_constant_product(p0t0=p0t0, p0t1=p0t1, p1t0=p1t0, p1t1=p1t1, p2t0=p2t0, p2t1=p2t1,fee0=fee0, fee1=fee1, fee2=fee2) - assert iseq(optimal_arb, optimal_arb_low_level_check), f"[test_bancor_v3_two_hop] Arb calculation result mismatch, pools likely ordered incorrectly, previous calc: {optimal_arb}, this calc: {optimal_arb_low_level_check}" - # max_arb_in = finder.max_arb_trade_in_constant_product(p0t0, p0t1, p1t0, p1t1, p2t0, p2t1, fee0=fee0, fee1=fee1, fee2=fee2) - # finder.ConfigObj.logger.info(f"\n\nfirst_check_pools: {first_check_pools}\n\nValidating trade, max_arb_in= {max_arb_in} {tkn0} -> {tkn1} -> {tkn3} -> {tkn5}, token amts: {p0t0, p0t1, p1t0, p1t1, p2t0, p2t1}, fees: {fee0, fee1, fee2}") - # - - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_get_fee_safe -# ------------------------------------------------------------ -def test_test_get_fee_safe(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = r - ( - ordered_trade_instructions_dct, - tx_in_count, - ) = bot._simple_ordering_by_src_token( - best_trade_instructions_dic, best_src_token - ) - - pool_cids = [curve['cid'] for curve in ordered_trade_instructions_dct] - first_check_pools = finder.get_exact_pools(pool_cids) - ext_fee = finder.get_fee_safe(first_check_pools[0].fee) - - for pool in first_check_pools: - ext_fee = finder.get_fee_safe(pool.fee) - assert type(ext_fee) == float, f"[test_bancor_v3_two_hop] Testing external pool, fee type is {type(ext_fee)} not float" - # - - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_combos -# ------------------------------------------------------------ -def test_test_combos(): -# ------------------------------------------------------------ - - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - #test_2_pools = [ConstantProductCurve(k=2921921249910.464, x=2760126.9934445512, x_act=2760126.9934445512, y_act=1058618.410258, pair='BNT-FF1C/USDC-eB48', cid='0xc4771395e1389e2e3a12ec22efbb7aff5b1c04e5ce9c7596a82e9dc8fdec725b', fee=0.0, descr='bancor_v3 BNT-FF1C/USDC-eB48 0.000', constr='uv2', params={'exchange': 'bancor_v3', 'tknx_dec': 18, 'tkny_dec': 6, 'tknx_addr': '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C', 'tkny_addr': '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 'blocklud': 17713739}), ConstantProductCurve(k=518129588.60853314, x=6351922.348885405, x_act=6351922.348885405, y_act=81.57051679, pair='BNT-FF1C/WBTC-C599', cid='0x3885d978c125e66686e3f678ab64d5b09e61f89bf6e87c9ff66e740fd06aeefa', fee=0.0, descr='bancor_v3 BNT-FF1C/WBTC-C599 0.000', constr='uv2', params={'exchange': 'bancor_v3', 'tknx_dec': 18, 'tkny_dec': 8, 'tknx_addr': '0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C', 'tkny_addr': '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 'blocklud': 17713739}), ConstantProductCurve(k=787603837541.6204, x=5107.692365701484, x_act=4.159867948255851, y_act=336571.44633978605, pair='WBTC-C599/USDC-eB48', cid='0x49ed97db2c080b7eac91dfaa7d51d5e8ac34c4dcfbcd3e8f2ed326a2a527b959', fee=0.003, descr='uniswap_v3 WBTC-C599/USDC-eB48 3000', constr='pkpp', params={'exchange': 'uniswap_v3', 'tknx_dec': 8, 'tkny_dec': 6, 'tknx_addr': '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599', 'tkny_addr': '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 'blocklud': 17713395, 'L': 887470.4713632})] - flt = {'MKR-79A2', 'TRAC-0A6F', 'MONA-412A', 'WBTC-C599', 'WOO-5D4B', 'MATIC-eBB0', 'BAT-87EF', 'UOS-5C8c', 'LRC-EafD', 'NMR-6671', 'DIP-cD83', 'TEMP-1aB9', 'ICHI-A881', 'USDC-eB48', 'ENS-9D72', 'vBNT-7f94', 'ANKR-EDD4', 'UNI-F984', 'REQ-938a', 'WETH-6Cc2', 'AAVE-DaE9', 'ENJ-3B9c', 'MANA-C942', 'wNXM-2bDE', 'QNT-4675', 'RLC-7375', 'CROWN-E0fa', 'CHZ-b4AF', 'USDT-1ec7', 'DAI-1d0F', 'RPL-A51f', 'HOT-26E2', 'LINK-86CA', 'wstETH-2Ca0'} - combos = finder.get_combos(flashloan_tokens=flt, CCm=CCm, arb_mode="b3_two_hop") - print(combos) - assert len(combos) >= 1122, "[test_bancor_v3_two_hop] Different data used for tests, expected 1122 combos" - - -# ------------------------------------------------------------ -# Test 042 -# File test_042_TestBancorV3ModeTwoHop.py -# Segment Test_get_miniverse_combos -# ------------------------------------------------------------ -def test_test_get_miniverse_combos(): -# ------------------------------------------------------------ - - arb_finder = bot._get_arb_finder("b3_two_hop") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=False, - ConfigObj=bot.ConfigObj, - ) - flt = {"0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C","0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2","0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48","0x514910771AF9Ca656af840dff83E8264EcF986CA"} - combos = finder.get_combos(flashloan_tokens=flt, CCm=CCm, arb_mode="b3_two_hop") - all_miniverses = finder.get_miniverse_combos(combos) - assert len(all_miniverses) >= 6, f"[test_bancor_v3_two_hop] Different data used for tests, expected 6 miniverses, found {len(all_miniverses)}" \ No newline at end of file diff --git a/fastlane_bot/tests/test_050_TestBancorV2.py b/fastlane_bot/tests/test_050_TestBancorV2.py deleted file mode 100644 index 45a036f8f..000000000 --- a/fastlane_bot/tests/test_050_TestBancorV2.py +++ /dev/null @@ -1,320 +0,0 @@ -# ------------------------------------------------------------ -# Auto generated test file `test_050_TestBancorV2.py` -# ------------------------------------------------------------ -# source file = NBTest_050_TestBancorV2.py -# test id = 050 -# test comment = TestBancorV2 -# ------------------------------------------------------------ - - - -""" -This module contains the tests for the exchanges classes -""" -from fastlane_bot import Bot, Config -from fastlane_bot.bot import CarbonBot -from fastlane_bot.helpers import TxRouteHandler -from fastlane_bot.tools.cpc import ConstantProductCurve as CPC -from fastlane_bot.events.exchanges import UniswapV2, UniswapV3, CarbonV1, BancorV3 -from fastlane_bot.events.interface import QueryInterface -from fastlane_bot.events.managers.manager import Manager -from fastlane_bot.events.interface import QueryInterface -from joblib import Parallel, delayed -from fastlane_bot.tools.cpc import ConstantProductCurve as CPC, T -from dataclasses import asdict -import math -import json -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(CarbonV1)) -print("{0.__name__} v{0.__VERSION__} ({0.__DATE__})".format(BancorV3)) -from fastlane_bot.testing import * -#plt.style.use('seaborn-dark') -plt.rcParams['figure.figsize'] = [12,6] -from fastlane_bot import __VERSION__ -require("3.0", __VERSION__) - - - -C = cfg = Config.new(config=Config.CONFIG_MAINNET) -cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN = 0.00001 -assert (C.NETWORK == C.NETWORK_MAINNET) -assert (C.PROVIDER == C.PROVIDER_ALCHEMY) -setup_bot = CarbonBot(ConfigObj=C) -pools = None - -with open('fastlane_bot/tests/_data/latest_pool_data_testing.json') as f: - pools = json.load(f) -pools = [pool for pool in pools] -pools[0] -static_pools = pools -state = pools -exchanges = list({ex['exchange_name'] for ex in state}) -db = QueryInterface(state=state, ConfigObj=C, exchanges=exchanges) -setup_bot.db = db - -static_pool_data_filename = "static_pool_data" - -static_pool_data = pd.read_csv(f"fastlane_bot/data/{static_pool_data_filename}.csv", low_memory=False) - -uniswap_v2_event_mappings = pd.read_csv("fastlane_bot/data/uniswap_v2_event_mappings.csv", low_memory=False) - -tokens = pd.read_csv("fastlane_bot/data/tokens.csv", low_memory=False) - -exchanges = "carbon_v1,bancor_v3,uniswap_v3,uniswap_v2,sushiswap_v2" - -exchanges = exchanges.split(",") - - -alchemy_max_block_fetch = 20 -static_pool_data["cid"] = [ - cfg.w3.keccak(text=f"{row['descr']}").hex() - for index, row in static_pool_data.iterrows() - ] -static_pool_data = [ - row for index, row in static_pool_data.iterrows() - if row["exchange_name"] in exchanges -] - -static_pool_data = pd.DataFrame(static_pool_data) -static_pool_data['exchange_name'].unique() -mgr = Manager( - web3=cfg.w3, - w3_async=cfg.w3_async, - cfg=cfg, - pool_data=static_pool_data.to_dict(orient="records"), - SUPPORTED_EXCHANGES=exchanges, - alchemy_max_block_fetch=alchemy_max_block_fetch, - uniswap_v2_event_mappings=uniswap_v2_event_mappings, - tokens=tokens.to_dict(orient="records"), -) - -start_time = time.time() -Parallel(n_jobs=-1, backend="threading")( - delayed(mgr.add_pool_to_exchange)(row) for row in mgr.pool_data -) -cfg.logger.info(f"Time taken to add initial pools: {time.time() - start_time}") - -mgr.deduplicate_pool_data() -cids = [pool["cid"] for pool in mgr.pool_data] -assert len(cids) == len(set(cids)), "duplicate cid's exist in the pool data" -def init_bot(mgr: Manager) -> 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) -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.address: (t.address, int(t.decimals)) for t in tokens if not math.isnan(t.decimals)} -flashloan_tokens = bot.RUN_FLASHLOAN_TOKENS -CCm = bot.get_curves() -pools = db.get_pool_data_with_tokens() - -arb_mode = "multi" - - -# ------------------------------------------------------------ -# Test 050 -# File test_050_TestBancorV2.py -# Segment Test_MIN_PROFIT -# ------------------------------------------------------------ -def test_test_min_profit(): -# ------------------------------------------------------------ - - assert(cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN <= 0.0001), f"[TestBancorV2Mode], default_min_profit_gas_token must be <= 0.02 for this Notebook to run, currently set to {cfg.DEFAULT_MIN_PROFIT_GAS_TOKEN}" - - - -# ------------------------------------------------------------ -# Test 050 -# File test_050_TestBancorV2.py -# Segment Test_Combos_and_Tokens -# ------------------------------------------------------------ -def test_test_combos_and_tokens(): -# ------------------------------------------------------------ - - arb_finder = bot._get_arb_finder("multi") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=arb_finder.AO_TOKENS, - ConfigObj=bot.ConfigObj, - ) - all_tokens, combos = finder.find_arbitrage() - assert type(all_tokens) == set, f"[NBTest_50_TestBancorV2] all_tokens is wrong data type. Expected set, found: {type(all_tokens)}" - assert type(combos) == list, f"[NBTest_50_TestBancorV2] combos is wrong data type. Expected list, found: {type(combos)}" - assert len(all_tokens) > 100, f"[NBTest_50_TestBancorV2] Using wrong dataset, expected at least 100 tokens, found {len(all_tokens)}" - assert len(combos) > 1000, f"[NBTest_50_TestBancorV2] Using wrong dataset, expected at least 100 combos, found {len(combos)}" - - - -# ------------------------------------------------------------ -# Test 050 -# File test_050_TestBancorV2.py -# Segment Test_Expected_Output_BancorV2 -# ------------------------------------------------------------ -def test_test_expected_output_bancorv2(): -# ------------------------------------------------------------ - - # + - arb_finder = bot._get_arb_finder("multi_pairwise_all") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=arb_finder.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - - arb_with_bancor_v2 = [] - for arb_opp in r: - pools = [] - for pool in arb_opp[2]: - pools += [curve for curve in CCm if curve.cid == pool['cid']] - for pool in pools: - if pool.params['exchange'] == "bancor_v2": - arb_with_bancor_v2.append(arb_opp) - - assert len(r) >= 27, f"[NBTest_50_TestBancorV2] Expected at least 27 arb opps, found {len(r)}" - assert len(arb_with_bancor_v2) >= 3, f"[NBTest_50_TestBancorV2] Expected at least 3 arb opps with Bancor V2 pools, found {len(arb_with_bancor_v2)}" - - # + - arb_finder = bot._get_arb_finder("multi_pairwise_all") - finder = arb_finder( - flashloan_tokens=flashloan_tokens, - CCm=CCm, - mode="bothin", - result=arb_finder.AO_CANDIDATES, - ConfigObj=bot.ConfigObj, - ) - r = finder.find_arbitrage() - arb_with_bancor_v2 = [] - for arb_opp in r: - pools = [] - for pool in arb_opp[2]: - pools += [curve for curve in CCm if curve.cid == pool['cid']] - for pool in pools: - if pool.params['exchange'] == "bancor_v2": - arb_with_bancor_v2.append(arb_opp) - - # get specific arb for tests - test_arb = arb_with_bancor_v2[0] - - ( - best_profit, - best_trade_instructions_df, - best_trade_instructions_dic, - best_src_token, - best_trade_instructions, - ) = test_arb - - # Order the trade instructions - ( - ordered_trade_instructions_dct, - tx_in_count, - ) = bot._simple_ordering_by_src_token( - best_trade_instructions_dic, best_src_token - ) - - # Scale the trade instructions - ordered_scaled_dcts = bot._basic_scaling( - ordered_trade_instructions_dct, best_src_token - ) - - # Convert the trade instructions - ordered_trade_instructions_objects = bot._convert_trade_instructions( - ordered_scaled_dcts - ) - - # Create the tx route handler - tx_route_handler = TxRouteHandler( - trade_instructions=ordered_trade_instructions_objects - ) - - # Aggregate the carbon trades - agg_trade_instructions = ( - tx_route_handler.aggregate_carbon_trades(ordered_trade_instructions_objects) - if bot._carbon_in_trade_route(ordered_trade_instructions_objects) - else ordered_trade_instructions_objects - ) - - # Calculate the trade instructions - calculated_trade_instructions = tx_route_handler.calculate_trade_outputs( - agg_trade_instructions - ) - - # Aggregate multiple Bancor V3 trades into a single trade - calculated_trade_instructions = tx_route_handler.aggregate_bancor_v3_trades( - calculated_trade_instructions - ) - - # Get the flashloan token - fl_token = fl_token_with_weth = calculated_trade_instructions[0].tknin_address - - # If the flashloan token is WETH, then use ETH - if fl_token == T.WETH: - fl_token = T.NATIVE_ETH - - best_profit = flashloan_tkn_profit = tx_route_handler.calculate_trade_profit(calculated_trade_instructions) - - # Use helper function to calculate profit - best_profit, flt_per_bnt, profit_usd = bot.calculate_profit( - CCm, best_profit, fl_token, - ) - - # Get the flashloan amount and token address - flashloan_amount = int(calculated_trade_instructions[0].amtin_wei) - flashloan_token_address = bot.ConfigObj.w3.to_checksum_address( - bot.db.get_token(tkn_address=fl_token).address - ) - - # Encode the trade instructions - encoded_trade_instructions = tx_route_handler.custom_data_encoder( - calculated_trade_instructions - ) - - # Get the deadline - deadline = bot._get_deadline(1) - - # Get the route struct - route_struct = [ - asdict(rs) - for rs in tx_route_handler.get_route_structs( - encoded_trade_instructions, deadline - ) - ] - b2pools = [pool['anchor'] for pool in mgr.pool_data if pool["exchange_name"] in "bancor_v2"] - bancor_v2_converter_addresses = [pool["anchor"] for pool in state if pool["exchange_name"] in "bancor_v2"] - assert arb_finder.__name__ == "FindArbitrageMultiPairwiseAll", f"[NBTest_50_TestBancorV2] Expected arb_finder class name name = FindArbitrageMultiPairwise, found {arb_finder.__name__}" - assert len(r) > 30, f"[NBTest_50_TestBancorV2] Expected at least 30 arb opps, found {len(r)}" - assert len(arb_with_bancor_v2) >= 3, f"[NBTest_50_TestBancorV2] Expected at least 3 arb opps with Bancor V2 pools, found {len(arb_with_bancor_v2)}" - assert encoded_trade_instructions[0].amtin_wei == flashloan_amount, f"[NBTest_50_TestBancorV2] First trade in should match flashloan amount, {encoded_trade_instructions[0].amtin_wei} does not = {flashloan_amount}" - assert route_struct[0]['customAddress'] in bancor_v2_converter_addresses or route_struct[1]['customAddress'] in bancor_v2_converter_addresses, f"[NBTest_50_TestBancorV2] customAddress for Bancor V2.1 trade must be converter token address, expected: anchor for Bancor V2 pool for one address, found: {route_struct[0]['customAddress']} and {route_struct[1]['customAddress']}" - # - - - - \ No newline at end of file