Skip to content

Commit f55236d

Browse files
committed
tag 1.0.0
1 parent e63f7e9 commit f55236d

23 files changed

+389
-31
lines changed

README.md

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,126 @@ Your contributions are most welcome!
3232
bybit-go-api is under active development with the latest features and updates from Bybit's API implemented promptly. The module utilizes minimal external libraries to provide a lightweight and efficient experience. If you've made enhancements or fixed bugs, please submit a pull request.
3333

3434
## Installation
35-
Ensure you have go 1.21.0 or higher. You can include bybit-go-api in your project using Maven or Gradle.
35+
Ensure you have go 1.21.0 or higher. And use dependencies as below
36+
```go
37+
require (
38+
github.com/google/uuid v1.4.0
39+
github.com/gorilla/websocket v1.5.1
40+
github.com/stretchr/testify v1.8.4
41+
)
42+
```
3643

3744
## Usage
3845
Note: Replace placeholders (like YOUR_API_KEY, links, or other details) with the actual information. You can also customize this template to better fit the actual state and details of your Java API.
3946
### Rest API
47+
- Place an order by Map
48+
```go
49+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
50+
params := map[string]interface{}{"category": "linear", "symbol": "BTCUSDT", "side": "Buy", "positionIdx": 0, "orderType": "Limit", "qty": "0.001", "price": "10000", "timeInForce": "GTC"}
51+
orderResult, err := client.NewTradeService(params).PlaceOrder(context.Background())
52+
if err != nil {
53+
fmt.Println(err)
54+
return
55+
}
56+
fmt.Println(bybit.PrettyPrint(orderResult))
57+
```
58+
59+
- Place an order by Trade Class
60+
```go
61+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
62+
orderResult, err := client.NewPlaceOrderService("linear", "XRPUSDT", "Buy", "Market", "10").Do(context.Background())
63+
if err != nil {
64+
fmt.Println(err)
65+
return
66+
}
67+
fmt.Println(bybit.PrettyPrint(orderResult))
68+
```
69+
70+
- Place batch order
71+
```go
72+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
73+
params := map[string]interface{}{"category": "option",
74+
"request": []map[string]interface{}{
75+
{
76+
"category": "option",
77+
"symbol": "BTC-10FEB23-24000-C",
78+
"orderType": "Limit",
79+
"side": "Buy",
80+
"qty": "0.1",
81+
"price": "5",
82+
"orderIv": "0.1",
83+
"timeInForce": "GTC",
84+
"orderLinkId": "9b381bb1-401",
85+
"mmp": false,
86+
"reduceOnly": false,
87+
},
88+
{
89+
"category": "option",
90+
"symbol": "BTC-10FEB23-24000-C",
91+
"orderType": "Limit",
92+
"side": "Buy",
93+
"qty": "0.1",
94+
"price": "5",
95+
"orderIv": "0.1",
96+
"timeInForce": "GTC",
97+
"orderLinkId": "82ee86dd-001",
98+
"mmp": false,
99+
"reduceOnly": false,
100+
},
101+
},
102+
}
103+
orderResult, err := client.NewTradeService(params).PlaceBatchOrder(context.Background())
104+
if err != nil {
105+
fmt.Println(err)
106+
return
107+
}
108+
fmt.Println(bybit.PrettyPrint(orderResult))
109+
```
110+
111+
- Get Position
112+
```go
113+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
114+
params := map[string]interface{}{"category": "linear", "settleCoin": "USDT", "limit": 10}
115+
orderResult, err := client.NewPositionService(params).GetPositionList(context.Background())
116+
if err != nil {
117+
fmt.Println(err)
118+
return
119+
}
120+
fmt.Println(bybit.PrettyPrint(orderResult))
121+
```
122+
123+
- Get Transaction Log
124+
```go
125+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
126+
params := map[string]interface{}{"accountType": "UNIFIED", "category": "linear"}
127+
accountResult, err := client.NewAccountService(params).GetTransactionLog(context.Background())
128+
if err != nil {
129+
fmt.Println(err)
130+
return
131+
}
132+
fmt.Println(bybit.PrettyPrint(accountResult))
133+
```
134+
40135
### Websocket public channel
136+
- Order book Subscribe
137+
```go
138+
ws := bybit.NewBybitPublicWebSocket("wss://stream.bybit.com/v5/public/spot", func(message string) error {
139+
fmt.Println("Received:", message)
140+
return nil
141+
})
142+
_ = ws.Connect([]string{"orderbook.1.BTCUSDT"})
143+
select {}
144+
```
145+
41146
### Websocket private channel
147+
```go
148+
ws := bybit.NewBybitPrivateWebSocket("wss://stream-testnet.bybit.com/v5/private", "YOUR_API_KEY", "YOUR_API_SECRET", func(message string) error {
149+
fmt.Println("Received:", message)
150+
return nil
151+
})
152+
_ = ws.Connect([]string{"order"})
153+
select {}
154+
```
42155

43156
## Contact
44157
For support, join our Bybit API community on [Telegram](https://t.me/Bybitapi).

bybit_api_client.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ func (c *Client) debug(format string, v ...interface{}) {
6464
}
6565
}
6666

67+
// FormatTimestamp formats a time into Unix timestamp in milliseconds, as requested by Binance.
68+
func FormatTimestamp(t time.Time) int64 {
69+
return t.UnixNano() / int64(time.Millisecond)
70+
}
71+
6772
func GetCurrentTime() int64 {
6873
now := time.Now()
6974
unixNano := now.UnixNano()

bybit_api_client_test.go

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package bybit_connector
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"io"
7+
"net/http"
8+
"net/url"
9+
"testing"
10+
"time"
11+
12+
"github.com/stretchr/testify/assert"
13+
"github.com/stretchr/testify/mock"
14+
"github.com/stretchr/testify/require"
15+
"github.com/stretchr/testify/suite"
16+
)
17+
18+
type baseTestSuite struct {
19+
suite.Suite
20+
client *mockedClient
21+
apiKey string
22+
apiSecret string
23+
baseURL string
24+
}
25+
26+
func (s *baseTestSuite) r() *require.Assertions {
27+
return s.Require()
28+
}
29+
30+
func (s *baseTestSuite) SetupTest() {
31+
s.apiKey = "dummyAPIKey"
32+
s.apiSecret = "dummyApiSecret"
33+
s.baseURL = "https://dummyapi.com"
34+
s.client = newMockedClient(s.apiKey, s.apiSecret, s.baseURL)
35+
}
36+
37+
func (s *baseTestSuite) mockDo(data []byte, err error, statusCode ...int) {
38+
s.client.Client.do = s.client.do
39+
code := http.StatusOK
40+
if len(statusCode) > 0 {
41+
code = statusCode[0]
42+
}
43+
s.client.On("do", anyHTTPRequest()).Return(newHTTPResponse(data, code), err)
44+
}
45+
46+
func (s *baseTestSuite) assertDo() {
47+
s.client.AssertCalled(s.T(), "do", anyHTTPRequest())
48+
}
49+
50+
func (s *baseTestSuite) assertReq(f func(r *request)) {
51+
s.client.assertReq = f
52+
}
53+
54+
func (s *baseTestSuite) assertRequestEqual(e, a *request) {
55+
s.assertURLValuesEqual(e.query, a.query)
56+
}
57+
58+
func (s *baseTestSuite) assertURLValuesEqual(e, a url.Values) {
59+
var eKeys, aKeys []string
60+
for k := range e {
61+
eKeys = append(eKeys, k)
62+
}
63+
for k := range a {
64+
aKeys = append(aKeys, k)
65+
}
66+
r := s.r()
67+
r.Len(aKeys, len(eKeys))
68+
for k := range a {
69+
switch k {
70+
case timestampKey, signatureKey:
71+
r.NotEmpty(a.Get(k))
72+
continue
73+
}
74+
r.Equal(e[k], a[k], k)
75+
}
76+
}
77+
78+
func anythingOfType(t string) mock.AnythingOfTypeArgument {
79+
return mock.AnythingOfType(t)
80+
}
81+
82+
func newContext() context.Context {
83+
return context.Background()
84+
}
85+
86+
func anyHTTPRequest() mock.AnythingOfTypeArgument {
87+
return anythingOfType("*http.Request")
88+
}
89+
90+
func newHTTPResponse(data []byte, statusCode int) *http.Response {
91+
return &http.Response{
92+
Body: io.NopCloser(bytes.NewBuffer(data)),
93+
StatusCode: statusCode,
94+
}
95+
}
96+
97+
func newRequest() *request {
98+
r := &request{
99+
query: url.Values{},
100+
}
101+
return r
102+
}
103+
104+
func newSignedRequest() *request {
105+
return newRequest().setParams(params{
106+
timestampKey: "",
107+
signatureKey: "",
108+
apiRequestKey: "",
109+
recvWindowKey: "5000",
110+
signTypeKey: "2",
111+
})
112+
}
113+
114+
type assertReqFunc func(r *request)
115+
116+
type mockedClient struct {
117+
mock.Mock
118+
*Client
119+
assertReq assertReqFunc
120+
}
121+
122+
func newMockedClient(apiKey, apiSecret, baseURL string) *mockedClient {
123+
m := new(mockedClient)
124+
m.Client = NewBybitHttpClient(apiKey, apiSecret, WithBaseURL(baseURL))
125+
return m
126+
}
127+
128+
func (m *mockedClient) do(req *http.Request) (*http.Response, error) {
129+
if m.assertReq != nil {
130+
r := newRequest()
131+
r.query = req.URL.Query()
132+
if req.Body != nil && req.ContentLength > 0 {
133+
bs := make([]byte, req.ContentLength)
134+
_, err := req.Body.Read(bs)
135+
if err != nil && err != io.EOF {
136+
return nil, err // Handle read error
137+
}
138+
_ = req.Body.Close() // Close the body if we have read from it
139+
r.body = bytes.NewBuffer(bs)
140+
}
141+
m.assertReq(r)
142+
}
143+
args := m.Called(req)
144+
return args.Get(0).(*http.Response), args.Error(1)
145+
}
146+
147+
func TestFormatTimestamp(t *testing.T) {
148+
tm, _ := time.Parse("2006-01-02 15:04:05", "2018-06-01 01:01:01")
149+
assert.Equal(t, int64(1527814861000), FormatTimestamp(tm))
150+
}

examples/Trade/place_batch_trade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func PlaceBatchTrade() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
params := map[string]interface{}{"category": "option",
1616
"request": []map[string]interface{}{
1717
{

examples/Trade/place_order.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func PlaceOrder() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
orderResult, err := client.NewPlaceOrderService("linear", "XRPUSDT", "Buy", "Market", "10").Do(context.Background())
1616
if err != nil {
1717
fmt.Println(err)

examples/Trade/place_trade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func PlaceTrade() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
params := map[string]interface{}{"category": "linear", "symbol": "BTCUSDT", "side": "Buy", "positionIdx": 0, "orderType": "Limit", "qty": "0.001", "price": "10000", "timeInForce": "GTC"}
1616
orderResult, err := client.NewTradeService(params).PlaceOrder(context.Background())
1717
if err != nil {

examples/account/transaction_log.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func PlaceTrade() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
params := map[string]interface{}{"accountType": "UNIFIED", "category": "linear"}
1616
accountResult, err := client.NewAccountService(params).GetTransactionLog(context.Background())
1717
if err != nil {

examples/app.go

Lines changed: 0 additions & 7 deletions
This file was deleted.

examples/asset/asset_exchange_records.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func AssetInfo() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
params := map[string]interface{}{"accountType": "spot"}
1616
assetResult, err := client.NewAssetService(params).GetAssetInfo(context.Background())
1717
if err != nil {

examples/asset/coin_info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ func main() {
1111
}
1212

1313
func GetCoinInfo() {
14-
client := bybit.NewBybitHttpClient("8wYkmpLsMg10eNQyPm", "Ouxc34myDnXvei54XsBZgoQzfGxO4bkr2Zsj", bybit.WithBaseURL(bybit.TESTNET))
14+
client := bybit.NewBybitHttpClient("YOUR_API_KEY", "YOUR_API_SECRET", bybit.WithBaseURL(bybit.TESTNET))
1515
params := map[string]interface{}{"coin": "USDT"}
1616
assetResult, err := client.NewAssetService(params).GetCoinInfo(context.Background())
1717
if err != nil {

0 commit comments

Comments
 (0)