Skip to content

Commit f84365d

Browse files
Merge pull request #115 from wyaeld/add-candle-service
Implement the rest v2 candle and wallet services After discussion with Bitfinex, this will be merged.
2 parents 53d0416 + 9b720f5 commit f84365d

File tree

6 files changed

+281
-0
lines changed

6 files changed

+281
-0
lines changed

examples/v2/rest-candles/main.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"log"
5+
bfx "github.com/bitfinexcom/bitfinex-api-go/v2"
6+
"github.com/bitfinexcom/bitfinex-api-go/v2/rest"
7+
"time"
8+
)
9+
10+
11+
func main() {
12+
c := rest.NewClient()
13+
14+
15+
log.Printf("1) Query Last Candle")
16+
candle, err := c.Candles.Last(bfx.TradingPrefix+bfx.BTCUSD, bfx.FiveMinutes)
17+
18+
if err != nil {
19+
log.Fatalf("getting candle: %s", err)
20+
}
21+
22+
log.Printf("last candle: %#v\n", candle)
23+
24+
now := time.Now()
25+
millis := now.UnixNano() / 1000000
26+
27+
prior := now.Add(time.Duration(-24) * time.Hour)
28+
millisStart := prior.UnixNano() / 1000000
29+
30+
31+
log.Printf("2) Query Candle History with no params")
32+
candles, err := c.Candles.History(bfx.TradingPrefix+bfx.BTCUSD, bfx.FiveMinutes)
33+
34+
if err != nil {
35+
log.Fatalf("getting candles: %s", err)
36+
}
37+
38+
log.Printf("length of candles is: %v", len(candles.Snapshot))
39+
40+
log.Printf("first candle is: %#v\n", candles.Snapshot[0])
41+
log.Printf("last candle is: %#v\n", candles.Snapshot[len(candles.Snapshot)-1])
42+
43+
start := bfx.Mts(millisStart)
44+
end := bfx.Mts(millis)
45+
46+
log.Printf("3) Query Candle History with params")
47+
candlesMore, err := c.Candles.HistoryWithQuery(
48+
bfx.TradingPrefix+bfx.BTCUSD,
49+
bfx.FiveMinutes,
50+
start,
51+
end,
52+
200,
53+
bfx.OldestFirst,
54+
)
55+
56+
if err != nil {
57+
log.Fatalf("getting candles: %s", err)
58+
}
59+
60+
log.Printf("length of candles is: %v", len(candlesMore.Snapshot))
61+
log.Printf("first candle is: %#v\n", candlesMore.Snapshot[0])
62+
log.Printf("last candle is: %#v\n", candlesMore.Snapshot[len(candlesMore.Snapshot)-1])
63+
64+
65+
66+
}
67+

examples/v2/rest-wallet/main.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"log"
6+
"os"
7+
"github.com/bitfinexcom/bitfinex-api-go/v2/rest"
8+
"github.com/davecgh/go-spew/spew"
9+
)
10+
11+
12+
// Set BFX_APIKEY and BFX_SECRET as :
13+
//
14+
// export BFX_API_KEY=YOUR_API_KEY
15+
// export BFX_API_SECRET=YOUR_API_SECRET
16+
//
17+
// you can obtain it from https://www.bitfinex.com/api
18+
19+
func main() {
20+
flag.Parse()
21+
22+
key := os.Getenv("BFX_API_KEY")
23+
secret := os.Getenv("BFX_API_SECRET")
24+
c := rest.NewClient().Credentials(key, secret)
25+
26+
wallets, err := c.Wallet.Wallet()
27+
28+
29+
if err != nil {
30+
log.Fatalf("getting wallet %s", err)
31+
}
32+
33+
spew.Dump(wallets)
34+
35+
36+
37+
}
38+

v2/rest/candles.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package rest
2+
3+
import (
4+
"github.com/bitfinexcom/bitfinex-api-go/v2"
5+
"path"
6+
"strings"
7+
"net/url"
8+
"fmt"
9+
)
10+
11+
// CandleService manages the Candles endpoint.
12+
type CandleService struct {
13+
Synchronous
14+
}
15+
16+
// Return Candles for the public account.
17+
func (c *CandleService) Last(symbol string, resolution bitfinex.CandleResolution) (*bitfinex.Candle, error) {
18+
if symbol == "" {
19+
return nil, fmt.Errorf("symbol cannot be empty")
20+
}
21+
22+
segments := []string{ "trade", string(resolution), symbol }
23+
24+
req := NewRequestWithMethod(path.Join("candles", strings.Join(segments,":"), "LAST"), "GET")
25+
req.Params = make(url.Values)
26+
raw, err := c.Request(req)
27+
28+
if err != nil {
29+
return nil, err
30+
}
31+
32+
cs, err := bitfinex.NewCandleFromRaw(symbol, resolution, raw)
33+
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
return cs, nil
39+
}
40+
41+
// Return Candles for the public account.
42+
func (c *CandleService) History(symbol string, resolution bitfinex.CandleResolution) (*bitfinex.CandleSnapshot, error) {
43+
if symbol == "" {
44+
return nil, fmt.Errorf("symbol cannot be empty")
45+
}
46+
47+
segments := []string{ "trade", string(resolution), symbol }
48+
49+
req := NewRequestWithMethod(path.Join("candles", strings.Join(segments,":"), "HIST"), "GET")
50+
51+
raw, err := c.Request(req)
52+
53+
if err != nil {
54+
return nil, err
55+
}
56+
57+
data := make([][]float64, 0, len(raw))
58+
for _, ifacearr := range raw {
59+
if arr, ok := ifacearr.([]interface{}); ok {
60+
sub := make([]float64, 0, len(arr))
61+
for _, iface := range arr {
62+
if flt, ok := iface.(float64); ok {
63+
sub = append(sub, flt)
64+
}
65+
}
66+
data = append(data, sub)
67+
}
68+
}
69+
70+
cs, err := bitfinex.NewCandleSnapshotFromRaw(symbol, resolution, data)
71+
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
return cs, nil
77+
}
78+
79+
80+
// Return Candles for the public account.
81+
func (c *CandleService) HistoryWithQuery(
82+
symbol string,
83+
resolution bitfinex.CandleResolution,
84+
start bitfinex.Mts,
85+
end bitfinex.Mts,
86+
limit bitfinex.QueryLimit,
87+
sort bitfinex.SortOrder,
88+
) (*bitfinex.CandleSnapshot, error) {
89+
90+
if symbol == "" {
91+
return nil, fmt.Errorf("symbol cannot be empty")
92+
}
93+
94+
segments := []string{ "trade", string(resolution), symbol }
95+
96+
req := NewRequestWithMethod(path.Join("candles", strings.Join(segments,":"), "HIST"), "GET")
97+
req.Params = make(url.Values)
98+
99+
//req.Params.Add("end", strconv.FormatInt(start, 10))
100+
//req.Params.Add("end", strconv.FormatInt(start, 10))
101+
req.Params.Add("end", string(end))
102+
req.Params.Add("start", string(start))
103+
req.Params.Add("limit", string(limit))
104+
req.Params.Add("sort", string(sort))
105+
106+
raw, err := c.Request(req)
107+
108+
if err != nil {
109+
return nil, err
110+
}
111+
112+
data := make([][]float64, 0, len(raw))
113+
for _, ifacearr := range raw {
114+
if arr, ok := ifacearr.([]interface{}); ok {
115+
sub := make([]float64, 0, len(arr))
116+
for _, iface := range arr {
117+
if flt, ok := iface.(float64); ok {
118+
sub = append(sub, flt)
119+
}
120+
}
121+
data = append(data, sub)
122+
}
123+
}
124+
125+
cs, err := bitfinex.NewCandleSnapshotFromRaw(symbol, resolution, data)
126+
127+
if err != nil {
128+
return nil, err
129+
}
130+
131+
return cs, nil
132+
}

v2/rest/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ type Client struct {
3131
nonce utils.NonceGenerator
3232

3333
// service providers
34+
Candles CandleService
3435
Orders OrderService
3536
Positions PositionService
3637
Trades TradeService
3738
Platform PlatformService
3839
Book BookService
40+
Wallet WalletService
3941

4042
Synchronous
4143
}
@@ -88,9 +90,11 @@ func NewClientWithSynchronousURLNonce(sync Synchronous, url string, nonce utils.
8890
}
8991
c.Orders = OrderService{Synchronous: c, requestFactory: c}
9092
c.Book = BookService{Synchronous: c}
93+
c.Candles = CandleService{Synchronous: c}
9194
c.Trades = TradeService{Synchronous: c, requestFactory: c}
9295
c.Platform = PlatformService{Synchronous: c}
9396
c.Positions = PositionService{Synchronous: c, requestFactory: c}
97+
c.Wallet = WalletService{Synchronous: c, requestFactory: c}
9498
return c
9599
}
96100

v2/rest/wallet.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package rest
2+
3+
import (
4+
"github.com/bitfinexcom/bitfinex-api-go/v2"
5+
"path"
6+
)
7+
8+
// WalletService manages data flow for the Wallet API endpoint
9+
type WalletService struct {
10+
requestFactory
11+
Synchronous
12+
}
13+
14+
// All returns all orders for the authenticated account.
15+
func (s *WalletService) Wallet() (*bitfinex.WalletSnapshot, error) {
16+
req, err := s.requestFactory.NewAuthenticatedRequest(path.Join("wallets"))
17+
if err != nil {
18+
return nil, err
19+
}
20+
raw, err := s.Request(req)
21+
if err != nil {
22+
return nil, err
23+
}
24+
25+
os, err := bitfinex.NewWalletSnapshotFromRaw(raw)
26+
if err != nil {
27+
return nil, err
28+
}
29+
30+
return os, nil
31+
}

v2/types.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ const (
3434
OneMonth CandleResolution = "1M"
3535
)
3636

37+
type Mts int64
38+
type SortOrder int
39+
const (
40+
OldestFirst SortOrder = 1
41+
NewestFirst SortOrder = -1
42+
)
43+
type QueryLimit int
44+
const QueryLimitMax QueryLimit = 1000
45+
3746
func CandleResolutionFromString(str string) (CandleResolution, error) {
3847
switch str {
3948
case string(OneMinute):

0 commit comments

Comments
 (0)