github.com/NpoolPlatform/chain-middleware@v0.0.0-20240228100535-eb1bcf896eb9/pkg/currency/coin.go (about)

     1  package currency
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	coincurrency1 "github.com/NpoolPlatform/chain-middleware/pkg/mw/coin/currency"
     8  	coincurrencyfeed1 "github.com/NpoolPlatform/chain-middleware/pkg/mw/coin/currency/feed"
     9  	coincurrencymwpb "github.com/NpoolPlatform/message/npool/chain/mw/v1/coin/currency"
    10  	coincurrencyfeedmwpb "github.com/NpoolPlatform/message/npool/chain/mw/v1/coin/currency/feed"
    11  
    12  	coinbase "github.com/NpoolPlatform/chain-middleware/pkg/currency/coinbase"
    13  	coingecko "github.com/NpoolPlatform/chain-middleware/pkg/currency/coingecko"
    14  
    15  	"github.com/NpoolPlatform/go-service-framework/pkg/logger"
    16  	cruder "github.com/NpoolPlatform/libent-cruder/pkg/cruder"
    17  	basetypes "github.com/NpoolPlatform/message/npool/basetypes/v1"
    18  	"github.com/shopspring/decimal"
    19  )
    20  
    21  //nolint:funlen,gocyclo
    22  func _refreshCoins(ctx context.Context, feedType basetypes.CurrencyFeedType) error {
    23  	offset := int32(0)
    24  	const limit = int32(100)
    25  
    26  	for {
    27  		h1, err := coincurrencyfeed1.NewHandler(
    28  			ctx,
    29  			coincurrencyfeed1.WithConds(&coincurrencyfeedmwpb.Conds{
    30  				FeedType: &basetypes.Uint32Val{Op: cruder.EQ, Value: uint32(feedType)},
    31  				Disabled: &basetypes.BoolVal{Op: cruder.EQ, Value: false},
    32  			}),
    33  			coincurrencyfeed1.WithOffset(offset),
    34  			coincurrencyfeed1.WithLimit(limit),
    35  		)
    36  		if err != nil {
    37  			logger.Sugar().Errorw(
    38  				"_refreshCoins",
    39  				"Error", err,
    40  			)
    41  			return err
    42  		}
    43  
    44  		feeds, _, err := h1.GetFeeds(ctx)
    45  		if err != nil {
    46  			logger.Sugar().Errorw(
    47  				"_refreshCoins",
    48  				"Error", err,
    49  			)
    50  			return err
    51  		}
    52  		if len(feeds) == 0 {
    53  			return nil
    54  		}
    55  
    56  		feedMap := map[string]*coincurrencyfeedmwpb.Feed{}
    57  		coinNames := []string{}
    58  
    59  		for _, _feed := range feeds {
    60  			if _feed.FeedCoinName == "" {
    61  				continue
    62  			}
    63  			feedMap[_feed.CoinTypeID] = _feed
    64  			coinNames = append(coinNames, _feed.FeedCoinName)
    65  		}
    66  		if len(coinNames) == 0 {
    67  			return fmt.Errorf("invalid feeds")
    68  		}
    69  
    70  		var prices map[string]decimal.Decimal
    71  		switch feedType {
    72  		case basetypes.CurrencyFeedType_CoinGecko:
    73  			prices, err = coingecko.CoinGeckoUSDPrices(coinNames)
    74  		case basetypes.CurrencyFeedType_CoinBase:
    75  			prices, err = coinbase.CoinBaseUSDPrices(coinNames)
    76  		default:
    77  			return fmt.Errorf("invalid feedtype")
    78  		}
    79  		if err != nil {
    80  			logger.Sugar().Errorw(
    81  				"_refreshCoins",
    82  				"Error", err,
    83  			)
    84  			return err
    85  		}
    86  
    87  		_feedMap := map[string][]*coincurrencyfeedmwpb.Feed{}
    88  		coinRefreshed := map[string]bool{}
    89  		for _, _feed := range feeds {
    90  			_feedMap[_feed.FeedCoinName] = append(_feedMap[_feed.FeedCoinName], _feed)
    91  		}
    92  
    93  		reqs := []*coincurrencymwpb.CurrencyReq{}
    94  		for _feedCoinName, _price := range prices {
    95  			_feeds, ok := _feedMap[_feedCoinName]
    96  			if !ok {
    97  				continue
    98  			}
    99  			_priceStr := _price.String()
   100  
   101  			for _, _feed := range _feeds {
   102  				reqs = append(reqs, &coincurrencymwpb.CurrencyReq{
   103  					CoinTypeID:      &_feed.CoinTypeID,
   104  					FeedType:        &feedType,
   105  					MarketValueHigh: &_priceStr,
   106  					MarketValueLow:  &_priceStr,
   107  				})
   108  				coinRefreshed[_feed.CoinTypeID] = true
   109  			}
   110  		}
   111  
   112  		for _, _feed := range feeds {
   113  			refreshed, ok := coinRefreshed[_feed.CoinTypeID]
   114  			if !ok {
   115  				logger.Sugar().Warnw(
   116  					"_refreshCoins",
   117  					"CoinTypeID", _feed.CoinTypeID,
   118  					"Refreshed", refreshed,
   119  					"FeedCoinName", _feed.FeedCoinName,
   120  				)
   121  			}
   122  		}
   123  
   124  		if len(reqs) == 0 {
   125  			continue
   126  		}
   127  
   128  		h2, err := coincurrency1.NewHandler(
   129  			ctx,
   130  			coincurrency1.WithReqs(reqs, true),
   131  		)
   132  		if err != nil {
   133  			logger.Sugar().Errorw(
   134  				"_refreshCoins",
   135  				"Error", err,
   136  			)
   137  			return err
   138  		}
   139  
   140  		_, err = h2.CreateCurrencies(ctx)
   141  		if err != nil {
   142  			logger.Sugar().Errorw(
   143  				"_refreshCoins",
   144  				"Error", err,
   145  			)
   146  			return err
   147  		}
   148  
   149  		offset += limit
   150  	}
   151  }
   152  
   153  func refreshCoins(ctx context.Context) {
   154  	if err := _refreshCoins(ctx, basetypes.CurrencyFeedType_CoinGecko); err != nil {
   155  		logger.Sugar().Warnw(
   156  			"refreshCoins",
   157  			"FeedType", basetypes.CurrencyFeedType_CoinGecko,
   158  			"Error", err,
   159  		)
   160  	}
   161  
   162  	if err := _refreshCoins(ctx, basetypes.CurrencyFeedType_CoinBase); err != nil {
   163  		logger.Sugar().Warnw(
   164  			"refreshCoins",
   165  			"FeedType", basetypes.CurrencyFeedType_CoinGecko,
   166  			"Error", err,
   167  		)
   168  	}
   169  }