mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 07:26:47 +00:00
* Fixes issue where getorders could not work due to unset asset type in rpcserver.go. Adds test. Also adds start and end date to the cli. * A few fixes * lint * fixes oopsie that affected doopsie * Ensures dates are set for all open order implementations. Adds new filter to ensure orders without dates are returned rather than filtered. Fixes up Binance OpenOrders implementation. Adds some extra typeconverts for binance * Add updated time to Binance GetActiveOrders. Update rpcserver.go to only set the time if its not empty. Also addressed bad expected value * Actually fixes things this time * Improves recvWindow to process openOrders * Adds asset type to getOrder as well * Fixes tests * Adds missing date fields * Fixes default time, updates default errors * Default start to last month, instead of last year
1099 lines
26 KiB
Go
1099 lines
26 KiB
Go
package order
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/currency"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
|
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
|
|
)
|
|
|
|
var errValidationCheckFailed = errors.New("validation check failed")
|
|
|
|
func TestValidate(t *testing.T) {
|
|
testPair := currency.NewPair(currency.BTC, currency.LTC)
|
|
tester := []struct {
|
|
ExpectedErr error
|
|
Submit *Submit
|
|
ValidOpts validate.Checker
|
|
}{
|
|
{
|
|
ExpectedErr: ErrSubmissionIsNil,
|
|
Submit: nil,
|
|
}, // nil struct
|
|
{
|
|
ExpectedErr: ErrPairIsEmpty,
|
|
Submit: &Submit{},
|
|
}, // empty pair
|
|
{
|
|
|
|
ExpectedErr: ErrAssetNotSet,
|
|
Submit: &Submit{Pair: testPair},
|
|
}, // valid pair but invalid asset
|
|
{
|
|
|
|
ExpectedErr: ErrSideIsInvalid,
|
|
Submit: &Submit{Pair: testPair, AssetType: asset.Spot},
|
|
}, // valid pair but invalid order side
|
|
{
|
|
ExpectedErr: ErrTypeIsInvalid,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Buy,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair and order side but invalid order type
|
|
{
|
|
ExpectedErr: ErrTypeIsInvalid,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Sell,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair and order side but invalid order type
|
|
{
|
|
ExpectedErr: ErrTypeIsInvalid,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Bid,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair and order side but invalid order type
|
|
{
|
|
ExpectedErr: ErrTypeIsInvalid,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Ask,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair and order side but invalid order type
|
|
{
|
|
ExpectedErr: ErrAmountIsInvalid,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Ask,
|
|
Type: Market,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair, order side, type but invalid amount
|
|
{
|
|
ExpectedErr: ErrPriceMustBeSetIfLimitOrder,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Ask,
|
|
Type: Limit,
|
|
Amount: 1,
|
|
AssetType: asset.Spot},
|
|
}, // valid pair, order side, type, amount but invalid price
|
|
{
|
|
ExpectedErr: errValidationCheckFailed,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Ask,
|
|
Type: Limit,
|
|
Amount: 1,
|
|
Price: 1000,
|
|
AssetType: asset.Spot},
|
|
ValidOpts: validate.Check(func() error { return errValidationCheckFailed }),
|
|
}, // custom validation error check
|
|
{
|
|
ExpectedErr: nil,
|
|
Submit: &Submit{Pair: testPair,
|
|
Side: Ask,
|
|
Type: Limit,
|
|
Amount: 1,
|
|
Price: 1000,
|
|
AssetType: asset.Spot},
|
|
ValidOpts: validate.Check(func() error { return nil }),
|
|
}, // valid order!
|
|
}
|
|
|
|
for x := range tester {
|
|
if err := tester[x].Submit.Validate(tester[x].ValidOpts); err != tester[x].ExpectedErr {
|
|
if err != nil && tester[x].ExpectedErr != nil {
|
|
if err.Error() == tester[x].ExpectedErr.Error() {
|
|
continue
|
|
}
|
|
}
|
|
t.Errorf("Unexpected result. Got: %v, want: %v", err, tester[x].ExpectedErr)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestOrderSides(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var os = Buy
|
|
if os.String() != "BUY" {
|
|
t.Errorf("unexpected string %s", os.String())
|
|
}
|
|
|
|
if os.Lower() != "buy" {
|
|
t.Errorf("unexpected string %s", os.Lower())
|
|
}
|
|
|
|
if os.Title() != "Buy" {
|
|
t.Errorf("unexpected string %s", os.Title())
|
|
}
|
|
}
|
|
|
|
func TestOrderTypes(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var ot Type = "Mo'Money"
|
|
|
|
if ot.String() != "Mo'Money" {
|
|
t.Errorf("unexpected string %s", ot.String())
|
|
}
|
|
|
|
if ot.Lower() != "mo'money" {
|
|
t.Errorf("unexpected string %s", ot.Lower())
|
|
}
|
|
|
|
if ot.Title() != "Mo'Money" {
|
|
t.Errorf("unexpected string %s", ot.Title())
|
|
}
|
|
}
|
|
|
|
func TestFilterOrdersByType(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var orders = []Detail{
|
|
{
|
|
Type: ImmediateOrCancel,
|
|
},
|
|
{
|
|
Type: Limit,
|
|
},
|
|
}
|
|
|
|
FilterOrdersByType(&orders, AnyType)
|
|
if len(orders) != 2 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 2, len(orders))
|
|
}
|
|
|
|
FilterOrdersByType(&orders, Limit)
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
|
|
FilterOrdersByType(&orders, Stop)
|
|
if len(orders) != 0 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 0, len(orders))
|
|
}
|
|
}
|
|
|
|
func TestFilterOrdersBySide(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var orders = []Detail{
|
|
{
|
|
Side: Buy,
|
|
},
|
|
{
|
|
Side: Sell,
|
|
},
|
|
{},
|
|
}
|
|
|
|
FilterOrdersBySide(&orders, AnySide)
|
|
if len(orders) != 3 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 3, len(orders))
|
|
}
|
|
|
|
FilterOrdersBySide(&orders, Buy)
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
|
|
FilterOrdersBySide(&orders, Sell)
|
|
if len(orders) != 0 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 0, len(orders))
|
|
}
|
|
}
|
|
|
|
func TestFilterOrdersByTimeRange(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var orders = []Detail{
|
|
{
|
|
Date: time.Unix(100, 0),
|
|
},
|
|
{
|
|
Date: time.Unix(110, 0),
|
|
},
|
|
{
|
|
Date: time.Unix(111, 0),
|
|
},
|
|
}
|
|
|
|
FilterOrdersByTimeRange(&orders, time.Unix(0, 0), time.Unix(0, 0))
|
|
if len(orders) != 3 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 3, len(orders))
|
|
}
|
|
|
|
FilterOrdersByTimeRange(&orders, time.Unix(100, 0), time.Unix(111, 0))
|
|
if len(orders) != 3 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 3, len(orders))
|
|
}
|
|
|
|
FilterOrdersByTimeRange(&orders, time.Unix(101, 0), time.Unix(111, 0))
|
|
if len(orders) != 2 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 2, len(orders))
|
|
}
|
|
|
|
FilterOrdersByTimeRange(&orders, time.Unix(200, 0), time.Unix(300, 0))
|
|
if len(orders) != 0 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 0, len(orders))
|
|
}
|
|
orders = append(orders, Detail{})
|
|
// test for event no timestamp is set on an order, best to include it
|
|
FilterOrdersByTimeRange(&orders, time.Unix(200, 0), time.Unix(300, 0))
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
}
|
|
|
|
func TestFilterOrdersByCurrencies(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
var orders = []Detail{
|
|
{
|
|
Pair: currency.NewPair(currency.BTC, currency.USD),
|
|
},
|
|
{
|
|
Pair: currency.NewPair(currency.LTC, currency.EUR),
|
|
},
|
|
{
|
|
Pair: currency.NewPair(currency.DOGE, currency.RUB),
|
|
},
|
|
}
|
|
|
|
currencies := []currency.Pair{currency.NewPair(currency.BTC, currency.USD),
|
|
currency.NewPair(currency.LTC, currency.EUR),
|
|
currency.NewPair(currency.DOGE, currency.RUB)}
|
|
FilterOrdersByCurrencies(&orders, currencies)
|
|
if len(orders) != 3 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 3, len(orders))
|
|
}
|
|
|
|
currencies = []currency.Pair{currency.NewPair(currency.BTC, currency.USD),
|
|
currency.NewPair(currency.LTC, currency.EUR)}
|
|
FilterOrdersByCurrencies(&orders, currencies)
|
|
if len(orders) != 2 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 2, len(orders))
|
|
}
|
|
|
|
currencies = []currency.Pair{currency.NewPair(currency.BTC, currency.USD)}
|
|
FilterOrdersByCurrencies(&orders, currencies)
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
|
|
currencies = []currency.Pair{}
|
|
FilterOrdersByCurrencies(&orders, currencies)
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
currencies = append(currencies, currency.Pair{})
|
|
FilterOrdersByCurrencies(&orders, currencies)
|
|
if len(orders) != 1 {
|
|
t.Errorf("Orders failed to be filtered. Expected %v, received %v", 1, len(orders))
|
|
}
|
|
}
|
|
|
|
func TestSortOrdersByPrice(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orders := []Detail{
|
|
{
|
|
Price: 100,
|
|
}, {
|
|
Price: 0,
|
|
}, {
|
|
Price: 50,
|
|
},
|
|
}
|
|
|
|
SortOrdersByPrice(&orders, false)
|
|
if orders[0].Price != 0 {
|
|
t.Errorf("Expected: '%v', received: '%v'", 0, orders[0].Price)
|
|
}
|
|
|
|
SortOrdersByPrice(&orders, true)
|
|
if orders[0].Price != 100 {
|
|
t.Errorf("Expected: '%v', received: '%v'", 100, orders[0].Price)
|
|
}
|
|
}
|
|
|
|
func TestSortOrdersByDate(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orders := []Detail{
|
|
{
|
|
Date: time.Unix(0, 0),
|
|
}, {
|
|
Date: time.Unix(1, 0),
|
|
}, {
|
|
Date: time.Unix(2, 0),
|
|
},
|
|
}
|
|
|
|
SortOrdersByDate(&orders, false)
|
|
if orders[0].Date.Unix() != time.Unix(0, 0).Unix() {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
time.Unix(0, 0).Unix(),
|
|
orders[0].Date.Unix())
|
|
}
|
|
|
|
SortOrdersByDate(&orders, true)
|
|
if orders[0].Date.Unix() != time.Unix(2, 0).Unix() {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
time.Unix(2, 0).Unix(),
|
|
orders[0].Date.Unix())
|
|
}
|
|
}
|
|
|
|
func TestSortOrdersByCurrency(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orders := []Detail{
|
|
{
|
|
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
|
|
currency.USD.String(),
|
|
"-"),
|
|
}, {
|
|
Pair: currency.NewPairWithDelimiter(currency.DOGE.String(),
|
|
currency.USD.String(),
|
|
"-"),
|
|
}, {
|
|
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
|
|
currency.RUB.String(),
|
|
"-"),
|
|
}, {
|
|
Pair: currency.NewPairWithDelimiter(currency.LTC.String(),
|
|
currency.EUR.String(),
|
|
"-"),
|
|
}, {
|
|
Pair: currency.NewPairWithDelimiter(currency.LTC.String(),
|
|
currency.AUD.String(),
|
|
"-"),
|
|
},
|
|
}
|
|
|
|
SortOrdersByCurrency(&orders, false)
|
|
if orders[0].Pair.String() != currency.BTC.String()+"-"+currency.RUB.String() {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
currency.BTC.String()+"-"+currency.RUB.String(),
|
|
orders[0].Pair.String())
|
|
}
|
|
|
|
SortOrdersByCurrency(&orders, true)
|
|
if orders[0].Pair.String() != currency.LTC.String()+"-"+currency.EUR.String() {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
currency.LTC.String()+"-"+currency.EUR.String(),
|
|
orders[0].Pair.String())
|
|
}
|
|
}
|
|
|
|
func TestSortOrdersByOrderSide(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orders := []Detail{
|
|
{
|
|
Side: Buy,
|
|
}, {
|
|
Side: Sell,
|
|
}, {
|
|
Side: Sell,
|
|
}, {
|
|
Side: Buy,
|
|
},
|
|
}
|
|
|
|
SortOrdersBySide(&orders, false)
|
|
if !strings.EqualFold(orders[0].Side.String(), Buy.String()) {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
Buy,
|
|
orders[0].Side)
|
|
}
|
|
|
|
SortOrdersBySide(&orders, true)
|
|
if !strings.EqualFold(orders[0].Side.String(), Sell.String()) {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
Sell,
|
|
orders[0].Side)
|
|
}
|
|
}
|
|
|
|
func TestSortOrdersByOrderType(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
orders := []Detail{
|
|
{
|
|
Type: Market,
|
|
}, {
|
|
Type: Limit,
|
|
}, {
|
|
Type: ImmediateOrCancel,
|
|
}, {
|
|
Type: TrailingStop,
|
|
},
|
|
}
|
|
|
|
SortOrdersByType(&orders, false)
|
|
if !strings.EqualFold(orders[0].Type.String(), ImmediateOrCancel.String()) {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
ImmediateOrCancel,
|
|
orders[0].Type)
|
|
}
|
|
|
|
SortOrdersByType(&orders, true)
|
|
if !strings.EqualFold(orders[0].Type.String(), TrailingStop.String()) {
|
|
t.Errorf("Expected: '%v', received: '%v'",
|
|
TrailingStop,
|
|
orders[0].Type)
|
|
}
|
|
}
|
|
|
|
var stringsToOrderSide = []struct {
|
|
in string
|
|
out Side
|
|
err error
|
|
}{
|
|
{"buy", Buy, nil},
|
|
{"BUY", Buy, nil},
|
|
{"bUy", Buy, nil},
|
|
{"sell", Sell, nil},
|
|
{"SELL", Sell, nil},
|
|
{"sElL", Sell, nil},
|
|
{"bid", Bid, nil},
|
|
{"BID", Bid, nil},
|
|
{"bId", Bid, nil},
|
|
{"ask", Ask, nil},
|
|
{"ASK", Ask, nil},
|
|
{"aSk", Ask, nil},
|
|
{"any", AnySide, nil},
|
|
{"ANY", AnySide, nil},
|
|
{"aNy", AnySide, nil},
|
|
{"woahMan", Buy, errors.New("woahMan not recognised as order side")},
|
|
}
|
|
|
|
func TestStringToOrderSide(t *testing.T) {
|
|
for i := range stringsToOrderSide {
|
|
testData := &stringsToOrderSide[i]
|
|
t.Run(testData.in, func(t *testing.T) {
|
|
out, err := StringToOrderSide(testData.in)
|
|
if err != nil {
|
|
if err.Error() != testData.err.Error() {
|
|
t.Error("Unexpected error", err)
|
|
}
|
|
} else if out != testData.out {
|
|
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var stringsToOrderType = []struct {
|
|
in string
|
|
out Type
|
|
err error
|
|
}{
|
|
{"limit", Limit, nil},
|
|
{"LIMIT", Limit, nil},
|
|
{"lImIt", Limit, nil},
|
|
{"market", Market, nil},
|
|
{"MARKET", Market, nil},
|
|
{"mArKeT", Market, nil},
|
|
{"immediate_or_cancel", ImmediateOrCancel, nil},
|
|
{"IMMEDIATE_OR_CANCEL", ImmediateOrCancel, nil},
|
|
{"iMmEdIaTe_Or_CaNcEl", ImmediateOrCancel, nil},
|
|
{"iMmEdIaTe Or CaNcEl", ImmediateOrCancel, nil},
|
|
{"stop", Stop, nil},
|
|
{"STOP", Stop, nil},
|
|
{"sToP", Stop, nil},
|
|
{"sToP LiMit", StopLimit, nil},
|
|
{"ExchangE sToP Limit", StopLimit, nil},
|
|
{"trailing_stop", TrailingStop, nil},
|
|
{"TRAILING_STOP", TrailingStop, nil},
|
|
{"tRaIlInG_sToP", TrailingStop, nil},
|
|
{"tRaIlInG sToP", TrailingStop, nil},
|
|
{"fOk", FillOrKill, nil},
|
|
{"exchange fOk", FillOrKill, nil},
|
|
{"ios", IOS, nil},
|
|
{"post_ONly", PostOnly, nil},
|
|
{"any", AnyType, nil},
|
|
{"ANY", AnyType, nil},
|
|
{"aNy", AnyType, nil},
|
|
{"trigger", Trigger, nil},
|
|
{"TRIGGER", Trigger, nil},
|
|
{"tRiGgEr", Trigger, nil},
|
|
{"woahMan", UnknownType, errors.New("woahMan not recognised as order type")},
|
|
}
|
|
|
|
func TestStringToOrderType(t *testing.T) {
|
|
for i := range stringsToOrderType {
|
|
testData := &stringsToOrderType[i]
|
|
t.Run(testData.in, func(t *testing.T) {
|
|
out, err := StringToOrderType(testData.in)
|
|
if err != nil {
|
|
if err.Error() != testData.err.Error() {
|
|
t.Error("Unexpected error", err)
|
|
}
|
|
} else if out != testData.out {
|
|
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
var stringsToOrderStatus = []struct {
|
|
in string
|
|
out Status
|
|
err error
|
|
}{
|
|
{"any", AnyStatus, nil},
|
|
{"ANY", AnyStatus, nil},
|
|
{"aNy", AnyStatus, nil},
|
|
{"new", New, nil},
|
|
{"NEW", New, nil},
|
|
{"nEw", New, nil},
|
|
{"active", Active, nil},
|
|
{"ACTIVE", Active, nil},
|
|
{"aCtIvE", Active, nil},
|
|
{"partially_filled", PartiallyFilled, nil},
|
|
{"PARTIALLY_FILLED", PartiallyFilled, nil},
|
|
{"pArTiAlLy_FiLlEd", PartiallyFilled, nil},
|
|
{"filled", Filled, nil},
|
|
{"FILLED", Filled, nil},
|
|
{"fIlLeD", Filled, nil},
|
|
{"cancelled", Cancelled, nil},
|
|
{"CANCELlED", Cancelled, nil},
|
|
{"cAnCellEd", Cancelled, nil},
|
|
{"pending_cancel", PendingCancel, nil},
|
|
{"PENDING_CANCEL", PendingCancel, nil},
|
|
{"pENdInG_cAnCeL", PendingCancel, nil},
|
|
{"rejected", Rejected, nil},
|
|
{"REJECTED", Rejected, nil},
|
|
{"rEjEcTeD", Rejected, nil},
|
|
{"expired", Expired, nil},
|
|
{"EXPIRED", Expired, nil},
|
|
{"eXpIrEd", Expired, nil},
|
|
{"hidden", Hidden, nil},
|
|
{"HIDDEN", Hidden, nil},
|
|
{"hIdDeN", Hidden, nil},
|
|
{"market_unavailable", MarketUnavailable, nil},
|
|
{"MARKET_UNAVAILABLE", MarketUnavailable, nil},
|
|
{"mArKeT_uNaVaIlAbLe", MarketUnavailable, nil},
|
|
{"insufficient_balance", InsufficientBalance, nil},
|
|
{"INSUFFICIENT_BALANCE", InsufficientBalance, nil},
|
|
{"iNsUfFiCiEnT_bAlAnCe", InsufficientBalance, nil},
|
|
{"PARTIALLY_CANCELLEd", PartiallyCancelled, nil},
|
|
{"partially canceLLed", PartiallyCancelled, nil},
|
|
{"opeN", Open, nil},
|
|
{"woahMan", UnknownStatus, errors.New("woahMan not recognised as order status")},
|
|
}
|
|
|
|
func TestStringToOrderStatus(t *testing.T) {
|
|
for i := range stringsToOrderStatus {
|
|
testData := &stringsToOrderStatus[i]
|
|
t.Run(testData.in, func(t *testing.T) {
|
|
out, err := StringToOrderStatus(testData.in)
|
|
if err != nil {
|
|
if err.Error() != testData.err.Error() {
|
|
t.Error("Unexpected error", err)
|
|
}
|
|
} else if out != testData.out {
|
|
t.Errorf("Unexpected output %v. Expected %v", out, testData.out)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestUpdateOrderFromModify(t *testing.T) {
|
|
var leet = "1337"
|
|
od := Detail{
|
|
ImmediateOrCancel: false,
|
|
HiddenOrder: false,
|
|
FillOrKill: false,
|
|
PostOnly: false,
|
|
Leverage: 0,
|
|
Price: 0,
|
|
Amount: 0,
|
|
LimitPriceUpper: 0,
|
|
LimitPriceLower: 0,
|
|
TriggerPrice: 0,
|
|
TargetAmount: 0,
|
|
ExecutedAmount: 0,
|
|
RemainingAmount: 0,
|
|
Fee: 0,
|
|
Exchange: "",
|
|
ID: "1",
|
|
AccountID: "",
|
|
ClientID: "",
|
|
WalletAddress: "",
|
|
Type: "",
|
|
Side: "",
|
|
Status: "",
|
|
AssetType: "",
|
|
Date: time.Time{},
|
|
LastUpdated: time.Time{},
|
|
Pair: currency.Pair{},
|
|
Trades: nil,
|
|
}
|
|
updated := time.Now()
|
|
|
|
pair, err := currency.NewPairFromString("BTCUSD")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
om := Modify{
|
|
ImmediateOrCancel: true,
|
|
HiddenOrder: true,
|
|
FillOrKill: true,
|
|
PostOnly: true,
|
|
Leverage: 1.0,
|
|
Price: 1,
|
|
Amount: 1,
|
|
LimitPriceUpper: 1,
|
|
LimitPriceLower: 1,
|
|
TriggerPrice: 1,
|
|
TargetAmount: 1,
|
|
ExecutedAmount: 1,
|
|
RemainingAmount: 1,
|
|
Fee: 1,
|
|
Exchange: "1",
|
|
InternalOrderID: "1",
|
|
ID: "1",
|
|
AccountID: "1",
|
|
ClientID: "1",
|
|
WalletAddress: "1",
|
|
Type: "1",
|
|
Side: "1",
|
|
Status: "1",
|
|
AssetType: "1",
|
|
LastUpdated: updated,
|
|
Pair: pair,
|
|
Trades: []TradeHistory{},
|
|
}
|
|
|
|
od.UpdateOrderFromModify(&om)
|
|
if od.InternalOrderID == "1" {
|
|
t.Error("Should not be able to update the internal order ID")
|
|
}
|
|
if !od.ImmediateOrCancel {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.HiddenOrder {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.FillOrKill {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.PostOnly {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Leverage != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Price != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Amount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LimitPriceLower != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LimitPriceUpper != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.TriggerPrice != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.TargetAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.ExecutedAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.RemainingAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Fee != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Exchange != "" {
|
|
t.Error("Should not be able to update exchange via modify")
|
|
}
|
|
if od.ID != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.ClientID != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.WalletAddress != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Type != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Side != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Status != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.AssetType != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LastUpdated != updated {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Pair.String() != "BTCUSD" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Trades != nil {
|
|
t.Error("Failed to update")
|
|
}
|
|
|
|
om.Trades = append(om.Trades, TradeHistory{TID: "1"}, TradeHistory{TID: "2"})
|
|
od.UpdateOrderFromModify(&om)
|
|
if len(od.Trades) != 2 {
|
|
t.Error("Failed to add trades")
|
|
}
|
|
om.Trades[0].Exchange = leet
|
|
om.Trades[0].Price = 1337
|
|
om.Trades[0].Fee = 1337
|
|
om.Trades[0].IsMaker = true
|
|
om.Trades[0].Timestamp = updated
|
|
om.Trades[0].Description = leet
|
|
om.Trades[0].Side = UnknownSide
|
|
om.Trades[0].Type = UnknownType
|
|
om.Trades[0].Amount = 1337
|
|
od.UpdateOrderFromModify(&om)
|
|
if od.Trades[0].Exchange == leet {
|
|
t.Error("Should not be able to update exchange from update")
|
|
}
|
|
if od.Trades[0].Price != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Fee != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if !od.Trades[0].IsMaker {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Timestamp != updated {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Description != leet {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Side != UnknownSide {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Type != UnknownType {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Amount != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
}
|
|
|
|
func TestUpdateOrderFromDetail(t *testing.T) {
|
|
var leet = "1337"
|
|
od := Detail{
|
|
ImmediateOrCancel: false,
|
|
HiddenOrder: false,
|
|
FillOrKill: false,
|
|
PostOnly: false,
|
|
Leverage: 0,
|
|
Price: 0,
|
|
Amount: 0,
|
|
LimitPriceUpper: 0,
|
|
LimitPriceLower: 0,
|
|
TriggerPrice: 0,
|
|
TargetAmount: 0,
|
|
ExecutedAmount: 0,
|
|
RemainingAmount: 0,
|
|
Fee: 0,
|
|
Exchange: "",
|
|
ID: "1",
|
|
AccountID: "",
|
|
ClientID: "",
|
|
WalletAddress: "",
|
|
Type: "",
|
|
Side: "",
|
|
Status: "",
|
|
AssetType: "",
|
|
Date: time.Time{},
|
|
LastUpdated: time.Time{},
|
|
Pair: currency.Pair{},
|
|
Trades: nil,
|
|
}
|
|
updated := time.Now()
|
|
|
|
pair, err := currency.NewPairFromString("BTCUSD")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
om := Detail{
|
|
ImmediateOrCancel: true,
|
|
HiddenOrder: true,
|
|
FillOrKill: true,
|
|
PostOnly: true,
|
|
Leverage: 1,
|
|
Price: 1,
|
|
Amount: 1,
|
|
LimitPriceUpper: 1,
|
|
LimitPriceLower: 1,
|
|
TriggerPrice: 1,
|
|
TargetAmount: 1,
|
|
ExecutedAmount: 1,
|
|
RemainingAmount: 1,
|
|
Fee: 1,
|
|
Exchange: "1",
|
|
InternalOrderID: "1",
|
|
ID: "1",
|
|
AccountID: "1",
|
|
ClientID: "1",
|
|
WalletAddress: "1",
|
|
Type: "1",
|
|
Side: "1",
|
|
Status: "1",
|
|
AssetType: "1",
|
|
LastUpdated: updated,
|
|
Pair: pair,
|
|
Trades: []TradeHistory{},
|
|
}
|
|
|
|
od.UpdateOrderFromDetail(&om)
|
|
if od.InternalOrderID == "1" {
|
|
t.Error("Should not be able to update the internal order ID")
|
|
}
|
|
if !od.ImmediateOrCancel {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.HiddenOrder {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.FillOrKill {
|
|
t.Error("Failed to update")
|
|
}
|
|
if !od.PostOnly {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Leverage != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Price != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Amount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LimitPriceLower != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LimitPriceUpper != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.TriggerPrice != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.TargetAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.ExecutedAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.RemainingAmount != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Fee != 1 {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Exchange != "" {
|
|
t.Error("Should not be able to update exchange via modify")
|
|
}
|
|
if od.ID != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.ClientID != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.WalletAddress != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Type != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Side != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Status != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.AssetType != "1" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.LastUpdated != updated {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Pair.String() != "BTCUSD" {
|
|
t.Error("Failed to update")
|
|
}
|
|
if od.Trades != nil {
|
|
t.Error("Failed to update")
|
|
}
|
|
|
|
om.Trades = append(om.Trades, TradeHistory{TID: "1"}, TradeHistory{TID: "2"})
|
|
od.UpdateOrderFromDetail(&om)
|
|
if len(od.Trades) != 2 {
|
|
t.Error("Failed to add trades")
|
|
}
|
|
om.Trades[0].Exchange = leet
|
|
om.Trades[0].Price = 1337
|
|
om.Trades[0].Fee = 1337
|
|
om.Trades[0].IsMaker = true
|
|
om.Trades[0].Timestamp = updated
|
|
om.Trades[0].Description = leet
|
|
om.Trades[0].Side = UnknownSide
|
|
om.Trades[0].Type = UnknownType
|
|
om.Trades[0].Amount = 1337
|
|
od.UpdateOrderFromDetail(&om)
|
|
if od.Trades[0].Exchange == leet {
|
|
t.Error("Should not be able to update exchange from update")
|
|
}
|
|
if od.Trades[0].Price != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Fee != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if !od.Trades[0].IsMaker {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Timestamp != updated {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Description != leet {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Side != UnknownSide {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Type != UnknownType {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
if od.Trades[0].Amount != 1337 {
|
|
t.Error("Failed to update trades")
|
|
}
|
|
}
|
|
|
|
func TestClassificationError_Error(t *testing.T) {
|
|
class := ClassificationError{OrderID: "1337", Exchange: "test", Err: errors.New("test error")}
|
|
if class.Error() != "test - OrderID: 1337 classification error: test error" {
|
|
t.Fatal("unexpected output")
|
|
}
|
|
class.OrderID = ""
|
|
if class.Error() != "test - classification error: test error" {
|
|
t.Fatal("unexpected output")
|
|
}
|
|
}
|
|
|
|
func TestValidationOnOrderTypes(t *testing.T) {
|
|
var cancelMe *Cancel
|
|
if cancelMe.Validate() != ErrCancelOrderIsNil {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
cancelMe = new(Cancel)
|
|
if cancelMe.Validate() != ErrPairIsEmpty {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
cancelMe.Pair = currency.NewPair(currency.BTC, currency.USDT)
|
|
if cancelMe.Validate() != ErrAssetNotSet {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
cancelMe.AssetType = asset.Spot
|
|
if cancelMe.Validate() != nil {
|
|
t.Fatal("should not error")
|
|
}
|
|
|
|
if cancelMe.Validate(cancelMe.StandardCancel()) == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
|
|
if cancelMe.Validate(validate.Check(func() error {
|
|
return nil
|
|
})) != nil {
|
|
t.Fatal("should return nil")
|
|
}
|
|
cancelMe.ID = "1337"
|
|
if cancelMe.Validate(cancelMe.StandardCancel()) != nil {
|
|
t.Fatal("should return nil")
|
|
}
|
|
|
|
var getOrders *GetOrdersRequest
|
|
if getOrders.Validate() != ErrGetOrdersRequestIsNil {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
getOrders = new(GetOrdersRequest)
|
|
if getOrders.Validate() == nil {
|
|
t.Fatal("should error since assetType hasn't been provided")
|
|
}
|
|
|
|
if getOrders.Validate(validate.Check(func() error {
|
|
return errors.New("this should error")
|
|
})) == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
|
|
if getOrders.Validate(validate.Check(func() error {
|
|
return nil
|
|
})) == nil {
|
|
t.Fatal("should output an error since assetType isn't provided")
|
|
}
|
|
|
|
var modifyOrder *Modify
|
|
if modifyOrder.Validate() != ErrModifyOrderIsNil {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
modifyOrder = new(Modify)
|
|
if modifyOrder.Validate() != ErrPairIsEmpty {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
p, err := currency.NewPairFromString("BTC-USD")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
modifyOrder.Pair = p
|
|
if modifyOrder.Validate() != ErrAssetNotSet {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
modifyOrder.AssetType = asset.Spot
|
|
if modifyOrder.Validate() != ErrOrderIDNotSet {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
|
|
modifyOrder.ClientOrderID = "1337"
|
|
if modifyOrder.Validate() != nil {
|
|
t.Fatal("should not error")
|
|
}
|
|
|
|
if modifyOrder.Validate(validate.Check(func() error {
|
|
return errors.New("this should error")
|
|
})) == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
|
|
if modifyOrder.Validate(validate.Check(func() error {
|
|
return nil
|
|
})) != nil {
|
|
t.Fatal("unexpected error")
|
|
}
|
|
}
|