| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- from web3Tools import *
- from calcTools import *
- def calOnlyLpInRouterArray(routerArray):
- onlyLpArray = []
- for router in routerArray:
- for lpInfo in router:
- lp = lpInfo['lp']
- if lp in onlyLpArray:
- continue
- if lp in nowBlockLpRes:
- continue
- onlyLpArray.append(lp)
- return onlyLpArray
- def findLpArrayRouter(lpArray, lpRouter256Info):
- routerArray = []
- sumUsed = {}
- for lpAddress in lpArray:
- if lpAddress not in lpRouter256Info:
- continue
- lpRouter = lpRouter256Info[lpAddress]
- for lpRouterI in lpRouter:
- sumValue = ''
- same = False
- for lpi in lpRouterI:
- sumValue = sumValue + lpi['lp'] + lpi['inToken']
- if lpi['lp'] == lpAddress:
- same = True
- if same:
- sumUsed[sumValue] = lpRouterI
- for key in sumUsed:
- routerArray.append(sumUsed[key])
- return routerArray
- def calLpInTradeInfo(tradeInfo):
- lpArray = []
- for i in tradeInfo:
- if i['to'] in topLpInfo and i['to'] not in lpArray:
- lpArray.append(i['to'])
- if i['from'] in topLpInfo and i['from'] not in lpArray:
- lpArray.append(i['from'])
- return lpArray
- def gethashInfo(hsResult):
- try:
- hashInfo = {}
- hashInfo['fromAddress'] = hsResult['from']
- hashInfo['toAddress']= hsResult['to']
- hashInfo['inputData'] = hsResult['input']
- hashInfo['function'] = hashInfo['inputData'][:10]
- hashInfo['value'] = int(hsResult['value'], 16)
- hashInfo['nonce'] = int(hsResult['nonce'], 16) # 对比nonce
- hashInfo['hash'] = hsResult['hash']
- hashInfo['gasLimit'] = int(hsResult['gas'], 16)
- hashInfo['type'] = int(hsResult['type'],16)
- hashInfo['gasPrice'] = int(hsResult['gasPrice'], 16)
- if hashInfo['type'] == 2:
- hashInfo['maxFeePerGas'] = int(hsResult['maxFeePerGas'], 16)
- hashInfo['maxPriorityFeePerGas'] = int(hsResult['maxPriorityFeePerGas'], 16)
- return hashInfo
- except:
- return False
-
- def getLpArrayResAfterTrade(fromAddress, toAddress, inputData, value, lpArray, block = 'latest'):
- paramsRes = {}
- paramsRes['to'] = toolsAddress
- paramsRes['data'] = '0xd94ccee1' + encodeInput(0x20, lpArray)
- params0 = {}
- params0['from'] = fromAddress
- params0['to'] = toAddress
- params0['data'] = inputData
- params0['value'] = hex(int(value))
- r = batchCall([params0, paramsRes], block)
- result = r['result'][1]['Return']
- result = w3.debug.decodeOutput(result)
- info = {}
- length = len(lpArray)
- for index in range(0, length):
- lpAddress = lpArray[index]
- r0 = result[index + 3]
- r1 = result[index + 4 + length]
- info[lpAddress] = [r0, r1]
- return info
- def calRouterProfit(router):
- # 整理LP信息
- for lpInfo in router:
- lpAddress = lpInfo['lp']
- r0 = nowBlockLpRes[lpAddress][0]
- r1 = nowBlockLpRes[lpAddress][1]
- lpInfo['fee'] = topLpInfo[lpAddress]['fee']
- if lpInfo['inToken'] < lpInfo['outToken']:
- lpInfo['rIn'] = r0
- lpInfo['rOut'] = r1
- else:
- lpInfo['rIn'] = r1
- lpInfo['rOut'] = r0
- # ABA
- if len(router) == 2:
- tokenLoan = router[1]['outToken']
- tokenIn0 = router[0]['inToken']
- tokenLoanETHPrice = baseTokenInfo[tokenLoan]['price'] * 10 ** baseTokenInfo[WETH]['decimals'] / 10 ** baseTokenInfo[tokenLoan]['decimals']
- # WETH - A - WETH
- tradeInfo = calBestAmountV2V2(router[0]['rIn'], router[0]['rOut'], router[0]['fee'], router[1]['rIn'], router[1]['rOut'], router[1]['fee'] )
- profit = tradeInfo['profit']
- tradeInfo['ethProfit'] = profit * tokenLoanETHPrice
- #printTime(router, amountIn0, amountOut0, amountOut1, profit)
- if tradeInfo['ethProfit'] < tradeMinProfit:
- return False
- else:
- tradeInfo['lp0'] = router[0]['lp']
- tradeInfo['lp1'] = router[1]['lp']
- tradeInfo['fee0'] = router[0]['fee']
- tradeInfo['fee1'] = router[1]['fee']
- tradeInfo['indexIn0'] = router[0]['indexIn']
- tradeInfo['indexIn1'] = router[1]['indexIn']
- tradeInfo['tokenLoan'] = tokenLoan
- tradeInfo['tokenIn0'] = tokenIn0
- tradeInfo['tradeToken0'] = router[0]['outToken']
- tradeInfo['type'] = 'type2'
- return tradeInfo
- # ABCA
- elif len(router) == 3:
- tokenLoan = router[2]['outToken']
- tokenIn0 = router[0]['inToken']
- tokenLoanETHPrice = baseTokenInfo[tokenLoan]['price'] * 10 ** baseTokenInfo[WETH]['decimals'] / 10 ** baseTokenInfo[tokenLoan]['decimals']
- tradeInfo = calBestAmountABCA(router[0]['rIn'], router[0]['rOut'], router[0]['fee'],
- router[1]['rIn'], router[1]['rOut'], router[1]['fee'],
- router[2]['rIn'], router[2]['rOut'], router[2]['fee'])
- profit = tradeInfo['profit']
- tradeInfo['ethProfit'] = profit * tokenLoanETHPrice
- #printTime(router, amountIn0, amountOut0, amountOut1, amountOut2, profit)
- if tradeInfo['ethProfit'] < tradeMinProfit:
- return False
- else:
- tradeInfo['lp0'] = router[0]['lp']
- tradeInfo['lp1'] = router[1]['lp']
- tradeInfo['lp2'] = router[2]['lp']
- tradeInfo['fee0'] = router[0]['fee']
- tradeInfo['fee1'] = router[1]['fee']
- tradeInfo['fee2'] = router[2]['fee']
- tradeInfo['indexIn0'] = router[0]['indexIn']
- tradeInfo['indexIn1'] = router[1]['indexIn']
- tradeInfo['indexIn2'] = router[2]['indexIn']
- tradeInfo['tokenLoan'] = tokenLoan
- tradeInfo['tokenIn0'] = tokenIn0
- tradeInfo['tradeToken0'] = router[0]['outToken']
- tradeInfo['tradeToken1'] = router[1]['outToken']
- tradeInfo['type'] = 'type3'
- return tradeInfo
- def getABAInput(lp0, lp1, lp2, tokenIn0, tokenLoan, fee0, fee1, fee2, lp0InIndex, lp1InIndex, lp2InIndex, minProfit):
- function = '0x5105a538'
- inputData = encodeInput(lp0, lp1, lp2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- fee0, fee1, fee2, lp0InIndex, lp1InIndex, lp2InIndex,
- tokenIn0, tokenLoan, minProfit, 0)
- inputData = function + inputData
- return inputData
- def callABAPending(tradeInfo, hashInfo):
- tradeInputData = getABAInput(tradeInfo['lp0'], tradeInfo['lp1'],tradeInfo['lp2'],
- tradeInfo['tokenIn0'], tradeInfo['tokenLoan'],
- tradeInfo['fee0'], tradeInfo['fee1'],tradeInfo['fee2'],
- tradeInfo['indexIn0'], tradeInfo['indexIn1'],tradeInfo['indexIn2'],
- baseTokenInfo[tradeInfo['tokenIn0']]['profitMin'])
- gasCalInputData = '0x4327f0db' + encodeInput(v5Address, 0x40, (len(tradeInputData) - 2)/2 , tradeInputData)
-
- paramsTrade = {}
- paramsTrade['from'] = myAddress
- paramsTrade['to'] = '0xEAf90BcB75e7B92900678c4aBD80883b414bEDD6'
- paramsTrade['data'] = gasCalInputData
- paramsHash = {}
- paramsHash['from'] = hashInfo['fromAddress']
- paramsHash['to'] = hashInfo['toAddress']
- paramsHash['data'] = hashInfo['inputData']
- paramsHash['value'] = hex(hashInfo['value'])
- result = batchCall([paramsHash,paramsTrade])
- result = result['result'][1]['Return']
- info = w3.debug.decodeOutput(result)
- r = {}
- r['gasUsed'] = info[1]
- r['info'] = info[3:]
- returnInfo = {'type':2, 'lp0': tradeInfo['lp0'], 'lpLoan':tradeInfo['lp1'], 'tokenIn':tradeInfo['tokenIn0'], 'tokenLoan':tradeInfo['tokenLoan'], 'profit':0, 'sumValue':0}
- if len(r['info']) != 23 or r['info'][-1] == 0:
- return returnInfo
- sumValue = r['info'][3] + r['info'][4] + r['info'][5] + r['info'][6] + r['info'][7] + r['info'][8]
- returnInfo['sumValue'] = sumValue
- returnInfo['profit'] = r['info'][-1]
- returnInfo['gasUsed'] = r['gasUsed']
- returnInfo['inputData'] = tradeInputData
- return returnInfo
- initTime = time.time()
- pendingInitTime = time.time()
- topLpInfo = readAny('topLP')
- lpRouterInfo = readAny('abcd')
- lpRouter256Info = readAny('256Router')
- r = w3.provider.make_request('eth_newPendingTransactionFilter',[])
- filterId = r['result']
- printTime(filterId)
- nowBlockLpRes = {}
- dataUsed = []
- while True:
- try:
-
- hsArry = w3.provider.make_request('eth_getFilterChanges', [filterId])
- hsArry = hsArry['result']
- nowBlockLpRes = {}
- blockNumber = w3.eth.blockNumber
- baseGasPrice = getBaseGasPrice(blockNumber) * 1.5
- if baseGasPrice < 3 * 1e9:
- baseGasPrice = 3 * 1e9
- if hsArry:
-
- for hsI in hsArry:
- tradeInfoArray = []
- #printTime('hsI OK')
- hsResult = w3.new.getTransaction(hsI)
- #printTime('hsResult OK')
- hashInfoExp = {
- 'blockHash': None,
- 'blockNumber': None,
- 'from': '0x7a5ddf8a2a924e4faa9d76b97b1363c864062df5',
- 'gas': '0x5208',
- 'gasPrice':
- '0x5968f26e',
- 'maxFeePerGas': '0x5968f26e',
- 'maxPriorityFeePerGas': '0x59682f00',
- 'hash': '0xe5eb2fb4ce91e96501e6ee6423198f3395341bab744cdad7eb2e354ac9fec8ac',
- 'input': '0x',
- 'nonce': '0x3',
- 'to': '0x92be6de0ae6d89a2378795553ecb4cdb820e0d7b',
- 'transactionIndex': None,
- 'value': '0x2386f26fc10000',
- 'type': '0x2',
- }
- hashInfo = gethashInfo(hsResult)
- if not hashInfo:
- continue
- if hashInfo['function'] not in swapFunction:
- continue
- if hashInfo['gasPrice'] > baseGasPrice * 5 or hashInfo['gasPrice'] > 20 * 1e9:
- continue
- #printTime(hsI)
- traceResult = w3.debug.traceCall(hashInfo['fromAddress'], hashInfo['toAddress'], hashInfo['inputData'], hashInfo['value'])
- #printTime('traceCall OK')
- if not traceResult:
- continue
- if 'error' in traceResult:
- continue
- if 'calls' not in traceResult:
- continue
- tradeInfo = w3.debug.transferDecodeFromCalldata(traceResult['calls'])
- #printTime('transferDecodeFromCalldata OK')
- if not tradeInfo:
- continue
- lpArray = calLpInTradeInfo(tradeInfo)
- if not lpArray:
- continue
- #printTime('calLpInTradeInfo OK', len(lpArray))
- lpRouterArray = findLpArrayRouter(lpArray, lpRouter256Info)
- if not lpRouterArray:
- continue
- #printTime('findLpArrayRouter OK', len(lpRouterArray))
- onlyLp = calOnlyLpInRouterArray(lpRouterArray)
- #printTime('calOnlyLpInRouterArray OK', len(onlyLp))
- # 获取余额
- lpResArray = getLpArrayResAfterTrade(hashInfo['fromAddress'], hashInfo['toAddress'], hashInfo['inputData'], hashInfo['value'], onlyLp)
- # 余额进行缓存
- for lpResI in lpResArray:
- nowBlockLpRes[lpResI] = lpResArray[lpResI]
- #printTime('RES OK')
- #计算每一个路由的利润
-
- for lpRouter in lpRouterArray:
- tradeInfo = calRouterProfit(lpRouter)
- if tradeInfo:
- type = tradeInfo['type']
- if type == 'type3':
- result = callABAPending(tradeInfo, hashInfo)
- if result['profit'] < tradeMinProfit:
- continue
- sumValue = result['sumValue']
- if sumValue in dataUsed:
- continue
- tokenLoanETHPrice = baseTokenInfo[tradeInfo['tokenLoan']]['price'] * 10 ** baseTokenInfo[WETH]['decimals'] / 10 ** \
- baseTokenInfo[tradeInfo['tokenLoan']]['decimals']
- result['ethProfit'] = result['profit'] * tokenLoanETHPrice
- result['ethProfit-E18'] = result['profit'] * tokenLoanETHPrice / 1e18
- result['tureProfit'] = result['ethProfit'] - result['gasUsed'] * int(hsResult['gasPrice'],16)
- result['maxPrice'] = result['ethProfit'] / result['gasUsed']
- if result['tureProfit'] < tradeMinProfit:
- continue
- tradeInfoArray.append(result)
-
- maxProfitInfo = {'tureProfit' : 0}
- for tradeInfoI in tradeInfoArray:
- if tradeInfoI['tureProfit'] > maxProfitInfo['tureProfit']:
- maxProfitInfo = tradeInfoI
- if maxProfitInfo['tureProfit'] > 0:
- printTime(maxProfitInfo['lp0'], maxProfitInfo['lpLoan'], maxProfitInfo['tureProfit'] / 1e18, hashInfo['hash'])
- tradeParams = {}
- tradeParams['to'] = v5Address
- tradeParams['data'] = maxProfitInfo['inputData']
- tradeParams['gas'] = hex(int(1e6))
- tradeParams['value'] = hex(0)
- tradeParams['type'] = hsResult['type']
-
- if tradeParams['type'] == '0x2':
- tradeParams['maxFeePerGas'] = hsResult['maxFeePerGas']
- tradeParams['maxPriorityFeePerGas'] = hsResult['maxPriorityFeePerGas']
- else:
- tradeParams['gasPrice'] = hsResult['gasPrice']
-
- params = {}
- params['method'] = 'sendTransaction'
- params['params'] = tradeParams
- try:
- hs = requests.post(url='http://127.0.0.1:410/operation', json=params).text
- if len(hs)>50:
- printTime(blockNumber, 'https://www.oklink.com/en/ethw/tx/' + str(hs))
- printTime('-' * 50)
- except:
- hs = 'err seed'
- pendingInitTime = time.time()
- time.sleep(0.0005)
- except BaseException as err:
- printTime(traceback.format_exc())
- printTime('loop', err)
- time.sleep(20)
- try:
- r = w3.provider.make_request('eth_newPendingTransactionFilter',[])
- filterId = r['result']
- printTime('filterId',filterId)
- except:
- time.sleep(10)
|