mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 06:53:52 +00:00
pkg/exchange: add login method
This commit is contained in:
parent
8d4213794b
commit
6c96d12d99
|
@ -76,7 +76,7 @@ func (c *RestClient) NewAuthenticatedRequest(ctx context.Context, method, refURL
|
|||
}
|
||||
|
||||
// See https://bitgetlimited.github.io/apidoc/en/spot/#signature
|
||||
// sign(
|
||||
// Sign(
|
||||
// timestamp +
|
||||
// method.toUpperCase() +
|
||||
// requestPath + "?" + queryString +
|
||||
|
@ -94,7 +94,7 @@ func (c *RestClient) NewAuthenticatedRequest(ctx context.Context, method, refURL
|
|||
}
|
||||
|
||||
signKey := timestamp + strings.ToUpper(method) + path + string(body)
|
||||
signature := sign(signKey, c.secret)
|
||||
signature := Sign(signKey, c.secret)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, method, pathURL.String(), bytes.NewReader(body))
|
||||
if err != nil {
|
||||
|
@ -110,7 +110,7 @@ func (c *RestClient) NewAuthenticatedRequest(ctx context.Context, method, refURL
|
|||
return req, nil
|
||||
}
|
||||
|
||||
func sign(payload string, secret string) string {
|
||||
func Sign(payload string, secret string) string {
|
||||
var sig = hmac.New(sha256.New, []byte(secret))
|
||||
_, err := sig.Write([]byte(payload))
|
||||
if err != nil {
|
||||
|
|
|
@ -6,6 +6,10 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi"
|
||||
)
|
||||
|
||||
const (
|
||||
PrivateWebSocketURL = "wss://ws.bitget.com/v2/ws/private"
|
||||
)
|
||||
|
||||
type APIResponse = bitgetapi.APIResponse
|
||||
|
||||
type Client struct {
|
||||
|
|
|
@ -83,8 +83,7 @@ func (e *Exchange) PlatformFeeCurrency() string {
|
|||
}
|
||||
|
||||
func (e *Exchange) NewStream() types.Stream {
|
||||
// TODO implement me
|
||||
panic("implement me")
|
||||
return NewStream(e.key, e.secret, e.passphrase)
|
||||
}
|
||||
|
||||
func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
||||
|
|
|
@ -5,10 +5,14 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/gorilla/websocket"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi"
|
||||
v2 "github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi/v2"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -21,6 +25,7 @@ var (
|
|||
type Stream struct {
|
||||
types.StandardStream
|
||||
|
||||
key, secret, passphrase string
|
||||
bookEventCallbacks []func(o BookEvent)
|
||||
marketTradeEventCallbacks []func(o MarketTradeEvent)
|
||||
KLineEventCallbacks []func(o KLineEvent)
|
||||
|
@ -28,10 +33,13 @@ type Stream struct {
|
|||
lastCandle map[string]types.KLine
|
||||
}
|
||||
|
||||
func NewStream() *Stream {
|
||||
func NewStream(key, secret, passphrase string) *Stream {
|
||||
stream := &Stream{
|
||||
StandardStream: types.NewStandardStream(),
|
||||
lastCandle: map[string]types.KLine{},
|
||||
key: key,
|
||||
secret: secret,
|
||||
passphrase: passphrase,
|
||||
}
|
||||
|
||||
stream.SetEndpointCreator(stream.createEndpoint)
|
||||
|
@ -89,7 +97,7 @@ func (s *Stream) createEndpoint(_ context.Context) (string, error) {
|
|||
if s.PublicOnly {
|
||||
url = bitgetapi.PublicWebSocketURL
|
||||
} else {
|
||||
url = bitgetapi.PrivateWebSocketURL
|
||||
url = v2.PrivateWebSocketURL
|
||||
}
|
||||
return url, nil
|
||||
}
|
||||
|
@ -123,7 +131,22 @@ func (s *Stream) handlerConnect() {
|
|||
// errors are handled in the syncSubscriptions, so they are skipped here.
|
||||
_ = s.syncSubscriptions(WsEventSubscribe)
|
||||
} else {
|
||||
log.Error("*** PRIVATE API NOT IMPLEMENTED ***")
|
||||
timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
if err := s.Conn.WriteJSON(WsOp{
|
||||
Op: WsEventLogin,
|
||||
Args: []WsArg{
|
||||
{
|
||||
ApiKey: s.key,
|
||||
Passphrase: s.passphrase,
|
||||
Timestamp: timestamp,
|
||||
Sign: bitgetapi.Sign(fmt.Sprintf("%sGET/user/verify", timestamp), s.secret),
|
||||
},
|
||||
},
|
||||
}); err != nil {
|
||||
log.WithError(err).Error("failed to auth request")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@ func getTestClientOrSkip(t *testing.T) *Stream {
|
|||
t.Skip("skip test for CI")
|
||||
}
|
||||
|
||||
return NewStream()
|
||||
return NewStream(os.Getenv("BITGET_API_KEY"),
|
||||
os.Getenv("BITGET_API_SECRET"),
|
||||
os.Getenv("BITGET_API_PASSPHRASE"))
|
||||
}
|
||||
|
||||
func TestStream(t *testing.T) {
|
||||
|
@ -122,6 +124,14 @@ func TestStream(t *testing.T) {
|
|||
<-c
|
||||
})
|
||||
|
||||
t.Run("private test", func(t *testing.T) {
|
||||
err := s.Connect(context.Background())
|
||||
assert.NoError(t, err)
|
||||
|
||||
c := make(chan struct{})
|
||||
<-c
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestStream_parseWebSocketEvent(t *testing.T) {
|
||||
|
|
|
@ -34,6 +34,11 @@ type WsArg struct {
|
|||
Channel ChannelType `json:"channel"`
|
||||
// InstId Instrument ID. e.q. BTCUSDT, ETHUSDT
|
||||
InstId string `json:"instId"`
|
||||
|
||||
ApiKey string `json:"apiKey"`
|
||||
Passphrase string `json:"passphrase"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Sign string `json:"sign"`
|
||||
}
|
||||
|
||||
type WsEventType string
|
||||
|
@ -41,6 +46,7 @@ type WsEventType string
|
|||
const (
|
||||
WsEventSubscribe WsEventType = "subscribe"
|
||||
WsEventUnsubscribe WsEventType = "unsubscribe"
|
||||
WsEventLogin WsEventType = "login"
|
||||
WsEventError WsEventType = "error"
|
||||
)
|
||||
|
||||
|
@ -76,7 +82,7 @@ func (w *WsEvent) IsValid() error {
|
|||
case WsEventError:
|
||||
return fmt.Errorf("websocket request error, op: %s, code: %d, msg: %s", w.Op, w.Code, w.Msg)
|
||||
|
||||
case WsEventSubscribe, WsEventUnsubscribe:
|
||||
case WsEventSubscribe, WsEventUnsubscribe, WsEventLogin:
|
||||
// Actually, this code is unnecessary because the events are either `Subscribe` or `Unsubscribe`, But to avoid bugs
|
||||
// in the exchange, we still check.
|
||||
if w.Code != 0 || len(w.Msg) != 0 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user