Skip to content

Commit

Permalink
Get order (#12)
Browse files Browse the repository at this point in the history
* Added get order

* Updated readme
  • Loading branch information
0xdfgp committed Jul 7, 2018
1 parent 609cc99 commit ee3c265
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 1 deletion.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,23 @@ request := NewOrderRequest("BTCUSDT", "SELL", "MARKET", 10).
response, err := sdk.NewOrder(request)
```

### Query order (USER_DATA)
Get order detail.

Official doc: [Query order (USER_DATA)](https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md#query-order-user_data)

#### Example
```go
query := binance.NewGetOrderQuery("LTCBTC")
response, err := sdk.GetOrder(query)

// With all optional parameters (See official doc)
query := NewGetOrderQuery("LTCBTC").
OrderId(1).
OrigClientOrderId("myOrder1").
RecvWindow(2)
response, err := sdk.GetOrder(query)
```

## Available web socket streams:
Not available yet.
Expand Down
74 changes: 74 additions & 0 deletions get_order.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package binance

import (
"encoding/json"
)

type OpenOrder struct {
Symbol string `json:"symbol"`
OrderId int64 `json:"orderId"`
ClientOrderId string `json:"clientOrderId"`
Price float64 `json:"price,string"`
OriginalQuantity float64 `json:"origQty,string"`
ExecutedQuantity float64 `json:"executedQty,string"`
Status string `json:"status"`
TimeInForce string `json:"timeInForce"`
Type string `json:"type"`
Side string `json:"side"`
StopPrice float64 `json:"stopPrice,string"`
IcebergQuantity float64 `json:"icebergQty,string"`
Time int64 `json:"time"`
IsWorking bool `json:"isWorking"`
}

type getOrderQuery struct {
symbol *string
orderId *int64
origClientOrderId *string
recvWindow *int64
timestamp *int64
}

func NewGetOrderQuery(symbol string) *getOrderQuery {
return &getOrderQuery{
symbol: &symbol,
}
}

func (r *getOrderQuery) OrderId(value int64) *getOrderQuery {
r.orderId = &value
return r
}

func (r *getOrderQuery) OrigClientOrderId(value string) *getOrderQuery {
r.origClientOrderId = &value
return r
}

func (r *getOrderQuery) RecvWindow(value int64) *getOrderQuery {
r.recvWindow = &value
return r
}

func (sdk Sdk) GetOrder(query *getOrderQuery) (*OpenOrder, error) {
req := newRequest("GET", "/api/v3/order").
StringParam("symbol", query.symbol).
Int64Param("orderId", query.orderId).
StringParam("origClientOrderId", query.origClientOrderId).
Int64Param("recvWindow", query.recvWindow).
Int64Param("timestamp", sdk.clock.Now()).
Sign()

responseContent, err := sdk.client.Do(req)
if err != nil {
return nil, err
}

return parseOpenOrderResponse(responseContent)
}

func parseOpenOrderResponse(jsonContent []byte) (*OpenOrder, error) {
response := &OpenOrder{}
err := json.Unmarshal(jsonContent, &response)
return response, err
}
163 changes: 163 additions & 0 deletions get_order_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package binance

import (
"errors"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"strconv"
"testing"
"time"
)

func TestSdk_GetOrder(t *testing.T) {
method, url := "GET", "/api/v3/order"

t.Run("It should convert api response to an open order", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockedClock := NewMockClock(ctrl)
mockedClient := NewMockClient(ctrl)
sdk := Sdk{client: mockedClient, clock: mockedClock}

expectedTimestamp := time.Now().Unix()
mockedClock.EXPECT().Now().Return(&expectedTimestamp)

expectedRequest := newRequest(method, url).
Param("symbol", "LTCBTC").
Param("timestamp", strconv.FormatInt(expectedTimestamp, 10)).
Sign()

mockedClient.
EXPECT().
Do(expectedRequest).
MinTimes(1).
Return(validOpenOrderJson(), nil)

query := NewGetOrderQuery("LTCBTC")
response, _ := sdk.GetOrder(query)

assert.Equal(t, validOpenOrderResponse(), response)
})

t.Run("It should read optional parameters", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockedClock := NewMockClock(ctrl)
mockedClient := NewMockClient(ctrl)
sdk := Sdk{client: mockedClient, clock: mockedClock}

expectedTimestamp := time.Now().Unix()
mockedClock.EXPECT().Now().Return(&expectedTimestamp)

expectedRequest := newRequest(method, url).
Param("symbol", "LTCBTC").
Param("orderId", "1").
Param("origClientOrderId", "myOrder1").
Param("recvWindow", "2").
Param("timestamp", strconv.FormatInt(expectedTimestamp, 10)).
Sign()

mockedClient.
EXPECT().
Do(expectedRequest).
MinTimes(1).
Return(validOpenOrderJson(), nil)

query := NewGetOrderQuery("LTCBTC").
OrderId(1).
OrigClientOrderId("myOrder1").
RecvWindow(2)

response, _ := sdk.GetOrder(query)

assert.Equal(t, validOpenOrderResponse(), response)
})

t.Run("It should return error when api fails", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockedClock := NewMockClock(ctrl)
mockedClient := NewMockClient(ctrl)
sdk := Sdk{client: mockedClient, clock: mockedClock}

expectedTimestamp := time.Now().Unix()
mockedClock.EXPECT().Now().Return(&expectedTimestamp)

expectedRequest := newRequest(method, url).
Param("symbol", "LTCBTC").
Param("timestamp", strconv.FormatInt(expectedTimestamp, 10)).
Sign()

mockedClient.
EXPECT().
Do(expectedRequest).
MinTimes(1).
Return(nil, errors.New("error"))

query := NewGetOrderQuery("LTCBTC")
_, err := sdk.GetOrder(query)

assert.Error(t, err)
})

t.Run("It should return error when response cannot be mapped", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockedClock := NewMockClock(ctrl)
mockedClient := NewMockClient(ctrl)
sdk := Sdk{client: mockedClient, clock: mockedClock}

expectedTimestamp := time.Now().Unix()
mockedClock.EXPECT().Now().Return(&expectedTimestamp)

expectedRequest := newRequest(method, url).
Param("symbol", "LTCBTC").
Param("timestamp", strconv.FormatInt(expectedTimestamp, 10)).
Sign()

mockedClient.
EXPECT().
Do(expectedRequest).
MinTimes(1).
Return(invalidJson(), nil)

query := NewGetOrderQuery("LTCBTC")
_, err := sdk.GetOrder(query)

assert.Error(t, err)
})
}

func validOpenOrderJson() []byte {
return []byte(`{
"symbol": "LTCBTC",
"orderId": 1,
"clientOrderId": "myOrder1",
"price": "0.1",
"origQty": "1.0",
"executedQty": "0.0",
"status": "NEW",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "BUY",
"stopPrice": "0.0",
"icebergQty": "0.0",
"time": 1499827319559,
"isWorking": true
}`)
}

func validOpenOrderResponse() *OpenOrder {
return &OpenOrder{
Symbol: "LTCBTC",
OrderId: 1,
ClientOrderId: "myOrder1",
Price: 0.1,
OriginalQuantity: 1,
ExecutedQuantity: 0,
Status: "NEW",
TimeInForce: "GTC",
Type: "LIMIT",
Side: "BUY",
StopPrice: 0.0,
IcebergQuantity: 0.0,
Time: 1499827319559,
IsWorking: true,
}
}
2 changes: 1 addition & 1 deletion new_order_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
func TestSdk_NewOrder(t *testing.T) {
method, url := "POST", "/api/v3/order"

t.Run("It should convert api response to an FullOrder ACK by default", func(t *testing.T) {
t.Run("It should convert api response to a FullOrder", func(t *testing.T) {
ctrl := gomock.NewController(t)
mockedClock := NewMockClock(ctrl)
mockedClient := NewMockClient(ctrl)
Expand Down

0 comments on commit ee3c265

Please sign in to comment.