lpMaintenance.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. import { web3 } from "hardhat";
  2. import History from "../interface/history";
  3. import contracts from "../../config/contracts";
  4. import logger from "../../utils/logger";
  5. import {BigNumber} from "ethers";
  6. import {replaceAll} from "hardhat/internal/util/strings";
  7. import history from "../interface/history";
  8. const ierc20abi = require('../../abi/IERC20_ABI.json')
  9. // 初始化410 v2工具箱
  10. const v2ToolBy410Abi = require('../../abi/410_V2_TOOLS.json')
  11. const v2ToolBy410 = new web3.eth.Contract(v2ToolBy410Abi, contracts.V2_TOOLS_BY_410)
  12. export class LpMaintenance {
  13. tokenInstance: any = {}
  14. maxMemoryOfByte: number = 0
  15. async handleToken(pool: any, zero: boolean) {
  16. const token = {
  17. 'address': zero ? pool.token0 : pool.token1,
  18. 'symbol': zero ? pool.symbol0 : pool.symbol1,
  19. 'decimals': zero ? pool.decimals0 : pool.decimals1,
  20. 'name': 'xxxxxxxx'
  21. }
  22. let tokenObj = this.tokenInstance[token.address]
  23. if (!tokenObj) {
  24. tokenObj = new web3.eth.Contract(ierc20abi, token.address)
  25. this.tokenInstance[token.address] = tokenObj
  26. }
  27. token.name = await tokenObj.methods.name().call()
  28. token.name = token.name.replace(/[^A-Za-z0-9 ]+/g, '').substring(0, 37)
  29. return token
  30. }
  31. async saveToken(lp: any, type='token') {
  32. try {
  33. const token = await this.handleToken(lp, true)
  34. await history.appendOrUpdate(type, token.address, token)
  35. } catch (e) {}
  36. try {
  37. const token = await this.handleToken(lp, false)
  38. await history.appendOrUpdate(type, token.address, token)
  39. } catch (e) {}
  40. }
  41. async saveLp(lp: any, type='0') {
  42. await History.appendOrUpdate(type, lp.LP, lp)
  43. }
  44. async checkLpType(lp: any) {
  45. const ethTokenList = [
  46. '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH
  47. '0xaf3ccfd9b59b36628cc2f659a09d6440795b2520', // ETH
  48. '0x7bf88d2c0e32de92cdaf2d43ccdc23e8edfd5990' // WETHW
  49. ]
  50. const filterTypeList = [
  51. { type: 'topLp', limit: 10 * 1e18 },
  52. { type: 'normalLp', limit: 1 * 1e18 },
  53. { type: 'lp', limit: 0 },
  54. ]
  55. if (ethTokenList.indexOf(lp.token0.toLowerCase()) == -1
  56. && ethTokenList.indexOf(lp.token1.toLowerCase()) == -1) {
  57. return 'normalLp'
  58. }
  59. for (const filterType of filterTypeList) {
  60. if (ethTokenList.indexOf(lp.token0.toLowerCase()) != -1) {
  61. if (parseInt(lp.r0) >= filterType.limit) return filterType.type
  62. } else if (ethTokenList.indexOf(lp.token1.toLowerCase()) != -1) {
  63. if (parseInt(lp.r1) >= filterType.limit) return filterType.type
  64. }
  65. }
  66. }
  67. async handleLp(lp: any, oldType: any) {
  68. // 过滤Lp
  69. const lpType = await this.checkLpType(lp)
  70. if (lpType != oldType) {
  71. // 保存变更之后的的Token
  72. // await this.saveToken(lp, lpType)
  73. // 保存变更后的Lp
  74. await this.saveLp(lp, lpType)
  75. logger.debug(`lp:${lp.LP},${oldType}->${lpType}.`)
  76. }
  77. }
  78. showMemory (mainInfo: string) {
  79. const memoryUsage = process.memoryUsage()
  80. if (this.maxMemoryOfByte < memoryUsage.rss) {
  81. this.maxMemoryOfByte = memoryUsage.rss
  82. }
  83. logger.debug(`${mainInfo} ${this.format(memoryUsage.rss)}/${this.format(this.maxMemoryOfByte)}`)
  84. }
  85. format (bytes: any) {
  86. return (bytes / 1024 / 1024).toFixed(2) + ' MB';
  87. }
  88. generateAddressListByLpList (lpList: any) {
  89. const lpAddressList: any = []
  90. for (const lp of lpList) {
  91. lpAddressList.push(lp.dataObj.LP)
  92. }
  93. return lpAddressList
  94. }
  95. updateLocalLpListR0R1(lpList: any, r0s: any, r1s: any) {
  96. for (let index = 0; index < lpList.length; index++) {
  97. lpList[index].dataObj.r0 = r0s[index]
  98. lpList[index].dataObj.r1 = r1s[index]
  99. }
  100. }
  101. async run() {
  102. logger.debug('LP maintenance start.')
  103. while (true) {
  104. this.showMemory('pull db lp data...')
  105. const lpPullRst = await history.findByHashOrBlockOrDataVague('topLp', '', '', 0, 20000)
  106. if (!lpPullRst.state) continue
  107. const topLpList = lpPullRst.data
  108. logger.debug(`lp length:${topLpList.length}, generate address list...`)
  109. const lpList: any = [].concat(topLpList)
  110. const lpAddressList: any = this.generateAddressListByLpList(lpList)
  111. // 集中拉取r0,r1并更新本地的
  112. const size = 2000
  113. logger.debug(`update lp r0,r1 by 410 tools...`)
  114. for (let from = 0; from < topLpList.length; from += size) {
  115. logger.debug(`get lp info from ${from} to ${from + size}...`)
  116. const lpR0R1Info: any = await v2ToolBy410.methods.getPairSBalance(lpAddressList.slice(from, from + size)).call()
  117. const r0s = lpR0R1Info.amounts0
  118. const r1s = lpR0R1Info.amounts1
  119. this.updateLocalLpListR0R1(lpList.slice(from, from + size), r0s, r1s)
  120. }
  121. // 将lp类型有变动的全部更新
  122. for (const lpDbObj of lpList) {
  123. await this.handleLp(lpDbObj.dataObj, lpDbObj.block)
  124. }
  125. }
  126. }
  127. }
  128. async function main() {
  129. await new LpMaintenance().run()
  130. }
  131. main().catch((error) => {
  132. console.error(error);
  133. process.exitCode = 1;
  134. })