github.com/diadata-org/diadata@v1.4.593/pkg/dia/service/assetservice/source/traderjoev2_1.go (about) 1 package source 2 3 import ( 4 "math/big" 5 "strconv" 6 "strings" 7 8 "github.com/diadata-org/diadata/pkg/dia" 9 "github.com/diadata-org/diadata/pkg/dia/helpers/ethhelper" 10 traderjoe "github.com/diadata-org/diadata/pkg/dia/scraper/exchange-scrapers/traderjoe2.1" 11 models "github.com/diadata-org/diadata/pkg/model" 12 "github.com/diadata-org/diadata/pkg/utils" 13 "github.com/ethereum/go-ethereum/accounts/abi/bind" 14 "github.com/ethereum/go-ethereum/common" 15 "github.com/ethereum/go-ethereum/ethclient" 16 ) 17 18 // TraderJoeAssetSource manages the scraping of assets for the Trader Joe exchange. 19 type TraderJoeAssetSource struct { 20 RestClient *ethclient.Client 21 WsClient *ethclient.Client 22 relDB *models.RelDB 23 assetChannel chan dia.Asset 24 doneChannel chan bool 25 exchange dia.Exchange 26 startBlock uint64 27 factoryContractAddress common.Address 28 waitTime int 29 } 30 31 // NewTraderJoeAssetSource initializes a Trader Joe asset sourcer, creating an instance of the 32 // NewTraderJoeAssetSource struct. It configures necessary parameters, initiates asset fetching, and returns 33 // the initialized scraper. 34 func NewTraderJoeAssetSource(exchange dia.Exchange, relDB *models.RelDB) *TraderJoeAssetSource { 35 log.Info("NewTraderJoeLiquidityScraper ", exchange.Name) 36 log.Info("NewTraderJoeLiquidityScraper Address ", exchange.Contract) 37 38 var tjas *TraderJoeAssetSource 39 40 switch exchange.Name { 41 case dia.TraderJoeExchangeV2_1: 42 tjas = makeTraderJoeAssetSource(exchange, "", "", relDB, "200", uint64(17821282)) 43 case dia.TraderJoeExchangeV2_1Arbitrum: 44 tjas = makeTraderJoeAssetSource(exchange, "", "", relDB, "200", uint64(77473199)) 45 case dia.TraderJoeExchangeV2_1Avalanche: 46 tjas = makeTraderJoeAssetSource(exchange, "", "", relDB, "200", uint64(28371397)) 47 case dia.TraderJoeExchangeV2_1BNB: 48 tjas = makeTraderJoeAssetSource(exchange, "", "", relDB, "200", uint64(27099340)) 49 case dia.TraderJoeExchangeV2_2Avalanche: 50 tjas = makeTraderJoeAssetSource(exchange, "", "", relDB, "200", uint64(46536129)) 51 } 52 53 go func() { 54 tjas.fetchAssets() 55 }() 56 return tjas 57 } 58 59 // makeTraderJoeAssetSource initializes a Trader Joe asset source, creating an instance of the 60 // TraderJoeAssetSource struct with the specified configuration and parameters. 61 func makeTraderJoeAssetSource(exchange dia.Exchange, restDial string, wsDial string, relDB *models.RelDB, waitMilliSeconds string, startBlock uint64) *TraderJoeAssetSource { 62 var ( 63 restClient *ethclient.Client 64 wsClient *ethclient.Client 65 err error 66 assetChannel = make(chan dia.Asset) 67 doneChannel = make(chan bool) 68 tjas *TraderJoeAssetSource 69 ) 70 71 log.Infof("Init rest and ws client for %s.", exchange.BlockChain.Name) 72 restClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_REST", restDial)) 73 if err != nil { 74 log.Fatal("init rest client: ", err) 75 } 76 wsClient, err = ethclient.Dial(utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_URI_WS", wsDial)) 77 if err != nil { 78 log.Fatal("init ws client: ", err) 79 } 80 81 var waitTime int 82 waitTimeString := utils.Getenv(strings.ToUpper(exchange.BlockChain.Name)+"_WAIT_TIME", waitMilliSeconds) 83 waitTime, err = strconv.Atoi(waitTimeString) 84 if err != nil { 85 log.Error("could not parse wait time: ", err) 86 waitTime = 500 87 } 88 89 tjas = &TraderJoeAssetSource{ 90 RestClient: restClient, 91 WsClient: wsClient, 92 relDB: relDB, 93 assetChannel: assetChannel, 94 doneChannel: doneChannel, 95 exchange: exchange, 96 waitTime: waitTime, 97 startBlock: startBlock, 98 factoryContractAddress: common.HexToAddress(exchange.Contract), 99 } 100 return tjas 101 } 102 103 // fetchAssets retrieves pool creation events from the Trader Joe factory contract address and processes them. 104 func (tjas *TraderJoeAssetSource) fetchAssets() { 105 106 log.Info("Fetching Trader Joe LBPairCreated events...") 107 log.Info("Getting lb pairs creations from address: ", tjas.factoryContractAddress.Hex()) 108 109 var blocknumber int64 110 _, startblock, err := tjas.relDB.GetScraperIndex(tjas.exchange.Name, dia.SCRAPER_TYPE_ASSETCOLLECTOR) 111 if err != nil { 112 log.Error("GetScraperIndex: ", err) 113 } else { 114 tjas.startBlock = uint64(startblock) 115 } 116 117 // Initialize an Ethereum event filter for the Trader Joe factory contract. 118 contractFilter, err := traderjoe.NewTraderjoeFilterer(tjas.factoryContractAddress, tjas.WsClient) 119 if err != nil { 120 log.Error(err) 121 } 122 123 // Retrieve LBPairCreated events using the event filter. 124 lbPairCreated, err := contractFilter.FilterLBPairCreated( 125 &bind.FilterOpts{Start: tjas.startBlock}, 126 []common.Address{}, 127 []common.Address{}, 128 []*big.Int{}, 129 ) 130 if err != nil { 131 log.Error("filter pool created: ", err) 132 } 133 134 // Don't send duplicate assets to the main. 135 checkMap := make(map[string]struct{}) 136 137 // Iterate through the LBPairCreated events. 138 for lbPairCreated.Next() { 139 blocknumber = int64(lbPairCreated.Event.Raw.BlockNumber) 140 141 asset0, err := ethhelper.ETHAddressToAsset(lbPairCreated.Event.TokenX, tjas.RestClient, tjas.exchange.BlockChain.Name) 142 if err != nil { 143 log.Errorf("ETHAddressToAsset for address %s: %v", lbPairCreated.Event.TokenX.Hex(), err) 144 } 145 asset1, err := ethhelper.ETHAddressToAsset(lbPairCreated.Event.TokenY, tjas.RestClient, tjas.exchange.BlockChain.Name) 146 if err != nil { 147 log.Errorf("ETHAddressToAsset for address %s: %v", lbPairCreated.Event.TokenX.Hex(), err) 148 } 149 150 if _, ok := checkMap[asset0.Address]; !ok { 151 if asset0.Symbol != "" { 152 checkMap[asset0.Address] = struct{}{} 153 tjas.assetChannel <- asset0 154 } 155 } 156 if _, ok := checkMap[asset1.Address]; !ok { 157 if asset1.Symbol != "" { 158 checkMap[asset1.Address] = struct{}{} 159 tjas.assetChannel <- asset1 160 } 161 } 162 163 } 164 err = tjas.relDB.SetScraperIndex(tjas.exchange.Name, dia.SCRAPER_TYPE_ASSETCOLLECTOR, dia.INDEX_TYPE_BLOCKNUMBER, blocknumber) 165 if err != nil { 166 log.Error("SetScraperIndex: ", err) 167 } 168 // Signal that pool retrieval and processing is complete. 169 tjas.doneChannel <- true 170 } 171 172 // Asset returns a channel for receiving dia.Asset instances scraped by the Trader Joe asset source. 173 func (tjas *TraderJoeAssetSource) Asset() chan dia.Asset { 174 return tjas.assetChannel 175 } 176 177 // Done returns a channel for signaling the completion of Trader Joe asset scraping. 178 func (tjas *TraderJoeAssetSource) Done() chan bool { 179 return tjas.doneChannel 180 }