BugFix: RPCServer cannot retrieve open orders/getOrder due to unset asset type (#634)

* 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
This commit is contained in:
Scott
2021-02-25 17:13:21 +11:00
committed by GitHub
parent e80091de35
commit 50bbdabf43
45 changed files with 2066 additions and 1618 deletions

View File

@@ -16,6 +16,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/gctrpc"
"github.com/urfave/cli"
"google.golang.org/grpc"
)
var startTime, endTime, order string
@@ -1228,7 +1229,7 @@ func getForexRates(_ *cli.Context) error {
var getOrdersCommand = cli.Command{
Name: "getorders",
Usage: "gets the open orders",
ArgsUsage: "<exchange> <asset> <pair>",
ArgsUsage: "<exchange> <asset> <pair> <start> <end>",
Action: getOrders,
Flags: []cli.Flag{
cli.StringFlag{
@@ -1243,10 +1244,26 @@ var getOrdersCommand = cli.Command{
Name: "pair",
Usage: "the currency pair to get orders for",
},
cli.StringFlag{
Name: "start",
Usage: "start date, optional. Will filter any results before this date",
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
Destination: &startTime,
},
cli.StringFlag{
Name: "end",
Usage: "end date, optional. Will filter any results after this date",
Value: time.Now().Format(common.SimpleTimeFormat),
Destination: &endTime,
},
},
}
func getOrders(c *cli.Context) error {
if c.NArg() == 0 && c.NumFlags() == 0 {
return cli.ShowCommandHelp(c, "getorders")
}
var exchangeName string
var assetType string
var currencyPair string
@@ -1287,7 +1304,33 @@ func getOrders(c *cli.Context) error {
return err
}
conn, err := setupClient()
if !c.IsSet("start") {
if c.Args().Get(3) != "" {
startTime = c.Args().Get(3)
}
}
if !c.IsSet("end") {
if c.Args().Get(4) != "" {
endTime = c.Args().Get(4)
}
}
var s, e time.Time
s, err = time.Parse(common.SimpleTimeFormat, startTime)
if err != nil {
return fmt.Errorf("invalid time format for start: %v", err)
}
e, err = time.Parse(common.SimpleTimeFormat, endTime)
if err != nil {
return fmt.Errorf("invalid time format for end: %v", err)
}
if e.Before(s) {
return errors.New("start cannot be after end")
}
var conn *grpc.ClientConn
conn, err = setupClient()
if err != nil {
return err
}
@@ -1302,6 +1345,8 @@ func getOrders(c *cli.Context) error {
Base: p.Base.String(),
Quote: p.Quote.String(),
},
StartDate: negateLocalOffset(s),
EndDate: negateLocalOffset(e),
})
if err != nil {
return err
@@ -1322,13 +1367,17 @@ var getOrderCommand = cli.Command{
Usage: "the exchange to get the order for",
},
cli.StringFlag{
Name: "order_id",
Usage: "the order id to retrieve",
Name: "asset",
Usage: "required asset type",
},
cli.StringFlag{
Name: "pair",
Usage: "the pair to retrieve",
},
cli.StringFlag{
Name: "order_id",
Usage: "the order id to retrieve",
},
},
}
@@ -1340,19 +1389,32 @@ func getOrder(c *cli.Context) error {
var exchangeName string
var orderID string
var currencyPair string
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(2)
}
var assetType string
if c.IsSet("exchange") {
exchangeName = c.String("exchange")
} else {
exchangeName = c.Args().First()
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("asset") {
assetType = c.String("asset")
} else {
assetType = c.Args().Get(1)
}
assetType = strings.ToLower(assetType)
if !validAsset(assetType) {
return errInvalidAsset
}
if c.IsSet("pair") {
currencyPair = c.String("pair")
} else {
currencyPair = c.Args().Get(2)
}
if !validPair(currencyPair) {
return errInvalidPair
}
@@ -1362,14 +1424,10 @@ func getOrder(c *cli.Context) error {
return err
}
if !validExchange(exchangeName) {
return errInvalidExchange
}
if c.IsSet("order_id") {
orderID = c.String("order_id")
} else {
orderID = c.Args().Get(1)
orderID = c.Args().Get(3)
}
conn, err := setupClient()
@@ -1387,6 +1445,7 @@ func getOrder(c *cli.Context) error {
Base: p.Base.String(),
Quote: p.Quote.String(),
},
Asset: assetType,
})
if err != nil {
return err
@@ -2702,7 +2761,7 @@ var withdrawalRequestCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Usage: "<id>",
Usage: "withdrawal id",
},
},
Action: withdrawlRequestByID,
@@ -2714,11 +2773,11 @@ var withdrawalRequestCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "<exchange>",
Usage: "exchange name",
},
cli.StringFlag{
Name: "id",
Usage: "<id>",
Usage: "withdrawal id",
},
},
Action: withdrawlRequestByExchangeID,
@@ -2730,11 +2789,11 @@ var withdrawalRequestCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "<exchange>",
Usage: "exchange name",
},
cli.Int64Flag{
Name: "limit",
Usage: "<limit>",
Usage: "max number of withdrawals to return",
},
cli.StringFlag{
Name: "currency",
@@ -2750,23 +2809,23 @@ var withdrawalRequestCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "exchange",
Usage: "<exchange>",
Usage: "the currency used in to withdraw",
},
cli.StringFlag{
Name: "start",
Usage: "<start>",
Usage: "the start date to get withdrawals from. Any withdrawal before this date will be filtered",
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
Destination: &startTime,
},
cli.StringFlag{
Name: "end",
Usage: "<end>",
Usage: "the end date to get withdrawals from. Any withdrawal after this date will be filtered",
Value: time.Now().Format(common.SimpleTimeFormat),
Destination: &endTime,
},
cli.Int64Flag{
Name: "limit",
Usage: "<limit>",
Usage: "max number of withdrawals to return",
},
},
Action: withdrawlRequestByDate,
@@ -3575,12 +3634,12 @@ var gctScriptCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "filename",
Usage: "<filename>",
Usage: "the script filename",
Destination: &filename,
},
cli.StringFlag{
Name: "path",
Usage: "<script path>",
Usage: "the directory of the script file",
Destination: &path,
},
},
@@ -3592,7 +3651,7 @@ var gctScriptCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "uuid",
Usage: "<uuid>",
Usage: "the unique id of the script in memory",
Destination: &uuid,
},
},
@@ -3604,7 +3663,7 @@ var gctScriptCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "name",
Usage: "<name>",
Usage: "the script name",
Destination: &uuid,
},
},
@@ -3626,7 +3685,7 @@ var gctScriptCommand = cli.Command{
Flags: []cli.Flag{
cli.StringFlag{
Name: "uuid",
Usage: "<uuid>",
Usage: "the unique id of the script in memory",
Destination: &uuid,
},
},
@@ -4162,13 +4221,13 @@ var getHistoricCandlesExtendedCommand = cli.Command{
},
cli.StringFlag{
Name: "start",
Usage: "<start>",
Usage: "the date to begin retrieveing candles. Any candles before this date will be filtered",
Value: time.Now().AddDate(0, -1, 0).Format(common.SimpleTimeFormat),
Destination: &startTime,
},
cli.StringFlag{
Name: "end",
Usage: "<end>",
Usage: "the date to end retrieveing candles. Any candles after this date will be filtered",
Value: time.Now().Format(common.SimpleTimeFormat),
Destination: &endTime,
},

View File

@@ -293,7 +293,7 @@ func (o *orderManager) Cancel(cancel *order.Cancel) error {
// and stores the result in the order manager
func (o *orderManager) GetOrderInfo(exchangeName, orderID string, cp currency.Pair, a asset.Item) (order.Detail, error) {
if orderID == "" {
return order.Detail{}, errors.New("order cannot be empty")
return order.Detail{}, errOrderCannotBeEmpty
}
exch := Bot.GetExchangeByName(exchangeName)

View File

@@ -1,12 +1,17 @@
package engine
import (
"errors"
"sync"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
var (
errOrderCannotBeEmpty = errors.New("order cannot be empty")
)
type orderManagerConfig struct {
EnforceLimitConfig bool
AllowMarketOrders bool

View File

@@ -50,18 +50,19 @@ import (
)
const (
errExchangeNameUnset = "exchange name unset"
errCurrencyPairUnset = "currency pair unset"
errStartEndTimesUnset = "invalid start and end times"
errAssetTypeUnset = "asset type unset"
errDispatchSystem = "dispatch system offline"
invalidArguments = "invalid arguments received"
errExchangeNameUnset = "exchange name unset"
errAssetTypeUnset = "asset type unset"
errDispatchSystem = "dispatch system offline"
invalidArguments = "invalid arguments received"
)
var (
errExchangeNotLoaded = errors.New("exchange is not loaded/doesn't exist")
errExchangeBaseNotFound = errors.New("cannot get exchange base")
errInvalidArguments = errors.New(invalidArguments)
errCurrencyPairUnset = errors.New("currency pair unset")
errCurrencyNotEnabled = errors.New("currency not enabled")
errInvalidStartEndTime = errors.New("invalid start and end times")
)
// RPCServer struct
@@ -801,38 +802,115 @@ func (s *RPCServer) GetForexRates(_ context.Context, r *gctrpc.GetForexRatesRequ
}
// GetOrders returns all open orders, filtered by exchange, currency pair or
// asset type
// asset type between optional dates
func (s *RPCServer) GetOrders(_ context.Context, r *gctrpc.GetOrdersRequest) (*gctrpc.GetOrdersResponse, error) {
if r == nil {
return nil, errInvalidArguments
}
exch := s.GetExchangeByName(r.Exchange)
if exch == nil {
return nil, errExchangeNotLoaded
}
if r.Pair == nil {
return nil, errCurrencyPairUnset
}
a, err := asset.New(r.AssetType)
if err != nil {
return nil, err
}
var start, end time.Time
if r.StartDate != "" {
start, err = time.Parse(common.SimpleTimeFormat, r.StartDate)
if err != nil {
return nil, err
}
}
if r.EndDate != "" {
end, err = time.Parse(common.SimpleTimeFormat, r.EndDate)
if err != nil {
return nil, err
}
}
if !start.IsZero() && !end.IsZero() && start.After(end) {
return nil, errInvalidStartEndTime
}
resp, err := exch.GetActiveOrders(&order.GetOrdersRequest{
Pairs: []currency.Pair{
currency.NewPairWithDelimiter(r.Pair.Base,
r.Pair.Quote, r.Pair.Delimiter),
},
})
cp := currency.NewPairWithDelimiter(
r.Pair.Base,
r.Pair.Quote,
r.Pair.Delimiter)
var pairs currency.Pairs
pairs, err = exch.GetEnabledPairs(a)
if err != nil {
return nil, err
}
if !pairs.Contains(cp, false) {
return nil, fmt.Errorf("%s %w %v, please check your config",
exch.GetName(),
errCurrencyNotEnabled,
cp.String())
}
request := &order.GetOrdersRequest{
Pairs: []currency.Pair{cp},
AssetType: a,
}
if !start.IsZero() {
request.StartTime = start
}
if !end.IsZero() {
request.EndTime = end
}
var resp []order.Detail
resp, err = exch.GetActiveOrders(request)
if err != nil {
return nil, err
}
var orders []*gctrpc.OrderDetails
for x := range resp {
orders = append(orders, &gctrpc.OrderDetails{
var trades []*gctrpc.TradeHistory
for i := range resp[x].Trades {
t := &gctrpc.TradeHistory{
Id: resp[x].Trades[i].TID,
Price: resp[x].Trades[i].Price,
Amount: resp[x].Trades[i].Amount,
Exchange: r.Exchange,
AssetType: a.String(),
OrderSide: resp[x].Trades[i].Side.String(),
Fee: resp[x].Trades[i].Fee,
Total: resp[x].Trades[i].Total,
}
if !resp[x].Trades[i].Timestamp.IsZero() {
t.CreationTime = resp[x].Trades[i].Timestamp.Unix()
}
trades = append(trades, t)
}
o := &gctrpc.OrderDetails{
Exchange: r.Exchange,
Id: resp[x].ID,
ClientOrderId: resp[x].ClientOrderID,
BaseCurrency: resp[x].Pair.Base.String(),
QuoteCurrency: resp[x].Pair.Quote.String(),
AssetType: asset.Spot.String(),
OrderType: resp[x].Type.String(),
AssetType: resp[x].AssetType.String(),
OrderSide: resp[x].Side.String(),
CreationTime: resp[x].Date.Unix(),
OrderType: resp[x].Type.String(),
Status: resp[x].Status.String(),
Price: resp[x].Price,
Amount: resp[x].Amount,
})
OpenVolume: resp[x].Amount - resp[x].ExecutedAmount,
Fee: resp[x].Fee,
Cost: resp[x].Cost,
Trades: trades,
}
if !resp[x].Date.IsZero() {
o.CreationTime = resp[x].Date.Unix()
}
if !resp[x].LastUpdated.IsZero() {
o.UpdateTime = resp[x].LastUpdated.Unix()
}
orders = append(orders, o)
}
return &gctrpc.GetOrdersResponse{Orders: orders}, nil
@@ -840,10 +918,16 @@ func (s *RPCServer) GetOrders(_ context.Context, r *gctrpc.GetOrdersRequest) (*g
// GetOrder returns order information based on exchange and order ID
func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gctrpc.OrderDetails, error) {
if r == nil {
return nil, errInvalidArguments
}
exch := s.GetExchangeByName(r.Exchange)
if exch == nil {
return nil, errExchangeNotLoaded
}
if r.Pair == nil {
return nil, errCurrencyPairUnset
}
pair := currency.Pair{
Delimiter: r.Pair.Delimiter,
@@ -851,9 +935,14 @@ func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gct
Quote: currency.NewCode(r.Pair.Quote),
}
result, err := s.OrderManager.GetOrderInfo(r.Exchange, r.OrderId, pair, "") // assetType will be implemented in the future
a, err := asset.New(r.Asset)
if err != nil {
return nil, fmt.Errorf("error whilst trying to retrieve info for order %s: %s", r.OrderId, err)
return nil, err
}
result, err := s.OrderManager.GetOrderInfo(r.Exchange, r.OrderId, pair, a)
if err != nil {
return nil, fmt.Errorf("error whilst trying to retrieve info for order %s: %w", r.OrderId, err)
}
var trades []*gctrpc.TradeHistory
for i := range result.Trades {
@@ -874,8 +963,8 @@ func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gct
if result.Date.Unix() > 0 {
creationTime = result.Date.Unix()
}
if result.CloseTime.Unix() > 0 {
updateTime = result.CloseTime.Unix()
if result.LastUpdated.Unix() > 0 {
updateTime = result.LastUpdated.Unix()
}
return &gctrpc.OrderDetails{
@@ -1542,7 +1631,7 @@ func (s *RPCServer) GetOrderbookStream(r *gctrpc.GetOrderbookStreamRequest, stre
}
if r.Pair.String() == "" {
return errors.New(errCurrencyPairUnset)
return errCurrencyPairUnset
}
if r.AssetType == "" {
@@ -1656,7 +1745,7 @@ func (s *RPCServer) GetTickerStream(r *gctrpc.GetTickerStreamRequest, stream gct
}
if r.Pair.String() == "" {
return errors.New(errCurrencyPairUnset)
return errCurrencyPairUnset
}
if r.AssetType == "" {
@@ -1795,13 +1884,13 @@ func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequ
// GetHistoricCandles returns historical candles for a given exchange
func (s *RPCServer) GetHistoricCandles(_ context.Context, r *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) {
if r.Exchange == "" {
return nil, errors.New(errExchangeNameUnset)
return nil, fmt.Errorf("%w. blank exchange name received", errInvalidArguments)
}
if r.Pair.String() == "" {
return nil, errors.New(errCurrencyPairUnset)
return nil, errCurrencyPairUnset
}
if r.Start == r.End {
return nil, errors.New(errStartEndTimesUnset)
return nil, errInvalidStartEndTime
}
var klineItem kline.Item

View File

@@ -7,6 +7,7 @@ import (
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
@@ -17,7 +18,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/database"
"github.com/thrasher-corp/gocryptotrader/database/drivers"
"github.com/thrasher-corp/gocryptotrader/database/repository"
"github.com/thrasher-corp/gocryptotrader/database/repository/exchange"
dbexchange "github.com/thrasher-corp/gocryptotrader/database/repository/exchange"
sqltrade "github.com/thrasher-corp/gocryptotrader/database/repository/trade"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
@@ -69,7 +70,7 @@ func RPCTestSetup(t *testing.T) *Engine {
t.Fatalf("failed to run migrations %v", err)
}
uuider, _ := uuid.NewV4()
err = exchange.Insert(exchange.Details{Name: testExchange, UUID: uuider})
err = dbexchange.Insert(dbexchange.Details{Name: testExchange, UUID: uuider})
if err != nil {
t.Fatalf("failed to insert exchange %v", err)
}
@@ -330,16 +331,16 @@ func TestGetHistoricCandles(t *testing.T) {
_, err := s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{
Exchange: "",
})
if err != nil && err.Error() != errExchangeNameUnset {
t.Error(err)
if !errors.Is(err, errInvalidArguments) {
t.Errorf("expected %v, received %v", errInvalidArguments, err)
}
_, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{
Exchange: testExchange,
Pair: &gctrpc.CurrencyPair{},
})
if err != nil && err.Error() != errCurrencyPairUnset {
t.Error(err)
if !errors.Is(err, errCurrencyPairUnset) {
t.Errorf("expected %v, received %v", errCurrencyPairUnset, err)
}
_, err = s.GetHistoricCandles(context.Background(), &gctrpc.GetHistoricCandlesRequest{
Exchange: testExchange,
@@ -348,8 +349,8 @@ func TestGetHistoricCandles(t *testing.T) {
Quote: currency.USD.String(),
},
})
if err != nil && err.Error() != errStartEndTimesUnset {
t.Error(err)
if !errors.Is(err, errInvalidStartEndTime) {
t.Errorf("expected %v, received %v", errInvalidStartEndTime, err)
}
var results *gctrpc.GetHistoricCandlesResponse
defaultStart := time.Date(2020, 1, 1, 1, 1, 1, 1, time.UTC)
@@ -818,3 +819,167 @@ func TestUpdateAccountInfo(t *testing.T) {
t.Fatalf("TestGetAccountInfo: Unexpected value of the 'TotalValue'")
}
}
func TestGetOrders(t *testing.T) {
exchName := "binance"
engerino := RPCTestSetup(t)
defer CleanRPCTest(t, engerino)
s := RPCServer{Engine: engerino}
_, err := s.GetOrders(context.Background(), nil)
if !errors.Is(err, errInvalidArguments) {
t.Errorf("expected %v, received %v", errInvalidArguments, err)
}
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{})
if !errors.Is(err, errExchangeNotLoaded) {
t.Errorf("expected %v, received %v", errExchangeNotLoaded, err)
}
err = engerino.LoadExchange(exchName, false, nil)
if err != nil {
t.Error(err)
}
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchName,
})
if !errors.Is(err, errCurrencyPairUnset) {
t.Errorf("expected %v, received %v", errCurrencyPairUnset, err)
}
p := &gctrpc.CurrencyPair{
Delimiter: "-",
Base: currency.BTC.String(),
Quote: currency.USDT.String(),
}
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchName,
Pair: p,
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, received %v", asset.ErrNotSupported, err)
}
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchName,
AssetType: asset.Spot.String(),
Pair: p,
StartDate: time.Now().Format(common.SimpleTimeFormat),
EndDate: time.Now().Add(-time.Hour).Format(common.SimpleTimeFormat),
})
if !errors.Is(err, errInvalidStartEndTime) {
t.Errorf("expected %v, received %v", errInvalidStartEndTime, err)
}
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchName,
AssetType: asset.Spot.String(),
Pair: p,
StartDate: time.Now().Format(common.SimpleTimeFormat),
EndDate: time.Now().Add(time.Hour).Format(common.SimpleTimeFormat),
})
if err != nil && !strings.Contains(err.Error(), "not supported due to unset/default API keys") {
t.Error(err)
}
if err == nil {
t.Error("expected error")
}
exch := engerino.GetExchangeByName(exchName)
if exch == nil {
t.Fatal("expected an exchange")
}
b := exch.GetBase()
b.API.Credentials.Key = "test"
b.API.Credentials.Secret = "test"
b.API.AuthenticatedSupport = true
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchName,
AssetType: asset.Spot.String(),
Pair: p,
})
if err == nil {
t.Error("expected error")
}
}
func TestGetOrder(t *testing.T) {
exchName := "binance"
engerino := RPCTestSetup(t)
defer CleanRPCTest(t, engerino)
s := RPCServer{Engine: engerino}
_, err := s.GetOrder(context.Background(), nil)
if !errors.Is(err, errInvalidArguments) {
t.Errorf("expected %v, received %v", errInvalidArguments, err)
}
_, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchName,
OrderId: "",
Pair: nil,
Asset: "",
})
if !errors.Is(err, errExchangeNotLoaded) {
t.Errorf("expected %v, received %v", errExchangeNotLoaded, err)
}
err = engerino.LoadExchange(exchName, false, nil)
if err != nil {
t.Error(err)
}
_, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchName,
OrderId: "",
Pair: nil,
Asset: "",
})
if !errors.Is(err, errCurrencyPairUnset) {
t.Errorf("expected %v, received %v", errCurrencyPairUnset, err)
}
p := &gctrpc.CurrencyPair{
Delimiter: "-",
Base: "BTC",
Quote: "USDT",
}
_, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchName,
OrderId: "",
Pair: p,
Asset: "",
})
if !errors.Is(err, asset.ErrNotSupported) {
t.Errorf("expected %v, received %v", asset.ErrNotSupported, err)
}
_, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchName,
OrderId: "",
Pair: p,
Asset: asset.Spot.String(),
})
if !errors.Is(err, errOrderCannotBeEmpty) {
t.Errorf("expected %v, received %v", errOrderCannotBeEmpty, err)
}
if Bot == nil {
Bot = engerino
}
err = Bot.OrderManager.Start()
if err != nil {
t.Fatal(err)
}
_, err = s.GetOrder(context.Background(), &gctrpc.GetOrderRequest{
Exchange: exchName,
OrderId: "1234",
Pair: p,
Asset: asset.Spot.String(),
})
if err == nil {
t.Error("expected error")
}
}

View File

@@ -388,7 +388,7 @@ func (a *Alphapoint) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detai
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}
@@ -434,7 +434,7 @@ func (a *Alphapoint) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}

View File

@@ -1,10 +1,15 @@
package asset
import (
"errors"
"fmt"
"strings"
)
var (
ErrNotSupported = errors.New("received unsupported asset type")
)
// Item stores the asset type
type Item string
@@ -101,7 +106,8 @@ func New(input string) (Item, error) {
return supported[i], nil
}
}
return "", fmt.Errorf("cannot create new asset: input %s mismatch to supported asset list %s",
return "", fmt.Errorf("%w %v, only supports %v",
ErrNotSupported,
input,
supported)
}

View File

@@ -548,24 +548,22 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC
// OpenOrders Current open orders. Get all open orders on a symbol.
// Careful when accessing this with no symbol: The number of requests counted against the rate limiter
// is significantly higher
func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
func (b *Binance) OpenOrders(pair currency.Pair) ([]QueryOrderData, error) {
var resp []QueryOrderData
params := url.Values{}
var symbol string
if pair != nil {
var err error
symbol, err = b.FormatSymbol(*pair, asset.Spot)
var p string
var err error
if !pair.IsEmpty() {
p, err = b.FormatSymbol(pair, asset.Spot)
if err != nil {
return resp, err
return nil, err
}
params.Add("symbol", p)
} else {
// extend the receive window when all currencies to prevent "recvwindow" error
params.Set("recvWindow", "10000")
}
if symbol != "" {
params.Set("symbol", symbol)
}
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, openOrders, params, openOrdersLimit(symbol), &resp); err != nil {
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, openOrders, params, openOrdersLimit(p), &resp); err != nil {
return resp, err
}
@@ -675,6 +673,17 @@ func (b *Binance) SendAuthHTTPRequest(ePath exchange.URL, method, path string, p
params = url.Values{}
}
recvWindow := 5 * time.Second
if params.Get("recvWindow") != "" {
// convert recvWindow value into time.Duration
var recvWindowParam int64
recvWindowParam, err = convert.Int64FromString(params.Get("recvWindow"))
if err != nil {
return err
}
recvWindow = time.Duration(recvWindowParam) * time.Millisecond
} else {
params.Set("recvWindow", strconv.FormatInt(convert.RecvWindow(recvWindow), 10))
}
params.Set("recvWindow", strconv.FormatInt(convert.RecvWindow(recvWindow), 10))
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
signature := params.Encode()

View File

@@ -1136,7 +1136,7 @@ func (b *Binance) FuturesOpenOrderData(symbol currency.Pair, orderID, origClient
func (b *Binance) GetFuturesAllOpenOrders(symbol currency.Pair, pair string) ([]FuturesOrderData, error) {
var resp []FuturesOrderData
params := url.Values{}
if symbol != (currency.Pair{}) {
if !symbol.IsEmpty() {
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp, err
@@ -1153,7 +1153,7 @@ func (b *Binance) GetFuturesAllOpenOrders(symbol currency.Pair, pair string) ([]
func (b *Binance) GetAllFuturesOrders(symbol currency.Pair, pair string, startTime, endTime time.Time, orderID, limit int64) ([]FuturesOrderData, error) {
var resp []FuturesOrderData
params := url.Values{}
if symbol != (currency.Pair{}) {
if !symbol.IsEmpty() {
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
if err != nil {
return resp, err

View File

@@ -1268,16 +1268,18 @@ func TestQueryOrder(t *testing.T) {
func TestOpenOrders(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := b.OpenOrders(currency.Pair{})
if err != nil {
t.Error(err)
}
p := currency.NewPair(currency.BTC, currency.USDT)
_, err := b.OpenOrders(&p)
switch {
case areTestAPIKeysSet() && err != nil:
t.Error("OpenOrders() error", err)
case !areTestAPIKeysSet() && err == nil && !mockTests:
t.Error("OpenOrders() expecting an error when no keys are set")
case mockTests && err != nil:
t.Error("Mock OpenOrders() error", err)
_, err = b.OpenOrders(p)
if err != nil {
t.Error(err)
}
}

View File

@@ -189,7 +189,6 @@ func (b *Binance) SetDefaults() {
b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
}
// Setup takes in the supplied exchange configuration details and sets params
@@ -919,7 +918,7 @@ func (b *Binance) CancelAllOrders(req *order.Cancel) (order.CancelAllResponse, e
cancelAllOrdersResponse.Status = make(map[string]string)
switch req.AssetType {
case asset.Spot, asset.Margin:
openOrders, err := b.OpenOrders(&req.Pair)
openOrders, err := b.OpenOrders(req.Pair)
if err != nil {
return cancelAllOrdersResponse, err
}
@@ -1013,10 +1012,11 @@ func (b *Binance) GetOrderInfo(orderID string, pair currency.Pair, assetType ass
Pair: pair,
Cost: resp.CummulativeQuoteQty,
AssetType: assetType,
CloseTime: resp.UpdateTime,
Status: status,
Price: resp.Price,
ExecutedAmount: resp.ExecutedQty,
Date: resp.Time,
LastUpdated: resp.UpdateTime,
}, nil
case asset.CoinMarginedFutures:
orderData, err := b.GetAllFuturesOrders(pair, "", time.Time{}, time.Time{}, orderIDInt, 0)
@@ -1052,6 +1052,8 @@ func (b *Binance) GetOrderInfo(orderID string, pair currency.Pair, assetType ass
respData.Side = orderVars.Side
respData.Status = orderVars.Status
respData.Type = orderVars.OrderType
respData.Date = orderData[0].Time
respData.LastUpdated = orderData[0].UpdateTime
case asset.USDTMarginedFutures:
orderData, err := b.UAllAccountOrders(currency.Pair{}, 0, 0, time.Time{}, time.Time{})
if err != nil {
@@ -1086,6 +1088,8 @@ func (b *Binance) GetOrderInfo(orderID string, pair currency.Pair, assetType ass
respData.Side = orderVars.Side
respData.Status = orderVars.Status
respData.Type = orderVars.OrderType
respData.Date = orderData[0].Time
respData.LastUpdated = orderData[0].UpdateTime
default:
return respData, fmt.Errorf("assetType %s not supported", assetType)
}
@@ -1143,119 +1147,109 @@ func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
if err := req.Validate(); err != nil {
return nil, err
}
addAll := len(req.Pairs) == 0
var orders []order.Detail
switch req.AssetType {
case asset.Spot, asset.Margin:
resp, err := b.OpenOrders(&currency.Pair{})
if err != nil {
return nil, err
}
for i := range resp {
pair, err := currency.NewPairFromString(resp[i].Symbol)
if err != nil {
return nil, err
}
if !addAll && !req.Pairs.Contains(pair, false) {
continue
}
orderSide := order.Side(strings.ToUpper(resp[i].Side))
orderType := order.Type(strings.ToUpper(resp[i].Type))
orders = append(orders, order.Detail{
Amount: resp[i].OrigQty,
Date: resp[i].Time,
Exchange: b.Name,
ID: strconv.FormatInt(resp[i].OrderID, 10),
Side: orderSide,
Type: orderType,
Price: resp[i].Price,
Status: order.Status(resp[i].Status),
Pair: pair,
AssetType: asset.Spot,
})
}
case asset.CoinMarginedFutures:
openOrders, err := b.GetFuturesAllOpenOrders(currency.Pair{}, "")
if err != nil {
return nil, err
}
for y := range openOrders {
pair, err := currency.NewPairFromString(openOrders[y].Symbol)
if err != nil {
return nil, err
}
if !addAll && !req.Pairs.Contains(pair, false) {
continue
}
var feeBuilder exchange.FeeBuilder
feeBuilder.Amount = openOrders[y].ExecutedQty
feeBuilder.PurchasePrice = openOrders[y].AvgPrice
feeBuilder.Pair = pair
fee, err := b.GetFee(&feeBuilder)
if err != nil {
return orders, err
}
orderVars := compatibleOrderVars(openOrders[y].Side, openOrders[y].Status, openOrders[y].OrderType)
orders = append(orders, order.Detail{
Price: openOrders[y].Price,
Amount: openOrders[y].OrigQty,
ExecutedAmount: openOrders[y].ExecutedQty,
RemainingAmount: openOrders[y].OrigQty - openOrders[y].ExecutedQty,
Fee: fee,
Exchange: b.Name,
ID: strconv.FormatInt(openOrders[y].OrderID, 10),
ClientOrderID: openOrders[y].ClientOrderID,
Type: orderVars.OrderType,
Side: orderVars.Side,
Status: orderVars.Status,
Pair: pair,
AssetType: asset.CoinMarginedFutures,
})
}
case asset.USDTMarginedFutures:
openOrders, err := b.UAllAccountOpenOrders(currency.Pair{})
if err != nil {
return nil, err
}
for y := range openOrders {
pair, err := currency.NewPairFromString(openOrders[y].Symbol)
if err != nil {
return nil, err
}
if !addAll && !req.Pairs.Contains(pair, false) {
continue
}
var feeBuilder exchange.FeeBuilder
feeBuilder.Amount = openOrders[y].ExecutedQty
feeBuilder.PurchasePrice = openOrders[y].AvgPrice
feeBuilder.Pair = pair
fee, err := b.GetFee(&feeBuilder)
if err != nil {
return orders, err
}
orderVars := compatibleOrderVars(openOrders[y].Side, openOrders[y].Status, openOrders[y].OrderType)
orders = append(orders, order.Detail{
Price: openOrders[y].Price,
Amount: openOrders[y].OrigQty,
ExecutedAmount: openOrders[y].ExecutedQty,
RemainingAmount: openOrders[y].OrigQty - openOrders[y].ExecutedQty,
Fee: fee,
Exchange: b.Name,
ID: strconv.FormatInt(openOrders[y].OrderID, 10),
ClientOrderID: openOrders[y].ClientOrderID,
Type: orderVars.OrderType,
Side: orderVars.Side,
Status: orderVars.Status,
Pair: pair,
AssetType: asset.USDTMarginedFutures,
})
}
default:
return orders, fmt.Errorf("assetType not supported")
if len(req.Pairs) == 0 || len(req.Pairs) >= 40 {
// sending an empty currency pair retrieves data for all currencies
req.Pairs = append(req.Pairs, currency.Pair{})
}
var orders []order.Detail
for i := range req.Pairs {
switch req.AssetType {
case asset.Spot, asset.Margin:
resp, err := b.OpenOrders(req.Pairs[i])
if err != nil {
return nil, err
}
for x := range resp {
orderSide := order.Side(strings.ToUpper(resp[x].Side))
orderType := order.Type(strings.ToUpper(resp[x].Type))
orders = append(orders, order.Detail{
Amount: resp[x].OrigQty,
Date: resp[x].Time,
Exchange: b.Name,
ID: strconv.FormatInt(resp[x].OrderID, 10),
Side: orderSide,
Type: orderType,
Price: resp[x].Price,
Status: order.Status(resp[x].Status),
Pair: req.Pairs[i],
AssetType: asset.Spot,
LastUpdated: resp[x].UpdateTime,
})
}
case asset.CoinMarginedFutures:
openOrders, err := b.GetFuturesAllOpenOrders(req.Pairs[i], "")
if err != nil {
return nil, err
}
for y := range openOrders {
var feeBuilder exchange.FeeBuilder
feeBuilder.Amount = openOrders[y].ExecutedQty
feeBuilder.PurchasePrice = openOrders[y].AvgPrice
feeBuilder.Pair = req.Pairs[i]
fee, err := b.GetFee(&feeBuilder)
if err != nil {
return orders, err
}
orderVars := compatibleOrderVars(openOrders[y].Side, openOrders[y].Status, openOrders[y].OrderType)
orders = append(orders, order.Detail{
Price: openOrders[y].Price,
Amount: openOrders[y].OrigQty,
ExecutedAmount: openOrders[y].ExecutedQty,
RemainingAmount: openOrders[y].OrigQty - openOrders[y].ExecutedQty,
Fee: fee,
Exchange: b.Name,
ID: strconv.FormatInt(openOrders[y].OrderID, 10),
ClientOrderID: openOrders[y].ClientOrderID,
Type: orderVars.OrderType,
Side: orderVars.Side,
Status: orderVars.Status,
Pair: req.Pairs[i],
AssetType: asset.CoinMarginedFutures,
Date: openOrders[y].Time,
LastUpdated: openOrders[y].UpdateTime,
})
}
case asset.USDTMarginedFutures:
openOrders, err := b.UAllAccountOpenOrders(req.Pairs[i])
if err != nil {
return nil, err
}
for y := range openOrders {
var feeBuilder exchange.FeeBuilder
feeBuilder.Amount = openOrders[y].ExecutedQuantity
feeBuilder.PurchasePrice = openOrders[y].AveragePrice
feeBuilder.Pair = req.Pairs[i]
fee, err := b.GetFee(&feeBuilder)
if err != nil {
return orders, err
}
orderVars := compatibleOrderVars(openOrders[y].Side, openOrders[y].Status, openOrders[y].OrderType)
orders = append(orders, order.Detail{
Price: openOrders[y].Price,
Amount: openOrders[y].OriginalQuantity,
ExecutedAmount: openOrders[y].ExecutedQuantity,
RemainingAmount: openOrders[y].OriginalQuantity - openOrders[y].ExecutedQuantity,
Fee: fee,
Exchange: b.Name,
ID: strconv.FormatInt(openOrders[y].OrderID, 10),
ClientOrderID: openOrders[y].ClientOrderID,
Type: orderVars.OrderType,
Side: orderVars.Side,
Status: orderVars.Status,
Pair: req.Pairs[i],
AssetType: asset.USDTMarginedFutures,
Date: openOrders[y].Time,
LastUpdated: openOrders[y].UpdateTime,
})
}
default:
return orders, fmt.Errorf("assetType not supported")
}
}
order.FilterOrdersByCurrencies(&orders, req.Pairs)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}
@@ -1291,7 +1285,6 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
if err != nil {
return nil, err
}
orders = append(orders, order.Detail{
Amount: resp[i].OrigQty,
Date: resp[i].Time,
@@ -1310,18 +1303,18 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
var orderHistory []FuturesOrderData
var err error
switch {
case !req.StartTicks.IsZero() && !req.EndTicks.IsZero() && req.OrderID == "":
if req.EndTicks.Before(req.StartTicks) {
case !req.StartTime.IsZero() && !req.EndTime.IsZero() && req.OrderID == "":
if req.EndTime.Before(req.StartTime) {
return nil, errors.New("endTime cannot be before startTime")
}
if time.Since(req.StartTicks) > time.Hour*24*30 {
if time.Since(req.StartTime) > time.Hour*24*30 {
return nil, fmt.Errorf("can only fetch orders 30 days out")
}
orderHistory, err = b.GetAllFuturesOrders(req.Pairs[i], "", req.StartTicks, req.EndTicks, 0, 0)
orderHistory, err = b.GetAllFuturesOrders(req.Pairs[i], "", req.StartTime, req.EndTime, 0, 0)
if err != nil {
return nil, err
}
case req.OrderID != "" && req.StartTicks.IsZero() && req.EndTicks.IsZero():
case req.OrderID != "" && req.StartTime.IsZero() && req.EndTime.IsZero():
fromID, err := strconv.ParseInt(req.OrderID, 10, 64)
if err != nil {
return nil, err
@@ -1357,6 +1350,7 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
Status: orderVars.Status,
Pair: req.Pairs[i],
AssetType: asset.CoinMarginedFutures,
Date: orderHistory[y].Time,
})
}
}
@@ -1365,18 +1359,18 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
var orderHistory []UFuturesOrderData
var err error
switch {
case !req.StartTicks.IsZero() && !req.EndTicks.IsZero() && req.OrderID == "":
if req.EndTicks.Before(req.StartTicks) {
case !req.StartTime.IsZero() && !req.EndTime.IsZero() && req.OrderID == "":
if req.EndTime.Before(req.StartTime) {
return nil, errors.New("endTime cannot be before startTime")
}
if time.Since(req.StartTicks) > time.Hour*24*7 {
if time.Since(req.StartTime) > time.Hour*24*7 {
return nil, fmt.Errorf("can only fetch orders 7 days out")
}
orderHistory, err = b.UAllAccountOrders(req.Pairs[i], 0, 0, req.StartTicks, req.EndTicks)
orderHistory, err = b.UAllAccountOrders(req.Pairs[i], 0, 0, req.StartTime, req.EndTime)
if err != nil {
return nil, err
}
case req.OrderID != "" && req.StartTicks.IsZero() && req.EndTicks.IsZero():
case req.OrderID != "" && req.StartTime.IsZero() && req.EndTime.IsZero():
fromID, err := strconv.ParseInt(req.OrderID, 10, 64)
if err != nil {
return nil, err
@@ -1412,6 +1406,7 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
Status: orderVars.Status,
Pair: req.Pairs[i],
AssetType: asset.USDTMarginedFutures,
Date: orderHistory[y].Time,
})
}
}
@@ -1420,7 +1415,7 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}

View File

@@ -262,30 +262,30 @@ type FuturesOrderGetData struct {
// FuturesOrderData stores order data for futures
type FuturesOrderData struct {
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumBase string `json:"cumBase"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
Time int64 `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumBase string `json:"cumBase"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Pair string `json:"pair"`
Time time.Time `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime time.Time `json:"updateTime"`
WorkingType string `json:"workingType"`
PriceProtect bool `json:"priceProtect"`
}
// OrderVars stores side, status and type for any order/trade

View File

@@ -211,6 +211,60 @@ func (a *QueryOrderData) UnmarshalJSON(data []byte) error {
return nil
}
// UnmarshalJSON deserialises the JSON info, including the timestamp
func (a *FuturesOrderData) UnmarshalJSON(data []byte) error {
type Alias FuturesOrderData
aux := &struct {
Time binanceTime `json:"time"`
UpdateTime binanceTime `json:"updateTime"`
*Alias
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
a.Time = aux.Time.Time()
a.UpdateTime = aux.UpdateTime.Time()
return nil
}
// UnmarshalJSON deserialises the JSON info, including the timestamp
func (a *UFuturesOrderData) UnmarshalJSON(data []byte) error {
type Alias UFuturesOrderData
aux := &struct {
Time binanceTime `json:"time"`
UpdateTime binanceTime `json:"updateTime"`
*Alias
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
a.Time = aux.Time.Time()
a.UpdateTime = aux.UpdateTime.Time()
return nil
}
// UnmarshalJSON deserialises the JSON info, including the timestamp
func (a *UOrderData) UnmarshalJSON(data []byte) error {
type Alias UOrderData
aux := &struct {
Time binanceTime `json:"time"`
UpdateTime binanceTime `json:"updateTime"`
*Alias
}{
Alias: (*Alias)(a),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
a.Time = aux.Time.Time()
a.UpdateTime = aux.UpdateTime.Time()
return nil
}
// UnmarshalJSON deserialises the JSON info, including the timestamp
func (a *Account) UnmarshalJSON(data []byte) error {
type Alias Account

View File

@@ -1,5 +1,7 @@
package binance
import "time"
var (
validFuturesIntervals = []string{
"1m", "3m", "5m", "15m", "30m",
@@ -183,56 +185,57 @@ type UCompositeIndexInfoData struct {
// UOrderData stores order data
type UOrderData struct {
ClientOrderID string `json:"clientOrderId"`
CumQty float64 `json:"cumQty,string"`
CumQuote float64 `json:"cumQuote,string"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
AvgPrice float64 `json:"avgPrice,string"`
OrigQty float64 `json:"origQty,string"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
OrigType string `json:"origType"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
Code int64 `json:"code"`
Msg string `json:"msg"`
ClientOrderID string `json:"clientOrderId"`
Time time.Time `json:"time"`
CumulativeQuantity float64 `json:"cumQty,string"`
CumulativeQuote float64 `json:"cumQuote,string"`
ExecutedQuantity float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
AveragePrice float64 `json:"avgPrice,string"`
OriginalQuantity float64 `json:"origQty,string"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
OriginalType string `json:"origType"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime time.Time `json:"updateTime"`
WorkingType string `json:"workingType"`
Code int64 `json:"code"`
Message string `json:"msg"`
}
// UFuturesOrderData stores order data for ufutures
type UFuturesOrderData struct {
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumQuote string `json:"cumQuote"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Time int64 `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime int64 `json:"updateTime"`
WorkingType string `json:"workingType"`
AvgPrice float64 `json:"avgPrice,string"`
ClientOrderID string `json:"clientOrderId"`
CumQuote string `json:"cumQuote"`
ExecutedQty float64 `json:"executedQty,string"`
OrderID int64 `json:"orderId"`
OrigQty float64 `json:"origQty,string"`
OrigType string `json:"origType"`
Price float64 `json:"price,string"`
ReduceOnly bool `json:"reduceOnly"`
Side string `json:"side"`
PositionSide string `json:"positionSide"`
Status string `json:"status"`
StopPrice float64 `json:"stopPrice,string"`
ClosePosition bool `json:"closePosition"`
Symbol string `json:"symbol"`
Time time.Time `json:"time"`
TimeInForce string `json:"timeInForce"`
OrderType string `json:"type"`
ActivatePrice float64 `json:"activatePrice,string"`
PriceRate float64 `json:"priceRate,string"`
UpdateTime time.Time `json:"updateTime"`
WorkingType string `json:"workingType"`
}
// UAccountBalanceV2Data stores account balance data for ufutures

View File

@@ -862,7 +862,7 @@ func (b *Bitfinex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -930,7 +930,7 @@ func (b *Bitfinex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
for i := range req.Pairs {
b.appendOptionalDelimiter(&req.Pairs[i])
}

View File

@@ -625,7 +625,7 @@ func (b *Bithumb) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
}
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -676,7 +676,7 @@ func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
}
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}

View File

@@ -719,6 +719,7 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
}
orderDetail := order.Detail{
Date: resp[i].Timestamp,
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
@@ -736,7 +737,7 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -786,7 +787,7 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}

View File

@@ -692,7 +692,7 @@ func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -775,7 +775,7 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}

View File

@@ -304,8 +304,8 @@ func TestGetFee(t *testing.T) {
// CryptocurrencyWithdrawalFee Basic
feeBuilder = setFeeBuilder()
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0005) || err != nil {
t.Errorf("Expected: %f, Received: %f", float64(0.0005), resp)
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00015) || err != nil {
t.Errorf("Expected: %f, Received: %f", float64(0.00015), resp)
t.Error(err)
}

View File

@@ -630,7 +630,7 @@ func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}
@@ -699,7 +699,7 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
}

View File

@@ -780,7 +780,7 @@ func (b *BTCMarkets) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detai
}
}
order.FilterOrdersByType(&resp, req.Type)
order.FilterOrdersByTickRange(&resp, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&resp, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&resp, req.Side)
return resp, nil
}

View File

@@ -821,7 +821,7 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -765,7 +765,7 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -818,7 +818,7 @@ func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Deta
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -928,7 +928,7 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
}
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -1034,7 +1034,7 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
}
}
order.FilterOrdersByTickRange(&allOrders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&allOrders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&allOrders, req.Side)
return allOrders, nil
}

View File

@@ -601,7 +601,7 @@ func (e *EXMO) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -652,7 +652,7 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -901,7 +901,7 @@ func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order
}
orderData, err := f.FetchOrderHistory(formattedPair.String(),
getOrdersRequest.StartTicks, getOrdersRequest.EndTicks, "")
getOrdersRequest.StartTime, getOrdersRequest.EndTime, "")
if err != nil {
return resp, err
}
@@ -938,8 +938,8 @@ func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order
resp = append(resp, tempResp)
}
triggerOrderData, err := f.GetTriggerOrderHistory(formattedPair.String(),
getOrdersRequest.StartTicks,
getOrdersRequest.EndTicks,
getOrdersRequest.StartTime,
getOrdersRequest.EndTime,
strings.ToLower(getOrdersRequest.Side.String()),
strings.ToLower(getOrdersRequest.Type.String()),
"")

View File

@@ -752,7 +752,7 @@ func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -798,7 +798,7 @@ func (g *Gateio) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -599,7 +599,7 @@ func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
@@ -624,7 +624,7 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
resp, err := g.GetTradeHistory(fpair.String(), req.StartTicks.Unix())
resp, err := g.GetTradeHistory(fpair.String(), req.StartTime.Unix())
if err != nil {
return nil, err
}
@@ -660,7 +660,7 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -719,7 +719,7 @@ func (h *HitBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -769,7 +769,7 @@ func (h *HitBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}

View File

@@ -1384,7 +1384,7 @@ func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
}
order.FilterOrdersByType(&orders, req.Type)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}
@@ -1435,7 +1435,7 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
for x := range req.Pairs {
var currentPage int64 = 0
for done := false; !done; {
orderHistory, err := h.GetSwapOrderHistory(req.Pairs[x], "all", "all", []order.Status{order.AnyStatus}, int64(req.EndTicks.Sub(req.StartTicks).Hours()/24), currentPage, 50)
orderHistory, err := h.GetSwapOrderHistory(req.Pairs[x], "all", "all", []order.Status{order.AnyStatus}, int64(req.EndTime.Sub(req.StartTime).Hours()/24), currentPage, 50)
if err != nil {
return orders, err
}
@@ -1479,7 +1479,7 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
for x := range req.Pairs {
var currentPage int64 = 0
for done := false; !done; {
openOrders, err := h.FGetOrderHistory(req.Pairs[x], "", "all", "all", "limit", []order.Status{order.AnyStatus}, int64(req.EndTicks.Sub(req.StartTicks).Hours()/24), currentPage, 50)
openOrders, err := h.FGetOrderHistory(req.Pairs[x], "", "all", "all", "limit", []order.Status{order.AnyStatus}, int64(req.EndTime.Sub(req.StartTime).Hours()/24), currentPage, 50)
if err != nil {
return orders, err
}
@@ -1528,7 +1528,7 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
}
}
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}

View File

@@ -553,7 +553,7 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
@@ -621,7 +621,7 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil

View File

@@ -1124,7 +1124,7 @@ func (k *Kraken) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
default:
return nil, fmt.Errorf("%s assetType not supported", req.AssetType)
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
return orders, nil
@@ -1140,11 +1140,11 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]or
switch getOrdersRequest.AssetType {
case asset.Spot:
req := GetClosedOrdersOptions{}
if getOrdersRequest.StartTicks.Unix() > 0 {
req.Start = strconv.FormatInt(getOrdersRequest.StartTicks.Unix(), 10)
if getOrdersRequest.StartTime.Unix() > 0 {
req.Start = strconv.FormatInt(getOrdersRequest.StartTime.Unix(), 10)
}
if getOrdersRequest.EndTicks.Unix() > 0 {
req.End = strconv.FormatInt(getOrdersRequest.EndTicks.Unix(), 10)
if getOrdersRequest.EndTime.Unix() > 0 {
req.End = strconv.FormatInt(getOrdersRequest.EndTime.Unix(), 10)
}
assetType := getOrdersRequest.AssetType

View File

@@ -582,7 +582,7 @@ func (l *LakeBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
@@ -630,7 +630,7 @@ func (l *LakeBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
order.FilterOrdersByCurrencies(&orders, req.Pairs)

View File

@@ -552,8 +552,8 @@ func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest
})
}
order.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks,
getOrdersRequest.EndTicks)
order.FilterOrdersByTimeRange(&orders, getOrdersRequest.StartTime,
getOrdersRequest.EndTime)
order.FilterOrdersBySide(&orders, getOrdersRequest.Side)
return orders, nil
@@ -638,8 +638,8 @@ func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest
})
}
order.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks,
getOrdersRequest.EndTicks)
order.FilterOrdersByTimeRange(&orders, getOrdersRequest.StartTime,
getOrdersRequest.EndTime)
order.FilterOrdersBySide(&orders, getOrdersRequest.Side)
return orders, nil

View File

@@ -203,7 +203,7 @@ func TestFilterOrdersBySide(t *testing.T) {
}
}
func TestFilterOrdersByTickRange(t *testing.T) {
func TestFilterOrdersByTimeRange(t *testing.T) {
t.Parallel()
var orders = []Detail{
@@ -218,25 +218,31 @@ func TestFilterOrdersByTickRange(t *testing.T) {
},
}
FilterOrdersByTickRange(&orders, time.Unix(0, 0), time.Unix(0, 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))
}
FilterOrdersByTickRange(&orders, time.Unix(100, 0), time.Unix(111, 0))
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))
}
FilterOrdersByTickRange(&orders, time.Unix(101, 0), time.Unix(111, 0))
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))
}
FilterOrdersByTickRange(&orders, time.Unix(200, 0), time.Unix(300, 0))
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) {
@@ -280,6 +286,11 @@ func TestFilterOrdersByCurrencies(t *testing.T) {
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) {

View File

@@ -205,11 +205,11 @@ type TradeHistory struct {
// GetOrdersRequest used for GetOrderHistory and GetOpenOrders wrapper functions
type GetOrdersRequest struct {
Type Type
Side Side
StartTicks time.Time
EndTicks time.Time
OrderID string
Type Type
Side Side
StartTime time.Time
EndTime time.Time
OrderID string
// Currencies Empty array = all currencies. Some endpoints only support
// singular currency enquiries
Pairs currency.Pairs

View File

@@ -427,20 +427,20 @@ func FilterOrdersByType(orders *[]Detail, orderType Type) {
*orders = filteredOrders
}
// FilterOrdersByTickRange removes any OrderDetails outside of the tick range
func FilterOrdersByTickRange(orders *[]Detail, startTicks, endTicks time.Time) {
if startTicks.IsZero() ||
endTicks.IsZero() ||
startTicks.Unix() == 0 ||
endTicks.Unix() == 0 ||
endTicks.Before(startTicks) {
// FilterOrdersByTimeRange removes any OrderDetails outside of the time range
func FilterOrdersByTimeRange(orders *[]Detail, startTime, endTime time.Time) {
if startTime.IsZero() ||
endTime.IsZero() ||
startTime.Unix() == 0 ||
endTime.Unix() == 0 ||
endTime.Before(startTime) {
return
}
var filteredOrders []Detail
for i := range *orders {
if (*orders)[i].Date.Unix() >= startTicks.Unix() &&
(*orders)[i].Date.Unix() <= endTicks.Unix() {
if ((*orders)[i].Date.Unix() >= startTime.Unix() && (*orders)[i].Date.Unix() <= endTime.Unix()) ||
(*orders)[i].Date.IsZero() {
filteredOrders = append(filteredOrders, (*orders)[i])
}
}
@@ -455,6 +455,9 @@ func FilterOrdersByCurrencies(orders *[]Detail, currencies []currency.Pair) {
if len(currencies) == 0 {
return
}
if len(currencies) == 1 && currencies[0].IsEmpty() {
return
}
var filteredOrders []Detail
for i := range *orders {

View File

@@ -767,7 +767,7 @@ func (p *Poloniex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
}
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersByCurrencies(&orders, req.Pairs)
order.FilterOrdersBySide(&orders, req.Side)
@@ -781,8 +781,8 @@ func (p *Poloniex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
resp, err := p.GetAuthenticatedTradeHistory(req.StartTicks.Unix(),
req.EndTicks.Unix(),
resp, err := p.GetAuthenticatedTradeHistory(req.StartTime.Unix(),
req.EndTime.Unix(),
10000)
if err != nil {
return nil, err

View File

@@ -347,8 +347,8 @@ func TestGetOrderHistory(t *testing.T) {
AssetType: asset.Spot,
Pairs: []currency.Pair{currency.NewPair(currency.LTC,
currency.BTC)},
StartTicks: time.Unix(0, 0),
EndTicks: time.Unix(math.MaxInt64, 0),
StartTime: time.Unix(0, 0),
EndTime: time.Unix(math.MaxInt64, 0),
}
_, err := y.GetOrderHistory(&getOrdersRequest)

View File

@@ -577,7 +577,7 @@ func (y *Yobit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
}
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -598,8 +598,8 @@ func (y *Yobit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
resp, err := y.GetTradeHistory(0,
10000,
math.MaxInt64,
req.StartTicks.Unix(),
req.EndTicks.Unix(),
req.StartTime.Unix(),
req.EndTime.Unix(),
"DESC",
fpair.String())
if err != nil {

View File

@@ -724,7 +724,7 @@ func (z *ZB) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
order.FilterOrdersBySide(&orders, req.Side)
return orders, nil
}
@@ -807,7 +807,7 @@ func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error
})
}
order.FilterOrdersByTickRange(&orders, req.StartTicks, req.EndTicks)
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)
return orders, nil
}

File diff suppressed because it is too large Load Diff

View File

@@ -317,6 +317,8 @@ message GetOrdersRequest {
string exchange = 1;
string asset_type = 2;
CurrencyPair pair = 3;
string start_date = 4;
string end_date = 5;
}
message GetOrdersResponse {
@@ -327,6 +329,7 @@ message GetOrderRequest {
string exchange = 1;
string order_id = 2;
CurrencyPair pair = 3;
string asset = 4;
}
message SubmitOrderRequest {

View File

@@ -3488,6 +3488,9 @@
},
"pair": {
"$ref": "#/definitions/gctrpcCurrencyPair"
},
"asset": {
"type": "string"
}
}
},
@@ -3527,6 +3530,12 @@
},
"pair": {
"$ref": "#/definitions/gctrpcCurrencyPair"
},
"start_date": {
"type": "string"
},
"end_date": {
"type": "string"
}
}
},

View File

@@ -11,6 +11,7 @@ import (
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// GoCryptoTraderClient is the client API for GoCryptoTrader service.
@@ -269,7 +270,7 @@ func (c *goCryptoTraderClient) UpdateAccountInfo(ctx context.Context, in *GetAcc
}
func (c *goCryptoTraderClient) GetAccountInfoStream(ctx context.Context, in *GetAccountInfoRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetAccountInfoStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[0], "/gctrpc.GoCryptoTrader/GetAccountInfoStream", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[0], "/gctrpc.GoCryptoTrader/GetAccountInfoStream", opts...)
if err != nil {
return nil, err
}
@@ -562,7 +563,7 @@ func (c *goCryptoTraderClient) SetExchangePair(ctx context.Context, in *SetExcha
}
func (c *goCryptoTraderClient) GetOrderbookStream(ctx context.Context, in *GetOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetOrderbookStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[1], "/gctrpc.GoCryptoTrader/GetOrderbookStream", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[1], "/gctrpc.GoCryptoTrader/GetOrderbookStream", opts...)
if err != nil {
return nil, err
}
@@ -594,7 +595,7 @@ func (x *goCryptoTraderGetOrderbookStreamClient) Recv() (*OrderbookResponse, err
}
func (c *goCryptoTraderClient) GetExchangeOrderbookStream(ctx context.Context, in *GetExchangeOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeOrderbookStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[2], "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[2], "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream", opts...)
if err != nil {
return nil, err
}
@@ -626,7 +627,7 @@ func (x *goCryptoTraderGetExchangeOrderbookStreamClient) Recv() (*OrderbookRespo
}
func (c *goCryptoTraderClient) GetTickerStream(ctx context.Context, in *GetTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetTickerStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[3], "/gctrpc.GoCryptoTrader/GetTickerStream", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[3], "/gctrpc.GoCryptoTrader/GetTickerStream", opts...)
if err != nil {
return nil, err
}
@@ -658,7 +659,7 @@ func (x *goCryptoTraderGetTickerStreamClient) Recv() (*TickerResponse, error) {
}
func (c *goCryptoTraderClient) GetExchangeTickerStream(ctx context.Context, in *GetExchangeTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeTickerStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[4], "/gctrpc.GoCryptoTrader/GetExchangeTickerStream", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[4], "/gctrpc.GoCryptoTrader/GetExchangeTickerStream", opts...)
if err != nil {
return nil, err
}
@@ -879,7 +880,7 @@ func (c *goCryptoTraderClient) GetRecentTrades(ctx context.Context, in *GetSaved
}
func (c *goCryptoTraderClient) GetHistoricTrades(ctx context.Context, in *GetSavedTradesRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetHistoricTradesClient, error) {
stream, err := c.cc.NewStream(ctx, &_GoCryptoTrader_serviceDesc.Streams[5], "/gctrpc.GoCryptoTrader/GetHistoricTrades", opts...)
stream, err := c.cc.NewStream(ctx, &GoCryptoTrader_ServiceDesc.Streams[5], "/gctrpc.GoCryptoTrader/GetHistoricTrades", opts...)
if err != nil {
return nil, err
}
@@ -1291,8 +1292,8 @@ type UnsafeGoCryptoTraderServer interface {
mustEmbedUnimplementedGoCryptoTraderServer()
}
func RegisterGoCryptoTraderServer(s *grpc.Server, srv GoCryptoTraderServer) {
s.RegisterService(&_GoCryptoTrader_serviceDesc, srv)
func RegisterGoCryptoTraderServer(s grpc.ServiceRegistrar, srv GoCryptoTraderServer) {
s.RegisterService(&GoCryptoTrader_ServiceDesc, srv)
}
func _GoCryptoTrader_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
@@ -2735,7 +2736,10 @@ func _GoCryptoTrader_SetExchangeTradeProcessing_Handler(srv interface{}, ctx con
return interceptor(ctx, in, info, handler)
}
var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{
// GoCryptoTrader_ServiceDesc is the grpc.ServiceDesc for GoCryptoTrader service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var GoCryptoTrader_ServiceDesc = grpc.ServiceDesc{
ServiceName: "gctrpc.GoCryptoTrader",
HandlerType: (*GoCryptoTraderServer)(nil),
Methods: []grpc.MethodDesc{