github.com/diadata-org/diadata@v1.4.593/pkg/dia/scraper/liquidity-scrapers/CamelotV3.go (about) 1 package liquidityscrapers 2 3 import ( 4 "math" 5 "math/big" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/diadata-org/diadata/pkg/dia/helpers/ethhelper" 11 camelotv3 "github.com/diadata-org/diadata/pkg/dia/scraper/exchange-scrapers/camelotv3" 12 models "github.com/diadata-org/diadata/pkg/model" 13 14 "github.com/diadata-org/diadata/pkg/utils" 15 16 "github.com/diadata-org/diadata/pkg/dia" 17 "github.com/ethereum/go-ethereum/accounts/abi/bind" 18 "github.com/ethereum/go-ethereum/common" 19 "github.com/ethereum/go-ethereum/ethclient" 20 ) 21 22 type CamelotV3Scraper struct { 23 RestClient *ethclient.Client 24 WsClient *ethclient.Client 25 relDB *models.RelDB 26 datastore *models.DB 27 poolChannel chan dia.Pool 28 doneChannel chan bool 29 blockchain string 30 startBlock uint64 31 factoryContract string 32 exchangeName string 33 waitTime int 34 } 35 36 // NewCamelotV3Scraper returns a new CamelotV3Scraper. 37 func NewCamelotV3Scraper(exchange dia.Exchange, relDB *models.RelDB, datastore *models.DB) *CamelotV3Scraper { 38 log.Info("NewCamelotScraper ", exchange.Name) 39 log.Info("NewCamelotScraper Address ", exchange.Contract) 40 41 var cls *CamelotV3Scraper 42 43 switch exchange.Name { 44 case dia.CamelotExchangeV3: 45 cls = makeCamelotV3Scraper(exchange, "", "", relDB, datastore, "200", uint64(101163738)) 46 case dia.ThenaV3Exchange: 47 cls = makeCamelotV3Scraper(exchange, "", "", relDB, datastore, "200", uint64(26030310)) 48 } 49 50 go func() { 51 cls.fetchPools() 52 }() 53 return cls 54 } 55 56 // makeCamelotV3Scraper returns a camelot scraper as used in NewCamelotV3Scraper. 57 func makeCamelotV3Scraper(exchange dia.Exchange, restDial string, wsDial string, relDB *models.RelDB, datastore *models.DB, waitMilliseconds string, startBlock uint64) *CamelotV3Scraper { 58 var ( 59 restClient *ethclient.Client 60 wsClient *ethclient.Client 61 err error 62 poolChannel = make(chan dia.Pool) 63 doneChannel = make(chan bool) 64 cls *CamelotV3Scraper 65 ) 66 67 log.Infof("Init rest and ws client for %s.", exchange.BlockChain.Name) 68 restClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_REST", restDial)) 69 if err != nil { 70 log.Fatal("init rest client: ", err) 71 } 72 wsClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_WS", wsDial)) 73 if err != nil { 74 log.Fatal("init ws client: ", err) 75 } 76 77 var waitTime int 78 waitTimeString := utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_WAIT_TIME", waitMilliseconds) 79 waitTime, err = strconv.Atoi(waitTimeString) 80 if err != nil { 81 log.Error("could not parse wait time: ", err) 82 waitTime = 500 83 } 84 85 cls = &CamelotV3Scraper{ 86 WsClient: wsClient, 87 RestClient: restClient, 88 relDB: relDB, 89 datastore: datastore, 90 poolChannel: poolChannel, 91 doneChannel: doneChannel, 92 blockchain: exchange.BlockChain.Name, 93 startBlock: startBlock, 94 factoryContract: exchange.Contract, 95 exchangeName: exchange.Name, 96 waitTime: waitTime, 97 } 98 return cls 99 } 100 101 // fetchPools fetches all registered pools from on-chain and sends them into the pool channel. 102 func (cls *CamelotV3Scraper) fetchPools() { 103 104 // filter from contract created https://etherscan.io/tx/0x1e20cd6d47d7021ae7e437792823517eeadd835df09dde17ab45afd7a5df4603 105 106 log.Info("get pool creations from address: ", cls.factoryContract) 107 poolsCount := 0 108 contract, err := camelotv3.NewCamelotv3Filterer(common.HexToAddress(cls.factoryContract), cls.WsClient) 109 if err != nil { 110 log.Error(err) 111 } 112 113 poolCreated, err := contract.FilterPool( 114 &bind.FilterOpts{Start: cls.startBlock}, 115 []common.Address{}, 116 []common.Address{}, 117 ) 118 if err != nil { 119 log.Error("filter pool created: ", err) 120 } 121 122 for poolCreated.Next() { 123 poolsCount++ 124 var ( 125 pool dia.Pool 126 asset0 dia.Asset 127 asset1 dia.Asset 128 ) 129 log.Info("pools count: ", poolsCount) 130 131 asset0, err = cls.relDB.GetAsset(poolCreated.Event.Token0.Hex(), cls.blockchain) 132 if err != nil { 133 asset0, err = ethhelper.ETHAddressToAsset(poolCreated.Event.Token0, cls.RestClient, cls.blockchain) 134 if err != nil { 135 log.Warn("cannot fetch asset from address ", poolCreated.Event.Token0.Hex()) 136 continue 137 } 138 } 139 asset1, err = cls.relDB.GetAsset(poolCreated.Event.Token1.Hex(), cls.blockchain) 140 if err != nil { 141 asset1, err = ethhelper.ETHAddressToAsset(poolCreated.Event.Token1, cls.RestClient, cls.blockchain) 142 if err != nil { 143 log.Warn("cannot fetch asset from address ", poolCreated.Event.Token1.Hex()) 144 continue 145 } 146 } 147 148 pool.Exchange = dia.Exchange{Name: cls.exchangeName} 149 pool.Blockchain = dia.BlockChain{Name: cls.blockchain} 150 pool.Address = poolCreated.Event.Pool.Hex() 151 152 balance0Big, err := ethhelper.GetBalanceOf(common.HexToAddress(asset0.Address), common.HexToAddress(pool.Address), cls.RestClient) 153 if err != nil { 154 log.Error("GetBalanceOf: ", err) 155 } 156 balance1Big, err := ethhelper.GetBalanceOf(common.HexToAddress(asset1.Address), common.HexToAddress(pool.Address), cls.RestClient) 157 if err != nil { 158 log.Error("GetBalanceOf: ", err) 159 } 160 balance0, _ := new(big.Float).Quo(big.NewFloat(0).SetInt(balance0Big), new(big.Float).SetFloat64(math.Pow10(int(asset0.Decimals)))).Float64() 161 balance1, _ := new(big.Float).Quo(big.NewFloat(0).SetInt(balance1Big), new(big.Float).SetFloat64(math.Pow10(int(asset1.Decimals)))).Float64() 162 163 pool.Assetvolumes = append(pool.Assetvolumes, dia.AssetVolume{Asset: asset0, Volume: balance0, Index: uint8(0)}) 164 pool.Assetvolumes = append(pool.Assetvolumes, dia.AssetVolume{Asset: asset1, Volume: balance1, Index: uint8(1)}) 165 166 // Determine USD liquidity 167 if balance0 > GLOBAL_NATIVE_LIQUIDITY_THRESHOLD && balance1 > GLOBAL_NATIVE_LIQUIDITY_THRESHOLD { 168 cls.datastore.GetPoolLiquiditiesUSD(&pool, priceCache) 169 } 170 171 pool.Time = time.Now() 172 173 cls.poolChannel <- pool 174 175 } 176 cls.doneChannel <- true 177 } 178 179 func (cls *CamelotV3Scraper) Pool() chan dia.Pool { 180 return cls.poolChannel 181 } 182 183 func (cls *CamelotV3Scraper) Done() chan bool { 184 return cls.doneChannel 185 }