import { web3 } from "hardhat"; import History from "../interface/history"; import contracts from "../../config/contracts"; import logger from "../../utils/logger"; import {BigNumber} from "ethers"; import {replaceAll} from "hardhat/internal/util/strings"; import swapPath from "../interface/swapPath"; import history from "../interface/history"; const ierc20abi = require('../../abi/IERC20_ABI.json') async function handlePosition(router: String, factory: String) { try { // 拉取当前pull状态信息 const pullState = await History.findByHashOrBlockOrDataVague('UNIV2DEX', factory, '', 0, 200) let nowPosition = 0 // 没有状态信息的情况 if (pullState.data.length == 0) { const appendRst = await History.appendOrUpdate('UNIV2DEX', factory, {"now": nowPosition}) logger.debug(appendRst) } else { nowPosition = pullState.data[0].dataObj.now } return nowPosition } catch (e) { logger.error(`Pull state error, router: ${router}, factory: ${factory}`) logger.error(e) } return 0 } async function handleAFactory(routerObj: any, position: number, pairsLength: number, v2_410_tool: any, lpList: any) { while (position < pairsLength) { try { const info = await v2_410_tool.methods.getPairIdInfo(routerObj.factory, position).call() const symbol0 = info['2'].replace(/[^A-Za-z0-9]+/g, '').substring(0, 10) const symbol1 = info['6'].replace(/[^A-Za-z0-9]+/g, '').substring(0, 10) const name = `${routerObj.name}_${symbol0}_${symbol1}` const sum2 = replaceAll(BigNumber.from(info['1']).add(BigNumber.from(info['5']))._hex, '0x0', '0x') const Lp = { LP: info['0'], decimals0: info['3'], decimals1: info['7'], factory: routerObj.factory, feei: routerObj.fee, id: position, name: name, r0: info['4'], r1: info['8'], router: routerObj.router, sum2: sum2, symbol0: symbol0, symbol1: symbol1, token0: info['1'], token1: info['5'], isEthW: routerObj.type == 'ETHW' } lpList.push(Lp) // 更新一次position await History.appendOrUpdate('UNIV2DEX', routerObj.factory, {"now": position}) } catch (e) {} position++ } } async function getAllLp(v2Router: any, fromZero: boolean, v2_410_tool: any, v2_factory_abi: any, lpList: any) { try { const v2_factory_address = v2Router.factory // 获取工厂实例 const v2_factory = new web3.eth.Contract(v2_factory_abi, v2_factory_address) // 获取当前pairsLength const pairsLength = await v2_factory.methods.allPairsLength().call() // 获取当前pull状态 const position = fromZero ? 0 : await handlePosition(v2Router.router, v2_factory_address) if (position + 1 < pairsLength) { logger.debug(`Router address: ${v2Router.router}`) logger.debug(`factory: ${v2_factory_address}, ${position + 1} / ${pairsLength}.`) await handleAFactory(v2Router, position, pairsLength, v2_410_tool, lpList) } } catch (e) { logger.error(`New contract error, router: ${v2Router.router}`) logger.error(e) } } async function saveLpToSwapPath(lpList: any) { for (let lpIndex in lpList) { const lp = lpList[lpIndex] let lpSum2List = [] lpSum2List.push(lp) const insertRst = await swapPath.appendOrUpdate(lp.sum2, '2', lpSum2List) logger.debug(`save path: ${lp.name}: ${insertRst.msg}, ${parseInt(lpIndex) + 1}/${lpList.length}`) } } async function handleToken(pool: any, zero: boolean) { const token = { 'address': zero ? pool.token0 : pool.token1, 'symbol': zero ? pool.symbol0 : pool.symbol1, 'decimal': zero ? pool.decimals0 : pool.decimals1, 'name': 'xxxxxxxx' } const tokenObj = new web3.eth.Contract(ierc20abi, token.address) token.name = await tokenObj.methods.name().call() token.name = token.name.replace(/[^A-Za-z0-9 ]+/g, '').substring(0, 37) return token } async function saveToken(lpList: any, type='token') { for (let lpIndex in lpList) { const lp = lpList[lpIndex] try { const token = await handleToken(lp, true) const saveRst = await history.appendOrUpdate(type, token.address, token) logger.debug(`${token.name} ${saveRst.msg}`) } catch (e) {} try { const token = await handleToken(lp, false) const saveRst = await history.appendOrUpdate(type, token.address, token) logger.debug(`${token.name} ${saveRst.msg}`) } catch (e) {} logger.debug(`insert token: ${parseInt(lpIndex) + 1} / ${lpList.length}`) } } async function saveLp(lpList: any, type='0') { for (let lpIndex in lpList) { const lp = lpList[lpIndex] const insertRst = await History.appendOrUpdate(type, lp.LP, lp) logger.debug(`insert lp:${insertRst.msg}, hash: ${lp.LP}, ${parseInt(lpIndex) + 1} / ${lpList.length}`) } } async function filterLp(lpList: any, filteredLpList: any) { for (let lpIndex in lpList) { const lp = lpList[lpIndex] if (lp.token0.toLowerCase() === '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') { if (parseInt(lp.r0) > 20 * 1e18) filteredLpList.push(lp) } else if (lp.token1.toLowerCase() === '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') { if (parseInt(lp.r1) > 20 * 1e18) filteredLpList.push(lp) } else { filteredLpList.push(lp) } } } async function main() { logger.debug('Pull v2 start.') const v2_factory_abi = require('../../abi/UNIV2_FACTORY_ABI.json') const v2_tool_abi = require('../../abi/410_V2_TOOLS.json') // 初始化410 v2工具箱 const v2_410_tool = new web3.eth.Contract(v2_tool_abi, contracts.TOOLS_410_V2) const v2RouterInfo = require('../../config/router-list.json') let fromZero: boolean = true const lpList: any = [] const filteredLpList: any = [] while (true) { for (let router_index = 0; router_index < v2RouterInfo.length; router_index++) { lpList.length = 0 filteredLpList.length = 0 // 1. 获取Lp await getAllLp(v2RouterInfo[router_index], fromZero, v2_410_tool, v2_factory_abi, lpList) // 2. 保存Lp信息 await saveLp(lpList, '0') // 3. 保存Lp的Token到Token表 await saveToken(lpList, 'token') // 4. 过滤Lp await filterLp(lpList, filteredLpList) // 5. 将过滤后的Lp保存到二阶表 await saveLpToSwapPath(filteredLpList) // 6. 保存筛选之后的的Token到TopToken表 await saveToken(filteredLpList, 'topToken') // 7. 保存过滤后的Lp到TopLp await saveLp(filteredLpList, 'topLp') if (lpList.length > 0) { logger.debug('') logger.debug('') logger.debug('') } } // 数据流、abstruct // v2RouterInfo.forEach(async (routerInfo) => { // const lpList = await getAllLp(routerInfo); // lpList.forEach(async (lp) => { // await saveLp(lp) // const token = parseToken(lp) // saveToken(token) // }) // }) // if (fromZero) fromZero = false; } } main().catch((error) => { console.error(error); process.exitCode = 1; })