Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ In addition, it defines the oracle's keyring and feeder account information.
The keyring's password is defined via environment variables or user input.
More information on the keyring can be found [here](#keyring)
Please see the [example configuration](price-feeder.example.toml) for more details.
Please see the [forex example configuration](price-feeder.example_forex.toml) for an example
configuration fetching Forex rates from polygon.io (premium API key required).

```shell
$ price-feeder /path/to/price_feeder_config.toml
Expand Down
36 changes: 32 additions & 4 deletions oracle/provider/binance.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,31 +199,51 @@ func (p *BinanceProvider) SubscribeCurrencyPairs(cps ...types.CurrencyPair) erro
func (p *BinanceProvider) GetTickerPrices(pairs ...types.CurrencyPair) (map[string]types.TickerPrice, error) {
tickerPrices := make(map[string]types.TickerPrice, len(pairs))

tickerErrs := 0
for _, cp := range pairs {
key := cp.String()
price, err := p.getTickerPrice(key)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
tickerErrs++
continue
}
tickerPrices[key] = price
}

if tickerErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoTickers.Error(),
p.endpoints.Name,
pairs,
)
}
return tickerPrices, nil
}

// GetCandlePrices returns the candlePrices based on the provided pairs.
func (p *BinanceProvider) GetCandlePrices(pairs ...types.CurrencyPair) (map[string][]types.CandlePrice, error) {
candlePrices := make(map[string][]types.CandlePrice, len(pairs))

candleErrs := 0
for _, cp := range pairs {
key := cp.String()
prices, err := p.getCandlePrices(key)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
candleErrs++
continue
}
candlePrices[key] = prices
}

if candleErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoCandles.Error(),
p.endpoints.Name,
pairs,
)
}
return candlePrices, nil
}

Expand All @@ -233,7 +253,11 @@ func (p *BinanceProvider) getTickerPrice(key string) (types.TickerPrice, error)

ticker, ok := p.tickers[key]
if !ok {
return types.TickerPrice{}, fmt.Errorf("binance failed to get ticker price for %s", key)
return types.TickerPrice{}, fmt.Errorf(
types.ErrTickerNotFound.Error(),
p.endpoints.Name,
key,
)
}

return ticker.toTickerPrice()
Expand All @@ -245,7 +269,11 @@ func (p *BinanceProvider) getCandlePrices(key string) ([]types.CandlePrice, erro

candles, ok := p.candles[key]
if !ok {
return []types.CandlePrice{}, fmt.Errorf("binance failed to get candle prices for %s", key)
return []types.CandlePrice{}, fmt.Errorf(
types.ErrCandleNotFound.Error(),
p.endpoints.Name,
key,
)
}

candleList := []types.CandlePrice{}
Expand Down
2 changes: 1 addition & 1 deletion oracle/provider/binance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func TestBinanceProvider_GetTickerPrices(t *testing.T) {

t.Run("invalid_request_invalid_ticker", func(t *testing.T) {
prices, err := p.GetTickerPrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.EqualError(t, err, "binance failed to get ticker price for FOOBAR")
require.EqualError(t, err, "binanceus has no ticker data for requested pairs: [FOOBAR]")
require.Nil(t, prices)
})
}
Expand Down
44 changes: 36 additions & 8 deletions oracle/provider/bitget.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,33 +202,53 @@ func (p *BitgetProvider) SubscribeCurrencyPairs(cps ...types.CurrencyPair) error
return nil
}

// GetTickerPrices returns the tickerPrices based on the saved map.
// GetTickerPrices returns the tickerPrices based on the provided pairs.
func (p *BitgetProvider) GetTickerPrices(pairs ...types.CurrencyPair) (map[string]types.TickerPrice, error) {
tickerPrices := make(map[string]types.TickerPrice, len(pairs))

tickerErrs := 0
for _, cp := range pairs {
price, err := p.getTickerPrice(cp)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
tickerErrs++
continue
}
tickerPrices[cp.String()] = price
}

if tickerErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoTickers.Error(),
p.endpoints.Name,
pairs,
)
}
return tickerPrices, nil
}

// GetTickerPrices returns the tickerPrices based on the saved map.
// GetCandlePrices returns the candlePrices based on the provided pairs.
func (p *BitgetProvider) GetCandlePrices(pairs ...types.CurrencyPair) (map[string][]types.CandlePrice, error) {
candlePrices := make(map[string][]types.CandlePrice, len(pairs))

candleErrs := 0
for _, cp := range pairs {
price, err := p.getCandlePrices(cp)
prices, err := p.getCandlePrices(cp)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
candleErrs++
continue
}
candlePrices[cp.String()] = price
candlePrices[cp.String()] = prices
}

if candleErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoCandles.Error(),
p.endpoints.Name,
pairs,
)
}
return candlePrices, nil
}

Expand Down Expand Up @@ -344,7 +364,11 @@ func (p *BitgetProvider) getTickerPrice(cp types.CurrencyPair) (types.TickerPric

ticker, ok := p.tickers[cp.String()]
if !ok {
return types.TickerPrice{}, fmt.Errorf("bitget failed to get ticker price for %s", cp.String())
return types.TickerPrice{}, fmt.Errorf(
types.ErrTickerNotFound.Error(),
p.endpoints.Name,
cp.String(),
)
}

return ticker.toTickerPrice()
Expand All @@ -356,7 +380,11 @@ func (p *BitgetProvider) getCandlePrices(cp types.CurrencyPair) ([]types.CandleP

candles, ok := p.candles[cp.String()]
if !ok {
return []types.CandlePrice{}, fmt.Errorf("failed to get candles price for %s", cp.String())
return []types.CandlePrice{}, fmt.Errorf(
types.ErrCandleNotFound.Error(),
p.endpoints.Name,
cp.String(),
)
}

candleList := []types.CandlePrice{}
Expand Down
4 changes: 2 additions & 2 deletions oracle/provider/bitget_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func TestBitgetProvider_GetTickerPrices(t *testing.T) {

t.Run("invalid_request_invalid_ticker", func(t *testing.T) {
prices, err := p.GetTickerPrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.EqualError(t, err, "bitget failed to get ticker price for FOOBAR")
require.EqualError(t, err, "bitget has no ticker data for requested pairs: [FOOBAR]")
require.Nil(t, prices)
})
}
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestBitgetProvider_GetCandlePrices(t *testing.T) {

t.Run("invalid_request_invalid_candle", func(t *testing.T) {
prices, err := p.GetCandlePrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.EqualError(t, err, "failed to get candles price for FOOBAR")
require.EqualError(t, err, "bitget has no candle data for requested pairs: [FOOBAR]")
require.Nil(t, prices)
})
}
Expand Down
40 changes: 30 additions & 10 deletions oracle/provider/coinbase.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,19 +192,28 @@ func (p *CoinbaseProvider) SubscribeCurrencyPairs(cps ...types.CurrencyPair) err
return nil
}

// GetTickerPrices returns the tickerPrices based on the saved map.
// GetTickerPrices returns the tickerPrices based on the provided pairs.
func (p *CoinbaseProvider) GetTickerPrices(pairs ...types.CurrencyPair) (map[string]types.TickerPrice, error) {
tickerPrices := make(map[string]types.TickerPrice, len(pairs))

for _, currencyPair := range pairs {
price, err := p.getTickerPrice(currencyPair)
tickerErrs := 0
for _, cp := range pairs {
price, err := p.getTickerPrice(cp)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
tickerErrs++
continue
}

tickerPrices[currencyPair.String()] = price
tickerPrices[cp.String()] = price
}

if tickerErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoTickers.Error(),
p.endpoints.Name,
pairs,
)
}
return tickerPrices, nil
}

Expand All @@ -213,16 +222,23 @@ func (p *CoinbaseProvider) GetTickerPrices(pairs ...types.CurrencyPair) (map[str
func (p *CoinbaseProvider) GetCandlePrices(pairs ...types.CurrencyPair) (map[string][]types.CandlePrice, error) {
tradeMap := make(map[string][]CoinbaseTrade, len(pairs))

tradeErrs := 0
for _, cp := range pairs {
key := currencyPairToCoinbasePair(cp)
tradeSet, err := p.getTradePrices(key)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
tradeErrs++
continue
}
tradeMap[key] = tradeSet
}
if len(tradeMap) == 0 {
return nil, fmt.Errorf("no trades have been received")
if tradeErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoTickers.Error(),
p.endpoints.Name,
pairs,
)
}

candles := make(map[string][]types.CandlePrice)
Expand Down Expand Up @@ -312,7 +328,11 @@ func (p *CoinbaseProvider) getTickerPrice(cp types.CurrencyPair) (types.TickerPr
return tickerPair.toTickerPrice()
}

return types.TickerPrice{}, fmt.Errorf("coinbase failed to get ticker price for %s", gp)
return types.TickerPrice{}, fmt.Errorf(
types.ErrTickerNotFound.Error(),
p.endpoints.Name,
gp,
)
}

func (p *CoinbaseProvider) getTradePrices(key string) ([]CoinbaseTrade, error) {
Expand Down
2 changes: 1 addition & 1 deletion oracle/provider/coinbase_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestCoinbaseProvider_GetTickerPrices(t *testing.T) {

t.Run("invalid_request_invalid_ticker", func(t *testing.T) {
prices, err := p.GetTickerPrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.EqualError(t, err, "coinbase failed to get ticker price for FOO-BAR")
require.EqualError(t, err, "coinbase has no ticker data for requested pairs: [FOOBAR]")
require.Nil(t, prices)
})
}
Expand Down
36 changes: 30 additions & 6 deletions oracle/provider/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,35 +205,59 @@ func (p *CryptoProvider) SubscribeCurrencyPairs(cps ...types.CurrencyPair) error
return nil
}

// GetTickerPrices returns the tickerPrices based on the saved map.
// GetTickerPrices returns the tickerPrices based on the provided pairs.
func (p *CryptoProvider) GetTickerPrices(pairs ...types.CurrencyPair) (map[string]types.TickerPrice, error) {
tickerPrices := make(map[string]types.TickerPrice, len(pairs))

tickerErrs := 0
for _, cp := range pairs {
key := currencyPairToCryptoPair(cp)
fmt.Println(
"key:",
key,
)
price, err := p.getTickerPrice(key)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
tickerErrs++
continue
}
tickerPrices[cp.String()] = price
}

if tickerErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoTickers.Error(),
p.endpoints.Name,
pairs,
)
}
return tickerPrices, nil
}

// GetCandlePrices returns the candlePrices based on the saved map
// GetCandlePrices returns the candlePrices based on the provided pairs.
func (p *CryptoProvider) GetCandlePrices(pairs ...types.CurrencyPair) (map[string][]types.CandlePrice, error) {
candlePrices := make(map[string][]types.CandlePrice, len(pairs))

candleErrs := 0
for _, cp := range pairs {
key := currencyPairToCryptoPair(cp)
prices, err := p.getCandlePrices(key)
if err != nil {
return nil, err
p.logger.Warn().Err(err)
candleErrs++
continue
}
candlePrices[cp.String()] = prices
}

if candleErrs == len(pairs) {
return nil, fmt.Errorf(
types.ErrNoCandles.Error(),
p.endpoints.Name,
pairs,
)
}
return candlePrices, nil
}

Expand All @@ -245,7 +269,7 @@ func (p *CryptoProvider) getTickerPrice(key string) (types.TickerPrice, error) {
if !ok {
return types.TickerPrice{}, fmt.Errorf(
types.ErrTickerNotFound.Error(),
ProviderCrypto,
p.endpoints.Name,
key,
)
}
Expand All @@ -261,7 +285,7 @@ func (p *CryptoProvider) getCandlePrices(key string) ([]types.CandlePrice, error
if !ok {
return []types.CandlePrice{}, fmt.Errorf(
types.ErrCandleNotFound.Error(),
ProviderCrypto,
p.endpoints.Name,
key,
)
}
Expand Down
4 changes: 2 additions & 2 deletions oracle/provider/crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func TestCryptoProvider_GetTickerPrices(t *testing.T) {
t.Run("invalid_request_invalid_ticker", func(t *testing.T) {
prices, err := p.GetTickerPrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.Error(t, err)
require.Equal(t, "crypto failed to get ticker price for FOO_BAR", err.Error())
require.Equal(t, "crypto has no ticker data for requested pairs: [FOOBAR]", err.Error())
require.Nil(t, prices)
})
}
Expand Down Expand Up @@ -110,7 +110,7 @@ func TestCryptoProvider_GetCandlePrices(t *testing.T) {

t.Run("invalid_request_invalid_candle", func(t *testing.T) {
prices, err := p.GetCandlePrices(types.CurrencyPair{Base: "FOO", Quote: "BAR"})
require.EqualError(t, err, "crypto failed to get candle price for FOO_BAR")
require.EqualError(t, err, "crypto has no candle data for requested pairs: [FOOBAR]")
require.Nil(t, prices)
})
}
Expand Down
Loading