github.com/status-im/status-go@v1.1.0/services/wallet/market/market_test.go (about)

     1  package market
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/golang/mock/gomock"
     8  
     9  	"github.com/ethereum/go-ethereum/event"
    10  
    11  	"github.com/stretchr/testify/require"
    12  
    13  	"github.com/status-im/status-go/services/wallet/thirdparty"
    14  	mock_thirdparty "github.com/status-im/status-go/services/wallet/thirdparty/mock"
    15  )
    16  
    17  type MockPriceProvider struct {
    18  	mock_thirdparty.MockMarketDataProvider
    19  	mockPrices map[string]map[string]float64
    20  }
    21  
    22  func NewMockPriceProvider(ctrl *gomock.Controller) *MockPriceProvider {
    23  	return &MockPriceProvider{
    24  		MockMarketDataProvider: *mock_thirdparty.NewMockMarketDataProvider(ctrl),
    25  	}
    26  }
    27  
    28  func (mpp *MockPriceProvider) setMockPrices(prices map[string]map[string]float64) {
    29  	mpp.mockPrices = prices
    30  }
    31  
    32  func (mpp *MockPriceProvider) ID() string {
    33  	return "MockPriceProvider"
    34  }
    35  
    36  func (mpp *MockPriceProvider) FetchPrices(symbols []string, currencies []string) (map[string]map[string]float64, error) {
    37  	res := make(map[string]map[string]float64)
    38  	for _, symbol := range symbols {
    39  		res[symbol] = make(map[string]float64)
    40  		for _, currency := range currencies {
    41  			res[symbol][currency] = mpp.mockPrices[symbol][currency]
    42  		}
    43  	}
    44  	return res, nil
    45  }
    46  
    47  type MockPriceProviderWithError struct {
    48  	MockPriceProvider
    49  }
    50  
    51  func (mpp *MockPriceProviderWithError) FetchPrices(symbols []string, currencies []string) (map[string]map[string]float64, error) {
    52  	return nil, errors.New("error")
    53  }
    54  
    55  func setupTestPrice(t *testing.T, providers []thirdparty.MarketDataProvider) *Manager {
    56  	return NewManager(providers, &event.Feed{})
    57  }
    58  
    59  var mockPrices = map[string]map[string]float64{
    60  	"BTC": {
    61  		"USD": 1.23456,
    62  		"EUR": 2.34567,
    63  		"DAI": 3.45678,
    64  		"ARS": 9.87654,
    65  	},
    66  	"ETH": {
    67  		"USD": 4.56789,
    68  		"EUR": 5.67891,
    69  		"DAI": 6.78912,
    70  		"ARS": 8.76543,
    71  	},
    72  	"SNT": {
    73  		"USD": 7.654,
    74  		"EUR": 6.0,
    75  		"DAI": 1455.12,
    76  		"ARS": 0.0,
    77  	},
    78  }
    79  
    80  func TestPrice(t *testing.T) {
    81  	ctrl := gomock.NewController(t)
    82  	defer ctrl.Finish()
    83  	priceProvider := NewMockPriceProvider(ctrl)
    84  	priceProvider.setMockPrices(mockPrices)
    85  
    86  	manager := setupTestPrice(t, []thirdparty.MarketDataProvider{priceProvider, priceProvider})
    87  
    88  	{
    89  		rst := manager.GetCachedPrices()
    90  		require.Empty(t, rst)
    91  	}
    92  
    93  	{
    94  		symbols := []string{"BTC", "ETH"}
    95  		currencies := []string{"USD", "EUR"}
    96  		rst, err := manager.FetchPrices(symbols, currencies)
    97  		require.NoError(t, err)
    98  		for _, symbol := range symbols {
    99  			for _, currency := range currencies {
   100  				require.Equal(t, rst[symbol][currency], mockPrices[symbol][currency])
   101  			}
   102  		}
   103  	}
   104  
   105  	{
   106  		symbols := []string{"BTC", "ETH", "SNT"}
   107  		currencies := []string{"USD", "EUR", "DAI", "ARS"}
   108  		rst, err := manager.FetchPrices(symbols, currencies)
   109  		require.NoError(t, err)
   110  		for _, symbol := range symbols {
   111  			for _, currency := range currencies {
   112  				require.Equal(t, rst[symbol][currency], mockPrices[symbol][currency])
   113  			}
   114  		}
   115  	}
   116  
   117  	cache := manager.GetCachedPrices()
   118  	for symbol, pricePerCurrency := range mockPrices {
   119  		for currency, price := range pricePerCurrency {
   120  			require.Equal(t, price, cache[symbol][currency].Price)
   121  		}
   122  	}
   123  }
   124  
   125  func TestFetchPriceErrorFirstProvider(t *testing.T) {
   126  	ctrl := gomock.NewController(t)
   127  	defer ctrl.Finish()
   128  	priceProvider := NewMockPriceProvider(ctrl)
   129  	priceProvider.setMockPrices(mockPrices)
   130  	priceProviderWithError := &MockPriceProviderWithError{}
   131  	symbols := []string{"BTC", "ETH"}
   132  	currencies := []string{"USD", "EUR"}
   133  
   134  	manager := setupTestPrice(t, []thirdparty.MarketDataProvider{priceProviderWithError, priceProvider})
   135  	rst, err := manager.FetchPrices(symbols, currencies)
   136  	require.NoError(t, err)
   137  	for _, symbol := range symbols {
   138  		for _, currency := range currencies {
   139  			require.Equal(t, rst[symbol][currency], mockPrices[symbol][currency])
   140  		}
   141  	}
   142  }
   143  
   144  func TestFetchTokenMarketValues(t *testing.T) {
   145  	ctrl := gomock.NewController(t)
   146  	defer ctrl.Finish()
   147  
   148  	symbols := []string{"BTC", "ETH"}
   149  	currency := "EUR"
   150  	expectedMarketValues := map[string]thirdparty.TokenMarketValues{
   151  		"BTC": {
   152  			MKTCAP:          1000000000,
   153  			HIGHDAY:         1.23456,
   154  			LOWDAY:          1.00000,
   155  			CHANGEPCTHOUR:   0.1,
   156  			CHANGEPCTDAY:    0.2,
   157  			CHANGEPCT24HOUR: 0.3,
   158  			CHANGE24HOUR:    0.4,
   159  		},
   160  		"ETH": {
   161  			MKTCAP:          2000000000,
   162  			HIGHDAY:         4.56789,
   163  			LOWDAY:          4.00000,
   164  			CHANGEPCTHOUR:   0.5,
   165  			CHANGEPCTDAY:    0.6,
   166  			CHANGEPCT24HOUR: 0.7,
   167  			CHANGE24HOUR:    0.8,
   168  		},
   169  	}
   170  
   171  	// Can't use fake provider, because the key {receiver, method} will be different, no match
   172  	provider := mock_thirdparty.NewMockMarketDataProvider(ctrl)
   173  	provider.EXPECT().ID().Return("MockPriceProvider").AnyTimes()
   174  	provider.EXPECT().FetchTokenMarketValues(symbols, currency).Return(expectedMarketValues, nil)
   175  	manager := setupTestPrice(t, []thirdparty.MarketDataProvider{provider})
   176  	marketValues, err := manager.FetchTokenMarketValues(symbols, currency)
   177  	require.NoError(t, err)
   178  	require.Equal(t, expectedMarketValues, marketValues)
   179  
   180  	// Test error
   181  	provider.EXPECT().FetchTokenMarketValues(symbols, currency).Return(nil, errors.New("error"))
   182  	marketValues, err = manager.FetchTokenMarketValues(symbols, currency)
   183  	require.Error(t, err)
   184  	require.Nil(t, marketValues)
   185  }