From ba0010936d1fe506c21a9f6ed8874dbc714c7174 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Thu, 21 Oct 2021 20:56:30 -0700 Subject: [PATCH 01/29] refactor private endpoints to extract a query interface to be able to omit certain parameters --- go.mod | 11 ++- go.sum | 87 ++++++++++++++++++++ newton.go | 120 ++++++--------------------- newton_test.go | 160 ++++++++++++++++++++++++------------ query/actions.go | 37 +++++++++ query/actions_test.go | 57 +++++++++++++ query/balances.go | 15 ++++ query/balances_test.go | 39 +++++++++ query/common.go | 45 ++++++++++ query/open_orders.go | 32 ++++++++ query/open_orders_test.go | 52 ++++++++++++ query/order_history.go | 42 ++++++++++ query/order_history_test.go | 61 ++++++++++++++ 13 files changed, 612 insertions(+), 146 deletions(-) create mode 100644 go.sum create mode 100644 query/actions.go create mode 100644 query/actions_test.go create mode 100644 query/balances.go create mode 100644 query/balances_test.go create mode 100644 query/common.go create mode 100644 query/open_orders.go create mode 100644 query/open_orders_test.go create mode 100644 query/order_history.go create mode 100644 query/order_history_test.go diff --git a/go.mod b/go.mod index c8b25d9..afc5c81 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,12 @@ module github.com/dhiaayachi/go-newton-co -go 1.15 +go 1.17 + +require ( + github.com/golang/protobuf v1.5.2 // indirect + github.com/onsi/gomega v1.16.0 // indirect + golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..ad2e821 --- /dev/null +++ b/go.sum @@ -0,0 +1,87 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/newton.go b/newton.go index 02b6ef1..2b6c35d 100644 --- a/newton.go +++ b/newton.go @@ -14,28 +14,17 @@ import ( "strconv" "strings" "time" + + "github.com/dhiaayachi/go-newton-co/query" ) const baseUrl = "https://api.newton.co/v1" -type ActionType string - -const ( - DEPOSIT ActionType = "DEPOSIT" - WITHDRAWAL ActionType = "WITHDRAWAL" - TRANSACT ActionType = "TRANSACT" -) - type Newton struct { clientId string clientSecret string } -type Args struct { - Key string - Value string -} - type NewOrderReq struct { OrderType string `json:"order_type"` TimeInForce string `json:"time_in_force"` @@ -90,7 +79,7 @@ type OpenOrdersResp struct { } } -type OrdersHistoryResp struct { +type OrderHistoryResp struct { OrdersHistory []struct { OrderID string `json:"order_id"` Symbol string `json:"symbol"` @@ -175,7 +164,7 @@ func (n *Newton) sign(req *http.Request) error { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) doPublicQuery(path string, method string, args []Args, body string) (*http.Response, error) { +func (n *Newton) doPublicQuery(path string, method string, args []query.Parameter, body string) (*http.Response, error) { url := baseUrl + path req, _ := http.NewRequest(method, url, nil) @@ -198,7 +187,7 @@ func (n *Newton) doPublicQuery(path string, method string, args []Args, body str } func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { - res, err := n.doPublicQuery("/order/tick-sizes", http.MethodGet, []Args{}, "") + res, err := n.doPublicQuery("/order/tick-sizes", http.MethodGet, []query.Parameter{}, "") if err != nil { return nil, err } @@ -224,7 +213,7 @@ func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { } func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { - res, err := n.doPublicQuery("/order/maximums", http.MethodGet, []Args{}, "") + res, err := n.doPublicQuery("/order/maximums", http.MethodGet, []query.Parameter{}, "") if err != nil { return nil, err } @@ -250,7 +239,7 @@ func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { } func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { - res, err := n.doPublicQuery("/fees", http.MethodGet, []Args{}, "") + res, err := n.doPublicQuery("/fees", http.MethodGet, []query.Parameter{}, "") if err != nil { return nil, err } @@ -276,13 +265,13 @@ func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { } func (n *Newton) GetSymbols(baseAsset, quoteAsset string) (*GetSymbolsResp, error) { - args := []Args{} + args := []query.Parameter{} if baseAsset != "" { - args = append(args, Args{Key: "base_asset", Value: baseAsset}) + args = append(args, query.Parameter{Key: "base_asset", Value: baseAsset}) } if quoteAsset != "" { - args = append(args, Args{Key: "quote_asset", Value: quoteAsset}) + args = append(args, query.Parameter{Key: "quote_asset", Value: quoteAsset}) } res, err := n.doPublicQuery("/symbols", http.MethodGet, args, "") @@ -311,7 +300,7 @@ func (n *Newton) GetSymbols(baseAsset, quoteAsset string) (*GetSymbolsResp, erro } func (n *Newton) HealthCheck() error { - res, err := n.doPublicQuery("/symbols", http.MethodGet, []Args{}, "") + res, err := n.doPublicQuery("/symbols", http.MethodGet, []query.Parameter{}, "") if err != nil { return err } @@ -329,7 +318,7 @@ func (n *Newton) HealthCheck() error { } func (n *Newton) GetMinimumTradeAmount() (*GetMinTradeAmountsResp, error) { - res, err := n.doPublicQuery("/order/minimums", http.MethodGet, []Args{}, "") + res, err := n.doPublicQuery("/order/minimums", http.MethodGet, []query.Parameter{}, "") if err != nil { return nil, err } @@ -356,12 +345,12 @@ func (n *Newton) GetMinimumTradeAmount() (*GetMinTradeAmountsResp, error) { // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) doPrivateQuery(path string, method string, args []Args, body string) (*http.Response, error) { +func (n *Newton) doPrivateQuery(path string, method string, parameters []query.Parameter, body string) (*http.Response, error) { url := baseUrl + path req, _ := http.NewRequest(method, url, bytes.NewBuffer([]byte(body))) q := req.URL.Query() - for _, a := range args { + for _, a := range parameters { q.Add(a.Key, a.Value) } req.URL.RawQuery = q.Encode() @@ -377,13 +366,8 @@ func (n *Newton) doPrivateQuery(path string, method string, args []Args, body st return res, err } -func (n *Newton) Balances(asset string) (*BalancesResp, error) { - - a := make([]Args, 1) - - a[0].Key = "asset" - a[0].Value = asset - res, err := n.doPrivateQuery("/balances", http.MethodGet, a, "") +func (n *Newton) Balances(query *query.Balances) (*BalancesResp, error) { + res, err := n.doPrivateQuery("/balances", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err } @@ -408,26 +392,8 @@ func (n *Newton) Balances(asset string) (*BalancesResp, error) { return &b, nil } -func (n *Newton) Actions(actionType ActionType, limit int, offset int, startDate int64, endDate int64) (*ActionsResp, error) { - - a := make([]Args, 5) - - a[0].Key = "action_type" - a[0].Value = string(actionType) - - a[1].Key = "end_date" - a[1].Value = strconv.FormatInt(endDate, 10) - - a[2].Key = "limit" - a[2].Value = strconv.Itoa(limit) - - a[3].Key = "offset" - a[3].Value = strconv.Itoa(offset) - - a[4].Key = "start_date" - a[4].Value = strconv.FormatInt(startDate, 10) - - res, err := n.doPrivateQuery("/actions", http.MethodGet, a, "") +func (n *Newton) Actions(query *query.Actions) (*ActionsResp, error) { + res, err := n.doPrivateQuery("/actions", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err } @@ -451,29 +417,8 @@ func (n *Newton) Actions(actionType ActionType, limit int, offset int, startDate return &r, nil } -func (n *Newton) OrdersHistory(limit int, offset int, startDate int64, endDate int64, symbol string, timeInForce string) (*OrdersHistoryResp, error) { - - a := make([]Args, 10) - - a[1].Key = "end_date" - a[1].Value = strconv.FormatInt(endDate, 10) - - a[2].Key = "limit" - a[2].Value = strconv.Itoa(limit) - - a[3].Key = "offset" - a[3].Value = strconv.Itoa(offset) - - a[4].Key = "start_date" - a[4].Value = strconv.FormatInt(startDate, 10) - - a[5].Key = "symbol" - a[5].Value = symbol - - a[6].Key = "time_in_force" - a[6].Value = timeInForce - - res, err := n.doPrivateQuery("/order/history", http.MethodGet, a, "") +func (n *Newton) OrderHistory(query *query.OrderHistory) (*OrderHistoryResp, error) { + res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err } @@ -488,7 +433,7 @@ func (n *Newton) OrdersHistory(limit int, offset int, startDate int64, endDate i return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) } - var r OrdersHistoryResp + var r OrderHistoryResp err = json.Unmarshal(body, &r.OrdersHistory) if err != nil { return nil, err @@ -497,23 +442,8 @@ func (n *Newton) OrdersHistory(limit int, offset int, startDate int64, endDate i return &r, nil } -func (n *Newton) OpenOrders(limit int, offset int, symbol string, timeInForce string) (*OpenOrdersResp, error) { - - a := make([]Args, 10) - - a[1].Key = "limit" - a[1].Value = strconv.Itoa(limit) - - a[2].Key = "offset" - a[2].Value = strconv.Itoa(offset) - - a[3].Key = "symbol" - a[3].Value = symbol - - a[4].Key = "time_in_force" - a[4].Value = timeInForce - - res, err := n.doPrivateQuery("/order/history", http.MethodGet, a, "") +func (n *Newton) OpenOrders(query *query.OpenOrders) (*OpenOrdersResp, error) { + res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err } @@ -523,11 +453,13 @@ func (n *Newton) OpenOrders(limit int, offset int, symbol string, timeInForce st log.Printf("error:%s", err.Error()) } }() + + body, _ := ioutil.ReadAll(res.Body) if res.StatusCode != http.StatusOK { return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) } - body, _ := ioutil.ReadAll(res.Body) + var r OpenOrdersResp err = json.Unmarshal(body, &r.OpenOrders) diff --git a/newton_test.go b/newton_test.go index f622849..0640d22 100644 --- a/newton_test.go +++ b/newton_test.go @@ -4,6 +4,9 @@ import ( "os" "testing" "time" + + "github.com/dhiaayachi/go-newton-co/query" + "github.com/onsi/gomega" ) func getSecrets() (string, string) { @@ -13,113 +16,168 @@ func getSecrets() (string, string) { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// func TestGetTickSizes(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.GetTickSizes() + _, err := sut.GetTickSizes() - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } func TestGetMaximumTradeAmounts(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.GetMaximumTradeAmounts() + _, err := sut.GetMaximumTradeAmounts() - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } func TestGetApplicableFees(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.GetApplicableFees() + _, err := sut.GetApplicableFees() - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } func TestSymbolsNoQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.GetSymbols("", "") + _, err := sut.GetSymbols("", "") - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } func TestHealthCheck(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - err := n.HealthCheck() + err := sut.HealthCheck() - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } func TestGetMinTradeAmounts(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.GetMinimumTradeAmount() + _, err := sut.GetMinimumTradeAmount() - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// -func TestBalance(t *testing.T) { +func TestBalances(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.Balances("BTC") + q := &query.Balances{Asset: "BTC"} + _, err := sut.Balances(q) - if err != nil { - t.Error("test failed: " + err.Error()) - } + g.Expect(err).Should(gomega.BeNil()) } -func TestAction(t *testing.T) { +func TestBalancesNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.Actions(DEPOSIT, 1, 0, time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), time.Date(2020, 01, 02, 00, 00, 00, 00, time.Local).Unix()) + q := &query.Balances{Asset: query.NO_FILTER} + _, err := sut.Balances(q) + + g.Expect(err).Should(gomega.BeNil()) +} - if err != nil { - t.Error("test failed: " + err.Error()) +func TestActions(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + ClientId, ClientSecret := getSecrets() + sut := New(ClientId, ClientSecret) + + q := &query.Actions{ + ActionType: query.DEPOSIT, + Limit: 1, + Offset: 0, + StartDate: time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), + EndDate: time.Date(2020, 01, 02, 00, 00, 00, 00, time.Local).Unix(), } + + _, err := sut.Actions(q) + + g.Expect(err).Should(gomega.BeNil()) } -func TestOrderHistory(t *testing.T) { +func TestActionsNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) + + req := &query.Actions{ + ActionType: query.ActionType(query.NO_FILTER), + Limit: int(query.ANY), + Offset: int(query.ANY), + StartDate: int64(query.ANY), + EndDate: int64(query.ANY), + } - _, err := n.OrdersHistory(1, 0, time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), time.Date(2020, 01, 01, 01, 00, 00, 00, time.Local).Unix(), "", "") + _, err := sut.Actions(req) + + g.Expect(err).Should(gomega.BeNil()) +} - if err != nil { - t.Error("test failed: " + err.Error()) +func TestOrderHistory(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + ClientId, ClientSecret := getSecrets() + sut := New(ClientId, ClientSecret) + + q := &query.OrderHistory{ + Limit: 1, + Offset: 0, + StartDate: time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), + EndDate: time.Date(2020, 01, 01, 01, 00, 00, 00, time.Local).Unix(), + Symbol: "BTC_USDC", + TimeInForce: "IOC", } + + _, err := sut.OrderHistory(q) + + g.Expect(err).Should(gomega.BeNil()) } func TestOpenOrders(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ClientId, ClientSecret := getSecrets() - n := New(ClientId, ClientSecret) + sut := New(ClientId, ClientSecret) - _, err := n.OpenOrders(1, 0, "", "") + q := &query.OpenOrders{ + Limit: 1, + Offset: 0, + Symbol: "BTC_USDC", + TimeInForce: "IOC"} - if err != nil { - t.Error("test failed: " + err.Error()) - } + _, err := sut.OpenOrders(q) + + g.Expect(err).Should(gomega.BeNil()) } diff --git a/query/actions.go b/query/actions.go new file mode 100644 index 0000000..9ead83c --- /dev/null +++ b/query/actions.go @@ -0,0 +1,37 @@ +package query + +import "strconv" + +type Actions struct { + ActionType ActionType + Limit int + Offset int + StartDate int64 + EndDate int64 +} + +func (arp Actions) GetParameters() []Parameter { + params := make([]Parameter, 0) + + if arp.ActionType != ActionType(NO_FILTER) { + params = append(params, Parameter{string(ActionTypeKey), string(arp.ActionType)}) + } + + if arp.Limit != int(ANY) { + params = append(params, Parameter{string(Limit), strconv.Itoa(arp.Limit)}) + } + + if arp.Offset != int(ANY) { + params = append(params, Parameter{string(Offset), strconv.Itoa(arp.Offset)}) + } + + if arp.StartDate != int64(ANY) { + params = append(params, Parameter{string(StartDate), strconv.FormatInt(arp.StartDate, 10)}) + } + + if arp.EndDate != int64(ANY) { + params = append(params, Parameter{string(EndDate), strconv.FormatInt(arp.EndDate, 10)}) + } + + return params +} diff --git a/query/actions_test.go b/query/actions_test.go new file mode 100644 index 0000000..cb06820 --- /dev/null +++ b/query/actions_test.go @@ -0,0 +1,57 @@ +package query_test + +import ( + "strconv" + "testing" + "time" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestActionsQueryNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Actions{ + query.ActionType(query.NO_FILTER), + int(query.ANY), + int(query.ANY), + int64(query.ANY), + int64(query.ANY), + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestActionsQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + actionType := query.DEPOSIT + limit := 1 + offset := 2 + startTime := time.Now().Unix() + endTime := startTime + 1 + + sut := &query.Actions{ + query.DEPOSIT, + limit, + offset, + startTime, + endTime, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(5)) + + g.Expect(parameters).Should(gomega.ContainElements( + gomega.BeEquivalentTo(query.Parameter{string(query.ActionTypeKey), string(actionType)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Limit), strconv.Itoa(limit)}) , + gomega.BeEquivalentTo(query.Parameter{string(query.Offset), strconv.Itoa(offset)}) , + gomega.BeEquivalentTo(query.Parameter{string(query.StartDate), strconv.FormatInt(startTime, 10)}) , + gomega.BeEquivalentTo(query.Parameter{string(query.EndDate), strconv.FormatInt(endTime, 10)}) , + )) +} diff --git a/query/balances.go b/query/balances.go new file mode 100644 index 0000000..8f15839 --- /dev/null +++ b/query/balances.go @@ -0,0 +1,15 @@ +package query + +type Balances struct { + Asset string +} + +func (b Balances) GetParameters() []Parameter { + params := make([]Parameter, 0) + + if b.Asset != "" { + params = append(params, Parameter{string(Asset), b.Asset}) + } + + return params +} diff --git a/query/balances_test.go b/query/balances_test.go new file mode 100644 index 0000000..9942f1a --- /dev/null +++ b/query/balances_test.go @@ -0,0 +1,39 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestBalancesQueryNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Balances{ + query.NO_FILTER, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestBalancesQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + asset := "BTC" + + sut := &query.Balances{ + asset, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(1)) + + g.Expect(parameters).Should(gomega.ContainElements( + gomega.BeEquivalentTo(query.Parameter{string(query.Asset), asset}), + )) +} diff --git a/query/common.go b/query/common.go new file mode 100644 index 0000000..ee636c4 --- /dev/null +++ b/query/common.go @@ -0,0 +1,45 @@ +package query + +type ActionType string + +const ( + DEPOSIT ActionType = "DEPOSIT" + WITHDRAWAL ActionType = "WITHDRAWAL" + TRANSACT ActionType = "TRANSACT" +) + +type QueryParameterKey string + +const ( + Asset QueryParameterKey = "asset" + ActionTypeKey QueryParameterKey = "action_type" + Limit QueryParameterKey = "limit" + Offset QueryParameterKey = "offset" + StartDate QueryParameterKey = "start_date" + EndDate QueryParameterKey = "end_date" + Symbol QueryParameterKey = "symbol" + TimeInForce QueryParameterKey = "time_in_force" +) + +type TimeInForceAllowedValue string + +const ( + NO_FILTER_VALUE TimeInForceAllowedValue = "" + IOC TimeInForceAllowedValue = "IOC" + GTC TimeInForceAllowedValue = "GTC" + GTD TimeInForceAllowedValue = "GTD" +) + +const ( + ANY int = -1 + NO_FILTER string = "" +) + +type Parameter struct { + Key string + Value string +} + +type Query interface { + Parameters() []Parameter +} diff --git a/query/open_orders.go b/query/open_orders.go new file mode 100644 index 0000000..656a504 --- /dev/null +++ b/query/open_orders.go @@ -0,0 +1,32 @@ +package query + +import "strconv" + +type OpenOrders struct { + Limit int + Offset int + Symbol string + TimeInForce TimeInForceAllowedValue +} + +func (oo OpenOrders) GetParameters() []Parameter { + params := make([]Parameter, 0) + + if oo.Limit != ANY { + params = append(params, Parameter{string(Limit), strconv.Itoa(oo.Limit)}) + } + + if oo.Offset != ANY { + params = append(params, Parameter{string(Offset), strconv.Itoa(oo.Offset)}) + } + + if oo.Symbol != NO_FILTER { + params = append(params, Parameter{string(Symbol), oo.Symbol}) + } + + if string(oo.TimeInForce) != NO_FILTER { + params = append(params, Parameter{string(TimeInForce), string(oo.TimeInForce)}) + } + + return params +} diff --git a/query/open_orders_test.go b/query/open_orders_test.go new file mode 100644 index 0000000..216a0e1 --- /dev/null +++ b/query/open_orders_test.go @@ -0,0 +1,52 @@ +package query_test + +import ( + "strconv" + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestOpenOrdersQueryNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OpenOrders{ + query.ANY, + query.ANY, + query.NO_FILTER, + query.NO_FILTER_VALUE, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestOpenOrdersQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + limit := 1 + offset := 0 + symbol := "BTC_USDC" + timeInForce := query.IOC + + sut := &query.OpenOrders{ + limit, + offset, + symbol, + timeInForce, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(4)) + + g.Expect(parameters).Should(gomega.ContainElements( + gomega.BeEquivalentTo(query.Parameter{string(query.Limit), strconv.Itoa(limit)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Offset), strconv.Itoa(offset)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Symbol), symbol}), + gomega.BeEquivalentTo(query.Parameter{string(query.TimeInForce), string(timeInForce)}), + )) +} diff --git a/query/order_history.go b/query/order_history.go new file mode 100644 index 0000000..5655076 --- /dev/null +++ b/query/order_history.go @@ -0,0 +1,42 @@ +package query + +import "strconv" + +type OrderHistory struct { + Limit int + Offset int + StartDate int64 + EndDate int64 + Symbol string + TimeInForce TimeInForceAllowedValue +} + +func (oh OrderHistory) GetParameters() []Parameter { + params := make([]Parameter, 0) + + if oh.Limit != ANY { + params = append(params, Parameter{string(Limit), strconv.Itoa(oh.Limit)}) + } + + if oh.Offset != ANY { + params = append(params, Parameter{string(Offset), strconv.Itoa(oh.Offset)}) + } + + if oh.StartDate != int64(ANY) { + params = append(params, Parameter{string(StartDate), strconv.Itoa(int(oh.StartDate))}) + } + + if oh.EndDate != int64(ANY) { + params = append(params, Parameter{string(EndDate), strconv.Itoa(int(oh.EndDate))}) + } + + if oh.Symbol != NO_FILTER { + params = append(params, Parameter{string(Symbol), oh.Symbol}) + } + + if string(oh.TimeInForce) != NO_FILTER { + params = append(params, Parameter{string(TimeInForce), string(oh.TimeInForce)}) + } + + return params +} diff --git a/query/order_history_test.go b/query/order_history_test.go new file mode 100644 index 0000000..d718be5 --- /dev/null +++ b/query/order_history_test.go @@ -0,0 +1,61 @@ +package query_test + +import ( + "strconv" + "testing" + "time" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestOrdersHistoryQueryNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OrderHistory{ + query.ANY, + query.ANY, + int64(query.ANY), + int64(query.ANY), + query.NO_FILTER, + query.NO_FILTER_VALUE, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestOrdersHistoryQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + limit := 1 + offset := 0 + startDate := time.Now().Unix() + endDate := startDate + 1 + symbol := "BTC_USDC" + timeInForce := query.IOC + + sut := &query.OrderHistory{ + limit, + offset, + startDate, + endDate, + symbol, + timeInForce, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(6)) + + g.Expect(parameters).Should(gomega.ContainElements( + gomega.BeEquivalentTo(query.Parameter{string(query.Limit), strconv.Itoa(limit)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Offset), strconv.Itoa(offset)}), + gomega.BeEquivalentTo(query.Parameter{string(query.StartDate), strconv.FormatInt(startDate, 10)}), + gomega.BeEquivalentTo(query.Parameter{string(query.EndDate), strconv.FormatInt(endDate, 10)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Symbol), symbol}), + gomega.BeEquivalentTo(query.Parameter{string(query.TimeInForce), string(timeInForce)}), + )) +} From 7e3ea233fc274b6deccfd1e26a59e7502a81492a Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Thu, 21 Oct 2021 21:24:11 -0700 Subject: [PATCH 02/29] implement quert for public api and pass query inteface to all private methods --- newton.go | 25 ++++++++----------------- newton_test.go | 27 ++++++++++++++++++++++++--- query/balances.go | 2 +- query/common.go | 4 +++- query/symbols.go | 19 +++++++++++++++++++ query/symbols_test.go | 43 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 98 insertions(+), 22 deletions(-) create mode 100644 query/symbols.go create mode 100644 query/symbols_test.go diff --git a/newton.go b/newton.go index 2b6c35d..7017da4 100644 --- a/newton.go +++ b/newton.go @@ -164,12 +164,12 @@ func (n *Newton) sign(req *http.Request) error { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) doPublicQuery(path string, method string, args []query.Parameter, body string) (*http.Response, error) { +func (n *Newton) doPublicQuery(path string, method string, parameters []query.Parameter, body string) (*http.Response, error) { url := baseUrl + path req, _ := http.NewRequest(method, url, nil) q := req.URL.Query() - for _, a := range args { + for _, a := range parameters { q.Add(a.Key, a.Value) } req.URL.RawQuery = q.Encode() @@ -264,17 +264,8 @@ func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { return &resp, nil } -func (n *Newton) GetSymbols(baseAsset, quoteAsset string) (*GetSymbolsResp, error) { - args := []query.Parameter{} - if baseAsset != "" { - args = append(args, query.Parameter{Key: "base_asset", Value: baseAsset}) - } - - if quoteAsset != "" { - args = append(args, query.Parameter{Key: "quote_asset", Value: quoteAsset}) - } - - res, err := n.doPublicQuery("/symbols", http.MethodGet, args, "") +func (n *Newton) GetSymbols(query query.Query) (*GetSymbolsResp, error) { + res, err := n.doPublicQuery("/symbols", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err } @@ -366,7 +357,7 @@ func (n *Newton) doPrivateQuery(path string, method string, parameters []query.P return res, err } -func (n *Newton) Balances(query *query.Balances) (*BalancesResp, error) { +func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { res, err := n.doPrivateQuery("/balances", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err @@ -392,7 +383,7 @@ func (n *Newton) Balances(query *query.Balances) (*BalancesResp, error) { return &b, nil } -func (n *Newton) Actions(query *query.Actions) (*ActionsResp, error) { +func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { res, err := n.doPrivateQuery("/actions", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err @@ -417,7 +408,7 @@ func (n *Newton) Actions(query *query.Actions) (*ActionsResp, error) { return &r, nil } -func (n *Newton) OrderHistory(query *query.OrderHistory) (*OrderHistoryResp, error) { +func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err @@ -442,7 +433,7 @@ func (n *Newton) OrderHistory(query *query.OrderHistory) (*OrderHistoryResp, err return &r, nil } -func (n *Newton) OpenOrders(query *query.OpenOrders) (*OpenOrdersResp, error) { +func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") if err != nil { return nil, err diff --git a/newton_test.go b/newton_test.go index 0640d22..1087657 100644 --- a/newton_test.go +++ b/newton_test.go @@ -54,7 +54,28 @@ func TestSymbolsNoQuery(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.GetSymbols("", "") + q := &query.Symbols{ + BaseAsset: query.NO_FILTER, + QuoteAsset: query.NO_FILTER, + } + + _, err := sut.GetSymbols(q) + + g.Expect(err).Should(gomega.BeNil()) +} + +func TestSymbolsWithQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + ClientId, ClientSecret := getSecrets() + sut := New(ClientId, ClientSecret) + + q := &query.Symbols{ + BaseAsset: "BTC", + QuoteAsset: "ETH", + } + + _, err := sut.GetSymbols(q) g.Expect(err).Should(gomega.BeNil()) } @@ -95,7 +116,7 @@ func TestBalances(t *testing.T) { g.Expect(err).Should(gomega.BeNil()) } -func TestBalancesNoFilter(t *testing.T) { +func TestBalancesNoQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) ClientId, ClientSecret := getSecrets() @@ -126,7 +147,7 @@ func TestActions(t *testing.T) { g.Expect(err).Should(gomega.BeNil()) } -func TestActionsNoFilter(t *testing.T) { +func TestActionsNoQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) ClientId, ClientSecret := getSecrets() diff --git a/query/balances.go b/query/balances.go index 8f15839..d9abc3f 100644 --- a/query/balances.go +++ b/query/balances.go @@ -7,7 +7,7 @@ type Balances struct { func (b Balances) GetParameters() []Parameter { params := make([]Parameter, 0) - if b.Asset != "" { + if b.Asset != NO_FILTER { params = append(params, Parameter{string(Asset), b.Asset}) } diff --git a/query/common.go b/query/common.go index ee636c4..3ef849b 100644 --- a/query/common.go +++ b/query/common.go @@ -19,6 +19,8 @@ const ( EndDate QueryParameterKey = "end_date" Symbol QueryParameterKey = "symbol" TimeInForce QueryParameterKey = "time_in_force" + BaseAsset = "base_asset" + QuoteAsset = "quote_asset" ) type TimeInForceAllowedValue string @@ -41,5 +43,5 @@ type Parameter struct { } type Query interface { - Parameters() []Parameter + GetParameters() []Parameter } diff --git a/query/symbols.go b/query/symbols.go new file mode 100644 index 0000000..4f0ecc5 --- /dev/null +++ b/query/symbols.go @@ -0,0 +1,19 @@ +package query + +type Symbols struct { + BaseAsset, QuoteAsset string +} + +func (s Symbols) GetParameters() []Parameter { + params := make([]Parameter, 0) + + if s.BaseAsset != NO_FILTER { + params = append(params, Parameter{string(BaseAsset), s.BaseAsset}) + } + + if s.QuoteAsset != NO_FILTER { + params = append(params, Parameter{string(QuoteAsset), s.QuoteAsset}) + } + + return params +} diff --git a/query/symbols_test.go b/query/symbols_test.go new file mode 100644 index 0000000..2f2e057 --- /dev/null +++ b/query/symbols_test.go @@ -0,0 +1,43 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestSymbolsQueryNoFilter(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Symbols{ + query.NO_FILTER, + query.NO_FILTER, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestSymbolsQuery(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + baseAsset := "BTC" + quoteAsset := "ETH" + + sut := &query.Symbols{ + baseAsset, + quoteAsset, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(2)) + + g.Expect(parameters).Should(gomega.ContainElements( + gomega.BeEquivalentTo(query.Parameter{string(query.BaseAsset), baseAsset}), + gomega.BeEquivalentTo(query.Parameter{string(query.QuoteAsset), quoteAsset}), + )) +} From 6606f34db6e5fdea1dec4b77182887a7139f2c44 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Thu, 21 Oct 2021 22:03:08 -0700 Subject: [PATCH 03/29] refactor to reduce code duplication --- newton.go | 214 +++++++++++++----------------------- newton_test.go | 1 + query/actions.go | 4 + query/actions_test.go | 14 +++ query/balances.go | 4 + query/balances_test.go | 10 ++ query/common.go | 1 + query/open_orders.go | 4 + query/open_orders_test.go | 13 +++ query/order_history.go | 4 + query/order_history_test.go | 15 +++ query/symbols.go | 4 + query/symbols_test.go | 11 ++ 13 files changed, 162 insertions(+), 137 deletions(-) diff --git a/newton.go b/newton.go index 7017da4..53f826c 100644 --- a/newton.go +++ b/newton.go @@ -162,23 +162,24 @@ func (n *Newton) sign(req *http.Request) error { return nil } -// Public API -/////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) doPublicQuery(path string, method string, parameters []query.Parameter, body string) (*http.Response, error) { +func (n *Newton) doQuery(path string, method string, parameters []query.Parameter, isPublic bool, body string) (*http.Response, error) { url := baseUrl + path - req, _ := http.NewRequest(method, url, nil) + req, _ := http.NewRequest(method, url, bytes.NewBuffer([]byte(body))) q := req.URL.Query() for _, a := range parameters { q.Add(a.Key, a.Value) } req.URL.RawQuery = q.Encode() if method != http.MethodGet { - _, err := req.Body.Read([]byte(body)) + req.Header.Add("content-type", "application/json") + } + + if !isPublic { + err := n.sign(req) if err != nil { return nil, err } - req.Header.Add("content-type", "application/json") } res, err := http.DefaultClient.Do(req) @@ -186,11 +187,7 @@ func (n *Newton) doPublicQuery(path string, method string, parameters []query.Pa return res, err } -func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { - res, err := n.doPublicQuery("/order/tick-sizes", http.MethodGet, []query.Parameter{}, "") - if err != nil { - return nil, err - } +func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { defer func() { err := res.Body.Close() if err != nil { @@ -201,7 +198,31 @@ func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) } - body, _ := ioutil.ReadAll(res.Body) + body, err := ioutil.ReadAll(res.Body) + + if err != nil { + return nil, err + } + + if res.StatusCode != http.StatusOK { + return nil, errors.New(fmt.Sprintf("request failed :: %d :: %s", res.StatusCode, body)) + } + + return body, nil +} + +// Public API +/////////////////////////////////////////////////////////////////////////////////////////////////// +func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { + res, err := n.doQuery("/order/tick-sizes", http.MethodGet, []query.Parameter{}, true, "") + if err != nil { + return nil, err + } + + body, err := n.parseResponse(res) + if err != nil { + return nil, err + } var resp GetTickSizesResp err = json.Unmarshal(body, &resp.Ticks) @@ -213,21 +234,15 @@ func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { } func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { - res, err := n.doPublicQuery("/order/maximums", http.MethodGet, []query.Parameter{}, "") + res, err := n.doQuery("/order/maximums", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) - } - body, _ := ioutil.ReadAll(res.Body) + body, err := n.parseResponse(res) + if err != nil { + return nil, err + } var resp GetMaxTradeAmountsResp err = json.Unmarshal(body, &resp.TradeAmounts) @@ -239,21 +254,15 @@ func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { } func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { - res, err := n.doPublicQuery("/fees", http.MethodGet, []query.Parameter{}, "") + res, err := n.doQuery("/fees", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) - } - body, _ := ioutil.ReadAll(res.Body) + body, err := n.parseResponse(res) + if err != nil { + return nil, err + } var resp GetApplicableFeesResp err = json.Unmarshal(body, &resp.Fees) @@ -265,21 +274,15 @@ func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { } func (n *Newton) GetSymbols(query query.Query) (*GetSymbolsResp, error) { - res, err := n.doPublicQuery("/symbols", http.MethodGet, query.GetParameters(), "") + res, err := n.doQuery("/symbols", http.MethodGet, query.GetParameters(), true, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) - } - body, _ := ioutil.ReadAll(res.Body) + body, err := n.parseResponse(res) + if err != nil { + return nil, err + } var resp GetSymbolsResp err = json.Unmarshal(body, &resp.Symbols) @@ -291,16 +294,11 @@ func (n *Newton) GetSymbols(query query.Query) (*GetSymbolsResp, error) { } func (n *Newton) HealthCheck() error { - res, err := n.doPublicQuery("/symbols", http.MethodGet, []query.Parameter{}, "") + res, err := n.doQuery("/symbols", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() + if res.StatusCode != http.StatusOK { return errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) } @@ -309,21 +307,15 @@ func (n *Newton) HealthCheck() error { } func (n *Newton) GetMinimumTradeAmount() (*GetMinTradeAmountsResp, error) { - res, err := n.doPublicQuery("/order/minimums", http.MethodGet, []query.Parameter{}, "") + res, err := n.doQuery("/order/minimums", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) - } - body, _ := ioutil.ReadAll(res.Body) + body, err := n.parseResponse(res) + if err != nil { + return nil, err + } var resp GetMinTradeAmountsResp err = json.Unmarshal(body, &resp.TradeAmounts) @@ -336,43 +328,16 @@ func (n *Newton) GetMinimumTradeAmount() (*GetMinTradeAmountsResp, error) { // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) doPrivateQuery(path string, method string, parameters []query.Parameter, body string) (*http.Response, error) { - url := baseUrl + path - - req, _ := http.NewRequest(method, url, bytes.NewBuffer([]byte(body))) - q := req.URL.Query() - for _, a := range parameters { - q.Add(a.Key, a.Value) - } - req.URL.RawQuery = q.Encode() - if method != http.MethodGet { - req.Header.Add("content-type", "application/json") - } - err := n.sign(req) +func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { + res, err := n.doQuery("/balances", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } - res, err := http.DefaultClient.Do(req) - return res, err -} - -func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { - res, err := n.doPrivateQuery("/balances", http.MethodGet, query.GetParameters(), "") + body, err := n.parseResponse(res) if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) - } - - body, _ := ioutil.ReadAll(res.Body) var b BalancesResp err = json.Unmarshal(body, &b.Balances) @@ -384,19 +349,14 @@ func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { } func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { - res, err := n.doPrivateQuery("/actions", http.MethodGet, query.GetParameters(), "") + res, err := n.doQuery("/actions", http.MethodGet, query.GetParameters(), false, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - body, _ := ioutil.ReadAll(res.Body) - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) + + body, err := n.parseResponse(res) + if err != nil { + return nil, err } var r ActionsResp @@ -409,19 +369,14 @@ func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { } func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { - res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") + res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), false, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - body, _ := ioutil.ReadAll(res.Body) - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) + + body, err := n.parseResponse(res) + if err != nil { + return nil, err } var r OrderHistoryResp @@ -434,24 +389,16 @@ func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { } func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { - res, err := n.doPrivateQuery("/order/history", http.MethodGet, query.GetParameters(), "") + res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), false, "") if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - body, _ := ioutil.ReadAll(res.Body) - if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) + body, err := n.parseResponse(res) + if err != nil { + return nil, err } - - var r OpenOrdersResp err = json.Unmarshal(body, &r.OpenOrders) if err != nil { @@ -470,23 +417,16 @@ func (n *Newton) NewOrder(orderType string, timeInForce string, side string, sym return nil, err } - res, err := n.doPrivateQuery("/order/new", http.MethodPost, nil, string(b)) + res, err := n.doQuery("/order/new", http.MethodPost, nil, false, string(b)) if err != nil { return nil, err } - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - body, _ := ioutil.ReadAll(res.Body) - return nil, errors.New(fmt.Sprintf("request failed :: %d %s", res.StatusCode, body)) + + body, err := n.parseResponse(res) + if err != nil { + return nil, err } - body, _ := ioutil.ReadAll(res.Body) - var r OpenOrdersResp err = json.Unmarshal(body, &r.OpenOrders) if err != nil { diff --git a/newton_test.go b/newton_test.go index 1087657..3282f84 100644 --- a/newton_test.go +++ b/newton_test.go @@ -13,6 +13,7 @@ func getSecrets() (string, string) { return os.Getenv("CLIENT_ID"), os.Getenv("CLIENT_SECRET") } + // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// func TestGetTickSizes(t *testing.T) { diff --git a/query/actions.go b/query/actions.go index 9ead83c..6235e26 100644 --- a/query/actions.go +++ b/query/actions.go @@ -35,3 +35,7 @@ func (arp Actions) GetParameters() []Parameter { return params } + +func (arp Actions) IsPublic() bool { + return false +} diff --git a/query/actions_test.go b/query/actions_test.go index cb06820..d707c12 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -55,3 +55,17 @@ func TestActionsQuery(t *testing.T) { gomega.BeEquivalentTo(query.Parameter{string(query.EndDate), strconv.FormatInt(endTime, 10)}) , )) } + +func TestActionsIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Actions{ + query.ActionType(query.NO_FILTER), + int(query.ANY), + int(query.ANY), + int64(query.ANY), + int64(query.ANY), + } + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/balances.go b/query/balances.go index d9abc3f..508ee53 100644 --- a/query/balances.go +++ b/query/balances.go @@ -13,3 +13,7 @@ func (b Balances) GetParameters() []Parameter { return params } + +func (b Balances) IsPublic() bool { + return false +} diff --git a/query/balances_test.go b/query/balances_test.go index 9942f1a..c346c47 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -37,3 +37,13 @@ func TestBalancesQuery(t *testing.T) { gomega.BeEquivalentTo(query.Parameter{string(query.Asset), asset}), )) } + +func TestBalancesIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Balances{ + query.NO_FILTER, + } + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/common.go b/query/common.go index 3ef849b..d3e3edf 100644 --- a/query/common.go +++ b/query/common.go @@ -44,4 +44,5 @@ type Parameter struct { type Query interface { GetParameters() []Parameter + IsPublic() bool } diff --git a/query/open_orders.go b/query/open_orders.go index 656a504..48fa3e5 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -30,3 +30,7 @@ func (oo OpenOrders) GetParameters() []Parameter { return params } + +func (oo OpenOrders) IsPublic() bool { + return false +} diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 216a0e1..75eac43 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -50,3 +50,16 @@ func TestOpenOrdersQuery(t *testing.T) { gomega.BeEquivalentTo(query.Parameter{string(query.TimeInForce), string(timeInForce)}), )) } + +func TestOpenOrdersIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OpenOrders{ + query.ANY, + query.ANY, + query.NO_FILTER, + query.NO_FILTER_VALUE, + } + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/order_history.go b/query/order_history.go index 5655076..8795053 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -40,3 +40,7 @@ func (oh OrderHistory) GetParameters() []Parameter { return params } + +func (oh OrderHistory) IsPublic() bool { + return false +} diff --git a/query/order_history_test.go b/query/order_history_test.go index d718be5..c7e8e9b 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -59,3 +59,18 @@ func TestOrdersHistoryQuery(t *testing.T) { gomega.BeEquivalentTo(query.Parameter{string(query.TimeInForce), string(timeInForce)}), )) } + +func TestOrderHistoryIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OrderHistory{ + query.ANY, + query.ANY, + int64(query.ANY), + int64(query.ANY), + query.NO_FILTER, + query.NO_FILTER_VALUE, + } + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/symbols.go b/query/symbols.go index 4f0ecc5..9e33b0d 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -17,3 +17,7 @@ func (s Symbols) GetParameters() []Parameter { return params } + +func (s Symbols) IsPublic() bool { + return true +} diff --git a/query/symbols_test.go b/query/symbols_test.go index 2f2e057..10fdc0a 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -41,3 +41,14 @@ func TestSymbolsQuery(t *testing.T) { gomega.BeEquivalentTo(query.Parameter{string(query.QuoteAsset), quoteAsset}), )) } + +func TestSymbolsIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Symbols{ + query.NO_FILTER, + query.NO_FILTER, + } + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From c7ecc9852e2fb86943516726fb43f98f39edda93 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 20:48:56 -0700 Subject: [PATCH 04/29] fix warnings about printing errors --- newton.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/newton.go b/newton.go index 53f826c..9aafcb8 100644 --- a/newton.go +++ b/newton.go @@ -6,7 +6,6 @@ import ( "crypto/sha256" "encoding/base64" "encoding/json" - "errors" "fmt" "io/ioutil" "log" @@ -195,7 +194,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { } }() if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) + return nil, fmt.Errorf("request failed :: %d", res.StatusCode) } body, err := ioutil.ReadAll(res.Body) @@ -205,7 +204,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { } if res.StatusCode != http.StatusOK { - return nil, errors.New(fmt.Sprintf("request failed :: %d :: %s", res.StatusCode, body)) + return nil, fmt.Errorf("request failed :: %d :: %s", res.StatusCode, body) } return body, nil @@ -300,7 +299,7 @@ func (n *Newton) HealthCheck() error { } if res.StatusCode != http.StatusOK { - return errors.New(fmt.Sprintf("request failed :: %d", res.StatusCode)) + return fmt.Errorf("request failed :: %d", res.StatusCode) } return nil From 9391f4d38fc9422ca7f88eca6cfb1b5bde919bdb Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 20:51:13 -0700 Subject: [PATCH 05/29] correct endpoints for OpenOrders and HealthCheck --- newton_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/newton_test.go b/newton_test.go index 3282f84..4bf4ba5 100644 --- a/newton_test.go +++ b/newton_test.go @@ -1,7 +1,6 @@ package newton import ( - "os" "testing" "time" @@ -10,7 +9,7 @@ import ( ) func getSecrets() (string, string) { - return os.Getenv("CLIENT_ID"), os.Getenv("CLIENT_SECRET") + return "0198ab98-0475-437e-a4e6-5594398e5562", "220eeda0-e216-45f2-9d3b-e52b1ea90e7b" } From 916a89c4ed20b1a871dc1f668f28d3b54759f8e0 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 20:52:15 -0700 Subject: [PATCH 06/29] remove "Get" prefixes from the API for consistency --- newton.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/newton.go b/newton.go index 9aafcb8..4cc007a 100644 --- a/newton.go +++ b/newton.go @@ -212,7 +212,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { +func (n *Newton) TickSizes() (*GetTickSizesResp, error) { res, err := n.doQuery("/order/tick-sizes", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err @@ -232,7 +232,7 @@ func (n *Newton) GetTickSizes() (*GetTickSizesResp, error) { return &resp, nil } -func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { +func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { res, err := n.doQuery("/order/maximums", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err @@ -252,7 +252,7 @@ func (n *Newton) GetMaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { return &resp, nil } -func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { +func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { res, err := n.doQuery("/fees", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err @@ -272,7 +272,7 @@ func (n *Newton) GetApplicableFees() (*GetApplicableFeesResp, error) { return &resp, nil } -func (n *Newton) GetSymbols(query query.Query) (*GetSymbolsResp, error) { +func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { res, err := n.doQuery("/symbols", http.MethodGet, query.GetParameters(), true, "") if err != nil { return nil, err @@ -293,7 +293,7 @@ func (n *Newton) GetSymbols(query query.Query) (*GetSymbolsResp, error) { } func (n *Newton) HealthCheck() error { - res, err := n.doQuery("/symbols", http.MethodGet, []query.Parameter{}, true, "") + res, err := n.doQuery("/health-check", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return err } @@ -305,7 +305,7 @@ func (n *Newton) HealthCheck() error { return nil } -func (n *Newton) GetMinimumTradeAmount() (*GetMinTradeAmountsResp, error) { +func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { res, err := n.doQuery("/order/minimums", http.MethodGet, []query.Parameter{}, true, "") if err != nil { return nil, err From d525d4e1422c4d5be996feb115c7c8766a2597c3 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 20:57:22 -0700 Subject: [PATCH 07/29] implement TickSizes query --- newton.go | 3 ++- query/tick_sizes.go | 12 ++++++++++++ query/tick_sizes_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 query/tick_sizes.go create mode 100644 query/tick_sizes_test.go diff --git a/newton.go b/newton.go index 4cc007a..d92effc 100644 --- a/newton.go +++ b/newton.go @@ -213,7 +213,8 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// func (n *Newton) TickSizes() (*GetTickSizesResp, error) { - res, err := n.doQuery("/order/tick-sizes", http.MethodGet, []query.Parameter{}, true, "") + query := &query.TickSizes{} + res, err := n.doQuery("/order/tick-sizes", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } diff --git a/query/tick_sizes.go b/query/tick_sizes.go new file mode 100644 index 0000000..f13e67d --- /dev/null +++ b/query/tick_sizes.go @@ -0,0 +1,12 @@ +package query + +type TickSizes struct { +} + +func (ts TickSizes) GetParameters() []Parameter { + return []Parameter{} +} + +func (ts TickSizes) IsPublic() bool { + return true +} diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go new file mode 100644 index 0000000..3be7dd9 --- /dev/null +++ b/query/tick_sizes_test.go @@ -0,0 +1,27 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestTickSizesGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestTickSizesIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From 788fcae2d1d047e8bf13ad5e06fed45eb0802ff2 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 20:59:27 -0700 Subject: [PATCH 08/29] rename query get parameter unit tests --- query/actions_test.go | 4 ++-- query/balances_test.go | 4 ++-- query/open_orders_test.go | 4 ++-- query/order_history_test.go | 4 ++-- query/symbols_test.go | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/query/actions_test.go b/query/actions_test.go index d707c12..7ecd5a9 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -10,7 +10,7 @@ import ( "github.com/onsi/gomega" ) -func TestActionsQueryNoFilter(t *testing.T) { +func TestActionsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.Actions{ @@ -26,7 +26,7 @@ func TestActionsQueryNoFilter(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } -func TestActionsQuery(t *testing.T) { +func TestActionsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) actionType := query.DEPOSIT diff --git a/query/balances_test.go b/query/balances_test.go index c346c47..4b0d5c8 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -8,7 +8,7 @@ import ( "github.com/onsi/gomega" ) -func TestBalancesQueryNoFilter(t *testing.T) { +func TestBalancesGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.Balances{ @@ -20,7 +20,7 @@ func TestBalancesQueryNoFilter(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } -func TestBalancesQuery(t *testing.T) { +func TestBalancesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) asset := "BTC" diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 75eac43..97d4979 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -9,7 +9,7 @@ import ( "github.com/onsi/gomega" ) -func TestOpenOrdersQueryNoFilter(t *testing.T) { +func TestOpenOrdersGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.OpenOrders{ @@ -24,7 +24,7 @@ func TestOpenOrdersQueryNoFilter(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } -func TestOpenOrdersQuery(t *testing.T) { +func TestOpenOrdersGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) limit := 1 diff --git a/query/order_history_test.go b/query/order_history_test.go index c7e8e9b..672a9ae 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -10,7 +10,7 @@ import ( "github.com/onsi/gomega" ) -func TestOrdersHistoryQueryNoFilter(t *testing.T) { +func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.OrderHistory{ @@ -27,7 +27,7 @@ func TestOrdersHistoryQueryNoFilter(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } -func TestOrdersHistoryQuery(t *testing.T) { +func TestOrdersHistoryGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) limit := 1 diff --git a/query/symbols_test.go b/query/symbols_test.go index 10fdc0a..67adcfc 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -8,7 +8,7 @@ import ( "github.com/onsi/gomega" ) -func TestSymbolsQueryNoFilter(t *testing.T) { +func TestSymbolsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.Symbols{ @@ -21,7 +21,7 @@ func TestSymbolsQueryNoFilter(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } -func TestSymbolsQuery(t *testing.T) { +func TestSymbolsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) baseAsset := "BTC" From a50216a21fa0b02ecb9d904101edcb35e1c4260f Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 21:04:29 -0700 Subject: [PATCH 09/29] implement maximum trade amounts query --- newton.go | 3 ++- query/maximum_trade_amounts.go | 12 ++++++++++++ query/maximum_trade_amounts_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 query/maximum_trade_amounts.go create mode 100644 query/maximum_trade_amounts_test.go diff --git a/newton.go b/newton.go index d92effc..8a35748 100644 --- a/newton.go +++ b/newton.go @@ -234,7 +234,8 @@ func (n *Newton) TickSizes() (*GetTickSizesResp, error) { } func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { - res, err := n.doQuery("/order/maximums", http.MethodGet, []query.Parameter{}, true, "") + query := &query.MaximumTradeAmounts{} + res, err := n.doQuery("/order/maximums", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go new file mode 100644 index 0000000..7394400 --- /dev/null +++ b/query/maximum_trade_amounts.go @@ -0,0 +1,12 @@ +package query + +type MaximumTradeAmounts struct { +} + +func (mta MaximumTradeAmounts) GetParameters() []Parameter { + return []Parameter{} +} + +func (mta MaximumTradeAmounts) IsPublic() bool { + return true +} diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go new file mode 100644 index 0000000..13b50bf --- /dev/null +++ b/query/maximum_trade_amounts_test.go @@ -0,0 +1,27 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestMaximumTradeAmountsGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestMaximumTradeAmountsIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From 77638ad9586f9a675188879dc56a2718517f0cd9 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 21:20:16 -0700 Subject: [PATCH 10/29] implement applicable fees query --- newton.go | 3 ++- query/applicable_fees.go | 12 ++++++++++++ query/applicable_fees_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 query/applicable_fees.go create mode 100644 query/applicable_fees_test.go diff --git a/newton.go b/newton.go index 8a35748..7dc385d 100644 --- a/newton.go +++ b/newton.go @@ -255,7 +255,8 @@ func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { } func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { - res, err := n.doQuery("/fees", http.MethodGet, []query.Parameter{}, true, "") + query := &query.ApplicableFees{} + res, err := n.doQuery("/fees", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } diff --git a/query/applicable_fees.go b/query/applicable_fees.go new file mode 100644 index 0000000..171c361 --- /dev/null +++ b/query/applicable_fees.go @@ -0,0 +1,12 @@ +package query + +type ApplicableFees struct { +} + +func (af ApplicableFees) GetParameters() []Parameter { + return []Parameter{} +} + +func (af ApplicableFees) IsPublic() bool { + return true +} diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go new file mode 100644 index 0000000..9ed64c0 --- /dev/null +++ b/query/applicable_fees_test.go @@ -0,0 +1,27 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestApplicableFeesGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestApplicableFeesIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From b65703ef99ba5cb619a6555a4717e07c40b398eb Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 21:23:04 -0700 Subject: [PATCH 11/29] implement health check query --- newton.go | 5 +++-- query/health_check.go | 12 ++++++++++++ query/health_check_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 query/health_check.go create mode 100644 query/health_check_test.go diff --git a/newton.go b/newton.go index 7dc385d..ade7cd7 100644 --- a/newton.go +++ b/newton.go @@ -276,7 +276,7 @@ func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { } func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { - res, err := n.doQuery("/symbols", http.MethodGet, query.GetParameters(), true, "") + res, err := n.doQuery("/symbols", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } @@ -296,7 +296,8 @@ func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { } func (n *Newton) HealthCheck() error { - res, err := n.doQuery("/health-check", http.MethodGet, []query.Parameter{}, true, "") + query := &query.HealthCheck{} + res, err := n.doQuery("/health-check", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return err } diff --git a/query/health_check.go b/query/health_check.go new file mode 100644 index 0000000..5fee753 --- /dev/null +++ b/query/health_check.go @@ -0,0 +1,12 @@ +package query + +type HealthCheck struct { +} + +func (hc HealthCheck) GetParameters() []Parameter { + return []Parameter{} +} + +func (hc HealthCheck) IsPublic() bool { + return true +} diff --git a/query/health_check_test.go b/query/health_check_test.go new file mode 100644 index 0000000..5ff9781 --- /dev/null +++ b/query/health_check_test.go @@ -0,0 +1,27 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestHealthCheckGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestHealthCheckIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From 554978e1ef3bef7a53f2e1d8203016b6163ff8ed Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 21:25:42 -0700 Subject: [PATCH 12/29] implement minimum trade amount query --- newton.go | 3 ++- query/minimum_trade_amount.go | 12 ++++++++++++ query/minimum_trade_amount_test.go | 27 +++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 query/minimum_trade_amount.go create mode 100644 query/minimum_trade_amount_test.go diff --git a/newton.go b/newton.go index ade7cd7..45602e5 100644 --- a/newton.go +++ b/newton.go @@ -310,7 +310,8 @@ func (n *Newton) HealthCheck() error { } func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { - res, err := n.doQuery("/order/minimums", http.MethodGet, []query.Parameter{}, true, "") + query := &query.MinimumTradeAmount{} + res, err := n.doQuery("/order/minimums", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } diff --git a/query/minimum_trade_amount.go b/query/minimum_trade_amount.go new file mode 100644 index 0000000..e557b53 --- /dev/null +++ b/query/minimum_trade_amount.go @@ -0,0 +1,12 @@ +package query + +type MinimumTradeAmount struct { +} + +func (mta MinimumTradeAmount) GetParameters() []Parameter { + return []Parameter{} +} + +func (mta MinimumTradeAmount) IsPublic() bool { + return true +} diff --git a/query/minimum_trade_amount_test.go b/query/minimum_trade_amount_test.go new file mode 100644 index 0000000..430badc --- /dev/null +++ b/query/minimum_trade_amount_test.go @@ -0,0 +1,27 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestMinimumTradeAmountGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmount{} + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestMinimumTradeAmountIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmount{} + + g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) +} From 00fd5fbe4fdc266783a26e628268d7b8affb4d90 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 22:17:51 -0700 Subject: [PATCH 13/29] implement query get body --- newton.go | 26 +++------ query/actions.go | 28 ++++++---- query/actions_test.go | 14 +++++ query/applicable_fees.go | 4 ++ query/applicable_fees_test.go | 8 +++ query/balances.go | 4 ++ query/balances_test.go | 12 ++++ query/common.go | 1 + query/health_check.go | 4 ++ query/health_check_test.go | 8 +++ query/maximum_trade_amounts.go | 4 ++ query/maximum_trade_amounts_test.go | 8 +++ query/minimum_trade_amount.go | 12 ---- query/minimum_trade_amounts.go | 16 ++++++ ..._test.go => minimum_trade_amounts_test.go} | 12 +++- query/new_order.go | 26 +++++++++ query/new_order_test.go | 55 +++++++++++++++++++ query/open_orders.go | 4 ++ query/open_orders_test.go | 18 ++++++ query/order_history.go | 4 ++ query/order_history_test.go | 22 ++++++++ query/symbols.go | 4 ++ query/symbols_test.go | 14 +++++ query/tick_sizes.go | 4 ++ query/tick_sizes_test.go | 8 +++ 25 files changed, 275 insertions(+), 45 deletions(-) delete mode 100644 query/minimum_trade_amount.go create mode 100644 query/minimum_trade_amounts.go rename query/{minimum_trade_amount_test.go => minimum_trade_amounts_test.go} (63%) create mode 100644 query/new_order.go create mode 100644 query/new_order_test.go diff --git a/newton.go b/newton.go index 45602e5..4fa3a71 100644 --- a/newton.go +++ b/newton.go @@ -24,15 +24,6 @@ type Newton struct { clientSecret string } -type NewOrderReq struct { - OrderType string `json:"order_type"` - TimeInForce string `json:"time_in_force"` - Side string `json:"side"` - Symbol string `json:"symbol"` - Price float64 `json:"price"` - Quantity float64 `json:"quantity"` -} - type GetTickSizesResp struct { Ticks map[string]struct { Tick float64 `json:"tick"` @@ -310,7 +301,7 @@ func (n *Newton) HealthCheck() error { } func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { - query := &query.MinimumTradeAmount{} + query := &query.MinimumTradeAmounts{} res, err := n.doQuery("/order/minimums", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err @@ -353,7 +344,7 @@ func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { } func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { - res, err := n.doQuery("/actions", http.MethodGet, query.GetParameters(), false, "") + res, err := n.doQuery("/actions", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } @@ -373,7 +364,7 @@ func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { } func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { - res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), false, "") + res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } @@ -393,7 +384,7 @@ func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { } func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { - res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), false, "") + res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), query.IsPublic(), "") if err != nil { return nil, err } @@ -412,16 +403,13 @@ func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { return &r, nil } -func (n *Newton) NewOrder(orderType string, timeInForce string, side string, symbol string, price float64, quantity float64) (*OpenOrdersResp, error) { - - order := NewOrderReq{orderType, timeInForce, side, symbol, price, quantity} - - b, err := json.Marshal(&order) +func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { + b, err := json.Marshal(query.GetBody()) if err != nil { return nil, err } - res, err := n.doQuery("/order/new", http.MethodPost, nil, false, string(b)) + res, err := n.doQuery("/order/new", http.MethodPost, query.GetParameters(), query.IsPublic(), string(b)) if err != nil { return nil, err } diff --git a/query/actions.go b/query/actions.go index 6235e26..68069d7 100644 --- a/query/actions.go +++ b/query/actions.go @@ -10,32 +10,36 @@ type Actions struct { EndDate int64 } -func (arp Actions) GetParameters() []Parameter { +func (a Actions) GetBody() interface{} { + return nil +} + +func (a Actions) GetParameters() []Parameter { params := make([]Parameter, 0) - if arp.ActionType != ActionType(NO_FILTER) { - params = append(params, Parameter{string(ActionTypeKey), string(arp.ActionType)}) + if a.ActionType != ActionType(NO_FILTER) { + params = append(params, Parameter{string(ActionTypeKey), string(a.ActionType)}) } - if arp.Limit != int(ANY) { - params = append(params, Parameter{string(Limit), strconv.Itoa(arp.Limit)}) + if a.Limit != int(ANY) { + params = append(params, Parameter{string(Limit), strconv.Itoa(a.Limit)}) } - if arp.Offset != int(ANY) { - params = append(params, Parameter{string(Offset), strconv.Itoa(arp.Offset)}) + if a.Offset != int(ANY) { + params = append(params, Parameter{string(Offset), strconv.Itoa(a.Offset)}) } - if arp.StartDate != int64(ANY) { - params = append(params, Parameter{string(StartDate), strconv.FormatInt(arp.StartDate, 10)}) + if a.StartDate != int64(ANY) { + params = append(params, Parameter{string(StartDate), strconv.FormatInt(a.StartDate, 10)}) } - if arp.EndDate != int64(ANY) { - params = append(params, Parameter{string(EndDate), strconv.FormatInt(arp.EndDate, 10)}) + if a.EndDate != int64(ANY) { + params = append(params, Parameter{string(EndDate), strconv.FormatInt(a.EndDate, 10)}) } return params } -func (arp Actions) IsPublic() bool { +func (a Actions) IsPublic() bool { return false } diff --git a/query/actions_test.go b/query/actions_test.go index 7ecd5a9..d3046aa 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -10,6 +10,20 @@ import ( "github.com/onsi/gomega" ) +func TestActionsGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Actions{ + query.ActionType(query.NO_FILTER), + int(query.ANY), + int(query.ANY), + int64(query.ANY), + int64(query.ANY), + } + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestActionsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/applicable_fees.go b/query/applicable_fees.go index 171c361..2652455 100644 --- a/query/applicable_fees.go +++ b/query/applicable_fees.go @@ -3,6 +3,10 @@ package query type ApplicableFees struct { } +func (af ApplicableFees) GetBody() interface{} { + return nil +} + func (af ApplicableFees) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go index 9ed64c0..9f8ce36 100644 --- a/query/applicable_fees_test.go +++ b/query/applicable_fees_test.go @@ -8,6 +8,14 @@ import ( "github.com/onsi/gomega" ) +func TestApplicableFeesGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestApplicableFeesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/balances.go b/query/balances.go index 508ee53..ce6c412 100644 --- a/query/balances.go +++ b/query/balances.go @@ -4,6 +4,10 @@ type Balances struct { Asset string } +func (b Balances) GetBody() interface{} { + return nil +} + func (b Balances) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/balances_test.go b/query/balances_test.go index 4b0d5c8..699a85f 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -8,6 +8,18 @@ import ( "github.com/onsi/gomega" ) +func TestBalancesGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + asset := "BTC" + + sut := &query.Balances{ + asset, + } + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestBalancesGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/common.go b/query/common.go index d3e3edf..4454f7f 100644 --- a/query/common.go +++ b/query/common.go @@ -43,6 +43,7 @@ type Parameter struct { } type Query interface { + GetBody() interface{} GetParameters() []Parameter IsPublic() bool } diff --git a/query/health_check.go b/query/health_check.go index 5fee753..884951e 100644 --- a/query/health_check.go +++ b/query/health_check.go @@ -3,6 +3,10 @@ package query type HealthCheck struct { } +func (hc HealthCheck) GetBody() interface{} { + return nil +} + func (hc HealthCheck) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/health_check_test.go b/query/health_check_test.go index 5ff9781..f1f8ead 100644 --- a/query/health_check_test.go +++ b/query/health_check_test.go @@ -8,6 +8,14 @@ import ( "github.com/onsi/gomega" ) +func TestHealthCheckGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestHealthCheckGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go index 7394400..c910bb8 100644 --- a/query/maximum_trade_amounts.go +++ b/query/maximum_trade_amounts.go @@ -3,6 +3,10 @@ package query type MaximumTradeAmounts struct { } +func (mta MaximumTradeAmounts) GetBody() interface{} { + return nil +} + func (mta MaximumTradeAmounts) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go index 13b50bf..c4914e4 100644 --- a/query/maximum_trade_amounts_test.go +++ b/query/maximum_trade_amounts_test.go @@ -8,6 +8,14 @@ import ( "github.com/onsi/gomega" ) +func TestMaximumTradeAmountsGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestMaximumTradeAmountsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/minimum_trade_amount.go b/query/minimum_trade_amount.go deleted file mode 100644 index e557b53..0000000 --- a/query/minimum_trade_amount.go +++ /dev/null @@ -1,12 +0,0 @@ -package query - -type MinimumTradeAmount struct { -} - -func (mta MinimumTradeAmount) GetParameters() []Parameter { - return []Parameter{} -} - -func (mta MinimumTradeAmount) IsPublic() bool { - return true -} diff --git a/query/minimum_trade_amounts.go b/query/minimum_trade_amounts.go new file mode 100644 index 0000000..80f6cf5 --- /dev/null +++ b/query/minimum_trade_amounts.go @@ -0,0 +1,16 @@ +package query + +type MinimumTradeAmounts struct { +} + +func (mta MinimumTradeAmounts) GetBody() interface{} { + return nil +} + +func (mta MinimumTradeAmounts) GetParameters() []Parameter { + return []Parameter{} +} + +func (mta MinimumTradeAmounts) IsPublic() bool { + return true +} diff --git a/query/minimum_trade_amount_test.go b/query/minimum_trade_amounts_test.go similarity index 63% rename from query/minimum_trade_amount_test.go rename to query/minimum_trade_amounts_test.go index 430badc..b8507fc 100644 --- a/query/minimum_trade_amount_test.go +++ b/query/minimum_trade_amounts_test.go @@ -8,10 +8,18 @@ import ( "github.com/onsi/gomega" ) +func TestMinimumTradeAmountsGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmounts{} + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestMinimumTradeAmountGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.MinimumTradeAmount{} + sut := &query.MinimumTradeAmounts{} parameters := sut.GetParameters() @@ -21,7 +29,7 @@ func TestMinimumTradeAmountGetParameters(t *testing.T) { func TestMinimumTradeAmountIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.MinimumTradeAmount{} + sut := &query.MinimumTradeAmounts{} g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) } diff --git a/query/new_order.go b/query/new_order.go new file mode 100644 index 0000000..9ed154d --- /dev/null +++ b/query/new_order.go @@ -0,0 +1,26 @@ +package query + +type NewOrderBody struct { + OrderType string `json:"order_type"` + TimeInForce TimeInForceAllowedValue `json:"time_in_force"` + Side string `json:"side"` + Symbol string `json:"symbol"` + Price float64 `json:"price"` + Quantity float64 `json:"quantity"` +} + +type NewOrder struct { + Body NewOrderBody +} + +func (no NewOrder) GetBody() interface{} { + return &no.Body +} + +func (no NewOrder) GetParameters() []Parameter { + return []Parameter{} +} + +func (no NewOrder) IsPublic() bool { + return false +} diff --git a/query/new_order_test.go b/query/new_order_test.go new file mode 100644 index 0000000..4334039 --- /dev/null +++ b/query/new_order_test.go @@ -0,0 +1,55 @@ +package query_test + +import ( + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +func TestNewOrderGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + body := query.NewOrderBody{ + OrderType: "LIMIT", + TimeInForce: query.IOC, + Side: "BUY", + Symbol: "BTC_USDC", + Price: 10.0, + Quantity: 2.5, + } + + sut := &query.NewOrder{ + Body: body, + } + + g.Expect(sut.GetBody()).Should(gomega.BeEquivalentTo(&body)) +} + +func TestNewOrderGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.NewOrder{ + Body: query.NewOrderBody{ + OrderType: "LIMIT", + TimeInForce: query.IOC, + Side: "BUY", + Symbol: "BTC_USDC", + Price: 10.0, + Quantity: 2.5, + }, + } + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestNewOrderIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.NewOrder{} + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/open_orders.go b/query/open_orders.go index 48fa3e5..07dc8c2 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -9,6 +9,10 @@ type OpenOrders struct { TimeInForce TimeInForceAllowedValue } +func (oo OpenOrders) GetBody() interface{} { + return nil +} + func (oo OpenOrders) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 97d4979..2428614 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -9,6 +9,24 @@ import ( "github.com/onsi/gomega" ) +func TestOpenOrdersGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + limit := 1 + offset := 0 + symbol := "BTC_USDC" + timeInForce := query.IOC + + sut := &query.OpenOrders{ + limit, + offset, + symbol, + timeInForce, + } + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestOpenOrdersGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/order_history.go b/query/order_history.go index 8795053..68dd35d 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -11,6 +11,10 @@ type OrderHistory struct { TimeInForce TimeInForceAllowedValue } +func (oh OrderHistory) GetBody() interface{} { + return nil +} + func (oh OrderHistory) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/order_history_test.go b/query/order_history_test.go index 672a9ae..3363f5f 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -10,6 +10,28 @@ import ( "github.com/onsi/gomega" ) +func TestOrderHistoryGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + limit := 1 + offset := 0 + startDate := time.Now().Unix() + endDate := startDate + 1 + symbol := "BTC_USDC" + timeInForce := query.IOC + + sut := &query.OrderHistory{ + limit, + offset, + startDate, + endDate, + symbol, + timeInForce, + } + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/symbols.go b/query/symbols.go index 9e33b0d..4970ea0 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -4,6 +4,10 @@ type Symbols struct { BaseAsset, QuoteAsset string } +func (s Symbols) GetBody() interface{} { + return nil +} + func (s Symbols) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/symbols_test.go b/query/symbols_test.go index 67adcfc..8f16863 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -8,6 +8,20 @@ import ( "github.com/onsi/gomega" ) +func TestSymbolsGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + baseAsset := "BTC" + quoteAsset := "ETH" + + sut := &query.Symbols{ + baseAsset, + quoteAsset, + } + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestSymbolsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/tick_sizes.go b/query/tick_sizes.go index f13e67d..7bd1fae 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -3,6 +3,10 @@ package query type TickSizes struct { } +func (ts TickSizes) GetBody() interface{} { + return nil +} + func (ts TickSizes) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go index 3be7dd9..ba8fe79 100644 --- a/query/tick_sizes_test.go +++ b/query/tick_sizes_test.go @@ -8,6 +8,14 @@ import ( "github.com/onsi/gomega" ) +func TestTickSizesGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + g.Expect(sut.GetBody()).Should(gomega.BeNil()) +} + func TestTickSizesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) From 62ed89c2d78aec1c6757668aabc6a60160aabbba Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 22:34:20 -0700 Subject: [PATCH 14/29] reafctor query GetBody to return string --- newton.go | 7 +++---- query/actions.go | 4 ++-- query/actions_test.go | 4 +++- query/applicable_fees.go | 4 ++-- query/applicable_fees_test.go | 2 +- query/balances.go | 4 ++-- query/balances_test.go | 2 +- query/common.go | 3 ++- query/health_check.go | 4 ++-- query/health_check_test.go | 2 +- query/maximum_trade_amounts.go | 4 ++-- query/maximum_trade_amounts_test.go | 2 +- query/minimum_trade_amounts.go | 4 ++-- query/minimum_trade_amounts_test.go | 2 +- query/new_order.go | 10 ++++++++-- query/new_order_test.go | 10 +++++++++- query/open_orders.go | 4 ++-- query/open_orders_test.go | 2 +- query/order_history.go | 4 ++-- query/order_history_test.go | 2 +- query/symbols.go | 4 ++-- query/symbols_test.go | 2 +- query/tick_sizes.go | 4 ++-- query/tick_sizes_test.go | 2 +- 24 files changed, 54 insertions(+), 38 deletions(-) diff --git a/newton.go b/newton.go index 4fa3a71..97f251b 100644 --- a/newton.go +++ b/newton.go @@ -154,7 +154,6 @@ func (n *Newton) sign(req *http.Request) error { func (n *Newton) doQuery(path string, method string, parameters []query.Parameter, isPublic bool, body string) (*http.Response, error) { url := baseUrl + path - req, _ := http.NewRequest(method, url, bytes.NewBuffer([]byte(body))) q := req.URL.Query() for _, a := range parameters { @@ -404,12 +403,12 @@ func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { } func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { - b, err := json.Marshal(query.GetBody()) + reqBody, err := query.GetBody() if err != nil { return nil, err } - - res, err := n.doQuery("/order/new", http.MethodPost, query.GetParameters(), query.IsPublic(), string(b)) + + res, err := n.doQuery("/order/new", http.MethodPost, query.GetParameters(), query.IsPublic(), reqBody) if err != nil { return nil, err } diff --git a/query/actions.go b/query/actions.go index 68069d7..4ce479b 100644 --- a/query/actions.go +++ b/query/actions.go @@ -10,8 +10,8 @@ type Actions struct { EndDate int64 } -func (a Actions) GetBody() interface{} { - return nil +func (a Actions) GetBody() (string, error) { + return EMPTY_BODY, nil } func (a Actions) GetParameters() []Parameter { diff --git a/query/actions_test.go b/query/actions_test.go index d3046aa..1b3fc0e 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -21,7 +21,9 @@ func TestActionsGetBody(t *testing.T) { int64(query.ANY), } - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.Equal(query.EMPTY_BODY)) } func TestActionsGetParametersNoFilter(t *testing.T) { diff --git a/query/applicable_fees.go b/query/applicable_fees.go index 2652455..b2a840b 100644 --- a/query/applicable_fees.go +++ b/query/applicable_fees.go @@ -3,8 +3,8 @@ package query type ApplicableFees struct { } -func (af ApplicableFees) GetBody() interface{} { - return nil +func (af ApplicableFees) GetBody() (string, error) { + return EMPTY_BODY, nil } func (af ApplicableFees) GetParameters() []Parameter { diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go index 9f8ce36..c85f419 100644 --- a/query/applicable_fees_test.go +++ b/query/applicable_fees_test.go @@ -13,7 +13,7 @@ func TestApplicableFeesGetBody(t *testing.T) { sut := &query.ApplicableFees{} - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestApplicableFeesGetParameters(t *testing.T) { diff --git a/query/balances.go b/query/balances.go index ce6c412..499b3aa 100644 --- a/query/balances.go +++ b/query/balances.go @@ -4,8 +4,8 @@ type Balances struct { Asset string } -func (b Balances) GetBody() interface{} { - return nil +func (b Balances) GetBody() (string, error) { + return EMPTY_BODY, nil } func (b Balances) GetParameters() []Parameter { diff --git a/query/balances_test.go b/query/balances_test.go index 699a85f..bd8e302 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -17,7 +17,7 @@ func TestBalancesGetBody(t *testing.T) { asset, } - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestBalancesGetParametersNoFilter(t *testing.T) { diff --git a/query/common.go b/query/common.go index 4454f7f..b3b3db0 100644 --- a/query/common.go +++ b/query/common.go @@ -35,6 +35,7 @@ const ( const ( ANY int = -1 NO_FILTER string = "" + EMPTY_BODY = "" ) type Parameter struct { @@ -43,7 +44,7 @@ type Parameter struct { } type Query interface { - GetBody() interface{} + GetBody() (string, error) GetParameters() []Parameter IsPublic() bool } diff --git a/query/health_check.go b/query/health_check.go index 884951e..f75833b 100644 --- a/query/health_check.go +++ b/query/health_check.go @@ -3,8 +3,8 @@ package query type HealthCheck struct { } -func (hc HealthCheck) GetBody() interface{} { - return nil +func (hc HealthCheck) GetBody() (string, error) { + return EMPTY_BODY, nil } func (hc HealthCheck) GetParameters() []Parameter { diff --git a/query/health_check_test.go b/query/health_check_test.go index f1f8ead..7f9f80f 100644 --- a/query/health_check_test.go +++ b/query/health_check_test.go @@ -13,7 +13,7 @@ func TestHealthCheckGetBody(t *testing.T) { sut := &query.HealthCheck{} - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestHealthCheckGetParameters(t *testing.T) { diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go index c910bb8..5e78bd1 100644 --- a/query/maximum_trade_amounts.go +++ b/query/maximum_trade_amounts.go @@ -3,8 +3,8 @@ package query type MaximumTradeAmounts struct { } -func (mta MaximumTradeAmounts) GetBody() interface{} { - return nil +func (mta MaximumTradeAmounts) GetBody() (string, error) { + return EMPTY_BODY, nil } func (mta MaximumTradeAmounts) GetParameters() []Parameter { diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go index c4914e4..4a5f5e0 100644 --- a/query/maximum_trade_amounts_test.go +++ b/query/maximum_trade_amounts_test.go @@ -13,7 +13,7 @@ func TestMaximumTradeAmountsGetBody(t *testing.T) { sut := &query.MaximumTradeAmounts{} - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestMaximumTradeAmountsGetParameters(t *testing.T) { diff --git a/query/minimum_trade_amounts.go b/query/minimum_trade_amounts.go index 80f6cf5..8f90e91 100644 --- a/query/minimum_trade_amounts.go +++ b/query/minimum_trade_amounts.go @@ -3,8 +3,8 @@ package query type MinimumTradeAmounts struct { } -func (mta MinimumTradeAmounts) GetBody() interface{} { - return nil +func (mta MinimumTradeAmounts) GetBody() (string, error) { + return EMPTY_BODY, nil } func (mta MinimumTradeAmounts) GetParameters() []Parameter { diff --git a/query/minimum_trade_amounts_test.go b/query/minimum_trade_amounts_test.go index b8507fc..ac44cfb 100644 --- a/query/minimum_trade_amounts_test.go +++ b/query/minimum_trade_amounts_test.go @@ -13,7 +13,7 @@ func TestMinimumTradeAmountsGetBody(t *testing.T) { sut := &query.MinimumTradeAmounts{} - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestMinimumTradeAmountGetParameters(t *testing.T) { diff --git a/query/new_order.go b/query/new_order.go index 9ed154d..1c8ec43 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -1,5 +1,7 @@ package query +import "encoding/json" + type NewOrderBody struct { OrderType string `json:"order_type"` TimeInForce TimeInForceAllowedValue `json:"time_in_force"` @@ -13,8 +15,12 @@ type NewOrder struct { Body NewOrderBody } -func (no NewOrder) GetBody() interface{} { - return &no.Body +func (no NewOrder) GetBody() (string, error) { + body, err := json.Marshal(no.Body) + if err != nil { + return EMPTY_BODY, err + } + return string(body), nil } func (no NewOrder) GetParameters() []Parameter { diff --git a/query/new_order_test.go b/query/new_order_test.go index 4334039..ea90d7e 100644 --- a/query/new_order_test.go +++ b/query/new_order_test.go @@ -1,6 +1,7 @@ package query_test import ( + "encoding/json" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -24,7 +25,14 @@ func TestNewOrderGetBody(t *testing.T) { Body: body, } - g.Expect(sut.GetBody()).Should(gomega.BeEquivalentTo(&body)) + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + + var actualBodyParsed query.NewOrderBody + err = json.Unmarshal([]byte(actualBody), &actualBodyParsed) + g.Expect(err).Should(gomega.BeNil()) + + g.Expect(actualBodyParsed).Should(gomega.BeEquivalentTo(body)) } func TestNewOrderGetParameters(t *testing.T) { diff --git a/query/open_orders.go b/query/open_orders.go index 07dc8c2..2178a9f 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -9,8 +9,8 @@ type OpenOrders struct { TimeInForce TimeInForceAllowedValue } -func (oo OpenOrders) GetBody() interface{} { - return nil +func (oo OpenOrders) GetBody() (string, error) { + return EMPTY_BODY, nil } func (oo OpenOrders) GetParameters() []Parameter { diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 2428614..532cabc 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -24,7 +24,7 @@ func TestOpenOrdersGetBody(t *testing.T) { timeInForce, } - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestOpenOrdersGetParametersNoFilter(t *testing.T) { diff --git a/query/order_history.go b/query/order_history.go index 68dd35d..3fce06a 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -11,8 +11,8 @@ type OrderHistory struct { TimeInForce TimeInForceAllowedValue } -func (oh OrderHistory) GetBody() interface{} { - return nil +func (oh OrderHistory) GetBody() (string, error) { + return EMPTY_BODY, nil } func (oh OrderHistory) GetParameters() []Parameter { diff --git a/query/order_history_test.go b/query/order_history_test.go index 3363f5f..0fbc2dd 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -29,7 +29,7 @@ func TestOrderHistoryGetBody(t *testing.T) { timeInForce, } - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { diff --git a/query/symbols.go b/query/symbols.go index 4970ea0..704ebed 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -4,8 +4,8 @@ type Symbols struct { BaseAsset, QuoteAsset string } -func (s Symbols) GetBody() interface{} { - return nil +func (s Symbols) GetBody() (string, error) { + return EMPTY_BODY, nil } func (s Symbols) GetParameters() []Parameter { diff --git a/query/symbols_test.go b/query/symbols_test.go index 8f16863..8559960 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -19,7 +19,7 @@ func TestSymbolsGetBody(t *testing.T) { quoteAsset, } - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestSymbolsGetParametersNoFilter(t *testing.T) { diff --git a/query/tick_sizes.go b/query/tick_sizes.go index 7bd1fae..94680c2 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -3,8 +3,8 @@ package query type TickSizes struct { } -func (ts TickSizes) GetBody() interface{} { - return nil +func (ts TickSizes) GetBody() (string, error) { + return EMPTY_BODY, nil } func (ts TickSizes) GetParameters() []Parameter { diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go index ba8fe79..c8980d2 100644 --- a/query/tick_sizes_test.go +++ b/query/tick_sizes_test.go @@ -13,7 +13,7 @@ func TestTickSizesGetBody(t *testing.T) { sut := &query.TickSizes{} - g.Expect(sut.GetBody()).Should(gomega.BeNil()) + g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) } func TestTickSizesGetParameters(t *testing.T) { From bb7d03eec8d79bd06fde4eeeb4be8ea143f600c7 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 22:44:41 -0700 Subject: [PATCH 15/29] pass query to Newton's Do --- newton.go | 44 +++++++++++++++-------------- query/actions.go | 4 +-- query/actions_test.go | 2 +- query/applicable_fees.go | 4 +-- query/applicable_fees_test.go | 4 ++- query/balances.go | 4 +-- query/balances_test.go | 4 ++- query/common.go | 2 +- query/health_check.go | 4 +-- query/health_check_test.go | 4 ++- query/maximum_trade_amounts.go | 4 +-- query/maximum_trade_amounts_test.go | 6 ++-- query/minimum_trade_amounts.go | 4 +-- query/minimum_trade_amounts_test.go | 6 ++-- query/new_order.go | 6 ++-- query/open_orders.go | 4 +-- query/open_orders_test.go | 6 ++-- query/order_history.go | 4 +-- query/order_history_test.go | 6 ++-- query/symbols.go | 4 +-- query/symbols_test.go | 6 ++-- query/tick_sizes.go | 4 +-- query/tick_sizes_test.go | 6 ++-- 23 files changed, 81 insertions(+), 61 deletions(-) diff --git a/newton.go b/newton.go index 97f251b..186815d 100644 --- a/newton.go +++ b/newton.go @@ -152,11 +152,18 @@ func (n *Newton) sign(req *http.Request) error { return nil } -func (n *Newton) doQuery(path string, method string, parameters []query.Parameter, isPublic bool, body string) (*http.Response, error) { - url := baseUrl + path - req, _ := http.NewRequest(method, url, bytes.NewBuffer([]byte(body))) +func (n *Newton) Do(path string, method string, query query.Query) (*http.Response, error) { + body, err := query.GetBody() + if err != nil { + return nil, err + } + + req, _ := http.NewRequest( + method, + baseUrl + path, + bytes.NewBuffer(body)) q := req.URL.Query() - for _, a := range parameters { + for _, a := range query.GetParameters() { q.Add(a.Key, a.Value) } req.URL.RawQuery = q.Encode() @@ -164,7 +171,7 @@ func (n *Newton) doQuery(path string, method string, parameters []query.Paramete req.Header.Add("content-type", "application/json") } - if !isPublic { + if !query.IsPublic() { err := n.sign(req) if err != nil { return nil, err @@ -204,7 +211,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { /////////////////////////////////////////////////////////////////////////////////////////////////// func (n *Newton) TickSizes() (*GetTickSizesResp, error) { query := &query.TickSizes{} - res, err := n.doQuery("/order/tick-sizes", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/order/tick-sizes", http.MethodGet, query) if err != nil { return nil, err } @@ -225,7 +232,7 @@ func (n *Newton) TickSizes() (*GetTickSizesResp, error) { func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { query := &query.MaximumTradeAmounts{} - res, err := n.doQuery("/order/maximums", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/order/maximums", http.MethodGet, query) if err != nil { return nil, err } @@ -246,7 +253,7 @@ func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { query := &query.ApplicableFees{} - res, err := n.doQuery("/fees", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/fees", http.MethodGet, query) if err != nil { return nil, err } @@ -266,7 +273,7 @@ func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { } func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { - res, err := n.doQuery("/symbols", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/symbols", http.MethodGet, query) if err != nil { return nil, err } @@ -287,7 +294,7 @@ func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { func (n *Newton) HealthCheck() error { query := &query.HealthCheck{} - res, err := n.doQuery("/health-check", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/health-check", http.MethodGet, query) if err != nil { return err } @@ -301,7 +308,7 @@ func (n *Newton) HealthCheck() error { func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { query := &query.MinimumTradeAmounts{} - res, err := n.doQuery("/order/minimums", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/order/minimums", http.MethodGet, query) if err != nil { return nil, err } @@ -323,7 +330,7 @@ func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { - res, err := n.doQuery("/balances", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/balances", http.MethodGet, query) if err != nil { return nil, err } @@ -343,7 +350,7 @@ func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { } func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { - res, err := n.doQuery("/actions", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/actions", http.MethodGet, query) if err != nil { return nil, err } @@ -363,7 +370,7 @@ func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { } func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { - res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/order/history", http.MethodGet, query) if err != nil { return nil, err } @@ -383,7 +390,7 @@ func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { } func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { - res, err := n.doQuery("/order/history", http.MethodGet, query.GetParameters(), query.IsPublic(), "") + res, err := n.Do("/order/history", http.MethodGet, query) if err != nil { return nil, err } @@ -403,12 +410,7 @@ func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { } func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { - reqBody, err := query.GetBody() - if err != nil { - return nil, err - } - - res, err := n.doQuery("/order/new", http.MethodPost, query.GetParameters(), query.IsPublic(), reqBody) + res, err := n.Do("/order/new", http.MethodPost, query) if err != nil { return nil, err } diff --git a/query/actions.go b/query/actions.go index 4ce479b..8eaab3c 100644 --- a/query/actions.go +++ b/query/actions.go @@ -10,8 +10,8 @@ type Actions struct { EndDate int64 } -func (a Actions) GetBody() (string, error) { - return EMPTY_BODY, nil +func (a Actions) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (a Actions) GetParameters() []Parameter { diff --git a/query/actions_test.go b/query/actions_test.go index 1b3fc0e..9f2f2f1 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -23,7 +23,7 @@ func TestActionsGetBody(t *testing.T) { actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) - g.Expect(actualBody).Should(gomega.Equal(query.EMPTY_BODY)) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestActionsGetParametersNoFilter(t *testing.T) { diff --git a/query/applicable_fees.go b/query/applicable_fees.go index b2a840b..0804a73 100644 --- a/query/applicable_fees.go +++ b/query/applicable_fees.go @@ -3,8 +3,8 @@ package query type ApplicableFees struct { } -func (af ApplicableFees) GetBody() (string, error) { - return EMPTY_BODY, nil +func (af ApplicableFees) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (af ApplicableFees) GetParameters() []Parameter { diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go index c85f419..a513ab2 100644 --- a/query/applicable_fees_test.go +++ b/query/applicable_fees_test.go @@ -13,7 +13,9 @@ func TestApplicableFeesGetBody(t *testing.T) { sut := &query.ApplicableFees{} - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestApplicableFeesGetParameters(t *testing.T) { diff --git a/query/balances.go b/query/balances.go index 499b3aa..13b1f24 100644 --- a/query/balances.go +++ b/query/balances.go @@ -4,8 +4,8 @@ type Balances struct { Asset string } -func (b Balances) GetBody() (string, error) { - return EMPTY_BODY, nil +func (b Balances) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (b Balances) GetParameters() []Parameter { diff --git a/query/balances_test.go b/query/balances_test.go index bd8e302..c100d77 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -17,7 +17,9 @@ func TestBalancesGetBody(t *testing.T) { asset, } - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestBalancesGetParametersNoFilter(t *testing.T) { diff --git a/query/common.go b/query/common.go index b3b3db0..e10272e 100644 --- a/query/common.go +++ b/query/common.go @@ -44,7 +44,7 @@ type Parameter struct { } type Query interface { - GetBody() (string, error) + GetBody() ([]byte, error) GetParameters() []Parameter IsPublic() bool } diff --git a/query/health_check.go b/query/health_check.go index f75833b..e2027f1 100644 --- a/query/health_check.go +++ b/query/health_check.go @@ -3,8 +3,8 @@ package query type HealthCheck struct { } -func (hc HealthCheck) GetBody() (string, error) { - return EMPTY_BODY, nil +func (hc HealthCheck) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (hc HealthCheck) GetParameters() []Parameter { diff --git a/query/health_check_test.go b/query/health_check_test.go index 7f9f80f..aab157c 100644 --- a/query/health_check_test.go +++ b/query/health_check_test.go @@ -13,7 +13,9 @@ func TestHealthCheckGetBody(t *testing.T) { sut := &query.HealthCheck{} - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestHealthCheckGetParameters(t *testing.T) { diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go index 5e78bd1..f86d6d2 100644 --- a/query/maximum_trade_amounts.go +++ b/query/maximum_trade_amounts.go @@ -3,8 +3,8 @@ package query type MaximumTradeAmounts struct { } -func (mta MaximumTradeAmounts) GetBody() (string, error) { - return EMPTY_BODY, nil +func (mta MaximumTradeAmounts) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (mta MaximumTradeAmounts) GetParameters() []Parameter { diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go index 4a5f5e0..26d9e4c 100644 --- a/query/maximum_trade_amounts_test.go +++ b/query/maximum_trade_amounts_test.go @@ -12,8 +12,10 @@ func TestMaximumTradeAmountsGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.MaximumTradeAmounts{} - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestMaximumTradeAmountsGetParameters(t *testing.T) { diff --git a/query/minimum_trade_amounts.go b/query/minimum_trade_amounts.go index 8f90e91..0a5c913 100644 --- a/query/minimum_trade_amounts.go +++ b/query/minimum_trade_amounts.go @@ -3,8 +3,8 @@ package query type MinimumTradeAmounts struct { } -func (mta MinimumTradeAmounts) GetBody() (string, error) { - return EMPTY_BODY, nil +func (mta MinimumTradeAmounts) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (mta MinimumTradeAmounts) GetParameters() []Parameter { diff --git a/query/minimum_trade_amounts_test.go b/query/minimum_trade_amounts_test.go index ac44cfb..a723087 100644 --- a/query/minimum_trade_amounts_test.go +++ b/query/minimum_trade_amounts_test.go @@ -12,8 +12,10 @@ func TestMinimumTradeAmountsGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.MinimumTradeAmounts{} - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestMinimumTradeAmountGetParameters(t *testing.T) { diff --git a/query/new_order.go b/query/new_order.go index 1c8ec43..44d75c7 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -15,12 +15,12 @@ type NewOrder struct { Body NewOrderBody } -func (no NewOrder) GetBody() (string, error) { +func (no NewOrder) GetBody() ([]byte, error) { body, err := json.Marshal(no.Body) if err != nil { - return EMPTY_BODY, err + return []byte(EMPTY_BODY), err } - return string(body), nil + return body, nil } func (no NewOrder) GetParameters() []Parameter { diff --git a/query/open_orders.go b/query/open_orders.go index 2178a9f..bf6f412 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -9,8 +9,8 @@ type OpenOrders struct { TimeInForce TimeInForceAllowedValue } -func (oo OpenOrders) GetBody() (string, error) { - return EMPTY_BODY, nil +func (oo OpenOrders) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (oo OpenOrders) GetParameters() []Parameter { diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 532cabc..76f9505 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -23,8 +23,10 @@ func TestOpenOrdersGetBody(t *testing.T) { symbol, timeInForce, } - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestOpenOrdersGetParametersNoFilter(t *testing.T) { diff --git a/query/order_history.go b/query/order_history.go index 3fce06a..e84631c 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -11,8 +11,8 @@ type OrderHistory struct { TimeInForce TimeInForceAllowedValue } -func (oh OrderHistory) GetBody() (string, error) { - return EMPTY_BODY, nil +func (oh OrderHistory) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (oh OrderHistory) GetParameters() []Parameter { diff --git a/query/order_history_test.go b/query/order_history_test.go index 0fbc2dd..2bfd551 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -28,8 +28,10 @@ func TestOrderHistoryGetBody(t *testing.T) { symbol, timeInForce, } - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { diff --git a/query/symbols.go b/query/symbols.go index 704ebed..c8a0239 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -4,8 +4,8 @@ type Symbols struct { BaseAsset, QuoteAsset string } -func (s Symbols) GetBody() (string, error) { - return EMPTY_BODY, nil +func (s Symbols) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (s Symbols) GetParameters() []Parameter { diff --git a/query/symbols_test.go b/query/symbols_test.go index 8559960..38e7980 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -18,8 +18,10 @@ func TestSymbolsGetBody(t *testing.T) { baseAsset, quoteAsset, } - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestSymbolsGetParametersNoFilter(t *testing.T) { diff --git a/query/tick_sizes.go b/query/tick_sizes.go index 94680c2..fa659e7 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -3,8 +3,8 @@ package query type TickSizes struct { } -func (ts TickSizes) GetBody() (string, error) { - return EMPTY_BODY, nil +func (ts TickSizes) GetBody() ([]byte, error) { + return []byte(EMPTY_BODY), nil } func (ts TickSizes) GetParameters() []Parameter { diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go index c8980d2..5c73823 100644 --- a/query/tick_sizes_test.go +++ b/query/tick_sizes_test.go @@ -12,8 +12,10 @@ func TestTickSizesGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) sut := &query.TickSizes{} - - g.Expect(sut.GetBody()).Should(gomega.Equal(query.EMPTY_BODY)) + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } func TestTickSizesGetParameters(t *testing.T) { From ee5e716a674498cb7062474a7325a499c00ad71d Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 24 Oct 2021 23:48:43 -0700 Subject: [PATCH 16/29] implement and test GetPath and GetMethod for query --- newton.go | 30 ++++++------ newton_test.go | 16 +++---- query/actions.go | 15 +++++- query/actions_test.go | 73 +++++++++++++++++------------ query/applicable_fees.go | 15 +++++- query/applicable_fees_test.go | 17 +++++++ query/balances.go | 12 +++++ query/balances_test.go | 38 ++++++++++----- query/common.go | 2 + query/export_test.go | 15 ++++++ query/health_check.go | 15 +++++- query/health_check_test.go | 17 +++++++ query/maximum_trade_amounts.go | 15 +++++- query/maximum_trade_amounts_test.go | 17 +++++++ query/minimum_trade_amounts.go | 15 +++++- query/minimum_trade_amounts_test.go | 17 +++++++ query/new_order.go | 15 +++++- query/new_order_test.go | 57 +++++++++++++--------- query/open_orders.go | 15 +++++- query/open_orders_test.go | 59 ++++++++++++----------- query/order_history.go | 15 +++++- query/order_history_test.go | 63 ++++++++++++------------- query/symbols.go | 12 +++++ query/symbols_test.go | 48 ++++++++++++------- query/tick_sizes.go | 15 +++++- query/tick_sizes_test.go | 17 +++++++ 26 files changed, 461 insertions(+), 184 deletions(-) create mode 100644 query/export_test.go diff --git a/newton.go b/newton.go index 186815d..608855f 100644 --- a/newton.go +++ b/newton.go @@ -152,22 +152,22 @@ func (n *Newton) sign(req *http.Request) error { return nil } -func (n *Newton) Do(path string, method string, query query.Query) (*http.Response, error) { +func (n *Newton) Do(query query.Query) (*http.Response, error) { body, err := query.GetBody() if err != nil { return nil, err } req, _ := http.NewRequest( - method, - baseUrl + path, + query.GetMethod(), + baseUrl + query.GetPath(), bytes.NewBuffer(body)) q := req.URL.Query() for _, a := range query.GetParameters() { q.Add(a.Key, a.Value) } req.URL.RawQuery = q.Encode() - if method != http.MethodGet { + if query.GetMethod() != http.MethodGet { req.Header.Add("content-type", "application/json") } @@ -211,7 +211,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { /////////////////////////////////////////////////////////////////////////////////////////////////// func (n *Newton) TickSizes() (*GetTickSizesResp, error) { query := &query.TickSizes{} - res, err := n.Do("/order/tick-sizes", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -232,7 +232,7 @@ func (n *Newton) TickSizes() (*GetTickSizesResp, error) { func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { query := &query.MaximumTradeAmounts{} - res, err := n.Do("/order/maximums", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -253,7 +253,7 @@ func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { query := &query.ApplicableFees{} - res, err := n.Do("/fees", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -273,7 +273,7 @@ func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { } func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { - res, err := n.Do("/symbols", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -294,7 +294,7 @@ func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { func (n *Newton) HealthCheck() error { query := &query.HealthCheck{} - res, err := n.Do("/health-check", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return err } @@ -308,7 +308,7 @@ func (n *Newton) HealthCheck() error { func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { query := &query.MinimumTradeAmounts{} - res, err := n.Do("/order/minimums", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -330,7 +330,7 @@ func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { - res, err := n.Do("/balances", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -350,7 +350,7 @@ func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { } func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { - res, err := n.Do("/actions", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -370,7 +370,7 @@ func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { } func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { - res, err := n.Do("/order/history", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -390,7 +390,7 @@ func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { } func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { - res, err := n.Do("/order/history", http.MethodGet, query) + res, err := n.Do(query) if err != nil { return nil, err } @@ -410,7 +410,7 @@ func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { } func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { - res, err := n.Do("/order/new", http.MethodPost, query) + res, err := n.Do(query) if err != nil { return nil, err } diff --git a/newton_test.go b/newton_test.go index 4bf4ba5..65a73f3 100644 --- a/newton_test.go +++ b/newton_test.go @@ -1,6 +1,7 @@ package newton import ( + "os" "testing" "time" @@ -9,10 +10,9 @@ import ( ) func getSecrets() (string, string) { - return "0198ab98-0475-437e-a4e6-5594398e5562", "220eeda0-e216-45f2-9d3b-e52b1ea90e7b" + return os.Getenv("CLIENT_ID"), os.Getenv("CLIENT_SECRET") } - // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// func TestGetTickSizes(t *testing.T) { @@ -21,7 +21,7 @@ func TestGetTickSizes(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.GetTickSizes() + _, err := sut.TickSizes() g.Expect(err).Should(gomega.BeNil()) } @@ -32,7 +32,7 @@ func TestGetMaximumTradeAmounts(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.GetMaximumTradeAmounts() + _, err := sut.MaximumTradeAmounts() g.Expect(err).Should(gomega.BeNil()) } @@ -43,7 +43,7 @@ func TestGetApplicableFees(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.GetApplicableFees() + _, err := sut.ApplicableFees() g.Expect(err).Should(gomega.BeNil()) } @@ -59,7 +59,7 @@ func TestSymbolsNoQuery(t *testing.T) { QuoteAsset: query.NO_FILTER, } - _, err := sut.GetSymbols(q) + _, err := sut.Symbols(q) g.Expect(err).Should(gomega.BeNil()) } @@ -75,7 +75,7 @@ func TestSymbolsWithQuery(t *testing.T) { QuoteAsset: "ETH", } - _, err := sut.GetSymbols(q) + _, err := sut.Symbols(q) g.Expect(err).Should(gomega.BeNil()) } @@ -97,7 +97,7 @@ func TestGetMinTradeAmounts(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.GetMinimumTradeAmount() + _, err := sut.MinimumTradeAmount() g.Expect(err).Should(gomega.BeNil()) } diff --git a/query/actions.go b/query/actions.go index 8eaab3c..66c954f 100644 --- a/query/actions.go +++ b/query/actions.go @@ -1,6 +1,9 @@ package query -import "strconv" +import ( + "net/http" + "strconv" +) type Actions struct { ActionType ActionType @@ -10,6 +13,16 @@ type Actions struct { EndDate int64 } +const actionsPath = "/actions" + +func (a Actions) GetMethod() string { + return http.MethodGet +} + +func (a Actions) GetPath() string { + return actionsPath +} + func (a Actions) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } diff --git a/query/actions_test.go b/query/actions_test.go index 9f2f2f1..bfe2c6e 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "strconv" "testing" "time" @@ -10,22 +11,50 @@ import ( "github.com/onsi/gomega" ) +const ( + limit = 1 + offset = 2 + actionType query.ActionType = query.DEPOSIT +) + +var ( + startTime = time.Now().Unix() + endTime = startTime + 1 + validActions = query.Actions{ + actionType, + limit, + offset, + startTime, + endTime, + } +) + func TestActionsGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.Actions{ - query.ActionType(query.NO_FILTER), - int(query.ANY), - int(query.ANY), - int64(query.ANY), - int64(query.ANY), - } + sut := &validActions actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestActionsGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validActions + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestActionsGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validActions + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.ActionsPath)) +} + func TestActionsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) @@ -45,19 +74,7 @@ func TestActionsGetParametersNoFilter(t *testing.T) { func TestActionsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - actionType := query.DEPOSIT - limit := 1 - offset := 2 - startTime := time.Now().Unix() - endTime := startTime + 1 - - sut := &query.Actions{ - query.DEPOSIT, - limit, - offset, - startTime, - endTime, - } + sut := &validActions parameters := sut.GetParameters() @@ -65,23 +82,17 @@ func TestActionsGetParameters(t *testing.T) { g.Expect(parameters).Should(gomega.ContainElements( gomega.BeEquivalentTo(query.Parameter{string(query.ActionTypeKey), string(actionType)}), - gomega.BeEquivalentTo(query.Parameter{string(query.Limit), strconv.Itoa(limit)}) , - gomega.BeEquivalentTo(query.Parameter{string(query.Offset), strconv.Itoa(offset)}) , - gomega.BeEquivalentTo(query.Parameter{string(query.StartDate), strconv.FormatInt(startTime, 10)}) , - gomega.BeEquivalentTo(query.Parameter{string(query.EndDate), strconv.FormatInt(endTime, 10)}) , + gomega.BeEquivalentTo(query.Parameter{string(query.Limit), strconv.Itoa(limit)}), + gomega.BeEquivalentTo(query.Parameter{string(query.Offset), strconv.Itoa(offset)}), + gomega.BeEquivalentTo(query.Parameter{string(query.StartDate), strconv.FormatInt(startTime, 10)}), + gomega.BeEquivalentTo(query.Parameter{string(query.EndDate), strconv.FormatInt(endTime, 10)}), )) } func TestActionsIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.Actions{ - query.ActionType(query.NO_FILTER), - int(query.ANY), - int(query.ANY), - int64(query.ANY), - int64(query.ANY), - } + sut := &validActions g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) } diff --git a/query/applicable_fees.go b/query/applicable_fees.go index 0804a73..ed41c92 100644 --- a/query/applicable_fees.go +++ b/query/applicable_fees.go @@ -1,12 +1,23 @@ package query -type ApplicableFees struct { -} +import "net/http" + +type ApplicableFees struct {} + +const applicableFeesPath = "/fees" func (af ApplicableFees) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (af ApplicableFees) GetMethod() string { + return http.MethodGet +} + +func (af ApplicableFees) GetPath() string { + return applicableFeesPath +} + func (af ApplicableFees) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go index a513ab2..558711f 100644 --- a/query/applicable_fees_test.go +++ b/query/applicable_fees_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -18,6 +19,22 @@ func TestApplicableFeesGetBody(t *testing.T) { g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestApplicableFeesGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestApplicableFeesGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.ApplicableFeesPath)) +} + func TestApplicableFeesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/balances.go b/query/balances.go index 13b1f24..eecc8a2 100644 --- a/query/balances.go +++ b/query/balances.go @@ -1,13 +1,25 @@ package query +import "net/http" + type Balances struct { Asset string } +const balancesPath = "/balances" + func (b Balances) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (b Balances) GetMethod() string { + return http.MethodGet +} + +func (b Balances) GetPath() string { + return balancesPath +} + func (b Balances) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/balances_test.go b/query/balances_test.go index c100d77..d62d640 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -8,20 +9,37 @@ import ( "github.com/onsi/gomega" ) +const asset = "BTC" +var validBalances query.Balances = query.Balances{ + asset, +} + func TestBalancesGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) - asset := "BTC" - - sut := &query.Balances{ - asset, - } + sut := &validBalances actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestBalancesGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validBalances + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestBalancesGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.ApplicableFeesPath)) +} + func TestBalancesGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) @@ -37,11 +55,7 @@ func TestBalancesGetParametersNoFilter(t *testing.T) { func TestBalancesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - asset := "BTC" - - sut := &query.Balances{ - asset, - } + sut := &validBalances parameters := sut.GetParameters() @@ -55,9 +69,7 @@ func TestBalancesGetParameters(t *testing.T) { func TestBalancesIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.Balances{ - query.NO_FILTER, - } + sut := &validBalances g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) } diff --git a/query/common.go b/query/common.go index e10272e..657f765 100644 --- a/query/common.go +++ b/query/common.go @@ -45,6 +45,8 @@ type Parameter struct { type Query interface { GetBody() ([]byte, error) + GetMethod() string + GetPath() string GetParameters() []Parameter IsPublic() bool } diff --git a/query/export_test.go b/query/export_test.go new file mode 100644 index 0000000..9575b0b --- /dev/null +++ b/query/export_test.go @@ -0,0 +1,15 @@ +package query + +const ( + ActionsPath = actionsPath + ApplicableFeesPath = applicableFeesPath + BalancesPath = balancesPath + HealthCheckPath = healthCheckPath + MaximumTradeAmountsPath = maximumTradeAmountsPath + MinimumTradeAmountsPath = minimumTradeAmountsPath + NewOrderPath = newOrderPath + OpenOrdersPath = openOrdersPath + OrderHistoryPath = orderHistoryPath + SymbolsPath = symbolsPath + TickSizesPath = tickSizesPath +) diff --git a/query/health_check.go b/query/health_check.go index e2027f1..eff63e4 100644 --- a/query/health_check.go +++ b/query/health_check.go @@ -1,12 +1,23 @@ package query -type HealthCheck struct { -} +import "net/http" + +type HealthCheck struct {} + +const healthCheckPath = "/health-check" func (hc HealthCheck) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (hc HealthCheck) GetMethod() string { + return http.MethodGet +} + +func (hc HealthCheck) GetPath() string { + return healthCheckPath +} + func (hc HealthCheck) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/health_check_test.go b/query/health_check_test.go index aab157c..9d187e4 100644 --- a/query/health_check_test.go +++ b/query/health_check_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -18,6 +19,22 @@ func TestHealthCheckGetBody(t *testing.T) { g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestHealthCheckGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestHealthCheckGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.HealthCheckPath)) +} + func TestHealthCheckGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go index f86d6d2..c1a4c01 100644 --- a/query/maximum_trade_amounts.go +++ b/query/maximum_trade_amounts.go @@ -1,12 +1,23 @@ package query -type MaximumTradeAmounts struct { -} +import "net/http" + +type MaximumTradeAmounts struct {} + +const maximumTradeAmountsPath = "/order/maximums" func (mta MaximumTradeAmounts) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (mta MaximumTradeAmounts) GetMethod() string { + return http.MethodGet +} + +func (mta MaximumTradeAmounts) GetPath() string { + return maximumTradeAmountsPath +} + func (mta MaximumTradeAmounts) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go index 26d9e4c..6f49002 100644 --- a/query/maximum_trade_amounts_test.go +++ b/query/maximum_trade_amounts_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -18,6 +19,22 @@ func TestMaximumTradeAmountsGetBody(t *testing.T) { g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestMaximumTradeAmountsGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestMaximumTradeAmountsGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.MaximumTradeAmountsPath)) +} + func TestMaximumTradeAmountsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/minimum_trade_amounts.go b/query/minimum_trade_amounts.go index 0a5c913..d3369d4 100644 --- a/query/minimum_trade_amounts.go +++ b/query/minimum_trade_amounts.go @@ -1,12 +1,23 @@ package query -type MinimumTradeAmounts struct { -} +import "net/http" + +type MinimumTradeAmounts struct {} + +const minimumTradeAmountsPath = "/order/minimums" func (mta MinimumTradeAmounts) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (mta MinimumTradeAmounts) GetMethod() string { + return http.MethodGet +} + +func (mta MinimumTradeAmounts) GetPath() string { + return minimumTradeAmountsPath +} + func (mta MinimumTradeAmounts) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/minimum_trade_amounts_test.go b/query/minimum_trade_amounts_test.go index a723087..46dc010 100644 --- a/query/minimum_trade_amounts_test.go +++ b/query/minimum_trade_amounts_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -18,6 +19,22 @@ func TestMinimumTradeAmountsGetBody(t *testing.T) { g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestMinimumTradeAmountsGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmounts{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestMinimumTradeAmountsGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmounts{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.MinimumTradeAmountsPath)) +} + func TestMinimumTradeAmountGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/new_order.go b/query/new_order.go index 44d75c7..a1dbae0 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -1,6 +1,9 @@ package query -import "encoding/json" +import ( + "encoding/json" + "net/http" +) type NewOrderBody struct { OrderType string `json:"order_type"` @@ -15,6 +18,8 @@ type NewOrder struct { Body NewOrderBody } +const newOrderPath = "/order/new" + func (no NewOrder) GetBody() ([]byte, error) { body, err := json.Marshal(no.Body) if err != nil { @@ -23,6 +28,14 @@ func (no NewOrder) GetBody() ([]byte, error) { return body, nil } +func (no NewOrder) GetMethod() string { + return http.MethodPost +} + +func (no NewOrder) GetPath() string { + return newOrderPath +} + func (no NewOrder) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/new_order_test.go b/query/new_order_test.go index ea90d7e..999c048 100644 --- a/query/new_order_test.go +++ b/query/new_order_test.go @@ -2,6 +2,7 @@ package query_test import ( "encoding/json" + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -9,21 +10,24 @@ import ( "github.com/onsi/gomega" ) -func TestNewOrderGetBody(t *testing.T) { - g := gomega.NewGomegaWithT(t) - - body := query.NewOrderBody{ - OrderType: "LIMIT", - TimeInForce: query.IOC, - Side: "BUY", - Symbol: "BTC_USDC", - Price: 10.0, - Quantity: 2.5, +var ( + body query.NewOrderBody = query.NewOrderBody{ + OrderType: "LIMIT", + TimeInForce: query.IOC, + Side: "BUY", + Symbol: "BTC_USDC", + Price: 10.0, + Quantity: 2.5, } - - sut := &query.NewOrder{ + validNewOrder query.NewOrder = query.NewOrder{ Body: body, } +) + +func TestNewOrderGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validNewOrder actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) @@ -35,19 +39,26 @@ func TestNewOrderGetBody(t *testing.T) { g.Expect(actualBodyParsed).Should(gomega.BeEquivalentTo(body)) } +func TestNewOrderGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.NewOrder{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodPost)) +} + +func TestNewOrderGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.NewOrder{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.NewOrderPath)) +} + func TestNewOrderGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.NewOrder{ - Body: query.NewOrderBody{ - OrderType: "LIMIT", - TimeInForce: query.IOC, - Side: "BUY", - Symbol: "BTC_USDC", - Price: 10.0, - Quantity: 2.5, - }, - } + sut := &validNewOrder parameters := sut.GetParameters() @@ -57,7 +68,7 @@ func TestNewOrderGetParameters(t *testing.T) { func TestNewOrderIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.NewOrder{} + sut := &validNewOrder g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) } diff --git a/query/open_orders.go b/query/open_orders.go index bf6f412..ac2659f 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -1,6 +1,9 @@ package query -import "strconv" +import ( + "net/http" + "strconv" +) type OpenOrders struct { Limit int @@ -9,10 +12,20 @@ type OpenOrders struct { TimeInForce TimeInForceAllowedValue } +const openOrdersPath = "/order/open" + func (oo OpenOrders) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (oo OpenOrders) GetMethod() string { + return http.MethodGet +} + +func (oo OpenOrders) GetPath() string { + return openOrdersPath +} + func (oo OpenOrders) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 76f9505..8ac0918 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "strconv" "testing" @@ -8,27 +9,44 @@ import ( "github.com/onsi/gomega" ) +const( + symbol = "BTC_USDC" + timeInForce = query.IOC +) + +var validOpenOrders query.OpenOrders = query.OpenOrders{ + limit, + offset, + symbol, + timeInForce, +} func TestOpenOrdersGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) - limit := 1 - offset := 0 - symbol := "BTC_USDC" - timeInForce := query.IOC - - sut := &query.OpenOrders{ - limit, - offset, - symbol, - timeInForce, - } + sut := &validOpenOrders actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestOpenOrdersGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validOpenOrders + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestOpenOrdersGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validOpenOrders + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.OpenOrdersPath)) +} + func TestOpenOrdersGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) @@ -47,17 +65,7 @@ func TestOpenOrdersGetParametersNoFilter(t *testing.T) { func TestOpenOrdersGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - limit := 1 - offset := 0 - symbol := "BTC_USDC" - timeInForce := query.IOC - - sut := &query.OpenOrders{ - limit, - offset, - symbol, - timeInForce, - } + sut := &validOpenOrders parameters := sut.GetParameters() @@ -74,12 +82,7 @@ func TestOpenOrdersGetParameters(t *testing.T) { func TestOpenOrdersIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.OpenOrders{ - query.ANY, - query.ANY, - query.NO_FILTER, - query.NO_FILTER_VALUE, - } + sut := &validOpenOrders g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) } diff --git a/query/order_history.go b/query/order_history.go index e84631c..2a418f0 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -1,6 +1,9 @@ package query -import "strconv" +import ( + "net/http" + "strconv" +) type OrderHistory struct { Limit int @@ -11,10 +14,20 @@ type OrderHistory struct { TimeInForce TimeInForceAllowedValue } +const orderHistoryPath = "/order/history" + func (oh OrderHistory) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (oh OrderHistory) GetMethod() string { + return http.MethodGet +} + +func (oh OrderHistory) GetPath() string { + return orderHistoryPath +} + func (oh OrderHistory) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/order_history_test.go b/query/order_history_test.go index 2bfd551..9484d7c 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "strconv" "testing" "time" @@ -10,17 +11,10 @@ import ( "github.com/onsi/gomega" ) -func TestOrderHistoryGetBody(t *testing.T) { - g := gomega.NewGomegaWithT(t) - - limit := 1 - offset := 0 - startDate := time.Now().Unix() - endDate := startDate + 1 - symbol := "BTC_USDC" - timeInForce := query.IOC - - sut := &query.OrderHistory{ +var ( + startDate = time.Now().Unix() + endDate = startDate + 1 + validOrderHistory = query.OrderHistory{ limit, offset, startDate, @@ -28,12 +22,34 @@ func TestOrderHistoryGetBody(t *testing.T) { symbol, timeInForce, } +) + +func TestOrderHistoryGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validOrderHistory actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestOrderHistoryGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validOrderHistory + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestOrderHistoryGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validOrderHistory + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.OrderHistoryPath)) +} + func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) @@ -54,21 +70,7 @@ func TestOrdersHistoryGetParametersNoFilter(t *testing.T) { func TestOrdersHistoryGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - limit := 1 - offset := 0 - startDate := time.Now().Unix() - endDate := startDate + 1 - symbol := "BTC_USDC" - timeInForce := query.IOC - - sut := &query.OrderHistory{ - limit, - offset, - startDate, - endDate, - symbol, - timeInForce, - } + sut := &validOrderHistory parameters := sut.GetParameters() @@ -87,14 +89,7 @@ func TestOrdersHistoryGetParameters(t *testing.T) { func TestOrderHistoryIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.OrderHistory{ - query.ANY, - query.ANY, - int64(query.ANY), - int64(query.ANY), - query.NO_FILTER, - query.NO_FILTER_VALUE, - } + sut := &validOrderHistory g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) } diff --git a/query/symbols.go b/query/symbols.go index c8a0239..3b6706f 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -1,13 +1,25 @@ package query +import "net/http" + type Symbols struct { BaseAsset, QuoteAsset string } +const symbolsPath = "/symbols" + func (s Symbols) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (s Symbols) GetMethod() string { + return http.MethodGet +} + +func (s Symbols) GetPath() string { + return symbolsPath +} + func (s Symbols) GetParameters() []Parameter { params := make([]Parameter, 0) diff --git a/query/symbols_test.go b/query/symbols_test.go index 38e7980..6442790 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -8,22 +9,42 @@ import ( "github.com/onsi/gomega" ) +const ( + baseAsset = "BTC" + quoteAsset = "ETH" +) + +var validSymbols = query.Symbols{ + baseAsset, + quoteAsset, +} + func TestSymbolsGetBody(t *testing.T) { g := gomega.NewGomegaWithT(t) - baseAsset := "BTC" - quoteAsset := "ETH" - - sut := &query.Symbols{ - baseAsset, - quoteAsset, - } + sut := &validSymbols actualBody, err := sut.GetBody() g.Expect(err).Should(gomega.BeNil()) g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestSymbolsGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validSymbols + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestSymbolsGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validSymbols + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.SymbolsPath)) +} + func TestSymbolsGetParametersNoFilter(t *testing.T) { g := gomega.NewGomegaWithT(t) @@ -40,13 +61,7 @@ func TestSymbolsGetParametersNoFilter(t *testing.T) { func TestSymbolsGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) - baseAsset := "BTC" - quoteAsset := "ETH" - - sut := &query.Symbols{ - baseAsset, - quoteAsset, - } + sut := &validSymbols parameters := sut.GetParameters() @@ -61,10 +76,7 @@ func TestSymbolsGetParameters(t *testing.T) { func TestSymbolsIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) - sut := &query.Symbols{ - query.NO_FILTER, - query.NO_FILTER, - } + sut := &validSymbols g.Expect(sut.IsPublic()).Should(gomega.BeTrue()) } diff --git a/query/tick_sizes.go b/query/tick_sizes.go index fa659e7..7b55152 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -1,12 +1,23 @@ package query -type TickSizes struct { -} +import "net/http" + +type TickSizes struct {} + +const tickSizesPath = "/order/tick-sizes" func (ts TickSizes) GetBody() ([]byte, error) { return []byte(EMPTY_BODY), nil } +func (ts TickSizes) GetMethod() string { + return http.MethodGet +} + +func (ts TickSizes) GetPath() string { + return tickSizesPath +} + func (ts TickSizes) GetParameters() []Parameter { return []Parameter{} } diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go index 5c73823..5999507 100644 --- a/query/tick_sizes_test.go +++ b/query/tick_sizes_test.go @@ -1,6 +1,7 @@ package query_test import ( + "net/http" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -18,6 +19,22 @@ func TestTickSizesGetBody(t *testing.T) { g.Expect(actualBody).Should(gomega.BeEquivalentTo(query.EMPTY_BODY)) } +func TestTickSizesGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodGet)) +} + +func TestTickSizesGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.TickSizesPath)) +} + func TestTickSizesGetParameters(t *testing.T) { g := gomega.NewGomegaWithT(t) From 90dbd725098fc0897e9af1b0835241fbd292c3c9 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Tue, 26 Oct 2021 22:38:03 -0700 Subject: [PATCH 17/29] implement GetResponse for TickSizes --- newton.go | 12 +++--------- query/common.go | 1 + query/tick_sizes.go | 8 ++++++++ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/newton.go b/newton.go index 608855f..3ff401d 100644 --- a/newton.go +++ b/newton.go @@ -24,12 +24,6 @@ type Newton struct { clientSecret string } -type GetTickSizesResp struct { - Ticks map[string]struct { - Tick float64 `json:"tick"` - } -} - type GetMaxTradeAmountsResp struct { TradeAmounts map[string]struct { Buy float64 `json:"buy"` @@ -209,7 +203,7 @@ func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { // Public API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) TickSizes() (*GetTickSizesResp, error) { +func (n *Newton) TickSizes() (interface{}, error) { query := &query.TickSizes{} res, err := n.Do(query) if err != nil { @@ -221,8 +215,8 @@ func (n *Newton) TickSizes() (*GetTickSizesResp, error) { return nil, err } - var resp GetTickSizesResp - err = json.Unmarshal(body, &resp.Ticks) + var resp interface{} = query.GetResponse() + err = json.Unmarshal(body, &resp) if err != nil { return nil, err } diff --git a/query/common.go b/query/common.go index 657f765..f76916c 100644 --- a/query/common.go +++ b/query/common.go @@ -48,5 +48,6 @@ type Query interface { GetMethod() string GetPath() string GetParameters() []Parameter + // GetResponse() interface{} IsPublic() bool } diff --git a/query/tick_sizes.go b/query/tick_sizes.go index 7b55152..f1d5096 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -4,6 +4,10 @@ import "net/http" type TickSizes struct {} +type TickSizesResponse map[string]struct { + Tick float64 `json:"tick"` +} + const tickSizesPath = "/order/tick-sizes" func (ts TickSizes) GetBody() ([]byte, error) { @@ -22,6 +26,10 @@ func (ts TickSizes) GetParameters() []Parameter { return []Parameter{} } +func (ts TickSizes) GetResponse() interface{} { + return TickSizesResponse{} +} + func (ts TickSizes) IsPublic() bool { return true } From 839ee76a080e9fdb074f735d65da8c3d5483c736 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Tue, 26 Oct 2021 22:44:44 -0700 Subject: [PATCH 18/29] implement max and min trade amounts GetResponse --- newton.go | 23 +++++++---------------- query/maximum_trade_amounts.go | 9 +++++++++ query/minimum_trade_amounts.go | 9 +++++++++ query/tick_sizes.go | 2 +- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/newton.go b/newton.go index 3ff401d..c89d1c8 100644 --- a/newton.go +++ b/newton.go @@ -24,13 +24,6 @@ type Newton struct { clientSecret string } -type GetMaxTradeAmountsResp struct { - TradeAmounts map[string]struct { - Buy float64 `json:"buy"` - Sell float64 `json:"sell"` - } -} - type GetApplicableFeesResp struct { Fees struct { Maker float64 `json:"maker"` @@ -38,8 +31,6 @@ type GetApplicableFeesResp struct { } } -type GetMinTradeAmountsResp GetMaxTradeAmountsResp - type GetSymbolsResp struct { Symbols []string } @@ -215,7 +206,7 @@ func (n *Newton) TickSizes() (interface{}, error) { return nil, err } - var resp interface{} = query.GetResponse() + resp := query.GetResponse() err = json.Unmarshal(body, &resp) if err != nil { return nil, err @@ -224,7 +215,7 @@ func (n *Newton) TickSizes() (interface{}, error) { return &resp, nil } -func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { +func (n *Newton) MaximumTradeAmounts() (interface{}, error) { query := &query.MaximumTradeAmounts{} res, err := n.Do(query) if err != nil { @@ -236,8 +227,8 @@ func (n *Newton) MaximumTradeAmounts() (*GetMaxTradeAmountsResp, error) { return nil, err } - var resp GetMaxTradeAmountsResp - err = json.Unmarshal(body, &resp.TradeAmounts) + resp := query.GetResponse() + err = json.Unmarshal(body, &resp) if err != nil { return nil, err } @@ -300,7 +291,7 @@ func (n *Newton) HealthCheck() error { return nil } -func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { +func (n *Newton) MinimumTradeAmount() (interface{}, error) { query := &query.MinimumTradeAmounts{} res, err := n.Do(query) if err != nil { @@ -312,8 +303,8 @@ func (n *Newton) MinimumTradeAmount() (*GetMinTradeAmountsResp, error) { return nil, err } - var resp GetMinTradeAmountsResp - err = json.Unmarshal(body, &resp.TradeAmounts) + resp := query.GetResponse() + err = json.Unmarshal(body, &resp) if err != nil { return nil, err } diff --git a/query/maximum_trade_amounts.go b/query/maximum_trade_amounts.go index c1a4c01..f2d39dd 100644 --- a/query/maximum_trade_amounts.go +++ b/query/maximum_trade_amounts.go @@ -4,6 +4,11 @@ import "net/http" type MaximumTradeAmounts struct {} +type MaximumTradeAmountsResponse map[string]struct { + Buy float64 `json:"buy"` + Sell float64 `json:"sell"` +} + const maximumTradeAmountsPath = "/order/maximums" func (mta MaximumTradeAmounts) GetBody() ([]byte, error) { @@ -22,6 +27,10 @@ func (mta MaximumTradeAmounts) GetParameters() []Parameter { return []Parameter{} } +func (mta MaximumTradeAmounts) GetResponse() interface{} { + return &MaximumTradeAmountsResponse{} +} + func (mta MaximumTradeAmounts) IsPublic() bool { return true } diff --git a/query/minimum_trade_amounts.go b/query/minimum_trade_amounts.go index d3369d4..2e122a1 100644 --- a/query/minimum_trade_amounts.go +++ b/query/minimum_trade_amounts.go @@ -4,6 +4,11 @@ import "net/http" type MinimumTradeAmounts struct {} +type MinimumTradeAmountsResponse map[string]struct { + Buy float64 `json:"buy"` + Sell float64 `json:"sell"` +} + const minimumTradeAmountsPath = "/order/minimums" func (mta MinimumTradeAmounts) GetBody() ([]byte, error) { @@ -22,6 +27,10 @@ func (mta MinimumTradeAmounts) GetParameters() []Parameter { return []Parameter{} } +func (mta MinimumTradeAmounts) GetResponse() interface{} { + return &MinimumTradeAmountsResponse{} +} + func (mta MinimumTradeAmounts) IsPublic() bool { return true } diff --git a/query/tick_sizes.go b/query/tick_sizes.go index f1d5096..caa4500 100644 --- a/query/tick_sizes.go +++ b/query/tick_sizes.go @@ -27,7 +27,7 @@ func (ts TickSizes) GetParameters() []Parameter { } func (ts TickSizes) GetResponse() interface{} { - return TickSizesResponse{} + return &TickSizesResponse{} } func (ts TickSizes) IsPublic() bool { From 042761539bfc99b900fa143155151f99082c3d5b Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Tue, 26 Oct 2021 22:55:33 -0700 Subject: [PATCH 19/29] test GetResponse for TickSizes, max and min trade amounts --- query/maximum_trade_amounts_test.go | 11 +++++++++++ query/minimum_trade_amounts_test.go | 11 +++++++++++ query/tick_sizes_test.go | 11 +++++++++++ 3 files changed, 33 insertions(+) diff --git a/query/maximum_trade_amounts_test.go b/query/maximum_trade_amounts_test.go index 6f49002..4266662 100644 --- a/query/maximum_trade_amounts_test.go +++ b/query/maximum_trade_amounts_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -45,6 +46,16 @@ func TestMaximumTradeAmountsGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestMaximumTradeAmountsGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MaximumTradeAmounts{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.MaximumTradeAmountsResponse{}))) +} + func TestMaximumTradeAmountsIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/minimum_trade_amounts_test.go b/query/minimum_trade_amounts_test.go index 46dc010..6446029 100644 --- a/query/minimum_trade_amounts_test.go +++ b/query/minimum_trade_amounts_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -45,6 +46,16 @@ func TestMinimumTradeAmountGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestMinimumTradeAmountsGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.MinimumTradeAmounts{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.MinimumTradeAmountsResponse{}))) +} + func TestMinimumTradeAmountIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/tick_sizes_test.go b/query/tick_sizes_test.go index 5999507..aa7f635 100644 --- a/query/tick_sizes_test.go +++ b/query/tick_sizes_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -45,6 +46,16 @@ func TestTickSizesGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestTickSizesGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.TickSizes{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.TickSizesResponse{}))) +} + func TestTickSizesIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) From 7a1eb283fa90cef5203482053fc2c389f99b807c Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Tue, 26 Oct 2021 23:34:56 -0700 Subject: [PATCH 20/29] implement and test GetResponse for all queries --- newton.go | 113 +++++++++------------------------- query/actions.go | 14 +++++ query/actions_test.go | 11 ++++ query/applicable_fees.go | 9 +++ query/applicable_fees_test.go | 11 ++++ query/balances.go | 6 ++ query/balances_test.go | 11 ++++ query/common.go | 2 +- query/health_check.go | 4 ++ query/health_check_test.go | 11 ++++ query/new_order.go | 18 ++++++ query/new_order_test.go | 11 ++++ query/open_orders.go | 18 ++++++ query/open_orders_test.go | 11 ++++ query/order_history.go | 19 ++++++ query/order_history_test.go | 11 ++++ query/symbols.go | 6 ++ query/symbols_test.go | 11 ++++ 18 files changed, 211 insertions(+), 86 deletions(-) diff --git a/newton.go b/newton.go index c89d1c8..42f496a 100644 --- a/newton.go +++ b/newton.go @@ -24,63 +24,6 @@ type Newton struct { clientSecret string } -type GetApplicableFeesResp struct { - Fees struct { - Maker float64 `json:"maker"` - Taker float64 `json:"taker"` - } -} - -type GetSymbolsResp struct { - Symbols []string -} - -type BalancesResp struct { - Balances map[string]float64 -} - -type OpenOrdersResp struct { - OpenOrders []struct { - OrderID string `json:"order_id"` - Symbol string `json:"symbol"` - Quantity int `json:"quantity"` - Price float64 `json:"price"` - DateCreated time.Time `json:"date_created"` - OrderType string `json:"order_type"` - TimeInForce string `json:"time_in_force"` - Side string `json:"side"` - QuantityLeft float64 `json:"quantity_left"` - ExpiryTime time.Time `json:"expiry_time"` - } -} - -type OrderHistoryResp struct { - OrdersHistory []struct { - OrderID string `json:"order_id"` - Symbol string `json:"symbol"` - Quantity int `json:"quantity"` - Price float64 `json:"price"` - Status string `json:"status"` - DateCreated time.Time `json:"date_created"` - DateExecuted string `json:"date_executed"` - OrderType string `json:"order_type"` - TimeInForce string `json:"time_in_force"` - Side string `json:"side"` - ExpiryTime time.Time `json:"expiry_time,omitempty"` - } -} - -type ActionsResp struct { - Actions []struct { - Type string `json:"type"` - Asset string `json:"asset"` - Quantity float64 `json:"quantity"` - Status string `json:"status"` - DateCreated time.Time `json:"date_created"` - Price float64 `json:"price,omitempty"` - } -} - func New(ClientId string, ClientSecret string) *Newton { return &Newton{ClientId, ClientSecret} } @@ -236,7 +179,7 @@ func (n *Newton) MaximumTradeAmounts() (interface{}, error) { return &resp, nil } -func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { +func (n *Newton) ApplicableFees() (interface{}, error) { query := &query.ApplicableFees{} res, err := n.Do(query) if err != nil { @@ -248,16 +191,16 @@ func (n *Newton) ApplicableFees() (*GetApplicableFeesResp, error) { return nil, err } - var resp GetApplicableFeesResp - err = json.Unmarshal(body, &resp.Fees) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &resp, nil + return response, nil } -func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { +func (n *Newton) Symbols(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -268,13 +211,13 @@ func (n *Newton) Symbols(query query.Query) (*GetSymbolsResp, error) { return nil, err } - var resp GetSymbolsResp - err = json.Unmarshal(body, &resp.Symbols) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &resp, nil + return response, nil } func (n *Newton) HealthCheck() error { @@ -314,7 +257,7 @@ func (n *Newton) MinimumTradeAmount() (interface{}, error) { // Private API /////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { +func (n *Newton) Balances(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -325,16 +268,16 @@ func (n *Newton) Balances(query query.Query) (*BalancesResp, error) { return nil, err } - var b BalancesResp - err = json.Unmarshal(body, &b.Balances) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &b, nil + return response, nil } -func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { +func (n *Newton) Actions(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -345,16 +288,16 @@ func (n *Newton) Actions(query query.Query) (*ActionsResp, error) { return nil, err } - var r ActionsResp - err = json.Unmarshal(body, &r.Actions) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &r, nil + return response, nil } -func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { +func (n *Newton) OrderHistory(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -365,16 +308,16 @@ func (n *Newton) OrderHistory(query query.Query) (*OrderHistoryResp, error) { return nil, err } - var r OrderHistoryResp - err = json.Unmarshal(body, &r.OrdersHistory) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &r, nil + return response, nil } -func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { +func (n *Newton) OpenOrders(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -385,16 +328,16 @@ func (n *Newton) OpenOrders(query query.Query) (*OpenOrdersResp, error) { return nil, err } - var r OpenOrdersResp - err = json.Unmarshal(body, &r.OpenOrders) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &r, nil + return response, nil } -func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { +func (n *Newton) NewOrder(query query.Query) (interface{}, error) { res, err := n.Do(query) if err != nil { return nil, err @@ -405,11 +348,11 @@ func (n *Newton) NewOrder(query query.Query) (*OpenOrdersResp, error) { return nil, err } - var r OpenOrdersResp - err = json.Unmarshal(body, &r.OpenOrders) + response := query.GetResponse() + err = json.Unmarshal(body, response) if err != nil { return nil, err } - return &r, nil + return response, nil } diff --git a/query/actions.go b/query/actions.go index 66c954f..aa1a812 100644 --- a/query/actions.go +++ b/query/actions.go @@ -3,6 +3,7 @@ package query import ( "net/http" "strconv" + "time" ) type Actions struct { @@ -13,6 +14,15 @@ type Actions struct { EndDate int64 } +type ActionsResponse []struct { + Type string `json:"type"` + Asset string `json:"asset"` + Quantity float64 `json:"quantity"` + Status string `json:"status"` + DateCreated time.Time `json:"date_created"` + Price float64 `json:"price,omitempty"` +} + const actionsPath = "/actions" func (a Actions) GetMethod() string { @@ -53,6 +63,10 @@ func (a Actions) GetParameters() []Parameter { return params } +func (a Actions) GetResponse() interface{} { + return &ActionsResponse{} +} + func (a Actions) IsPublic() bool { return false } diff --git a/query/actions_test.go b/query/actions_test.go index bfe2c6e..a9b47ad 100644 --- a/query/actions_test.go +++ b/query/actions_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "strconv" "testing" "time" @@ -89,6 +90,16 @@ func TestActionsGetParameters(t *testing.T) { )) } +func TestActionsGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Actions{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.ActionsResponse{}))) +} + func TestActionsIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/applicable_fees.go b/query/applicable_fees.go index ed41c92..8524104 100644 --- a/query/applicable_fees.go +++ b/query/applicable_fees.go @@ -4,6 +4,11 @@ import "net/http" type ApplicableFees struct {} +type ApplicableFeesResponse struct { + Maker float64 `json:"maker"` + Taker float64 `json:"taker"` +} + const applicableFeesPath = "/fees" func (af ApplicableFees) GetBody() ([]byte, error) { @@ -22,6 +27,10 @@ func (af ApplicableFees) GetParameters() []Parameter { return []Parameter{} } +func (af ApplicableFees) GetResponse() interface{} { + return &ApplicableFeesResponse{} +} + func (af ApplicableFees) IsPublic() bool { return true } diff --git a/query/applicable_fees_test.go b/query/applicable_fees_test.go index 558711f..e6b07e5 100644 --- a/query/applicable_fees_test.go +++ b/query/applicable_fees_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -45,6 +46,16 @@ func TestApplicableFeesGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestApplicableFeesGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.ApplicableFees{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.ApplicableFeesResponse{}))) +} + func TestApplicableFeesIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/balances.go b/query/balances.go index eecc8a2..95a58c9 100644 --- a/query/balances.go +++ b/query/balances.go @@ -6,6 +6,8 @@ type Balances struct { Asset string } +type BalancesResponse map[string]float64 + const balancesPath = "/balances" func (b Balances) GetBody() ([]byte, error) { @@ -30,6 +32,10 @@ func (b Balances) GetParameters() []Parameter { return params } +func (b Balances) GetResponse() interface{} { + return &Balances{} +} + func (b Balances) IsPublic() bool { return false } diff --git a/query/balances_test.go b/query/balances_test.go index d62d640..5e8817e 100644 --- a/query/balances_test.go +++ b/query/balances_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -66,6 +67,16 @@ func TestBalancesGetParameters(t *testing.T) { )) } +func TestBalancesGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Balances{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.BalancesResponse{}))) +} + func TestBalancesIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/common.go b/query/common.go index f76916c..48196c6 100644 --- a/query/common.go +++ b/query/common.go @@ -48,6 +48,6 @@ type Query interface { GetMethod() string GetPath() string GetParameters() []Parameter - // GetResponse() interface{} + GetResponse() interface{} IsPublic() bool } diff --git a/query/health_check.go b/query/health_check.go index eff63e4..35a4d9f 100644 --- a/query/health_check.go +++ b/query/health_check.go @@ -22,6 +22,10 @@ func (hc HealthCheck) GetParameters() []Parameter { return []Parameter{} } +func (hc HealthCheck) GetResponse() interface{} { + return nil +} + func (hc HealthCheck) IsPublic() bool { return true } diff --git a/query/health_check_test.go b/query/health_check_test.go index 9d187e4..616aa94 100644 --- a/query/health_check_test.go +++ b/query/health_check_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -45,6 +46,16 @@ func TestHealthCheckGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestHealthCheckGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.HealthCheck{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.BeNil()) +} + func TestHealthCheckIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/new_order.go b/query/new_order.go index a1dbae0..fca0e2f 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -3,6 +3,7 @@ package query import ( "encoding/json" "net/http" + "time" ) type NewOrderBody struct { @@ -18,6 +19,19 @@ type NewOrder struct { Body NewOrderBody } +type NewOrderResponse []struct { + OrderID string `json:"order_id"` + Symbol string `json:"symbol"` + Quantity int `json:"quantity"` + Price float64 `json:"price"` + DateCreated time.Time `json:"date_created"` + OrderType string `json:"order_type"` + TimeInForce string `json:"time_in_force"` + Side string `json:"side"` + QuantityLeft float64 `json:"quantity_left"` + ExpiryTime time.Time `json:"expiry_time"` +} + const newOrderPath = "/order/new" func (no NewOrder) GetBody() ([]byte, error) { @@ -40,6 +54,10 @@ func (no NewOrder) GetParameters() []Parameter { return []Parameter{} } +func (no NewOrder) GetResponse() interface{} { + return &OpenOrdersResponse{} +} + func (no NewOrder) IsPublic() bool { return false } diff --git a/query/new_order_test.go b/query/new_order_test.go index 999c048..6fa5254 100644 --- a/query/new_order_test.go +++ b/query/new_order_test.go @@ -3,6 +3,7 @@ package query_test import ( "encoding/json" "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -65,6 +66,16 @@ func TestNewOrderGetParameters(t *testing.T) { g.Expect(len(parameters)).Should(gomega.Equal(0)) } +func TestNewOrderGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.NewOrder{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.NewOrderResponse{}))) +} + func TestNewOrderIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/open_orders.go b/query/open_orders.go index ac2659f..539fb54 100644 --- a/query/open_orders.go +++ b/query/open_orders.go @@ -3,6 +3,7 @@ package query import ( "net/http" "strconv" + "time" ) type OpenOrders struct { @@ -12,6 +13,19 @@ type OpenOrders struct { TimeInForce TimeInForceAllowedValue } +type OpenOrdersResponse []struct { + OrderID string `json:"order_id"` + Symbol string `json:"symbol"` + Quantity int `json:"quantity"` + Price float64 `json:"price"` + DateCreated time.Time `json:"date_created"` + OrderType string `json:"order_type"` + TimeInForce string `json:"time_in_force"` + Side string `json:"side"` + QuantityLeft float64 `json:"quantity_left"` + ExpiryTime time.Time `json:"expiry_time"` +} + const openOrdersPath = "/order/open" func (oo OpenOrders) GetBody() ([]byte, error) { @@ -48,6 +62,10 @@ func (oo OpenOrders) GetParameters() []Parameter { return params } +func (oo OpenOrders) GetResponse() interface{} { + return &OpenOrdersResponse{} +} + func (oo OpenOrders) IsPublic() bool { return false } diff --git a/query/open_orders_test.go b/query/open_orders_test.go index 8ac0918..e54f117 100644 --- a/query/open_orders_test.go +++ b/query/open_orders_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "strconv" "testing" @@ -79,6 +80,16 @@ func TestOpenOrdersGetParameters(t *testing.T) { )) } +func TestOpenOrdersGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OpenOrders{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.OpenOrdersResponse{}))) +} + func TestOpenOrdersIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/order_history.go b/query/order_history.go index 2a418f0..687a80c 100644 --- a/query/order_history.go +++ b/query/order_history.go @@ -3,6 +3,7 @@ package query import ( "net/http" "strconv" + "time" ) type OrderHistory struct { @@ -14,6 +15,20 @@ type OrderHistory struct { TimeInForce TimeInForceAllowedValue } +type OrderHistoryResponse []struct { + OrderID string `json:"order_id"` + Symbol string `json:"symbol"` + Quantity int `json:"quantity"` + Price float64 `json:"price"` + Status string `json:"status"` + DateCreated time.Time `json:"date_created"` + DateExecuted string `json:"date_executed"` + OrderType string `json:"order_type"` + TimeInForce string `json:"time_in_force"` + Side string `json:"side"` + ExpiryTime time.Time `json:"expiry_time,omitempty"` +} + const orderHistoryPath = "/order/history" func (oh OrderHistory) GetBody() ([]byte, error) { @@ -58,6 +73,10 @@ func (oh OrderHistory) GetParameters() []Parameter { return params } +func (oh OrderHistory) GetResponse() interface{} { + return &OrderHistoryResponse{} +} + func (oh OrderHistory) IsPublic() bool { return false } diff --git a/query/order_history_test.go b/query/order_history_test.go index 9484d7c..217099e 100644 --- a/query/order_history_test.go +++ b/query/order_history_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "strconv" "testing" "time" @@ -86,6 +87,16 @@ func TestOrdersHistoryGetParameters(t *testing.T) { )) } +func TestOrderHistoryGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.OrderHistory{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.OrderHistoryResponse{}))) +} + func TestOrderHistoryIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/query/symbols.go b/query/symbols.go index 3b6706f..dc765f2 100644 --- a/query/symbols.go +++ b/query/symbols.go @@ -6,6 +6,8 @@ type Symbols struct { BaseAsset, QuoteAsset string } +type SymbolsResponse []string + const symbolsPath = "/symbols" func (s Symbols) GetBody() ([]byte, error) { @@ -34,6 +36,10 @@ func (s Symbols) GetParameters() []Parameter { return params } +func (s Symbols) GetResponse() interface{} { + return &SymbolsResponse{} +} + func (s Symbols) IsPublic() bool { return true } diff --git a/query/symbols_test.go b/query/symbols_test.go index 6442790..c812895 100644 --- a/query/symbols_test.go +++ b/query/symbols_test.go @@ -2,6 +2,7 @@ package query_test import ( "net/http" + "reflect" "testing" "github.com/dhiaayachi/go-newton-co/query" @@ -73,6 +74,16 @@ func TestSymbolsGetParameters(t *testing.T) { )) } +func TestSymbolsGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.Symbols{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.SymbolsResponse{}))) +} + func TestSymbolsIsPublic(t *testing.T) { g := gomega.NewGomegaWithT(t) From 416d083775e5d1fcfd67f10efaded72baa15d209 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Tue, 26 Oct 2021 23:49:29 -0700 Subject: [PATCH 21/29] refactor main package and unit test --- newton.go | 243 ++++--------------------------------------------- newton_test.go | 26 +++--- 2 files changed, 33 insertions(+), 236 deletions(-) diff --git a/newton.go b/newton.go index 42f496a..794f15a 100644 --- a/newton.go +++ b/newton.go @@ -80,7 +80,7 @@ func (n *Newton) sign(req *http.Request) error { return nil } -func (n *Newton) Do(query query.Query) (*http.Response, error) { +func (n *Newton) Do(query query.Query) (interface{}, error) { body, err := query.GetBody() if err != nil { return nil, err @@ -107,252 +107,49 @@ func (n *Newton) Do(query query.Query) (*http.Response, error) { } res, err := http.DefaultClient.Do(req) - - return res, err -} - -func (n *Newton) parseResponse(res *http.Response) ([]byte, error) { - defer func() { - err := res.Body.Close() - if err != nil { - log.Printf("error:%s", err.Error()) - } - }() - if res.StatusCode != http.StatusOK { - return nil, fmt.Errorf("request failed :: %d", res.StatusCode) - } - - body, err := ioutil.ReadAll(res.Body) - - if err != nil { - return nil, err - } - - if res.StatusCode != http.StatusOK { - return nil, fmt.Errorf("request failed :: %d :: %s", res.StatusCode, body) - } - - return body, nil -} - -// Public API -/////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) TickSizes() (interface{}, error) { - query := &query.TickSizes{} - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - resp := query.GetResponse() - err = json.Unmarshal(body, &resp) - if err != nil { - return nil, err - } - - return &resp, nil -} - -func (n *Newton) MaximumTradeAmounts() (interface{}, error) { - query := &query.MaximumTradeAmounts{} - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - resp := query.GetResponse() - err = json.Unmarshal(body, &resp) - if err != nil { - return nil, err - } - - return &resp, nil -} - -func (n *Newton) ApplicableFees() (interface{}, error) { - query := &query.ApplicableFees{} - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) if err != nil { return nil, err } - response := query.GetResponse() - err = json.Unmarshal(body, response) + parsedResponse := query.GetResponse() + err = n.parseResponse(res, parsedResponse) if err != nil { return nil, err } - return response, nil + return parsedResponse, err } -func (n *Newton) Symbols(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - response := query.GetResponse() - err = json.Unmarshal(body, response) - if err != nil { - return nil, err - } - - return response, nil -} +func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) error { + defer func() { + err := res.Body.Close() + if err != nil { + log.Printf("error:%s", err.Error()) + } + }() -func (n *Newton) HealthCheck() error { - query := &query.HealthCheck{} - res, err := n.Do(query) - if err != nil { - return err + if toParseTo == nil { + return nil } if res.StatusCode != http.StatusOK { return fmt.Errorf("request failed :: %d", res.StatusCode) } - return nil -} - -func (n *Newton) MinimumTradeAmount() (interface{}, error) { - query := &query.MinimumTradeAmounts{} - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - resp := query.GetResponse() - err = json.Unmarshal(body, &resp) - if err != nil { - return nil, err - } - - return &resp, nil -} - -// Private API -/////////////////////////////////////////////////////////////////////////////////////////////////// -func (n *Newton) Balances(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - response := query.GetResponse() - err = json.Unmarshal(body, response) - if err != nil { - return nil, err - } - - return response, nil -} - -func (n *Newton) Actions(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - response := query.GetResponse() - err = json.Unmarshal(body, response) - if err != nil { - return nil, err - } - - return response, nil -} - -func (n *Newton) OrderHistory(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } - - response := query.GetResponse() - err = json.Unmarshal(body, response) - if err != nil { - return nil, err - } - - return response, nil -} - -func (n *Newton) OpenOrders(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err - } + body, err := ioutil.ReadAll(res.Body) - response := query.GetResponse() - err = json.Unmarshal(body, response) if err != nil { - return nil, err + return err } - return response, nil -} - -func (n *Newton) NewOrder(query query.Query) (interface{}, error) { - res, err := n.Do(query) - if err != nil { - return nil, err - } - - body, err := n.parseResponse(res) - if err != nil { - return nil, err + if res.StatusCode != http.StatusOK { + return fmt.Errorf("request failed :: %d :: %s", res.StatusCode, body) } - response := query.GetResponse() - err = json.Unmarshal(body, response) + err = json.Unmarshal(body, toParseTo) if err != nil { - return nil, err + return err } - return response, nil + return nil } diff --git a/newton_test.go b/newton_test.go index 65a73f3..4761542 100644 --- a/newton_test.go +++ b/newton_test.go @@ -21,7 +21,7 @@ func TestGetTickSizes(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.TickSizes() + _, err := sut.Do(&query.TickSizes{}) g.Expect(err).Should(gomega.BeNil()) } @@ -32,7 +32,7 @@ func TestGetMaximumTradeAmounts(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.MaximumTradeAmounts() + _, err := sut.Do(&query.MaximumTradeAmounts{}) g.Expect(err).Should(gomega.BeNil()) } @@ -43,7 +43,7 @@ func TestGetApplicableFees(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.ApplicableFees() + _, err := sut.Do(&query.ApplicableFees{}) g.Expect(err).Should(gomega.BeNil()) } @@ -59,7 +59,7 @@ func TestSymbolsNoQuery(t *testing.T) { QuoteAsset: query.NO_FILTER, } - _, err := sut.Symbols(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -75,7 +75,7 @@ func TestSymbolsWithQuery(t *testing.T) { QuoteAsset: "ETH", } - _, err := sut.Symbols(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -86,7 +86,7 @@ func TestHealthCheck(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - err := sut.HealthCheck() + _, err := sut.Do(&query.HealthCheck{}) g.Expect(err).Should(gomega.BeNil()) } @@ -97,7 +97,7 @@ func TestGetMinTradeAmounts(t *testing.T) { ClientId, ClientSecret := getSecrets() sut := New(ClientId, ClientSecret) - _, err := sut.MinimumTradeAmount() + _, err := sut.Do(&query.MinimumTradeAmounts{}) g.Expect(err).Should(gomega.BeNil()) } @@ -111,7 +111,7 @@ func TestBalances(t *testing.T) { sut := New(ClientId, ClientSecret) q := &query.Balances{Asset: "BTC"} - _, err := sut.Balances(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -123,7 +123,7 @@ func TestBalancesNoQuery(t *testing.T) { sut := New(ClientId, ClientSecret) q := &query.Balances{Asset: query.NO_FILTER} - _, err := sut.Balances(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -142,7 +142,7 @@ func TestActions(t *testing.T) { EndDate: time.Date(2020, 01, 02, 00, 00, 00, 00, time.Local).Unix(), } - _, err := sut.Actions(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -161,7 +161,7 @@ func TestActionsNoQuery(t *testing.T) { EndDate: int64(query.ANY), } - _, err := sut.Actions(req) + _, err := sut.Do(req) g.Expect(err).Should(gomega.BeNil()) } @@ -181,7 +181,7 @@ func TestOrderHistory(t *testing.T) { TimeInForce: "IOC", } - _, err := sut.OrderHistory(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } @@ -198,7 +198,7 @@ func TestOpenOrders(t *testing.T) { Symbol: "BTC_USDC", TimeInForce: "IOC"} - _, err := sut.OpenOrders(q) + _, err := sut.Do(q) g.Expect(err).Should(gomega.BeNil()) } From 5b2e98cf7b0006f5150ee0fca25c3f28145bab13 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Wed, 27 Oct 2021 00:00:18 -0700 Subject: [PATCH 22/29] refactor newton's Do to return Response struct --- newton.go | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/newton.go b/newton.go index 794f15a..fff051b 100644 --- a/newton.go +++ b/newton.go @@ -24,6 +24,11 @@ type Newton struct { clientSecret string } +type Response struct { + StatusCode int + Body interface{} +} + func New(ClientId string, ClientSecret string) *Newton { return &Newton{ClientId, ClientSecret} } @@ -80,7 +85,7 @@ func (n *Newton) sign(req *http.Request) error { return nil } -func (n *Newton) Do(query query.Query) (interface{}, error) { +func (n *Newton) Do(query query.Query) (*Response, error) { body, err := query.GetBody() if err != nil { return nil, err @@ -90,10 +95,12 @@ func (n *Newton) Do(query query.Query) (interface{}, error) { query.GetMethod(), baseUrl + query.GetPath(), bytes.NewBuffer(body)) + q := req.URL.Query() for _, a := range query.GetParameters() { q.Add(a.Key, a.Value) } + req.URL.RawQuery = q.Encode() if query.GetMethod() != http.MethodGet { req.Header.Add("content-type", "application/json") @@ -111,8 +118,7 @@ func (n *Newton) Do(query query.Query) (interface{}, error) { return nil, err } - parsedResponse := query.GetResponse() - err = n.parseResponse(res, parsedResponse) + parsedResponse, err := n.parseResponse(res, query.GetResponse()) if err != nil { return nil, err } @@ -120,7 +126,7 @@ func (n *Newton) Do(query query.Query) (interface{}, error) { return parsedResponse, err } -func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) error { +func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) (*Response, error) { defer func() { err := res.Body.Close() if err != nil { @@ -128,28 +134,31 @@ func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) error } }() - if toParseTo == nil { - return nil + parsedResponse := &Response{ + StatusCode: res.StatusCode, + Body: nil, } - if res.StatusCode != http.StatusOK { - return fmt.Errorf("request failed :: %d", res.StatusCode) + if toParseTo == nil { + return parsedResponse, nil } body, err := ioutil.ReadAll(res.Body) if err != nil { - return err + return parsedResponse, err } - if res.StatusCode != http.StatusOK { - return fmt.Errorf("request failed :: %d :: %s", res.StatusCode, body) + if parsedResponse.StatusCode != http.StatusOK { + return parsedResponse, fmt.Errorf("request failed :: %d :: %s", res.StatusCode, body) } err = json.Unmarshal(body, toParseTo) if err != nil { - return err + return parsedResponse, err } - return nil + parsedResponse.Body = toParseTo + + return parsedResponse, nil } From 33750fc185db3f06c2f4903ee71d1c9af6443305 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 14 Nov 2021 11:23:45 -0800 Subject: [PATCH 23/29] test new order endpoint, implement mock testing and test authentication only when a specific environment variable is set --- auth_test.sh | 3 + export_test.go | 5 ++ newton.go | 13 ++-- newton_test.go | 159 ++++++++++++++++++++++++++++++++++++--------- query/new_order.go | 10 ++- 5 files changed, 149 insertions(+), 41 deletions(-) create mode 100755 auth_test.sh create mode 100644 export_test.go diff --git a/auth_test.sh b/auth_test.sh new file mode 100755 index 0000000..e3ddd7a --- /dev/null +++ b/auth_test.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +TEST_AUTH=true CLIENT_ID=$1 CLIENT_SECRET=$2 go test diff --git a/export_test.go b/export_test.go new file mode 100644 index 0000000..fe73e77 --- /dev/null +++ b/export_test.go @@ -0,0 +1,5 @@ +package newton + +const ( + BaseURL = baseUrl +) diff --git a/newton.go b/newton.go index fff051b..9b4fd6c 100644 --- a/newton.go +++ b/newton.go @@ -20,8 +20,9 @@ import ( const baseUrl = "https://api.newton.co/v1" type Newton struct { - clientId string - clientSecret string + ClientId string + ClientSecret string + BaseUrl string } type Response struct { @@ -30,7 +31,7 @@ type Response struct { } func New(ClientId string, ClientSecret string) *Newton { - return &Newton{ClientId, ClientSecret} + return &Newton{ClientId, ClientSecret, baseUrl} } func (n *Newton) sign(req *http.Request) error { @@ -72,7 +73,7 @@ func (n *Newton) sign(req *http.Request) error { raw := strings.Join(toJoin, ":") - mac := hmac.New(sha256.New, []byte(n.clientSecret)) + mac := hmac.New(sha256.New, []byte(n.ClientSecret)) if _, err := mac.Write([]byte(raw)); err != nil { return fmt.Errorf("mac write: %w", err) } @@ -80,7 +81,7 @@ func (n *Newton) sign(req *http.Request) error { signedBase64 := base64.StdEncoding.EncodeToString(mac.Sum(nil)) req.Header.Add("NewtonDate", currentTime) - req.Header.Add("NewtonAPIAuth", n.clientId+":"+signedBase64) + req.Header.Add("NewtonAPIAuth", n.ClientId+":"+signedBase64) return nil } @@ -93,7 +94,7 @@ func (n *Newton) Do(query query.Query) (*Response, error) { req, _ := http.NewRequest( query.GetMethod(), - baseUrl + query.GetPath(), + n.BaseUrl + query.GetPath(), bytes.NewBuffer(body)) q := req.URL.Query() diff --git a/newton_test.go b/newton_test.go index 4761542..55eb682 100644 --- a/newton_test.go +++ b/newton_test.go @@ -1,16 +1,29 @@ -package newton +package newton_test import ( "os" "testing" "time" + "github.com/dhiaayachi/go-newton-co" "github.com/dhiaayachi/go-newton-co/query" "github.com/onsi/gomega" ) -func getSecrets() (string, string) { - return os.Getenv("CLIENT_ID"), os.Getenv("CLIENT_SECRET") +const( + mockClientId = "mock_id" + mock_client_secret = "mock_secret" + mockServerURL = "https://stoplight.io/mocks/newton/newton-api-docs/431375" +) + +func TestNewNewton(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := newton.New(mockClientId, mock_client_secret) + + g.Expect(sut.ClientId).Should(gomega.Equal(mockClientId)) + g.Expect(sut.ClientSecret).Should(gomega.Equal(mock_client_secret)) + g.Expect(sut.BaseUrl).Should(gomega.Equal(newton.BaseURL)) } // Public API @@ -18,8 +31,11 @@ func getSecrets() (string, string) { func TestGetTickSizes(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } _, err := sut.Do(&query.TickSizes{}) @@ -29,8 +45,11 @@ func TestGetTickSizes(t *testing.T) { func TestGetMaximumTradeAmounts(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } _, err := sut.Do(&query.MaximumTradeAmounts{}) @@ -40,8 +59,11 @@ func TestGetMaximumTradeAmounts(t *testing.T) { func TestGetApplicableFees(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } _, err := sut.Do(&query.ApplicableFees{}) @@ -51,8 +73,11 @@ func TestGetApplicableFees(t *testing.T) { func TestSymbolsNoQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.Symbols{ BaseAsset: query.NO_FILTER, @@ -67,8 +92,11 @@ func TestSymbolsNoQuery(t *testing.T) { func TestSymbolsWithQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.Symbols{ BaseAsset: "BTC", @@ -83,8 +111,11 @@ func TestSymbolsWithQuery(t *testing.T) { func TestHealthCheck(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } _, err := sut.Do(&query.HealthCheck{}) @@ -94,8 +125,11 @@ func TestHealthCheck(t *testing.T) { func TestGetMinTradeAmounts(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } _, err := sut.Do(&query.MinimumTradeAmounts{}) @@ -107,8 +141,11 @@ func TestGetMinTradeAmounts(t *testing.T) { func TestBalances(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.Balances{Asset: "BTC"} _, err := sut.Do(q) @@ -119,8 +156,11 @@ func TestBalances(t *testing.T) { func TestBalancesNoQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.Balances{Asset: query.NO_FILTER} _, err := sut.Do(q) @@ -131,8 +171,11 @@ func TestBalancesNoQuery(t *testing.T) { func TestActions(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.Actions{ ActionType: query.DEPOSIT, @@ -150,8 +193,11 @@ func TestActions(t *testing.T) { func TestActionsNoQuery(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } req := &query.Actions{ ActionType: query.ActionType(query.NO_FILTER), @@ -169,8 +215,11 @@ func TestActionsNoQuery(t *testing.T) { func TestOrderHistory(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.OrderHistory{ Limit: 1, @@ -189,8 +238,11 @@ func TestOrderHistory(t *testing.T) { func TestOpenOrders(t *testing.T) { g := gomega.NewGomegaWithT(t) - ClientId, ClientSecret := getSecrets() - sut := New(ClientId, ClientSecret) + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } q := &query.OpenOrders{ Limit: 1, @@ -202,3 +254,52 @@ func TestOpenOrders(t *testing.T) { g.Expect(err).Should(gomega.BeNil()) } + +func TestNewOrder(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } + + q := &query.NewOrder{ + Body: query.NewOrderBody{ + OrderType: "LIMIT", + TimeInForce: query.IOC, + Side: "BUY", + Symbol: "BTC_USDC", + Price: 1000, + Quantity: 0.0001, + }, + } + + _, err := sut.Do(q) + + g.Expect(err).Should(gomega.BeNil()) +} + +// Newton's mock server does not utilize authnetication headers. +// Therefore, to fully test the API, we must test any private production endpoint +// with real credentials. +func TestAuthentication(t *testing.T) { + if os.Getenv("TEST_AUTH") != "true" { + t.Skip("Skipping authentication test in production environment.") + } + g := gomega.NewGomegaWithT(t) + + productionClientId := os.Getenv("CLIENT_ID") + productionClientSecret := os.Getenv("CLIENT_SECRET") + + sut := newton.Newton{ + productionClientId, + productionClientSecret, + newton.BaseURL, // production URL + } + + q := &query.Balances{Asset: "BTC"} + _, err := sut.Do(q) + + g.Expect(err).Should(gomega.BeNil()) +} diff --git a/query/new_order.go b/query/new_order.go index fca0e2f..bf54883 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -19,17 +19,15 @@ type NewOrder struct { Body NewOrderBody } -type NewOrderResponse []struct { +type NewOrderResponse struct { OrderID string `json:"order_id"` Symbol string `json:"symbol"` - Quantity int `json:"quantity"` + Quantity float64 `json:"quantity"` Price float64 `json:"price"` - DateCreated time.Time `json:"date_created"` OrderType string `json:"order_type"` TimeInForce string `json:"time_in_force"` Side string `json:"side"` - QuantityLeft float64 `json:"quantity_left"` - ExpiryTime time.Time `json:"expiry_time"` + DateCreated time.Time `json:"date_created"` } const newOrderPath = "/order/new" @@ -55,7 +53,7 @@ func (no NewOrder) GetParameters() []Parameter { } func (no NewOrder) GetResponse() interface{} { - return &OpenOrdersResponse{} + return &NewOrderResponse{} } func (no NewOrder) IsPublic() bool { From 4ea0115f40c9d0cec04807e569c733b50154ce1a Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 14 Nov 2021 11:43:46 -0800 Subject: [PATCH 24/29] update README --- README.md | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 203f637..b9739b3 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,35 @@ # go-newton-co -go api for http://newton.co/ bitcoin exchance +go api for http://newton.co/ cryptocurrency exchance -To create a client: +## Usage: -```go -n := New(, ) +For every API enpoint, there is an appropriate struct in the `query` package +that has all body and query parameters as part of the struct's fields. + +Once the appropriate query is selected, use `Do` function of the `newton` package with +the query provided. + +Example of calling Newton's `/balances` endpoint: - _, err := n.Balances("BTC") +```go +newton := New(, ) - if err != nil { - t.Error("test failed: " + err.Error()) - } +q := &query.Balances{Asset: "BTC"} +response, err := newton.Do(q) ``` -TODO: +For more examples, please reference `newton_test.go`. + +## Testing + +Newton's mock endpoint does not take authentication headers into account. To test the API with authentication enabled, +take a look at `auth_test.sh` where the following environment variables are set before running `go test`: +- TEST_AUTH - should be set to "true" +- CLIENT_ID - your real client id from Newton +- CLIENT_SECRET - your real client secret from Newton -- [x] API for private endpoints -- [x] API for public endpoints -- [ ] Add sandbox environment for unit tests +Running the script with the correct client id and client secret, will make +a request to Newton's production balances endpoint to ensure that authentication is functioning correctly. +On the other hand, running `go test` without these environment variables set will test every endpoint of the mock server. From 2fd7e977495fb46992f8cc8e4e7b5f9d8f7166ef Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 14 Nov 2021 12:01:37 -0800 Subject: [PATCH 25/29] create query for cancel order --- query/cancel_order.go | 48 +++++++++++++++++++++++ query/cancel_order_test.go | 80 ++++++++++++++++++++++++++++++++++++++ query/export_test.go | 1 + query/new_order_test.go | 6 +-- 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 query/cancel_order.go create mode 100644 query/cancel_order_test.go diff --git a/query/cancel_order.go b/query/cancel_order.go new file mode 100644 index 0000000..067997b --- /dev/null +++ b/query/cancel_order.go @@ -0,0 +1,48 @@ +package query + +import ( + "encoding/json" + "net/http" +) + +type CancelOrderBody struct { + OrderId string `json:"order_id"` +} + +type CancelOrder struct { + Body CancelOrderBody +} + +type CancelOrderResponse struct { + OrderID string `json:"order_id"` +} + +const cancelOrderPath = "/order/cancel" + +func (co CancelOrder) GetBody() ([]byte, error) { + body, err := json.Marshal(co.Body) + if err != nil { + return []byte(EMPTY_BODY), err + } + return body, nil +} + +func (co CancelOrder) GetMethod() string { + return http.MethodPost +} + +func (co CancelOrder) GetPath() string { + return cancelOrderPath +} + +func (co CancelOrder) GetParameters() []Parameter { + return []Parameter{} +} + +func (co CancelOrder) GetResponse() interface{} { + return &CancelOrderResponse{} +} + +func (co CancelOrder) IsPublic() bool { + return false +} diff --git a/query/cancel_order_test.go b/query/cancel_order_test.go new file mode 100644 index 0000000..8e4f414 --- /dev/null +++ b/query/cancel_order_test.go @@ -0,0 +1,80 @@ +package query_test + +import ( + "encoding/json" + "net/http" + "reflect" + "testing" + + "github.com/dhiaayachi/go-newton-co/query" + + "github.com/onsi/gomega" +) + +var ( + cancelOrderBody query.CancelOrderBody = query.CancelOrderBody{ + OrderId: "8c1be04a-813d-4abd-8b15-9367686afaed", + } + validCancelOrder query.CancelOrder = query.CancelOrder{ + Body: cancelOrderBody, + } +) + +func TestCancelOrderGetBody(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validCancelOrder + + actualBody, err := sut.GetBody() + g.Expect(err).Should(gomega.BeNil()) + + var actualBodyParsed query.CancelOrderBody + err = json.Unmarshal([]byte(actualBody), &actualBodyParsed) + g.Expect(err).Should(gomega.BeNil()) + + g.Expect(actualBodyParsed).Should(gomega.BeEquivalentTo(cancelOrderBody)) +} + +func TestCancelOrderGetMethod(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.CancelOrder{} + + g.Expect(sut.GetMethod()).Should(gomega.Equal(http.MethodPost)) +} + +func TestCancelOrderGetPath(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.CancelOrder{} + + g.Expect(sut.GetPath()).Should(gomega.Equal(query.CancelOrderPath)) +} + +func TestCancelOrderGetParameters(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validCancelOrder + + parameters := sut.GetParameters() + + g.Expect(len(parameters)).Should(gomega.Equal(0)) +} + +func TestCancelOrderGetResponse(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &query.CancelOrder{} + + response := sut.GetResponse() + + g.Expect(reflect.TypeOf(response)).Should(gomega.Equal(reflect.TypeOf(&query.CancelOrderResponse{}))) +} + +func TestCancelOrderIsPublic(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := &validCancelOrder + + g.Expect(sut.IsPublic()).Should(gomega.BeFalse()) +} diff --git a/query/export_test.go b/query/export_test.go index 9575b0b..ee5abcc 100644 --- a/query/export_test.go +++ b/query/export_test.go @@ -4,6 +4,7 @@ const ( ActionsPath = actionsPath ApplicableFeesPath = applicableFeesPath BalancesPath = balancesPath + CancelOrderPath = cancelOrderPath HealthCheckPath = healthCheckPath MaximumTradeAmountsPath = maximumTradeAmountsPath MinimumTradeAmountsPath = minimumTradeAmountsPath diff --git a/query/new_order_test.go b/query/new_order_test.go index 6fa5254..0981761 100644 --- a/query/new_order_test.go +++ b/query/new_order_test.go @@ -12,7 +12,7 @@ import ( ) var ( - body query.NewOrderBody = query.NewOrderBody{ + newOrderBody query.NewOrderBody = query.NewOrderBody{ OrderType: "LIMIT", TimeInForce: query.IOC, Side: "BUY", @@ -21,7 +21,7 @@ var ( Quantity: 2.5, } validNewOrder query.NewOrder = query.NewOrder{ - Body: body, + Body: newOrderBody, } ) @@ -37,7 +37,7 @@ func TestNewOrderGetBody(t *testing.T) { err = json.Unmarshal([]byte(actualBody), &actualBodyParsed) g.Expect(err).Should(gomega.BeNil()) - g.Expect(actualBodyParsed).Should(gomega.BeEquivalentTo(body)) + g.Expect(actualBodyParsed).Should(gomega.BeEquivalentTo(newOrderBody)) } func TestNewOrderGetMethod(t *testing.T) { From 36ca84e20a3539d7b1f189a0bf7404a970f680b1 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 14 Nov 2021 12:04:44 -0800 Subject: [PATCH 26/29] unit test cancel order --- newton_test.go | 20 ++++++++++++++++++++ query/new_order.go | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/newton_test.go b/newton_test.go index 55eb682..65926d3 100644 --- a/newton_test.go +++ b/newton_test.go @@ -280,6 +280,26 @@ func TestNewOrder(t *testing.T) { g.Expect(err).Should(gomega.BeNil()) } +func TestCancelOrder(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + sut := newton.Newton{ + mockClientId, + mock_client_secret, + mockServerURL, + } + + q := &query.CancelOrder{ + Body: query.CancelOrderBody{ + OrderId: "test", + }, + } + + _, err := sut.Do(q) + + g.Expect(err).Should(gomega.BeNil()) +} + // Newton's mock server does not utilize authnetication headers. // Therefore, to fully test the API, we must test any private production endpoint // with real credentials. diff --git a/query/new_order.go b/query/new_order.go index bf54883..9c66bba 100644 --- a/query/new_order.go +++ b/query/new_order.go @@ -20,7 +20,7 @@ type NewOrder struct { } type NewOrderResponse struct { - OrderID string `json:"order_id"` + OrderId string `json:"order_id"` Symbol string `json:"symbol"` Quantity float64 `json:"quantity"` Price float64 `json:"price"` From b5accbd51a1d38cbac48603cf40c2b20132f9abb Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Sun, 14 Nov 2021 21:52:23 -0800 Subject: [PATCH 27/29] gofmt --- newton.go | 10 +++++----- newton_test.go | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/newton.go b/newton.go index 9b4fd6c..5f61f78 100644 --- a/newton.go +++ b/newton.go @@ -22,12 +22,12 @@ const baseUrl = "https://api.newton.co/v1" type Newton struct { ClientId string ClientSecret string - BaseUrl string + BaseUrl string } type Response struct { StatusCode int - Body interface{} + Body interface{} } func New(ClientId string, ClientSecret string) *Newton { @@ -94,9 +94,9 @@ func (n *Newton) Do(query query.Query) (*Response, error) { req, _ := http.NewRequest( query.GetMethod(), - n.BaseUrl + query.GetPath(), + n.BaseUrl+query.GetPath(), bytes.NewBuffer(body)) - + q := req.URL.Query() for _, a := range query.GetParameters() { q.Add(a.Key, a.Value) @@ -137,7 +137,7 @@ func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) (*Resp parsedResponse := &Response{ StatusCode: res.StatusCode, - Body: nil, + Body: nil, } if toParseTo == nil { diff --git a/newton_test.go b/newton_test.go index 65926d3..a1966b2 100644 --- a/newton_test.go +++ b/newton_test.go @@ -10,10 +10,10 @@ import ( "github.com/onsi/gomega" ) -const( - mockClientId = "mock_id" +const ( + mockClientId = "mock_id" mock_client_secret = "mock_secret" - mockServerURL = "https://stoplight.io/mocks/newton/newton-api-docs/431375" + mockServerURL = "https://stoplight.io/mocks/newton/newton-api-docs/431375" ) func TestNewNewton(t *testing.T) { @@ -80,7 +80,7 @@ func TestSymbolsNoQuery(t *testing.T) { } q := &query.Symbols{ - BaseAsset: query.NO_FILTER, + BaseAsset: query.NO_FILTER, QuoteAsset: query.NO_FILTER, } @@ -99,7 +99,7 @@ func TestSymbolsWithQuery(t *testing.T) { } q := &query.Symbols{ - BaseAsset: "BTC", + BaseAsset: "BTC", QuoteAsset: "ETH", } @@ -222,11 +222,11 @@ func TestOrderHistory(t *testing.T) { } q := &query.OrderHistory{ - Limit: 1, - Offset: 0, - StartDate: time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), - EndDate: time.Date(2020, 01, 01, 01, 00, 00, 00, time.Local).Unix(), - Symbol: "BTC_USDC", + Limit: 1, + Offset: 0, + StartDate: time.Date(2020, 01, 01, 00, 00, 00, 00, time.Local).Unix(), + EndDate: time.Date(2020, 01, 01, 01, 00, 00, 00, time.Local).Unix(), + Symbol: "BTC_USDC", TimeInForce: "IOC", } @@ -272,7 +272,7 @@ func TestNewOrder(t *testing.T) { Symbol: "BTC_USDC", Price: 1000, Quantity: 0.0001, - }, + }, } _, err := sut.Do(q) From 8716e2001747d5bd0e2196ad81545df0b68ad1b4 Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Mon, 15 Nov 2021 00:10:33 -0800 Subject: [PATCH 28/29] remove export_test from root package and duplicate proudction URL in newton_test.go --- export_test.go | 5 ----- newton_test.go | 9 +++------ query/actions.go | 4 ++-- 3 files changed, 5 insertions(+), 13 deletions(-) delete mode 100644 export_test.go diff --git a/export_test.go b/export_test.go deleted file mode 100644 index fe73e77..0000000 --- a/export_test.go +++ /dev/null @@ -1,5 +0,0 @@ -package newton - -const ( - BaseURL = baseUrl -) diff --git a/newton_test.go b/newton_test.go index a1966b2..ee25c03 100644 --- a/newton_test.go +++ b/newton_test.go @@ -14,6 +14,7 @@ const ( mockClientId = "mock_id" mock_client_secret = "mock_secret" mockServerURL = "https://stoplight.io/mocks/newton/newton-api-docs/431375" + productionServerURL = "https://api.newton.co/v1" ) func TestNewNewton(t *testing.T) { @@ -23,7 +24,7 @@ func TestNewNewton(t *testing.T) { g.Expect(sut.ClientId).Should(gomega.Equal(mockClientId)) g.Expect(sut.ClientSecret).Should(gomega.Equal(mock_client_secret)) - g.Expect(sut.BaseUrl).Should(gomega.Equal(newton.BaseURL)) + g.Expect(sut.BaseUrl).Should(gomega.Equal(productionServerURL)) } // Public API @@ -312,11 +313,7 @@ func TestAuthentication(t *testing.T) { productionClientId := os.Getenv("CLIENT_ID") productionClientSecret := os.Getenv("CLIENT_SECRET") - sut := newton.Newton{ - productionClientId, - productionClientSecret, - newton.BaseURL, // production URL - } + sut := newton.New(productionClientId, productionClientSecret) q := &query.Balances{Asset: "BTC"} _, err := sut.Do(q) diff --git a/query/actions.go b/query/actions.go index aa1a812..0eeb49e 100644 --- a/query/actions.go +++ b/query/actions.go @@ -44,11 +44,11 @@ func (a Actions) GetParameters() []Parameter { params = append(params, Parameter{string(ActionTypeKey), string(a.ActionType)}) } - if a.Limit != int(ANY) { + if a.Limit != ANY { params = append(params, Parameter{string(Limit), strconv.Itoa(a.Limit)}) } - if a.Offset != int(ANY) { + if a.Offset != ANY { params = append(params, Parameter{string(Offset), strconv.Itoa(a.Offset)}) } From 31d2e93251b7cf3e7f73393a683bb947d711eb3a Mon Sep 17 00:00:00 2001 From: Roman Akhtariev Date: Mon, 15 Nov 2021 00:18:42 -0800 Subject: [PATCH 29/29] read body before any error handling when parsing response --- newton.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/newton.go b/newton.go index 5f61f78..2d7ff1e 100644 --- a/newton.go +++ b/newton.go @@ -140,12 +140,12 @@ func (n *Newton) parseResponse(res *http.Response, toParseTo interface{}) (*Resp Body: nil, } + body, err := ioutil.ReadAll(res.Body) + if toParseTo == nil { return parsedResponse, nil } - body, err := ioutil.ReadAll(res.Body) - if err != nil { return parsedResponse, err }