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 }