Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix panic #236

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions examples/v2/rest-wallet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import (
"log"
"os"

"github.com/bitfinexcom/bitfinex-api-go/v2/rest"
"github.com/davecgh/go-spew/spew"

"github.com/bitfinexcom/bitfinex-api-go/v2/rest"
)

// Set BFX_API_KEY and BFX_API_SECRET as :
Expand Down Expand Up @@ -65,7 +66,7 @@ func createDepositAddress(c *rest.Client) {
}

func withdraw(c *rest.Client) {
notfication, err := c.Wallet.Withdraw("exchange", "ethereum", 0.1, "0x5B4Dbe55dE0B565db6C63405D942886140083cE8")
notfication, err := c.Wallet.Withdraw("exchange", "ethereum", 0.1, "0x5B4Dbe55dE0B565db6C63405D942886140083cE8", "")
if err != nil {
log.Fatalf("withdraw %s", err)
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/models/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ const (
FrequencyTwoPerSecond BookFrequency = "F1"
// PriceLevelDefault provides a constant default price level for book subscriptions.
PriceLevelDefault int = 25

Withdraw MovementType = "WITHDRAW"
Deposit MovementType = "DEPOSIT"
)

var (
Expand Down Expand Up @@ -96,6 +99,8 @@ type StatusType string

type OrderType string

type MovementType string

func CandleResolutionFromString(str string) (CandleResolution, error) {
switch str {
case string(OneMinute):
Expand Down
13 changes: 10 additions & 3 deletions pkg/models/notification/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ func FromRaw(raw []interface{}) (n *Notification, err error) {
return
}

nraw := raw[4].([]interface{})
if len(nraw) == 0 {
return
nraw, ok := raw[4].([]interface{})
if !ok {
// raw[4] type of deposit_new message is object
if n.Type != "deposit_new" {
return nil, fmt.Errorf("raw[4] of %v message is not array, raw message: %v", n.Type, raw)
}
} else {
if len(nraw) == 0 {
return
}
}

switch n.Type {
Expand Down
110 changes: 110 additions & 0 deletions pkg/models/wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/bitfinexcom/bitfinex-api-go/pkg/convert"
"github.com/bitfinexcom/bitfinex-api-go/pkg/models/common"
)

type Wallet struct {
Expand Down Expand Up @@ -79,3 +80,112 @@ func SnapshotFromRaw(raw []interface{}) (s *Snapshot, err error) {

return
}

type Movement struct {
ID int64
common.MovementType
Currency string
CurrencyName string
StartedAt int64
LastUpdatedAt int64
Status string
Amount float64
Fee float64
DestinationAddress string
AddrTag string
TransactionId string
WithdrawTransactionNote string
}

type MovementSnapshot struct {
Snapshot []*Movement
}

// MovementFromRaw ...
// [
// ID,
// CURRENCY,
// CURRENCY_NAME,
// null,
// null,
// MTS_STARTED,
// MTS_UPDATED,
// null,
// null,
// STATUS,
// null,
// null,
// AMOUNT,
// FEES,
// null,
// null,
// DESTINATION_ADDRESS,
// null,
// null,
// null,
// TRANSACTION_ID,
// WITHDRAW_TRANSACTION_NOTE
// ]
//
func MovementFromRaw(raw []interface{}) (w *Movement, err error) {
defer func() {
if err1 := recover(); err1 != nil {
err = fmt.Errorf("parse movement err: %v", err1)
}
}()

if len(raw) < 22 {
err = fmt.Errorf("data slice too short for movement: %#v", raw)
return
}

w = &Movement{
ID: convert.I64ValOrZero(raw[0]),
Currency: convert.SValOrEmpty(raw[1]),
CurrencyName: convert.SValOrEmpty(raw[2]),
StartedAt: convert.I64ValOrZero(raw[5]),
LastUpdatedAt: convert.I64ValOrZero(raw[6]),
Status: convert.SValOrEmpty(raw[9]),
Fee: -convert.F64ValOrZero(raw[13]),
DestinationAddress: convert.SValOrEmpty(raw[16]),
AddrTag: convert.SValOrEmpty(raw[17]),
TransactionId: convert.SValOrEmpty(raw[20]),
WithdrawTransactionNote: convert.SValOrEmpty(raw[21]),
}

amount := convert.F64ValOrZero(raw[12])
if amount > 0 {
w.MovementType = common.Deposit
w.Amount = amount
} else {
w.MovementType = common.Withdraw
w.Amount = -amount
}

return
}

func MovementSnapshotFromRaw(raw []interface{}) (s *MovementSnapshot, err error) {
if len(raw) == 0 {
return s, fmt.Errorf("data slice too short for movements: %#v", raw)
}

movements := make([]*Movement, 0)
switch raw[0].(type) {
case []interface{}:
for _, v := range raw {
if l, ok := v.([]interface{}); ok {
w, err := MovementFromRaw(l)
if err != nil {
return s, err
}
movements = append(movements, w)
}
}
default:
return s, fmt.Errorf("not an movements snapshot")
}

s = &MovementSnapshot{Snapshot: movements}
return
}
31 changes: 31 additions & 0 deletions pkg/utils/routine.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package utils

import (
"fmt"
"os"
"runtime/debug"
"syscall"
)

var PanicMessage string

func GoWithRecover(f func()) {
go func() {
defer func() {
if err := recover(); err != nil {
PanicMessage = fmt.Sprintf("panic: %v\n%v\n", err, string(debug.Stack()))
_, _ = fmt.Fprint(os.Stderr, PanicMessage)

if err := os.Stderr.Sync(); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "sync stdout err: %v\n", err.Error())
}

if err := syscall.Kill(os.Getpid(), syscall.SIGUSR1); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "send signal err: %v", err)
}
}
}()

f()
}()
}
65 changes: 48 additions & 17 deletions v2/rest/orders.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,15 @@ func (s *OrderService) GetBySymbol(symbol string) (*order.Snapshot, error) {

// Retrieve an active order by the given ID
// See https://docs.bitfinex.com/reference#rest-auth-orders for more info
func (s *OrderService) GetByOrderId(orderID int64) (o *order.Order, err error) {
os, err := s.All()
func (s *OrderService) GetByOrderId(symbol string, orderID int64) (o *order.Order, err error) {
os, err := s.getActiveOrders(symbol, orderID)
if err != nil {
return nil, err
}
for _, order := range os.Snapshot {
if order.ID == orderID {
return order, nil

for _, od := range os.Snapshot {
if od.ID == orderID {
return od, nil
}
}
return nil, common.ErrNotFound
Expand All @@ -68,26 +69,26 @@ func (s *OrderService) GetByOrderId(orderID int64) (o *order.Order, err error) {
// See https://docs.bitfinex.com/reference#orders-history for more info
func (s *OrderService) AllHistory() (*order.Snapshot, error) {
// use no symbol, this will get all orders
return s.getHistoricalOrders("")
return s.getHistoricalOrders("", 0, 0, 0)
}

// Retrieves all past orders with the given symbol
// See https://docs.bitfinex.com/reference#orders-history for more info
func (s *OrderService) GetHistoryBySymbol(symbol string) (*order.Snapshot, error) {
func (s *OrderService) GetHistoryBySymbol(symbol string, startMs, endMs int64, limit int) (*order.Snapshot, error) {
// use no symbol, this will get all orders
return s.getHistoricalOrders(symbol)
return s.getHistoricalOrders(symbol, startMs, endMs, limit)
}

// Retrieve a single order in history with the given id
// See https://docs.bitfinex.com/reference#orders-history for more info
func (s *OrderService) GetHistoryByOrderId(orderID int64) (o *order.Order, err error) {
os, err := s.AllHistory()
func (s *OrderService) GetHistoryByOrderId(symbol string, orderID int64) (o *order.Order, err error) {
os, err := s.getHistoricalOrders(symbol, 0, 0, 0, orderID)
if err != nil {
return nil, err
}
for _, order := range os.Snapshot {
if order.ID == orderID {
return order, nil
for _, od := range os.Snapshot {
if od.ID == orderID {
return od, nil
}
}
return nil, common.ErrNotFound
Expand All @@ -108,8 +109,18 @@ func (s *OrderService) OrderTrades(symbol string, orderID int64) (*tradeexecutio
return tradeexecutionupdate.SnapshotFromRaw(raw)
}

func (s *OrderService) getActiveOrders(symbol string) (*order.Snapshot, error) {
req, err := s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol))
func (s *OrderService) getActiveOrders(symbol string, ids ...int64) (*order.Snapshot, error) {
var req Request
var err error
if len(ids) > 0 {
data := map[string]interface{}{
"id": ids,
}
req, err = s.requestFactory.NewAuthenticatedRequestWithData(common.PermissionRead, path.Join("orders", symbol), data)
} else {
req, err = s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol))
}

if err != nil {
return nil, err
}
Expand All @@ -127,8 +138,28 @@ func (s *OrderService) getActiveOrders(symbol string) (*order.Snapshot, error) {
return os, nil
}

func (s *OrderService) getHistoricalOrders(symbol string) (*order.Snapshot, error) {
req, err := s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol, "hist"))
func (s *OrderService) getHistoricalOrders(symbol string, start, end int64, limit int, ids ...int64) (*order.Snapshot, error) {
data := map[string]interface{}{}
if start != 0 {
data["start"] = start
}
if end != 0 {
data["end"] = end
}
if limit != 0 {
data["limit"] = limit
}
if len(ids) > 0 {
data["id"] = ids
}

var req Request
var err error
if len(data) > 0 {
req, err = s.requestFactory.NewAuthenticatedRequestWithData(common.PermissionRead, path.Join("orders", symbol, "hist"), data)
} else {
req, err = s.requestFactory.NewAuthenticatedRequest(common.PermissionRead, path.Join("orders", symbol, "hist"))
}
if err != nil {
return nil, err
}
Expand Down
33 changes: 32 additions & 1 deletion v2/rest/wallet.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package rest

import (
"context"
"fmt"
"strconv"

"github.com/bitfinexcom/bitfinex-api-go/pkg/models/common"
Expand Down Expand Up @@ -86,13 +88,16 @@ func (ws *WalletService) CreateDepositAddress(wallet, method string) (*notificat

// Submits a request to withdraw funds from the given Bitfinex wallet to the given address
// See https://docs.bitfinex.com/reference#withdraw for more info
func (ws *WalletService) Withdraw(wallet, method string, amount float64, address string) (*notification.Notification, error) {
func (ws *WalletService) Withdraw(wallet, method string, amount float64, address string, paymentId string) (*notification.Notification, error) {
body := map[string]interface{}{
"wallet": wallet,
"method": method,
"amount": strconv.FormatFloat(amount, 'f', -1, 64),
"address": address,
}
if paymentId != "" {
body["payment_id"] = paymentId
}
req, err := ws.requestFactory.NewAuthenticatedRequestWithData(common.PermissionWrite, "withdraw", body)
if err != nil {
return nil, err
Expand All @@ -103,3 +108,29 @@ func (ws *WalletService) Withdraw(wallet, method string, amount float64, address
}
return notification.FromRaw(raw)
}

// Movements view your past deposits/withdrawals. Currency can be specified to retrieve movements specific to that currency.
// See https://docs.bitfinex.com/reference#rest-auth-movements for more info
func (ws *WalletService) Movements(ctx context.Context, currency string, start, end int64, limit int) (*wallet.MovementSnapshot, error) {
body := map[string]interface{}{}
if start != 0 {
body["start"] = start
}
if end != 0 {
body["end"] = end
}
if limit != 0 {
body["limit"] = limit
}

req, err := ws.requestFactory.NewAuthenticatedRequestWithData(common.PermissionRead, fmt.Sprintf("movements/%s/hist", currency), body)
if err != nil {
return nil, err
}
raw, err := ws.Request(req)
if err != nil {
return nil, err
}

return wallet.MovementSnapshotFromRaw(raw)
}
Loading