const logger = require("../../utils/logger") const BaseModel = require("../../model/base-model"); module.exports = class FactoryLib { constructor(web3, chain) { this.web3 = web3 this.chain = chain this.factoryModel = new BaseModel(this.chain.id, BaseModel.MODULES.FACTORY) this.factoryContractMap = {} this.positionManagerContractMap = {} // abi加载 this.v2FactoryAbi = require('../../abi/UNIV2_FACTORY_ABI.json') this.positionManagerAbi = require('../../abi/UNIV3_POSITION_MANAGER_ABI.json') } async getFactoryList() { const requestRst = await this.factoryModel.find() if (requestRst.state) { return requestRst.data } else { logger.error(requestRst.msg) return [] } } getFactoryContract(factoryAddress) { if (!this.factoryContractMap[factoryAddress]) { this.factoryContractMap[factoryAddress] = new this.web3.eth.Contract(this.v2FactoryAbi, factoryAddress) } return this.factoryContractMap[factoryAddress] } getPositionManager(positionManagerAddress) { if (!this.positionManagerContractMap[positionManagerAddress]) { this.positionManagerContractMap[positionManagerAddress] = new this.web3.eth.Contract(this.positionManagerAbi, positionManagerAddress) } return this.positionManagerContractMap[positionManagerAddress] } async getPositionLength(positionManagerContract, low) { let high = 1_000_000 let checkNumber = low let prevLow = low let prevHigh = high async function check(checkNumber) { async function final_check(checkNumber) { try { await positionManagerContract.methods.positions(checkNumber).call() return true } catch (e) { return false } } // [,,,,,c(,,,,,,,)] let too_low = false for (let i = 1; i <= 5; i++) { too_low = too_low || (await final_check(checkNumber + i)) } if (too_low) return 'too_low' // [,,,,,(c,,,,,,,)] let too_high = true for (let i = 0; i < 5; i++) { too_high = too_high && (!await final_check(checkNumber + i)) } if (too_high) return 'too_high' return 'ok' } let count = 60 while (--count > 0) { let checkRst = await check(checkNumber) // logger.debug(`[${low}, ${high}], c: ${checkNumber}, ${checkRst}. [${++count}]`) if (checkRst === 'ok') { break } else { let tempHigh = high let tempLow = low if (checkNumber === low) { if (checkRst === 'too_high') { high = tempLow low = prevLow prevHigh = tempHigh prevLow = tempLow checkNumber = high } else if (checkRst === 'too_low') { low = low + Math.floor((high - low) / 2) prevLow = tempLow checkNumber = low } } else if (checkNumber === high) { if (checkRst === 'too_high') { high = low + Math.floor((high - low) / 2) prevHigh = tempHigh checkNumber = high } else if (checkRst === 'too_low') { low = tempHigh high = prevHigh prevHigh = tempHigh prevLow = tempLow checkNumber = low } } } } return checkNumber } async getPairsLength(factory) { if (factory.version === 'univ2') { // 获取工厂实例 const v2Factory = this.getFactoryContract(factory.hash) // 获取当前pairsLength return await v2Factory.methods.allPairsLength().call() } else if (factory.version === 'univ3') { // 获取positionManager const v3PositionManager = this.getPositionManager(factory.positionManager) return await this.getPositionLength(v3PositionManager, 0) } else { throw Error(`Unknown factory version: ${factory.version}, hash is: ${factory.hash}.`) } } }