mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
ftx: define order update response
This commit is contained in:
parent
2e2ae46bae
commit
d3cdd3c2a6
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user