github.com/diadata-org/diadata@v1.4.593/pkg/dia/service/assetservice/source/camelotv3.go (about)

     1  package source
     2  
     3  import (
     4  	"strconv"
     5  	"strings"
     6  
     7  	camelotv3 "github.com/diadata-org/diadata/pkg/dia/scraper/exchange-scrapers/camelotv3"
     8  	uniswapcontract "github.com/diadata-org/diadata/pkg/dia/scraper/exchange-scrapers/uniswap"
     9  	models "github.com/diadata-org/diadata/pkg/model"
    10  
    11  	"github.com/diadata-org/diadata/pkg/utils"
    12  
    13  	"github.com/diadata-org/diadata/pkg/dia"
    14  	"github.com/ethereum/go-ethereum/accounts/abi/bind"
    15  	"github.com/ethereum/go-ethereum/common"
    16  	"github.com/ethereum/go-ethereum/ethclient"
    17  )
    18  
    19  type CamelotV3AssetSource struct {
    20  	RestClient *ethclient.Client
    21  	WsClient   *ethclient.Client
    22  	relDB      *models.RelDB
    23  	// signaling channels for session initialization and finishing
    24  	assetChannel    chan dia.Asset
    25  	doneChannel     chan bool
    26  	blockchain      string
    27  	exchange        dia.Exchange
    28  	startBlock      uint64
    29  	factoryContract string
    30  	waitTime        int
    31  }
    32  
    33  // NewCamelotV3AssetSource returns a new CamelotV3AssetSource
    34  func NewCamelotV3AssetSource(exchange dia.Exchange, relDB *models.RelDB) *CamelotV3AssetSource {
    35  	log.Info("NewCamelotV3Scraper ", exchange.Name)
    36  	log.Info("NewCamelotV3Scraper Address ", exchange.Contract)
    37  
    38  	var uas *CamelotV3AssetSource
    39  
    40  	switch exchange.Name {
    41  	case dia.CamelotExchangeV3:
    42  		uas = makeCamelotV3AssetSource(exchange, "", "", relDB, "200", uint64(101163738))
    43  	case dia.ThenaV3Exchange:
    44  		uas = makeCamelotV3AssetSource(exchange, "", "", relDB, "200", uint64(26030310))
    45  	}
    46  
    47  	go func() {
    48  		uas.fetchAssets()
    49  	}()
    50  	return uas
    51  
    52  }
    53  
    54  // makeCamelotV3AssetSource returns a Camelot asset source.
    55  func makeCamelotV3AssetSource(exchange dia.Exchange, restDial string, wsDial string, relDB *models.RelDB, waitMilliseconds string, startBlock uint64) *CamelotV3AssetSource {
    56  	var (
    57  		restClient   *ethclient.Client
    58  		wsClient     *ethclient.Client
    59  		err          error
    60  		uas          *CamelotV3AssetSource
    61  		assetChannel = make(chan dia.Asset)
    62  		doneChannel  = make(chan bool)
    63  	)
    64  
    65  	log.Infof("Init rest and ws client for %s.", exchange.BlockChain.Name)
    66  	restClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_REST", restDial))
    67  	if err != nil {
    68  		log.Fatal("init rest client: ", err)
    69  	}
    70  	wsClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_WS", wsDial))
    71  	if err != nil {
    72  		log.Fatal("init rest client: ", err)
    73  	}
    74  
    75  	var waitTime int
    76  	waitTimeString := utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_WAIT_TIME", waitMilliseconds)
    77  	waitTime, err = strconv.Atoi(waitTimeString)
    78  	if err != nil {
    79  		log.Error("could not parse wait time: ", err)
    80  		waitTime = 500
    81  	}
    82  
    83  	uas = &CamelotV3AssetSource{
    84  		RestClient:      restClient,
    85  		WsClient:        wsClient,
    86  		relDB:           relDB,
    87  		assetChannel:    assetChannel,
    88  		doneChannel:     doneChannel,
    89  		blockchain:      exchange.BlockChain.Name,
    90  		startBlock:      startBlock,
    91  		factoryContract: exchange.Contract,
    92  		exchange:        exchange,
    93  		waitTime:        waitTime,
    94  	}
    95  	return uas
    96  }
    97  
    98  // getNumPairs returns the number of available pairs on Camelot
    99  func (uas *CamelotV3AssetSource) fetchAssets() {
   100  
   101  	// filter from contract created https://etherscan.io/tx/0x1e20cd6d47d7021ae7e437792823517eeadd835df09dde17ab45afd7a5df4603
   102  	var blocknumber int64
   103  
   104  	_, startblock, err := uas.relDB.GetScraperIndex(uas.exchange.Name, dia.SCRAPER_TYPE_ASSETCOLLECTOR)
   105  	if err != nil {
   106  		log.Error("GetScraperIndex: ", err)
   107  	} else {
   108  		uas.startBlock = uint64(startblock)
   109  	}
   110  
   111  	log.Infof("get pool creations from address %s at startblock %v.", uas.factoryContract, uas.startBlock)
   112  	poolsCount := 0
   113  	checkMap := make(map[string]struct{})
   114  	contract, err := camelotv3.NewCamelotv3Filterer(common.HexToAddress(uas.factoryContract), uas.WsClient)
   115  	if err != nil {
   116  		log.Error(err)
   117  	}
   118  
   119  	poolCreated, err := contract.FilterPool(
   120  		&bind.FilterOpts{Start: uas.startBlock},
   121  		[]common.Address{},
   122  		[]common.Address{},
   123  	)
   124  	if err != nil {
   125  		log.Error("filter pool created: ", err)
   126  	}
   127  	for poolCreated.Next() {
   128  		poolsCount++
   129  		log.Info("pools count: ", poolsCount)
   130  		blocknumber = int64(poolCreated.Event.Raw.BlockNumber)
   131  		// Don't repeat sending already sent assets
   132  		if _, ok := checkMap[poolCreated.Event.Token0.Hex()]; !ok {
   133  			checkMap[poolCreated.Event.Token0.Hex()] = struct{}{}
   134  			asset, err := uas.GetAssetFromAddress(poolCreated.Event.Token0)
   135  			if err != nil {
   136  				log.Warn("cannot fetch asset from address ", poolCreated.Event.Token0.Hex())
   137  			}
   138  			uas.assetChannel <- asset
   139  		}
   140  		if _, ok := checkMap[poolCreated.Event.Token1.Hex()]; !ok {
   141  			checkMap[poolCreated.Event.Token1.Hex()] = struct{}{}
   142  			asset, err := uas.GetAssetFromAddress(poolCreated.Event.Token1)
   143  			if err != nil {
   144  				log.Warn("cannot fetch asset from address ", poolCreated.Event.Token1.Hex())
   145  			}
   146  			uas.assetChannel <- asset
   147  		}
   148  	}
   149  	err = uas.relDB.SetScraperIndex(uas.exchange.Name, dia.SCRAPER_TYPE_ASSETCOLLECTOR, dia.INDEX_TYPE_BLOCKNUMBER, blocknumber)
   150  	if err != nil {
   151  		log.Error("SetScraperIndex: ", err)
   152  	}
   153  	uas.doneChannel <- true
   154  }
   155  
   156  func (uas *CamelotV3AssetSource) GetAssetFromAddress(address common.Address) (asset dia.Asset, err error) {
   157  	connection := uas.RestClient
   158  
   159  	var tokenContract *uniswapcontract.IERC20Caller
   160  
   161  	tokenContract, err = uniswapcontract.NewIERC20Caller(address, connection)
   162  	if err != nil {
   163  		log.Error(err)
   164  	}
   165  
   166  	symbol, err := tokenContract.Symbol(&bind.CallOpts{})
   167  	if err != nil {
   168  		log.Error(err)
   169  	}
   170  	name, err := tokenContract.Name(&bind.CallOpts{})
   171  	if err != nil {
   172  		log.Error(err)
   173  	}
   174  	decimals, err := tokenContract.Decimals(&bind.CallOpts{})
   175  	if err != nil {
   176  		log.Error(err)
   177  	}
   178  
   179  	asset = dia.Asset{
   180  		Symbol:     symbol,
   181  		Name:       name,
   182  		Address:    address.Hex(),
   183  		Blockchain: uas.blockchain,
   184  		Decimals:   decimals,
   185  	}
   186  
   187  	return
   188  }
   189  
   190  func (uas *CamelotV3AssetSource) Asset() chan dia.Asset {
   191  	return uas.assetChannel
   192  }
   193  
   194  func (uas *CamelotV3AssetSource) Done() chan bool {
   195  	return uas.doneChannel
   196  }