def estimateGas(web3_ins: Web3, fun_with_args: str, tx_args: Dict,
                contract_abi: List[Dict], contract_address: str) -> int:
    c = web3_ins.eth.contract(abi=contract_abi, address=contract_address)
    f = f"c.functions.{fun_with_args}.estimateGas({tx_args})"
    try:
        return eval(f)
    except:
        raise
    finally:
        logger.info("estimategas_contract_fun:{}".format(f))
Beispiel #2
0
def getWhiteTokens(tokens_file: str = "files/white_tokens.json",
                   redownload: bool = False) -> Dict:
    tmr = timer()
    next(tmr)
    logger.info("Loading tokens ...")
    with open(tokens_file, "a+") as rwop:
        tokens = {}
        rwop.seek(0)
        data = rwop.read()
        if data and not redownload:
            tokens = json.loads(data)
        else:
            tokens = downloadtokens()
            rwop.truncate(0)
            rwop.write(json.dumps(tokens, indent=4))

        logger.info(f"white_tokens_num: {len(tokens)} time_use: {next(tmr)}")
        return tokens
Beispiel #3
0
def getAllPairAddress(eth_http:str, pairs_file:str="files/all_pair_address.json",
        redownload:bool=False, programStatus:ProgramStatus=ProgramStatus()) -> List[str]:

    tmr = timer()
    next(tmr)
    logger.info("Loading all pair address ...")
    with open(pairs_file, "a+") as rwop:
        all_pairs_address = []
        rwop.seek(0)
        data = rwop.read()
        if data and not redownload:
            all_pairs_address = json.loads(data)
        else:
            all_pairs_address = get_allPairAddress(eth_http=eth_http, programStatus=programStatus)
            rwop.truncate(0)
            rwop.write(json.dumps(all_pairs_address, indent=4))

        logger.info(f"pairs_address_num: {len(all_pairs_address)} time_use: {next(tmr)}")
        return all_pairs_address
Beispiel #4
0
    def __init__(self, eth_http: str, pairs: List[Dict], white_tokens: Dict,
                 reserve_min_amount: int, fallback_fun: Callable[[List[Dict]],
                                                                 None]):
        threading.Thread.__init__(self)

        self.__lock = threading.Lock()
        self.__eth_http = eth_http
        self.__all_pairs = pairs
        self.__white_tokens = white_tokens
        self.__reserve_min_amount = reserve_min_amount
        self.__fallback_fun = fallback_fun
        self.__timer = timer()

        self.__white_pairs_change = True

        next(self.__timer)
        self.__white_pairs_index, self.__white_pairs_list = Liquidity.__filterPairs(
            self.__all_pairs, self.__white_tokens)
        logger.info(
            f"Liquidity white_pairs_num: {len(self.__white_pairs_list)} time_use: {next(self.__timer)}"
        )
Beispiel #5
0
    def __updateReserves(self, web3_ins: Web3,
                         batch_provider_ins: BatchHTTPProvider) -> None:
        next(self.__timer)
        get_reserves(web3_ins, batch_provider_ins, self.__white_pairs_list)
        pairs_len = len(self.__white_pairs_list)
        num = 0
        for i in range(0, pairs_len):
            num += self.__disablePair(i)

        self.__saveToFile()
        logger.info(f"__updateReserves all_pair_num: {pairs_len}")
        logger.info(f"__updateReserves disable_pair_num: {num}")
        logger.info(f"__updateReserves enable_pair_num: {pairs_len-num}")
        logger.info(f"__updateReserves time_use: {next(self.__timer)}")
Beispiel #6
0
def main(pairs:List[Dict])->None:
    pairs = randSelect(pairs, dfsUsePairNum)
    logger.info(f"pairs num_use: {len(pairs)}")

    next(tmr)
    currentPairs = []
    path = [tokenIn]
    bestTrades = []
    trades = findArb(
            pairs=pairs,
            tokenIn=tokenIn,
            tokenOut=tokenOut,
            maxHops=maxHops,
            currentPairs=currentPairs,
            path=path,
            bestTrades=bestTrades,
            programStatus=programStatus,
            count=10,
            )

    logger.info(f"dfs time_use: {next(tmr)}")
    for trade in trades:
        amountsOut = trade["amountsOut"]
        # in/out
        amount_in = amountsOut[0]
        amount_out = amountsOut[-1]

        logger.info(f"--- path0: {trade['path'][0]['symbol']} path-1: {trade['path'][-1]['symbol']}")

        #a = getAmountsOut(web3_ins=web3_ins, amount_in=amount_in, token_address_path=[d["address"] for d in trade["path"]])
        # amount out on slide point
        amount_out_slide_point = int(amount_out*(1-slidePoint))

        # min profit
        profit_slide_point = amount_out_slide_point - amount_in

        # swapExactTokensForTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        # exactAmountIn, amountOutMin
        fun_args = {
                "amountIn":amount_in,
                "amountOutMin":amount_out_slide_point,
                "path":[p["address"] for p in trade["path"]],
                "to": f"'{address_tx_sender}'",
                "deadline":int(time.time()+100),
                }
        fun_with_args = "swapExactTokensForTokensSupportingFeeOnTransferTokens({amountIn}, {amountOutMin}, {path}, {to}, {deadline})".format(**fun_args)
        tx_args = {
                "from": address_tx_sender
                }
        try:
            gas = estimateGas(
                    web3_ins=web3_ins,
                    fun_with_args=fun_with_args,
                    tx_args=tx_args,
                    contract_abi=router_abi.abi(),
                    contract_address=address_router_contract)

            logger.info(f"gasUsed: {gas}")
        except:
            logger.error(f"fun estimateGas get exception:{traceback.format_exc()}")
            return

        gas_fee = gasPrice*gas

        logger.info(f"gasFee: {gas_fee/pow(10,18)} Eth")
        logger.info(f"theoryProfit: {trade['profit']/pow(10,18)} Eth")
        logger.info(f"profitSlidePoint: {profit_slide_point/pow(10,18)} Eth")
        profit_fee_on = int(profit_slide_point-gas_fee)/pow(10, startToken['decimal'])
        tag = "Insufficient"
        if profit_fee_on >= minProfit:
            tag = "Satisfy"
            logger.info(json.dumps(trade, cls=JsonCustomEncoder))
        logger.info(f"---- {tag} ProfitFeeOn ----: {profit_fee_on} Eth")

        break
Beispiel #7
0
if __name__ == "__main__":
    usage = "usage: python3 main.py [options] arg"
    parser = OptionParser(usage=usage,description="command descibe")
    parser.add_option("--redownload_tokens", action='store_true', dest="redownload_tokens", default=False, help="redownload tokens")
    parser.add_option("--redownload_pairs_address", action='store_true', dest="redownload_pairs_address", default=False, help="redownload pairs address")
    parser.add_option("--redownload_pairs_info", action='store_true', dest="redownload_pairs_info", default=False, help="redownload pairs info")

    (options, args) = parser.parse_args()

    white_tokens = getWhiteTokens(redownload=options.redownload_tokens)
    all_pair_info = getAllPairInfo(
            eth_http=ethereum_http,
            redownload_pairinfo=options.redownload_pairs_info,
            redownload_pairaddress=options.redownload_pairs_address,
            programStatus=programStatus,
            )

    t = Liquidity(
            eth_http=ethereum_http,
            pairs=all_pair_info,
            white_tokens=white_tokens,
            reserve_min_amount=reserveMinAmount,
            fallback_fun=main,
            )
    t.start()
    t.join()

    logger.info("---- exit ----")

Beispiel #8
0
    def run(self):
        sync_topic = pair_abi.topic("Sync")
        while programStatus.running():
            try:
                web3_ins = Web3(Web3.HTTPProvider(self.__eth_http))
                batch_provider = BatchHTTPProvider(self.__eth_http)

                # update event from latest block
                latest_block = web3_ins.eth.getBlock("latest")
                logger.info(f"latest_block: {latest_block.number}")

                with self.__lock:
                    self.__updateReserves(web3_ins, batch_provider)

                attached_pair_contract = web3_ins.eth.contract(
                    abi=pair_abi.abi())
                event_filter = attached_pair_contract.events.Sync(
                ).createFilter(fromBlock=latest_block.number,
                               toBlock="latest",
                               topics=[sync_topic])
                block_filter = web3_ins.eth.filter("latest")

                # all events for latest block
                events = event_filter.get_all_entries()
                if events:
                    with self.__lock:
                        blk_events_count = {}
                        for event in events:
                            self.__dealEvent(event, blk_events_count)
                        logger.info(
                            f"Block liquidity_update_num(keys:{len(blk_events_count.keys())}): {json.dumps(blk_events_count)}"
                        )

                while programStatus.running():
                    blocks = block_filter.get_new_entries()
                    events = event_filter.get_new_entries()
                    if events:
                        with self.__lock:
                            blk_events_count = {}
                            for event in events:
                                self.__dealEvent(event, blk_events_count)
                            logger.info(
                                f"Block liquidity_update_num(keys:{len(blk_events_count.keys())}): {json.dumps(blk_events_count)}"
                            )

                    if not blocks:
                        self.__saveToFile()
                        continue

                    logger.info(f"new blocks: {[b.hex() for b in blocks]}")

                    with self.__lock:
                        # deepcopy self.__white_pairs_list
                        x = []
                        for d in self.__white_pairs_list:
                            if not d["enable"]:
                                continue

                            x1 = {}
                            for k, v in d.items():
                                v1 = v
                                if type(v) == dict:
                                    v1 = {tk: tv for tk, tv in v.items()}
                                x1.update({k: v1})
                            x.append(x1)

                        try:
                            self.__fallback_fun(x)
                        except:
                            logger.error(
                                f"exec __fallback_fun(x) get exception:{traceback.format_exc()}"
                            )
            except:
                logger.error(
                    f"exec Liquidity get exception:{traceback.format_exc()}")
                logger.warning("reconnect ...")
                time.sleep(3)