|
|
@@ -0,0 +1,204 @@
|
|
|
+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')
|
|
|
+
|
|
|
+export class PullAndPush {
|
|
|
+ fromHead: boolean = false
|
|
|
+ isFirst: boolean = false
|
|
|
+
|
|
|
+ constructor (_fromHead: boolean, _isFirst: boolean) {
|
|
|
+ this.fromHead = _fromHead
|
|
|
+ this.isFirst = _isFirst
|
|
|
+ }
|
|
|
+
|
|
|
+ async 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 getPoolByPosition(routerObj: any, position: number, v2ToolBy410: any) {
|
|
|
+ try {
|
|
|
+ const info = await v2ToolBy410.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'
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新一次position
|
|
|
+ await History.appendOrUpdate('UNIV2DEX', routerObj.factory, {"now": position})
|
|
|
+
|
|
|
+ return lp
|
|
|
+ } catch (e) {}
|
|
|
+
|
|
|
+ return undefined
|
|
|
+ }
|
|
|
+
|
|
|
+ async saveLpToSwapPath(lp: any) {
|
|
|
+ const lpSum2Query = await swapPath.findBySumValueAndLevel(lp.sum2, '2')
|
|
|
+ let lpSum2List = []
|
|
|
+
|
|
|
+ if (!this.isFirst && lpSum2Query.state) {
|
|
|
+ lpSum2List = JSON.parse(lpSum2Query.data.data)
|
|
|
+ }
|
|
|
+
|
|
|
+ lpSum2List.push(lp)
|
|
|
+
|
|
|
+ const insertRst = await swapPath.appendOrUpdate(lp.sum2, '2', lpSum2List)
|
|
|
+ logger.debug(`save path: ${lp.name}: ${insertRst.msg}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ async handleToken(pool: any, zero: boolean) {
|
|
|
+ const token = {
|
|
|
+ 'address': zero ? pool.token0 : pool.token1,
|
|
|
+ 'symbol': zero ? pool.symbol0 : pool.symbol1,
|
|
|
+ 'decimals': 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 saveToken(lp: any, type='token') {
|
|
|
+ try {
|
|
|
+ const token = await this.handleToken(lp, true)
|
|
|
+
|
|
|
+ const saveRst = await history.appendOrUpdate(type, token.address, token)
|
|
|
+ logger.debug(`${token.name} ${saveRst.msg}`)
|
|
|
+ } catch (e) {}
|
|
|
+
|
|
|
+ try {
|
|
|
+ const token = await this.handleToken(lp, false)
|
|
|
+
|
|
|
+ const saveRst = await history.appendOrUpdate(type, token.address, token)
|
|
|
+ logger.debug(`${token.name} ${saveRst.msg}`)
|
|
|
+ } catch (e) {}
|
|
|
+ }
|
|
|
+
|
|
|
+ async saveLp(lp: any, type='0') {
|
|
|
+ const insertRst = await History.appendOrUpdate(type, lp.LP, lp)
|
|
|
+ logger.debug(`insert lp:${insertRst.msg}, hash: ${lp.LP}.}`)
|
|
|
+ }
|
|
|
+
|
|
|
+ async filterLp(lp: any) {
|
|
|
+ if (lp.token0.toLowerCase() === '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') {
|
|
|
+ return parseInt(lp.r0) > 20 * 1e18
|
|
|
+ } else if (lp.token1.toLowerCase() === '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2') {
|
|
|
+ return parseInt(lp.r1) > 20 * 1e18
|
|
|
+ }
|
|
|
+
|
|
|
+ return true
|
|
|
+ }
|
|
|
+
|
|
|
+ async run() {
|
|
|
+ logger.debug('Pull v2 start.')
|
|
|
+
|
|
|
+ // 初始化410 v2工具箱
|
|
|
+ const v2ToolBy410Abi = require('../../abi/410_V2_TOOLS.json')
|
|
|
+ const v2ToolBy410 = new web3.eth.Contract(v2ToolBy410Abi, contracts.V2_TOOLS_BY_410)
|
|
|
+ const v2FactoryAbi = require('../../abi/UNIV2_FACTORY_ABI.json')
|
|
|
+ const routerList: Array<any> = require('../../config/router-list.json')
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ for (const routerObj of routerList) {
|
|
|
+ if (routerObj.type === 'univ3') continue
|
|
|
+
|
|
|
+ const v2FactoryAddress = routerObj.factory
|
|
|
+ // 获取工厂实例
|
|
|
+ const v2Factory = new web3.eth.Contract(v2FactoryAbi, v2FactoryAddress)
|
|
|
+ // 获取当前pull状态
|
|
|
+ let position = this.fromHead ? 0 : await this.handlePosition(routerObj.router, v2FactoryAddress)
|
|
|
+ // 获取当前pairsLength
|
|
|
+ const pairsLength = await v2Factory.methods.allPairsLength().call()
|
|
|
+ // 如果有未获取的池子
|
|
|
+ const haveNewLp = position + 1 < pairsLength
|
|
|
+
|
|
|
+ // 打印信息
|
|
|
+ if (haveNewLp) {
|
|
|
+ logger.debug(`Router address: ${routerObj.router}`)
|
|
|
+ logger.debug(`factory: ${v2FactoryAddress}, ${position + 1} / ${pairsLength}.`)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 挨个处理lp信息
|
|
|
+ while (position + 1 < pairsLength) {
|
|
|
+ logger.debug(`${position + 1} / ${pairsLength}`)
|
|
|
+ // 1. 获取lp
|
|
|
+ const lp = await this.getPoolByPosition(routerObj, position, v2ToolBy410)
|
|
|
+ // 2. 保存Lp信息
|
|
|
+ await this.saveLp(lp, '0')
|
|
|
+ // 3. 保存Lp的Token到Token表
|
|
|
+ await this.saveToken(lp, 'token')
|
|
|
+ // 4. 过滤Lp
|
|
|
+ if (await this.filterLp(lp)) {
|
|
|
+ // 5. 将过滤后的Lp保存到二阶表
|
|
|
+ await this.saveLpToSwapPath(lp)
|
|
|
+ // 6. 保存筛选之后的的Token到TopToken表
|
|
|
+ await this.saveToken(lp, 'topToken')
|
|
|
+ // 7. 保存过滤后的Lp到TopLp
|
|
|
+ await this.saveLp(lp, 'topLp')
|
|
|
+ }
|
|
|
+
|
|
|
+ position++
|
|
|
+ }
|
|
|
+
|
|
|
+ if (haveNewLp) {
|
|
|
+ logger.debug('')
|
|
|
+ logger.debug('')
|
|
|
+ logger.debug('')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.fromHead && this.isFirst) {
|
|
|
+ this.isFirst = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|