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

     1  package source
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/diadata-org/diadata/pkg/dia"
     7  	"github.com/diadata-org/diadata/pkg/dia/helpers/ethhelper"
     8  	models "github.com/diadata-org/diadata/pkg/model"
     9  	"github.com/diadata-org/diadata/pkg/utils"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	"github.com/ethereum/go-ethereum/ethclient"
    12  )
    13  
    14  const (
    15  	anyswapAPIUrl = "https://bridgeapi.anyswap.exchange/v3/serverinfoV3?chainId=all&version=STABLEV3"
    16  )
    17  
    18  var (
    19  	chainMap map[string]string
    20  )
    21  
    22  func init() {
    23  
    24  	chainMap = make(map[string]string)
    25  	chainMap["1"] = dia.ETHEREUM
    26  	chainMap["56"] = dia.BINANCESMARTCHAIN
    27  	chainMap["137"] = dia.POLYGON
    28  	chainMap["250"] = dia.FANTOM
    29  	chainMap["1284"] = dia.MOONBEAM
    30  	chainMap["1285"] = dia.MOONRIVER
    31  	chainMap["42161"] = dia.ARBITRUM
    32  	chainMap["43114"] = dia.AVALANCHE
    33  
    34  	// chainMap["66"] = chainInfo{Name: "OKExChain", Client: ""}
    35  	// chainMap["128"] = chainInfo{Name: "HuobiECOChain", Client: ""}
    36  	// chainMap["288"] = chainInfo{Name: "Boba", Client: ""}
    37  
    38  }
    39  
    40  type AnyswapAssetSource struct {
    41  	assetChannel chan dia.Asset
    42  	doneChannel  chan bool
    43  	URL          string
    44  	relDB        *models.RelDB
    45  }
    46  
    47  func NewAnyswapAssetSource(exchange dia.Exchange) *AnyswapAssetSource {
    48  
    49  	var assetChannel = make(chan dia.Asset)
    50  	var doneChannel = make(chan bool)
    51  
    52  	relDB, err := models.NewRelDataStore()
    53  	if err != nil {
    54  		log.Fatal("make new relational datastore: ", err)
    55  	}
    56  
    57  	sas := &AnyswapAssetSource{
    58  		assetChannel: assetChannel,
    59  		doneChannel:  doneChannel,
    60  		URL:          anyswapAPIUrl,
    61  		relDB:        relDB,
    62  	}
    63  
    64  	go func() {
    65  		sas.fetchAssets()
    66  	}()
    67  	return sas
    68  
    69  }
    70  
    71  func (sas *AnyswapAssetSource) Asset() chan dia.Asset {
    72  	return sas.assetChannel
    73  }
    74  
    75  func (sas *AnyswapAssetSource) Done() chan bool {
    76  	return sas.doneChannel
    77  }
    78  
    79  func (sas *AnyswapAssetSource) fetchAssets() {
    80  	allAssetsAllChains, err := sas.fetchEndpoint()
    81  	if err != nil {
    82  		log.Error("fetch endpoint: ", err)
    83  		return
    84  	}
    85  
    86  	clientMap, err := getClientMap()
    87  	if err != nil {
    88  		log.Error("get client map: ", err)
    89  	}
    90  
    91  	// @chainMap can be substituted with allAssetsAllChains as soon as we have clients for all chains.
    92  	for chainID := range clientMap {
    93  
    94  		allAssets := allAssetsAllChains[chainID]
    95  		for address := range allAssets {
    96  			asset, err := ethhelper.ETHAddressToAsset(common.HexToAddress(address), clientMap[chainID], chainMap[chainID])
    97  			if err != nil {
    98  				log.Error("fetch asset from on-chain: ", err)
    99  			}
   100  			sas.assetChannel <- asset
   101  		}
   102  
   103  	}
   104  	sas.doneChannel <- true
   105  
   106  }
   107  
   108  func getClientMap() (map[string]*ethclient.Client, error) {
   109  
   110  	clientMap := make(map[string]*ethclient.Client)
   111  	for key := range chainMap {
   112  		restClient, err := ethclient.Dial(utils.Getenv("ETH_URI_"+key, ""))
   113  		if err != nil {
   114  			log.Error("connecting to chainID: ", key)
   115  			return clientMap, err
   116  		}
   117  		clientMap[key] = restClient
   118  
   119  	}
   120  
   121  	return clientMap, nil
   122  }
   123  
   124  // fetchEndpoint returns all assets available in the Anyswap bridge obtained through an API endpoint.
   125  func (sas *AnyswapAssetSource) fetchEndpoint() (response map[string]map[string]interface{}, err error) {
   126  	// @response is of type map[chainID]map[assetAddress]interface{}
   127  	data, _, err := utils.GetRequest(sas.URL)
   128  	if err != nil {
   129  		return
   130  	}
   131  
   132  	err = json.Unmarshal(data, &response)
   133  	if err != nil {
   134  		return
   135  	}
   136  	return
   137  }