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  }