diff --git a/exchanges/orderbook/orderbook.go b/exchanges/orderbook/orderbook.go index d225985c..94d23690 100644 --- a/exchanges/orderbook/orderbook.go +++ b/exchanges/orderbook/orderbook.go @@ -8,11 +8,13 @@ import ( "github.com/thrasher-/gocryptotrader/currency" ) -// Const values for orderbook package +// const values for orderbook package const ( - ErrOrderbookForExchangeNotFound = "ticker for exchange does not exist" - ErrPrimaryCurrencyNotFound = "primary currency for orderbook not found" - ErrSecondaryCurrencyNotFound = "secondary currency for orderbook not found" + errExchangeOrderbookNotFound = "orderbook for exchange does not exist" + errPairNotSet = "orderbook currency pair not set" + errAssetTypeNotSet = "orderbook asset type not set" + errBaseCurrencyNotFound = "orderbook base currency not found" + errQuoteCurrencyNotFound = "orderbook quote currency not found" Spot = "SPOT" ) @@ -82,11 +84,11 @@ func Get(exchange string, p currency.Pair, orderbookType string) (Base, error) { } if !BaseCurrencyExists(exchange, p.Base) { - return Base{}, errors.New(ErrPrimaryCurrencyNotFound) + return Base{}, errors.New(errBaseCurrencyNotFound) } if !QuoteCurrencyExists(exchange, p) { - return Base{}, errors.New(ErrSecondaryCurrencyNotFound) + return Base{}, errors.New(errQuoteCurrencyNotFound) } return orderbook.Orderbook[p.Base.Item][p.Quote.Item][orderbookType], nil @@ -101,7 +103,7 @@ func GetByExchange(exchange string) (*Orderbook, error) { return &Orderbooks[x], nil } } - return nil, errors.New(ErrOrderbookForExchangeNotFound) + return nil, errors.New(errExchangeOrderbookNotFound) } // BaseCurrencyExists checks to see if the base currency of the orderbook map @@ -156,11 +158,11 @@ func CreateNewOrderbook(exchangeName string, orderbookNew *Base, orderbookType s // list func (o *Base) Process() error { if o.Pair.IsEmpty() { - return errors.New("orderbook currency pair not populated") + return errors.New(errPairNotSet) } if o.AssetType == "" { - return errors.New("orderbook asset type not set") + return errors.New(errAssetTypeNotSet) } if o.LastUpdated.IsZero() { diff --git a/exchanges/orderbook/orderbook_test.go b/exchanges/orderbook/orderbook_test.go index b18cefc5..d2c867a4 100644 --- a/exchanges/orderbook/orderbook_test.go +++ b/exchanges/orderbook/orderbook_test.go @@ -86,7 +86,7 @@ func TestGetOrderbook(t *testing.T) { t.Fatalf("Test failed. TestGetOrderbook failed to get orderbook. Error %s", err) } - if result.Pair.String() != c.String() { + if !result.Pair.Equal(c) { t.Fatal("Test failed. TestGetOrderbook failed. Mismatched pairs") } @@ -185,7 +185,7 @@ func TestCreateNewOrderbook(t *testing.T) { t.Fatal("Test failed. TestCreateNewOrderbook failed to create new orderbook") } - if result.Pair.String() != c.String() { + if !result.Pair.Equal(c) { t.Fatal("Test failed. TestCreateNewOrderbook result pair is incorrect") } @@ -204,41 +204,66 @@ func TestProcessOrderbook(t *testing.T) { Orderbooks = []Orderbook{} c := currency.NewPairFromStrings("BTC", "USD") base := Base{ - Pair: c, Asks: []Item{{Price: 100, Amount: 10}}, Bids: []Item{{Price: 200, Amount: 10}}, ExchangeName: "Exchange", - AssetType: Spot, } + // test for empty pair + base.Pair = currency.Pair{} err := base.Process() - if err != nil { - t.Error("Test Failed - Process() error", err) + if err == nil { + t.Error("empty pair should throw an err") } + // test for empty asset type + base.Pair = c + err = base.Process() + if err == nil { + t.Error("empty asset type should throw an err") + } + + // now process a valid orderbook + base.AssetType = Spot + err = base.Process() + if err != nil { + t.Error("unexpcted result: ", err) + } result, err := Get("Exchange", c, Spot) if err != nil { t.Fatal("Test failed. TestProcessOrderbook failed to create new orderbook") } - - if result.Pair.String() != c.String() { + if !result.Pair.Equal(c) { t.Fatal("Test failed. TestProcessOrderbook result pair is incorrect") } + // now test for processing a pair with a different quote currency c = currency.NewPairFromStrings("BTC", "GBP") base.Pair = c - err = base.Process() if err != nil { t.Error("Test Failed - Process() error", err) } - result, err = Get("Exchange", c, Spot) if err != nil { t.Fatal("Test failed. TestProcessOrderbook failed to retrieve new orderbook") } + if !result.Pair.Equal(c) { + t.Fatal("Test failed. TestProcessOrderbook result pair is incorrect") + } - if result.Pair.String() != c.String() { + // now test for processing a pair which has a different base currency + c = currency.NewPairFromStrings("LTC", "GBP") + base.Pair = c + err = base.Process() + if err != nil { + t.Error("Test Failed - Process() error", err) + } + result, err = Get("Exchange", c, Spot) + if err != nil { + t.Fatal("Test failed. TestProcessOrderbook failed to retrieve new orderbook") + } + if !result.Pair.Equal(c) { t.Fatal("Test failed. TestProcessOrderbook result pair is incorrect") } diff --git a/exchanges/ticker/ticker.go b/exchanges/ticker/ticker.go index 4b75fd27..38d9ac7c 100644 --- a/exchanges/ticker/ticker.go +++ b/exchanges/ticker/ticker.go @@ -10,11 +10,13 @@ import ( "github.com/thrasher-/gocryptotrader/currency" ) -// Const values for the ticker package +// const values for the ticker package const ( - ErrTickerForExchangeNotFound = "ticker for exchange does not exist" - ErrPrimaryCurrencyNotFound = "primary currency for ticker not found" - ErrSecondaryCurrencyNotFound = "secondary currency for ticker not found" + errExchangeTickerNotFound = "ticker for exchange does not exist" + errPairNotSet = "ticker currency pair not set" + errAssetTypeNotSet = "ticker asset type not set" + errBaseCurrencyNotFound = "ticker base currency not found" + errQuoteCurrencyNotFound = "ticker quote currency not found" Spot = "SPOT" ) @@ -75,12 +77,12 @@ func GetTicker(exchange string, p currency.Pair, tickerType string) (Price, erro return Price{}, err } - if !FirstCurrencyExists(exchange, p.Base) { - return Price{}, errors.New(ErrPrimaryCurrencyNotFound) + if !BaseCurrencyExists(exchange, p.Base) { + return Price{}, errors.New(errBaseCurrencyNotFound) } - if !SecondCurrencyExists(exchange, p) { - return Price{}, errors.New(ErrSecondaryCurrencyNotFound) + if !QuoteCurrencyExists(exchange, p) { + return Price{}, errors.New(errQuoteCurrencyNotFound) } return ticker.Price[p.Base.Upper().String()][p.Quote.Upper().String()][tickerType], nil @@ -95,12 +97,12 @@ func GetTickerByExchange(exchange string) (*Ticker, error) { return &Tickers[x], nil } } - return nil, errors.New(ErrTickerForExchangeNotFound) + return nil, errors.New(errExchangeTickerNotFound) } -// FirstCurrencyExists checks to see if the first currency of the Price map +// BaseCurrencyExists checks to see if the base currency of the ticker map // exists -func FirstCurrencyExists(exchange string, currency currency.Code) bool { +func BaseCurrencyExists(exchange string, currency currency.Code) bool { m.Lock() defer m.Unlock() for _, y := range Tickers { @@ -113,9 +115,9 @@ func FirstCurrencyExists(exchange string, currency currency.Code) bool { return false } -// SecondCurrencyExists checks to see if the second currency of the Price map +// QuoteCurrencyExists checks to see if the quote currency of the ticker map // exists -func SecondCurrencyExists(exchange string, p currency.Pair) bool { +func QuoteCurrencyExists(exchange string, p currency.Pair) bool { m.Lock() defer m.Unlock() for _, y := range Tickers { @@ -148,23 +150,29 @@ func CreateNewTicker(exchangeName string, tickerNew *Price, tickerType string) T // ProcessTicker processes incoming tickers, creating or updating the Tickers // list -func ProcessTicker(exchangeName string, tickerNew *Price, tickerType string) error { - if tickerNew.Pair.String() == "" { - return errors.New("") +func ProcessTicker(exchangeName string, tickerNew *Price, assetType string) error { + if tickerNew.Pair.IsEmpty() { + return errors.New(errPairNotSet) } - tickerNew.LastUpdated = time.Now() + if assetType == "" { + return errors.New(errAssetTypeNotSet) + } + + if tickerNew.LastUpdated.IsZero() { + tickerNew.LastUpdated = time.Now() + } ticker, err := GetTickerByExchange(exchangeName) if err != nil { - CreateNewTicker(exchangeName, tickerNew, tickerType) + CreateNewTicker(exchangeName, tickerNew, assetType) return nil } - if FirstCurrencyExists(exchangeName, tickerNew.Pair.Base) { + if BaseCurrencyExists(exchangeName, tickerNew.Pair.Base) { m.Lock() a := make(map[string]Price) - a[tickerType] = *tickerNew + a[assetType] = *tickerNew ticker.Price[tickerNew.Pair.Base.Upper().String()][tickerNew.Pair.Quote.Upper().String()] = a m.Unlock() return nil @@ -173,7 +181,7 @@ func ProcessTicker(exchangeName string, tickerNew *Price, tickerType string) err m.Lock() a := make(map[string]map[string]Price) b := make(map[string]Price) - b[tickerType] = *tickerNew + b[assetType] = *tickerNew a[tickerNew.Pair.Quote.Upper().String()] = b ticker.Price[tickerNew.Pair.Base.Upper().String()] = a m.Unlock() diff --git a/exchanges/ticker/ticker_test.go b/exchanges/ticker/ticker_test.go index 641cec2d..31552f5c 100644 --- a/exchanges/ticker/ticker_test.go +++ b/exchanges/ticker/ticker_test.go @@ -75,7 +75,7 @@ func TestGetTicker(t *testing.T) { if err != nil { t.Errorf("Test Failed - Ticker GetTicker init error: %s", err) } - if tickerPrice.Pair.String() != "BTCUSD" { + if !tickerPrice.Pair.Equal(newPair) { t.Error("Test Failed - ticker tickerPrice.CurrencyPair value is incorrect") } @@ -138,7 +138,7 @@ func TestGetTickerByExchange(t *testing.T) { } } -func TestFirstCurrencyExists(t *testing.T) { +func TestBaseCurrencyExists(t *testing.T) { newPair := currency.NewPairFromStrings("BTC", "USD") priceStruct := Price{ Pair: newPair, @@ -154,15 +154,15 @@ func TestFirstCurrencyExists(t *testing.T) { alphaTicker := CreateNewTicker("alphapoint", &priceStruct, Spot) Tickers = append(Tickers, alphaTicker) - if !FirstCurrencyExists("alphapoint", currency.BTC) { - t.Error("Test Failed - FirstCurrencyExists1 value return is incorrect") + if !BaseCurrencyExists("alphapoint", currency.BTC) { + t.Error("Test Failed - BaseCurrencyExists1 value return is incorrect") } - if FirstCurrencyExists("alphapoint", currency.NewCode("CATS")) { - t.Error("Test Failed - FirstCurrencyExists2 value return is incorrect") + if BaseCurrencyExists("alphapoint", currency.NewCode("CATS")) { + t.Error("Test Failed - BaseCurrencyExists2 value return is incorrect") } } -func TestSecondCurrencyExists(t *testing.T) { +func TestQuoteCurrencyExists(t *testing.T) { t.Parallel() newPair := currency.NewPairFromStrings("BTC", "USD") @@ -180,13 +180,13 @@ func TestSecondCurrencyExists(t *testing.T) { bitstampTicker := CreateNewTicker("bitstamp", &priceStruct, "SPOT") Tickers = append(Tickers, bitstampTicker) - if !SecondCurrencyExists("bitstamp", newPair) { - t.Error("Test Failed - SecondCurrencyExists1 value return is incorrect") + if !QuoteCurrencyExists("bitstamp", newPair) { + t.Error("Test Failed - QuoteCurrencyExists1 value return is incorrect") } newPair.Quote = currency.NewCode("DOGS") - if SecondCurrencyExists("bitstamp", newPair) { - t.Error("Test Failed - SecondCurrencyExists2 value return is incorrect") + if QuoteCurrencyExists("bitstamp", newPair) { + t.Error("Test Failed - QuoteCurrencyExists2 value return is incorrect") } } @@ -216,7 +216,7 @@ func TestCreateNewTicker(t *testing.T) { t.Error("Test Failed - ticker CreateNewTicker.ExchangeName value is not ANX") } - if newTicker.Price[currency.BTC.Upper().String()][currency.USD.Upper().String()][Spot].Pair.String() != "BTCUSD" { + if !newTicker.Price[currency.BTC.Upper().String()][currency.USD.Upper().String()][Spot].Pair.Equal(newPair) { t.Error("Test Failed - ticker newTicker.Price[BTC][USD].Pair.Pair().String() value is not expected 'BTCUSD'") } if reflect.TypeOf(newTicker.Price["BTC"]["USD"][Spot].Ask).String() != float64Type { @@ -250,7 +250,6 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers exchName := "bitstamp" newPair := currency.NewPairFromStrings("BTC", "USD") priceStruct := Price{ - Pair: newPair, Last: 1200, High: 1298, Low: 1148, @@ -260,37 +259,59 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers PriceATH: 1337, } - err := ProcessTicker(exchName, &Price{}, Spot) + // test for empty pair + err := ProcessTicker(exchName, &priceStruct, Spot) + if err == nil { + t.Fatal("empty pair should throw an err") + } + + // test for empty asset type + priceStruct.Pair = newPair + err = ProcessTicker(exchName, &priceStruct, "") if err == nil { t.Fatal("Test failed. ProcessTicker error cannot be nil") } + // now process a valid ticker err = ProcessTicker(exchName, &priceStruct, Spot) if err != nil { t.Fatal("Test failed. ProcessTicker error", err) } - result, err := GetTicker(exchName, newPair, Spot) if err != nil { t.Fatal("Test failed. TestProcessTicker failed to create and return a new ticker") } - - if result.Pair.String() != newPair.String() { + if !result.Pair.Equal(newPair) { t.Fatal("Test failed. TestProcessTicker pair mismatch") } - secondPair := currency.NewPairFromStrings("BTC", "AUD") - priceStruct.Pair = secondPair + // now test for processing a pair with a different quote currency + newPair = currency.NewPairFromStrings("BTC", "AUD") + priceStruct.Pair = newPair err = ProcessTicker(exchName, &priceStruct, Spot) if err != nil { t.Fatal("Test failed. ProcessTicker error", err) } - - result, err = GetTicker(exchName, secondPair, Spot) + result, err = GetTicker(exchName, newPair, Spot) if err != nil { t.Fatal("Test failed. TestProcessTicker failed to create and return a new ticker") } + result, err = GetTicker(exchName, newPair, Spot) + if err != nil { + t.Fatal("Test failed. TestProcessTicker failed to return an existing ticker") + } + // now test for processing a pair which has a different base currency + newPair = currency.NewPairFromStrings("LTC", "AUD") + priceStruct.Pair = newPair + err = ProcessTicker(exchName, &priceStruct, Spot) + if err != nil { + t.Fatal("Test failed. ProcessTicker error", err) + } + result, err = GetTicker(exchName, newPair, Spot) + if err != nil { + t.Fatal("Test failed. TestProcessTicker failed to create and return a new ticker") + } result, err = GetTicker(exchName, newPair, Spot) if err != nil { t.Fatal("Test failed. TestProcessTicker failed to return an existing ticker")