mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
* Fixes issue with BTSE processing of new events. Also prevents panics in the event some other unexpected data comes along * Removes old auth code * Parallelogram * BTSE Filters out zero values for REST orderbooks as they do not provide enough decimal places via API to have accurate orderbooks.
911 lines
22 KiB
Go
911 lines
22 KiB
Go
package btse
|
|
|
|
import (
|
|
"errors"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/common"
|
|
"github.com/thrasher-corp/gocryptotrader/config"
|
|
"github.com/thrasher-corp/gocryptotrader/core"
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
|
)
|
|
|
|
// Please supply your own keys here to do better tests
|
|
const (
|
|
apiKey = ""
|
|
apiSecret = ""
|
|
canManipulateRealOrders = false
|
|
testSPOTPair = "BTC-USD"
|
|
testFUTURESPair = "BTCPFC"
|
|
)
|
|
|
|
var b BTSE
|
|
|
|
func TestMain(m *testing.M) {
|
|
b.SetDefaults()
|
|
cfg := config.GetConfig()
|
|
err := cfg.LoadConfig("../../testdata/configtest.json", true)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
btseConfig, err := cfg.GetExchangeConfig("BTSE")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
btseConfig.API.AuthenticatedSupport = true
|
|
btseConfig.API.Credentials.Key = apiKey
|
|
btseConfig.API.Credentials.Secret = apiSecret
|
|
b.Websocket = sharedtestvalues.NewTestWebsocket()
|
|
err = b.Setup(btseConfig)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
os.Exit(m.Run())
|
|
}
|
|
|
|
func areTestAPIKeysSet() bool {
|
|
return b.ValidateAPICredentials()
|
|
}
|
|
|
|
func TestGetMarketsSummary(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.GetMarketSummary("", true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
ret, err := b.GetMarketSummary(testSPOTPair, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if len(ret) != 1 {
|
|
t.Errorf("expected only one result when requesting BTC-USD data received: %v", len(ret))
|
|
}
|
|
}
|
|
|
|
func TestFetchOrderBook(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.FetchOrderBook(testSPOTPair, 0, 1, 1, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
_, err = b.FetchOrderBook(testFUTURESPair, 0, 1, 1, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
_, err = b.FetchOrderBook(testSPOTPair, 1, 1, 1, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateOrderbook(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
p, err := currency.NewPairFromString(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = b.UpdateOrderbook(p, asset.Spot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
f, err := currency.NewPairFromString("BTC-PFC")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = b.UpdateOrderbook(f, asset.Futures)
|
|
if err != nil {
|
|
if !errors.Is(err, common.ErrNotYetImplemented) {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFetchOrderBookL2(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.FetchOrderBookL2(testSPOTPair, 20)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestOHLCV(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.OHLCV(testSPOTPair,
|
|
time.Now().AddDate(0, 0, -1),
|
|
time.Now(), 60)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.OHLCV(testSPOTPair, time.Now(), time.Now().AddDate(0, 0, -1), 60)
|
|
if err == nil {
|
|
t.Fatal("expected error if start is after end date")
|
|
}
|
|
}
|
|
|
|
func TestGetPrice(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.GetPrice(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestFormatExchangeKlineInterval(t *testing.T) {
|
|
ret := b.FormatExchangeKlineInterval(kline.OneDay)
|
|
if ret != "1440" {
|
|
t.Fatalf("unexpected result received: %v", ret)
|
|
}
|
|
}
|
|
|
|
func TestGetHistoricCandles(t *testing.T) {
|
|
t.Parallel()
|
|
curr, err := currency.NewPairFromString(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.GetHistoricCandles(
|
|
curr, asset.Spot,
|
|
time.Time{}, time.Time{},
|
|
kline.OneMin)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.GetHistoricCandles(
|
|
curr, asset.Spot,
|
|
time.Time{}, time.Time{},
|
|
kline.OneDay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
curr.Quote = currency.XRP
|
|
_, err = b.GetHistoricCandles(
|
|
curr, asset.Spot,
|
|
time.Time{}, time.Time{},
|
|
kline.OneMin)
|
|
if err == nil {
|
|
t.Fatal("expected error when requesting with disabled pair")
|
|
}
|
|
}
|
|
|
|
func TestGetHistoricCandlesExtended(t *testing.T) {
|
|
t.Parallel()
|
|
curr, err := currency.NewPairFromString(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.GetHistoricCandlesExtended(
|
|
curr, asset.Spot,
|
|
time.Time{}, time.Time{},
|
|
kline.OneMin)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestGetTrades(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.GetTrades(testSPOTPair,
|
|
time.Now().AddDate(0, 0, -1), time.Now(),
|
|
0, 0, 50, false, true)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
_, err = b.GetTrades(testSPOTPair,
|
|
time.Now(), time.Now().AddDate(0, -1, 0),
|
|
0, 0, 50, false, true)
|
|
if err == nil {
|
|
t.Error("expected error if start time is after end time")
|
|
}
|
|
|
|
_, err = b.GetTrades(testFUTURESPair,
|
|
time.Now().AddDate(0, 0, -1), time.Now(),
|
|
0, 0, 50, false, false)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestUpdateTicker(t *testing.T) {
|
|
t.Parallel()
|
|
curr, err := currency.NewPairFromString(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.UpdateTicker(curr, asset.Spot)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
curr, err = currency.NewPairFromString("BTC-PFC")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
_, err = b.UpdateTicker(curr, asset.Futures)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestGetServerTime(t *testing.T) {
|
|
t.Parallel()
|
|
_, err := b.GetServerTime()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetWalletInformation(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetWalletInformation()
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetFeeInformation(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetFeeInformation("")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetWalletHistory(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetWalletHistory(testSPOTPair,
|
|
time.Time{}, time.Time{},
|
|
50)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetWalletAddress(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetWalletAddress("XRP")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCreateWalletAddress(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.CreateWalletAddress("XRP")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetDepositAddress(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetDepositAddress(currency.XRP, "")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCreateOrder(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
_, err := b.CreateOrder("", 0.0,
|
|
false,
|
|
-1, "BUY", 100, 0, 0,
|
|
testSPOTPair, "GTC",
|
|
0.0, 0.0,
|
|
"LIMIT", "LIMIT")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestBTSEIndexOrderPeg(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
_, err := b.IndexOrderPeg("", 0.0,
|
|
false,
|
|
-1, "BUY", 100, 0, 0,
|
|
testSPOTPair, "GTC",
|
|
0.0, 0.0,
|
|
"", "LIMIT")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetOrders(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.GetOrders(testSPOTPair, "", "")
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetActiveOrders(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
var getOrdersRequest = order.GetOrdersRequest{
|
|
Pairs: []currency.Pair{
|
|
{
|
|
Delimiter: "-",
|
|
Base: currency.BTC,
|
|
Quote: currency.USD,
|
|
},
|
|
{
|
|
Delimiter: "-",
|
|
Base: currency.XRP,
|
|
Quote: currency.USD,
|
|
},
|
|
},
|
|
Type: order.AnyType,
|
|
}
|
|
|
|
_, err := b.GetActiveOrders(&getOrdersRequest)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetOrderHistory(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
var getOrdersRequest = order.GetOrdersRequest{
|
|
Type: order.AnyType,
|
|
}
|
|
_, err := b.GetOrderHistory(&getOrdersRequest)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestTradeHistory(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() {
|
|
t.Skip("API keys not set, skipping test")
|
|
}
|
|
_, err := b.TradeHistory("",
|
|
time.Time{}, time.Time{},
|
|
0, 0, 0,
|
|
false,
|
|
"", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestFormatWithdrawPermissions(t *testing.T) {
|
|
t.Parallel()
|
|
expected := exchange.NoAPIWithdrawalMethodsText
|
|
actual := b.FormatWithdrawPermissions()
|
|
if actual != expected {
|
|
t.Errorf("Expected: %s, Received: %s", expected, actual)
|
|
}
|
|
}
|
|
|
|
// TestGetFeeByTypeOfflineTradeFee logic test
|
|
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
|
feeBuilder := &exchange.FeeBuilder{
|
|
FeeType: exchange.CryptocurrencyTradeFee,
|
|
Pair: currency.NewPair(currency.BTC, currency.USD),
|
|
IsMaker: true,
|
|
Amount: 1,
|
|
PurchasePrice: 1000,
|
|
}
|
|
|
|
b.GetFeeByType(feeBuilder)
|
|
if !areTestAPIKeysSet() {
|
|
if feeBuilder.FeeType != exchange.OfflineTradeFee {
|
|
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
|
|
}
|
|
} else {
|
|
if feeBuilder.FeeType != exchange.CryptocurrencyTradeFee {
|
|
t.Errorf("Expected %v, received %v", exchange.CryptocurrencyTradeFee, feeBuilder.FeeType)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetFee(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
feeBuilder := &exchange.FeeBuilder{
|
|
FeeType: exchange.CryptocurrencyTradeFee,
|
|
Pair: currency.NewPair(currency.BTC, currency.USD),
|
|
IsMaker: true,
|
|
Amount: 1,
|
|
PurchasePrice: 1000,
|
|
}
|
|
|
|
if resp, err := b.GetFee(feeBuilder); resp != 1.000000 || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", 1.000000, resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.IsMaker = false
|
|
if resp, err := b.GetFee(feeBuilder); resp != 2.00000 || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", 2.00000, resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
|
if resp, err := b.GetFee(feeBuilder); resp != 0.0005 || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", 0.0005, resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.Pair.Base = currency.USDT
|
|
if resp, err := b.GetFee(feeBuilder); resp != 1.080000 || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", 1.080000, resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.FeeType = exchange.InternationalBankDepositFee
|
|
if resp, err := b.GetFee(feeBuilder); resp != float64(3) || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(3), resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.Amount = 1000000
|
|
if resp, err := b.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
|
|
if resp, err := b.GetFee(feeBuilder); resp != float64(900) || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(900), resp)
|
|
t.Error(err)
|
|
}
|
|
|
|
feeBuilder.Amount = 1000
|
|
if resp, err := b.GetFee(feeBuilder); resp != float64(25) || err != nil {
|
|
t.Errorf("GetFee() error. Expected: %f, Received: %f", float64(25), resp)
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestParseOrderTime(t *testing.T) {
|
|
expected := int64(1534792846)
|
|
actual, err := parseOrderTime("2018-08-20 19:20:46")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if expected != actual.Unix() {
|
|
t.Errorf("TestParseOrderTime expected: %d, got %d", expected, actual.Unix())
|
|
}
|
|
}
|
|
|
|
func TestSubmitOrder(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
var orderSubmission = &order.Submit{
|
|
Pair: currency.Pair{
|
|
Base: currency.BTC,
|
|
Quote: currency.USD,
|
|
},
|
|
Side: order.Buy,
|
|
Type: order.Limit,
|
|
Price: -100000000,
|
|
Amount: 1,
|
|
ClientID: "",
|
|
AssetType: asset.Spot,
|
|
}
|
|
response, err := b.SubmitOrder(orderSubmission)
|
|
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
|
t.Errorf("Order failed to be placed: %v", err)
|
|
} else if !areTestAPIKeysSet() && err == nil {
|
|
t.Error("Expecting an error when no keys are set")
|
|
}
|
|
}
|
|
|
|
func TestCancelAllAfter(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
|
|
err := b.CancelAllAfter(1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestCancelExchangeOrder(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
currencyPair := currency.NewPairWithDelimiter(currency.BTC.String(),
|
|
currency.USD.String(),
|
|
"-")
|
|
var orderCancellation = &order.Cancel{
|
|
ID: "b334ecef-2b42-4998-b8a4-b6b14f6d2671",
|
|
WalletAddress: core.BitcoinDonationAddress,
|
|
AccountID: "1",
|
|
Pair: currencyPair,
|
|
AssetType: asset.Spot,
|
|
}
|
|
err := b.CancelOrder(orderCancellation)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestCancelOrder(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
_, err := b.CancelExistingOrder("", testSPOTPair, "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestCancelAllExchangeOrders(t *testing.T) {
|
|
t.Parallel()
|
|
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
|
t.Skip("skipping test, either api keys are unset or canManipulateRealOrders is false")
|
|
}
|
|
currencyPair := currency.NewPairWithDelimiter(currency.BTC.String(),
|
|
currency.USD.String(),
|
|
"-")
|
|
var orderCancellation = &order.Cancel{
|
|
ID: "1",
|
|
WalletAddress: core.BitcoinDonationAddress,
|
|
AccountID: "1",
|
|
Pair: currencyPair,
|
|
AssetType: asset.Spot,
|
|
}
|
|
resp, err := b.CancelAllOrders(orderCancellation)
|
|
|
|
if err != nil {
|
|
t.Errorf("Could not cancel orders: %v", err)
|
|
}
|
|
for k, v := range resp.Status {
|
|
if strings.Contains(v, "Failed") {
|
|
t.Errorf("order id: %s failed to cancel: %v", k, v)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWsOrderbook(t *testing.T) {
|
|
t.Parallel()
|
|
pressXToJSON := []byte(`{"topic":"orderBookL2Api:BTC-USD_0","data":{"buyQuote":[{"price":"9272.0","size":"0.077"},{"price":"9271.0","size":"1.122"},{"price":"9270.0","size":"2.548"},{"price":"9267.5","size":"1.015"},{"price":"9265.5","size":"0.930"},{"price":"9265.0","size":"0.475"},{"price":"9264.5","size":"2.216"},{"price":"9264.0","size":"9.709"},{"price":"9263.5","size":"3.667"},{"price":"9263.0","size":"8.481"},{"price":"9262.5","size":"7.660"},{"price":"9262.0","size":"9.689"},{"price":"9261.5","size":"4.213"},{"price":"9261.0","size":"1.491"},{"price":"9260.5","size":"6.264"},{"price":"9260.0","size":"1.690"},{"price":"9259.5","size":"5.718"},{"price":"9259.0","size":"2.706"},{"price":"9258.5","size":"0.192"},{"price":"9258.0","size":"1.592"},{"price":"9257.5","size":"1.749"},{"price":"9257.0","size":"8.104"},{"price":"9256.0","size":"0.161"},{"price":"9252.0","size":"1.544"},{"price":"9249.5","size":"1.462"},{"price":"9247.5","size":"1.833"},{"price":"9247.0","size":"0.168"},{"price":"9245.5","size":"1.941"},{"price":"9244.0","size":"1.423"},{"price":"9243.5","size":"0.175"}],"currency":"USD","sellQuote":[{"price":"9303.5","size":"1.839"},{"price":"9303.0","size":"2.067"},{"price":"9302.0","size":"0.117"},{"price":"9298.5","size":"1.569"},{"price":"9297.0","size":"1.527"},{"price":"9295.0","size":"0.184"},{"price":"9294.0","size":"1.785"},{"price":"9289.0","size":"1.673"},{"price":"9287.5","size":"4.194"},{"price":"9287.0","size":"6.622"},{"price":"9286.5","size":"2.147"},{"price":"9286.0","size":"3.348"},{"price":"9285.5","size":"5.655"},{"price":"9285.0","size":"10.423"},{"price":"9284.5","size":"6.233"},{"price":"9284.0","size":"8.860"},{"price":"9283.5","size":"9.441"},{"price":"9283.0","size":"3.455"},{"price":"9282.5","size":"11.033"},{"price":"9282.0","size":"11.471"},{"price":"9281.5","size":"4.742"},{"price":"9281.0","size":"14.789"},{"price":"9280.5","size":"11.117"},{"price":"9280.0","size":"0.807"},{"price":"9279.5","size":"1.651"},{"price":"9279.0","size":"0.244"},{"price":"9278.5","size":"0.533"},{"price":"9277.0","size":"1.447"},{"price":"9273.0","size":"1.976"},{"price":"9272.5","size":"0.093"}]}}`)
|
|
err := b.wsHandleData(pressXToJSON)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestWsTrades(t *testing.T) {
|
|
t.Parallel()
|
|
pressXToJSON := []byte(`{"topic":"tradeHistory:BTC-USD","data":[{"amount":0.09,"gain":1,"newest":0,"price":9273.6,"serialId":0,"transactionUnixtime":1580349090693}]}`)
|
|
err := b.wsHandleData(pressXToJSON)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestWsOrderNotification(t *testing.T) {
|
|
t.Parallel()
|
|
status := []string{"ORDER_INSERTED", "ORDER_CANCELLED", "TRIGGER_INSERTED", "ORDER_FULL_TRANSACTED", "ORDER_PARTIALLY_TRANSACTED", "INSUFFICIENT_BALANCE", "TRIGGER_ACTIVATED", "MARKET_UNAVAILABLE"}
|
|
for i := range status {
|
|
pressXToJSON := []byte(`{"topic": "notificationApi","data": [{"symbol": "BTC-USD","orderID": "1234","orderMode": "MODE_BUY","orderType": "TYPE_LIMIT","price": "1","size": "1","status": "` + status[i] + `","timestamp": "1580349090693","type": "STOP","triggerPrice": "1"}]}`)
|
|
err := b.wsHandleData(pressXToJSON)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStatusToStandardStatus(t *testing.T) {
|
|
type TestCases struct {
|
|
Case string
|
|
Result order.Status
|
|
}
|
|
testCases := []TestCases{
|
|
{Case: "ORDER_INSERTED", Result: order.New},
|
|
{Case: "TRIGGER_INSERTED", Result: order.New},
|
|
{Case: "ORDER_CANCELLED", Result: order.Cancelled},
|
|
{Case: "ORDER_FULL_TRANSACTED", Result: order.Filled},
|
|
{Case: "ORDER_PARTIALLY_TRANSACTED", Result: order.PartiallyFilled},
|
|
{Case: "TRIGGER_ACTIVATED", Result: order.Active},
|
|
{Case: "INSUFFICIENT_BALANCE", Result: order.InsufficientBalance},
|
|
{Case: "MARKET_UNAVAILABLE", Result: order.MarketUnavailable},
|
|
{Case: "LOL", Result: order.UnknownStatus},
|
|
}
|
|
for i := range testCases {
|
|
result, _ := stringToOrderStatus(testCases[i].Case)
|
|
if result != testCases[i].Result {
|
|
t.Errorf("Exepcted: %v, received: %v", testCases[i].Result, result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFetchTradablePairs(t *testing.T) {
|
|
t.Parallel()
|
|
assets := b.GetAssetTypes()
|
|
for i := range assets {
|
|
data, err := b.FetchTradablePairs(assets[i])
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(data) == 0 {
|
|
t.Fatal("data cannot be zero")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMatchType(t *testing.T) {
|
|
t.Parallel()
|
|
ret := matchType(1, order.AnyType)
|
|
if !ret {
|
|
t.Fatal("expected true value")
|
|
}
|
|
|
|
ret = matchType(76, order.Market)
|
|
if ret {
|
|
t.Fatal("expected false match")
|
|
}
|
|
|
|
ret = matchType(76, order.Limit)
|
|
if !ret {
|
|
t.Fatal("expected true match")
|
|
}
|
|
|
|
ret = matchType(77, order.Market)
|
|
if !ret {
|
|
t.Fatal("expected true match")
|
|
}
|
|
}
|
|
|
|
func TestSeedOrderSizeLimits(t *testing.T) {
|
|
t.Parallel()
|
|
err := b.seedOrderSizeLimits()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestOrderSizeLimits(t *testing.T) {
|
|
t.Parallel()
|
|
seedOrderSizeLimitMap()
|
|
_, ok := OrderSizeLimits(testSPOTPair)
|
|
if !ok {
|
|
t.Fatal("expected BTC-USD to be found in map")
|
|
}
|
|
|
|
_, ok = OrderSizeLimits("XRP-GARBAGE")
|
|
if ok {
|
|
t.Fatal("expected false value for XRP-GARBAGE")
|
|
}
|
|
}
|
|
|
|
func seedOrderSizeLimitMap() {
|
|
testOrderSizeLimits := []struct {
|
|
name string
|
|
o OrderSizeLimit
|
|
}{
|
|
{
|
|
name: "XRP-USD",
|
|
o: OrderSizeLimit{
|
|
MinSizeIncrement: 1,
|
|
MinOrderSize: 1,
|
|
MaxOrderSize: 1000000,
|
|
},
|
|
},
|
|
{
|
|
name: "LTC-USD",
|
|
o: OrderSizeLimit{
|
|
MinSizeIncrement: 0.01,
|
|
MinOrderSize: 0.01,
|
|
MaxOrderSize: 5000,
|
|
},
|
|
},
|
|
{
|
|
name: "BTC-USD",
|
|
o: OrderSizeLimit{
|
|
MinSizeIncrement: 0.0001,
|
|
MinOrderSize: 1,
|
|
MaxOrderSize: 1000000,
|
|
},
|
|
},
|
|
}
|
|
|
|
orderSizeLimitMap.Range(func(key interface{}, _ interface{}) bool {
|
|
orderSizeLimitMap.Delete(key)
|
|
return true
|
|
})
|
|
|
|
for x := range testOrderSizeLimits {
|
|
orderSizeLimitMap.Store(testOrderSizeLimits[x].name, testOrderSizeLimits[x].o)
|
|
}
|
|
}
|
|
|
|
func TestWithinLimits(t *testing.T) {
|
|
t.Parallel()
|
|
seedOrderSizeLimitMap()
|
|
p, _ := currency.NewPairDelimiter("XRP-USD", "-")
|
|
v := b.withinLimits(p, 1.0)
|
|
if !v {
|
|
t.Fatal("expected valid limits")
|
|
}
|
|
v = b.withinLimits(p, 5.0000001)
|
|
if v {
|
|
t.Fatal("expected invalid limits")
|
|
}
|
|
v = b.withinLimits(p, 100)
|
|
if !v {
|
|
t.Fatal("expected valid limits")
|
|
}
|
|
v = b.withinLimits(p, 10.1)
|
|
if v {
|
|
t.Fatal("expected invalid limits")
|
|
}
|
|
|
|
p.Base = currency.LTC
|
|
v = b.withinLimits(p, 10)
|
|
if v {
|
|
t.Fatal("expected valid limits")
|
|
}
|
|
|
|
v = b.withinLimits(p, 0.009)
|
|
if !v {
|
|
t.Fatal("expected invalid limits")
|
|
}
|
|
p.Base = currency.BTC
|
|
v = b.withinLimits(p, 10)
|
|
if v {
|
|
t.Fatal("expected valid limits")
|
|
}
|
|
|
|
v = b.withinLimits(p, 0.001)
|
|
if !v {
|
|
t.Fatal("expected invalid limits")
|
|
}
|
|
}
|
|
|
|
func TestGetRecentTrades(t *testing.T) {
|
|
t.Parallel()
|
|
currencyPair, err := currency.NewPairFromString(testSPOTPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = b.GetRecentTrades(currencyPair, asset.Spot)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
currencyPair, err = currency.NewPairFromString(testFUTURESPair)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
_, err = b.GetRecentTrades(currencyPair, asset.Futures)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestGetHistoricTrades(t *testing.T) {
|
|
t.Parallel()
|
|
curr, _ := currency.NewPairFromString(testSPOTPair)
|
|
|
|
_, err := b.GetHistoricTrades(curr, asset.Spot, time.Now().Add(-time.Minute), time.Now())
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if err != common.ErrFunctionNotSupported {
|
|
t.Error("unexpected error")
|
|
}
|
|
}
|
|
|
|
func TestOrderbookFilter(t *testing.T) {
|
|
t.Parallel()
|
|
if !b.orderbookFilter(0, 1) {
|
|
t.Fatal("incorrect filtering")
|
|
}
|
|
if !b.orderbookFilter(1, 0) {
|
|
t.Fatal("incorrect filtering")
|
|
}
|
|
if !b.orderbookFilter(0, 0) {
|
|
t.Fatal("incorrect filtering")
|
|
}
|
|
if b.orderbookFilter(1, 1) {
|
|
t.Fatal("incorrect filtering")
|
|
}
|
|
}
|
|
|
|
func TestWsLogin(t *testing.T) {
|
|
t.Parallel()
|
|
data := []byte(`{"event":"login","success":true}`)
|
|
err := b.wsHandleData(data)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if !b.Websocket.CanUseAuthenticatedEndpoints() {
|
|
t.Error("expected true")
|
|
}
|
|
|
|
data = []byte(`{"event":"login","success":false}`)
|
|
err = b.wsHandleData(data)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
if b.Websocket.CanUseAuthenticatedEndpoints() {
|
|
t.Error("expected false")
|
|
}
|
|
}
|
|
|
|
func TestWsSubscription(t *testing.T) {
|
|
t.Parallel()
|
|
data := []byte(`{"event":"subscribe","channel":["orderBookL2Api:SFI-ETH_0","tradeHistory:SFI-ETH"]}`)
|
|
err := b.wsHandleData(data)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestWsUnexpectedData(t *testing.T) {
|
|
t.Parallel()
|
|
data := []byte(`{}`)
|
|
err := b.wsHandleData(data)
|
|
if err != nil && err.Error() != "BTSE - Unhandled websocket message: {}" {
|
|
t.Error(err)
|
|
}
|
|
if err == nil {
|
|
t.Error("expected error response from bad data")
|
|
}
|
|
}
|