ftx: define order update response

This commit is contained in:
ycdesu 2021-03-27 19:26:39 +08:00
parent 2e2ae46bae
commit d3cdd3c2a6
3 changed files with 112 additions and 0 deletions

View File

@ -18,6 +18,15 @@ func parseDatetime(s string) (time.Time, error) {
return time.Parse(timeLayout, s) return time.Parse(timeLayout, s)
} }
// used in unit test
func mustParseDatetime(s string) time.Time {
t, err := parseDatetime(s)
if err != nil {
panic(err)
}
return t
}
func (d *datetime) UnmarshalJSON(b []byte) error { func (d *datetime) UnmarshalJSON(b []byte) error {
// remove double quote from json string // remove double quote from json string
s := strings.Trim(string(b), "\"") s := strings.Trim(string(b), "\"")
@ -224,6 +233,7 @@ type order struct {
Ioc bool `json:"ioc"` Ioc bool `json:"ioc"`
PostOnly bool `json:"postOnly"` PostOnly bool `json:"postOnly"`
ClientId string `json:"clientId"` ClientId string `json:"clientId"`
Liquidation bool `json:"liquidation"`
} }
type orderResponse struct { type orderResponse struct {

View File

@ -24,6 +24,8 @@ type channel string
const orderbook channel = "orderbook" const orderbook channel = "orderbook"
const privateOrdersChannel channel = "orders" const privateOrdersChannel channel = "orders"
var errInvalidChannel = fmt.Errorf("invalid channel")
/* /*
Private: Private:
order update: `{'op': 'subscribe', 'channel': 'orders'}` order update: `{'op': 'subscribe', 'channel': 'orders'}`
@ -72,6 +74,47 @@ func loginBody(millis int64) string {
return fmt.Sprintf("%dwebsocket_login", millis) return fmt.Sprintf("%dwebsocket_login", millis)
} }
type websocketResponse struct {
mandatory
optionalFields
}
type mandatory struct {
Channel channel `json:"channel"`
Type respType `json:"type"`
}
type optionalFields struct {
Market string `json:"market"`
// Example: {"type": "error", "code": 404, "msg": "No such market: BTCUSDT"}
Code int64 `json:"code"`
Message string `json:"msg"`
Data json.RawMessage `json:"data"`
}
type orderUpdateResponse struct {
mandatory
Data order `json:"data"`
}
func (r websocketResponse) toOrderUpdateResponse() (orderUpdateResponse, error) {
if r.Channel != privateOrdersChannel {
return orderUpdateResponse{}, fmt.Errorf("can't convert %s channel data to %s: %w", r.Channel, privateOrdersChannel, errInvalidChannel)
}
var o orderUpdateResponse
if err := json.Unmarshal(r.Data, &o.Data); err != nil {
return orderUpdateResponse{}, err
}
o.mandatory = r.mandatory
return o, nil
}
type respType string type respType string
const errRespType respType = "error" const errRespType respType = "error"

View File

@ -182,3 +182,62 @@ func Test_newLoginRequest(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, strings.Contains(string(jsonStr), expectedSignature)) assert.True(t, strings.Contains(string(jsonStr), expectedSignature))
} }
func Test_websocketResponse_toOrderUpdateResponse(t *testing.T) {
input := []byte(`
{
"channel": "orders",
"type": "update",
"data": {
"id": 12345,
"clientId": "test-client-id",
"market": "SOL/USD",
"type": "limit",
"side": "buy",
"price": 0.5,
"size": 100.0,
"status": "closed",
"filledSize": 0.0,
"remainingSize": 0.0,
"reduceOnly": false,
"liquidation": false,
"avgFillPrice": null,
"postOnly": false,
"ioc": false,
"createdAt": "2021-03-27T11:00:36.418674+00:00"
}
}
`)
var raw websocketResponse
assert.NoError(t, json.Unmarshal(input, &raw))
r, err := raw.toOrderUpdateResponse()
assert.NoError(t, err)
assert.Equal(t, orderUpdateResponse{
mandatory: mandatory{
Channel: privateOrdersChannel,
Type: updateRespType,
},
Data: order{
ID: 12345,
ClientId: "test-client-id",
Market: "SOL/USD",
Type: "limit",
Side: "buy",
Price: 0.5,
Size: 100,
Status: "closed",
FilledSize: 0.0,
RemainingSize: 0.0,
ReduceOnly: false,
Liquidation: false,
AvgFillPrice: 0,
PostOnly: false,
Ioc: false,
CreatedAt: datetime{Time: mustParseDatetime("2021-03-27T11:00:36.418674+00:00")},
Future: "",
},
}, r)
}