mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-08 15:11:07 +00:00
exchanges/qa: Add exchange wrapper testing suite (#1159)
* initial concept of a nice validation tester for exchanges * adds some datahandler design * expand testing * more tests and fixes * minor end of day fix for bithumb * fixes implementation issues * more test coverage and improvements, but not sure if i should continue * fix more wrapper implementations * adds error type, more fixes * changes signature, fixes implementations * fixes more wrapper implementations * one more bit * more cleanup * WOW things work? * lintle 1/1337 * mini bump * fixes all linting * neaten * GetOrderInfo+ asset pair fixes+improvements * adds new websocket test * expand ws testing * fix bug, expand tests, improve implementation * code coverage of a lot of new codes * fixes everything * reverts accidental changes * minor fixes from reviewing code * removes Bitfinex cancelBatchOrder implementation * fixes dumb baby typo for babies * mini nit fixes * so many nits to address * addresses all the nits * Titlecase * switcheroo * removes websocket testing for now * fix appveyor, minor test fix * fixes typo, re-kindles killed kode * skip binance wrapper tests when running CI * expired context, huobi okx fixes * kodespull * fix ordering * time fix because why not * fix exmo, others * hopefully this fixes all of my life's problems * last thing today * huobi, more like hypotrophy * golangci-lint, more like mypooroldknee-splint * fix huobi times by removing them * should fix okx currency issues * blocks the application * adds last little contingency for pairs * addresses most nits and new problems * lovely fixed before seeing why okx sucks * fixes issues with okx websocket * the classic receieieivaier * lintle * adds test and fixes existing tests * expands error handling messages during setup * fixes dumb okx bugs introduced * quick fix for lint and exmo * fixes nixes * fix exmo deposit issue * lint * fixes issue with extra asset runs missing * fix surprise race * all the lint and merge fixes * fixes surprise bugs in OKx * fixes issues with times and chains * fixing all the merge stuff * merge fix * rm logs and a panic potential * lovely lint lament * an easy demonstration of scenario, but not of initial purpose * put it in the bin * Revert "put it in the bin" This reverts commit 15c6490f713233d43f10957367fcbf18e3818bdd. * re-add after immediate error popup * fix mini poor test design * okx okay * merge fixes * fixes issues discovered in lovely test * I FORGOT TO COMMIT THIS * nit fixaroonaboo * forgoetten test fix * revert old okx asset intrument work * fixes * revert problems I didnt understand. update bybit * fix merge bugs * test cleanup * further improvements * reshuffle and lint * rm redundant CI_TEST by rm the CI_TEST field that is redundant * path fix * move to its own section, dont run on 32 bit + appveyor * lint * fix lbank * address nits * let it rip * fix failing test time range * niteroo boogaloo * mod tidy, use common.SimpleTimeFormat
This commit is contained in:
@@ -41,12 +41,12 @@ const (
|
||||
bitfinexOrderCancelAll = "order/cancel/all"
|
||||
bitfinexOrderCancelReplace = "order/cancel/replace"
|
||||
bitfinexOrderStatus = "order/status"
|
||||
bitfinexInactiveOrders = "orders/hist"
|
||||
bitfinexInactiveOrders = "hist"
|
||||
bitfinexOrders = "orders"
|
||||
bitfinexPositions = "positions"
|
||||
bitfinexClaimPosition = "position/claim"
|
||||
bitfinexHistory = "history"
|
||||
bitfinexHistoryMovements = "history/movements"
|
||||
bitfinexHistoryMovements = "movements"
|
||||
bitfinexTradeHistory = "mytrades"
|
||||
bitfinexOfferNew = "offer/new"
|
||||
bitfinexOfferCancel = "offer/cancel"
|
||||
@@ -67,18 +67,20 @@ const (
|
||||
bitfinexV2AccountInfo = "auth/r/info/user"
|
||||
bitfinexV2MarginInfo = "auth/r/info/margin/"
|
||||
bitfinexV2FundingInfo = "auth/r/info/funding/%s"
|
||||
bitfinexV2Auth = "auth/"
|
||||
bitfinexDerivativeData = "status/deriv?"
|
||||
bitfinexPlatformStatus = "platform/status"
|
||||
bitfinexTickerBatch = "tickers"
|
||||
bitfinexTicker = "ticker/"
|
||||
bitfinexTrades = "trades/"
|
||||
bitfinexOrderbook = "book/"
|
||||
bitfinexStatistics = "stats1/"
|
||||
bitfinexHistoryShort = "hist"
|
||||
bitfinexCandles = "candles/trade"
|
||||
bitfinexKeyPermissions = "key_info"
|
||||
bitfinexMarginInfo = "margin_infos"
|
||||
bitfinexDepositMethod = "conf/pub:map:tx:method"
|
||||
bitfinexDepositAddress = "auth/w/deposit/address"
|
||||
bitfinexOrderUpdate = "auth/w/order/update"
|
||||
|
||||
bitfinexMarginPairs = "conf/pub:list:pair:margin"
|
||||
bitfinexSpotPairs = "conf/pub:list:pair:exchange"
|
||||
@@ -584,58 +586,58 @@ func (b *Bitfinex) GetTickerBatch(ctx context.Context) (map[string]Ticker, error
|
||||
for x := range response {
|
||||
symbol, ok := response[x][0].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert symbol")
|
||||
return nil, common.GetTypeAssertError("string", response[x][0], "symbol")
|
||||
}
|
||||
|
||||
var t Ticker
|
||||
if len(response[x]) > 11 {
|
||||
if t.FlashReturnRate, ok = response[x][1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert flashReturnRate")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][1], "FlashReturnRate")
|
||||
}
|
||||
if t.Bid, ok = response[x][2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][2], "bid")
|
||||
}
|
||||
var bidPeriod float64
|
||||
bidPeriod, ok = response[x][3].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert bidPeriod")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][3], "bidPeriod")
|
||||
}
|
||||
t.BidPeriod = int64(bidPeriod)
|
||||
if t.BidSize, ok = response[x][4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bidSize")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][4], "bidSize")
|
||||
}
|
||||
if t.Ask, ok = response[x][5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][5], "ask")
|
||||
}
|
||||
var askPeriod float64
|
||||
askPeriod, ok = response[x][6].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert askPeriod")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][6], "askPeriod")
|
||||
}
|
||||
t.AskPeriod = int64(askPeriod)
|
||||
if t.AskSize, ok = response[x][7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert askSize")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][7], "askSize")
|
||||
}
|
||||
if t.DailyChange, ok = response[x][8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChange")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][8], "dailyChange")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[x][9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChangePerc")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][9], "dailyChangePerc")
|
||||
}
|
||||
if t.Last, ok = response[x][10].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][10], "last")
|
||||
}
|
||||
if t.Volume, ok = response[x][11].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][11], "volume")
|
||||
}
|
||||
if t.High, ok = response[x][12].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][12], "high")
|
||||
}
|
||||
if t.Low, ok = response[x][13].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][13], "low")
|
||||
}
|
||||
if t.FFRAmountAvailable, ok = response[x][16].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert FFRAmountAvailable")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][16], "FFRAmountAvailable")
|
||||
}
|
||||
|
||||
tickers[symbol] = t
|
||||
@@ -643,34 +645,34 @@ func (b *Bitfinex) GetTickerBatch(ctx context.Context) (map[string]Ticker, error
|
||||
}
|
||||
|
||||
if t.Bid, ok = response[x][1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][1], "bid")
|
||||
}
|
||||
if t.BidSize, ok = response[x][2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid size")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][2], "bid size")
|
||||
}
|
||||
if t.Ask, ok = response[x][3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][3], "ask")
|
||||
}
|
||||
if t.AskSize, ok = response[x][4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask size")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][4], "ask size")
|
||||
}
|
||||
if t.DailyChange, ok = response[x][5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert daily change")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][5], "daily change")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[x][6].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert daily change perc")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][6], "daily change percent")
|
||||
}
|
||||
if t.Last, ok = response[x][7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][7], "last")
|
||||
}
|
||||
if t.Volume, ok = response[x][8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][8], "volume")
|
||||
}
|
||||
if t.High, ok = response[x][9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][9], "high")
|
||||
}
|
||||
if t.Low, ok = response[x][10].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
return nil, common.GetTypeAssertError("float64", response[x][10], "low")
|
||||
}
|
||||
tickers[symbol] = t
|
||||
}
|
||||
@@ -1520,6 +1522,32 @@ func (b *Bitfinex) NewOrder(ctx context.Context, currencyPair, orderType string,
|
||||
orderV1)
|
||||
}
|
||||
|
||||
// OrderUpdate will send an update signal for an existing order
|
||||
// and attempt to modify it
|
||||
func (b *Bitfinex) OrderUpdate(ctx context.Context, orderID, groupID, clientOrderID string, amount, price, leverage float64) (*Order, error) {
|
||||
req := make(map[string]interface{})
|
||||
if orderID != "" {
|
||||
req["id"] = orderID
|
||||
}
|
||||
if groupID != "" {
|
||||
req["gid"] = groupID
|
||||
}
|
||||
if clientOrderID != "" {
|
||||
req["cid"] = clientOrderID
|
||||
}
|
||||
req["price"] = strconv.FormatFloat(price, 'f', -1, 64)
|
||||
req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
if leverage > 1 {
|
||||
req["lev"] = strconv.FormatFloat(leverage, 'f', -1, 64)
|
||||
}
|
||||
response := Order{}
|
||||
return &response, b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderUpdate,
|
||||
req,
|
||||
&response,
|
||||
orderV1)
|
||||
}
|
||||
|
||||
// NewOrderMulti allows several new orders at once
|
||||
func (b *Bitfinex) NewOrderMulti(ctx context.Context, orders []PlaceOrder) (OrderMultiResponse, error) {
|
||||
response := OrderMultiResponse{}
|
||||
@@ -1551,7 +1579,6 @@ func (b *Bitfinex) CancelMultipleOrders(ctx context.Context, orderIDs []int64) (
|
||||
response := GenericResponse{}
|
||||
req := make(map[string]interface{})
|
||||
req["order_ids"] = orderIDs
|
||||
|
||||
return response.Result, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancelMulti,
|
||||
req,
|
||||
@@ -1559,6 +1586,152 @@ func (b *Bitfinex) CancelMultipleOrders(ctx context.Context, orderIDs []int64) (
|
||||
orderMulti)
|
||||
}
|
||||
|
||||
// CancelMultipleOrdersV2 cancels multiple orders
|
||||
func (b *Bitfinex) CancelMultipleOrdersV2(ctx context.Context, orderID, clientOrderID, groupOrderID int64, clientOrderIDDate time.Time, allOrders bool) ([]CancelMultiOrderResponse, error) {
|
||||
var response []interface{}
|
||||
req := make(map[string]interface{})
|
||||
if orderID > 0 {
|
||||
req["id"] = orderID
|
||||
}
|
||||
if clientOrderID > 0 {
|
||||
req["cid"] = clientOrderID
|
||||
}
|
||||
if !clientOrderIDDate.IsZero() {
|
||||
req["cid_date"] = clientOrderIDDate.Format("2006-01-02")
|
||||
}
|
||||
if groupOrderID > 0 {
|
||||
req["gid"] = groupOrderID
|
||||
}
|
||||
if allOrders {
|
||||
req["all"] = 1
|
||||
}
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancelMulti,
|
||||
req,
|
||||
&response,
|
||||
orderMulti)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var cancelledOrders []CancelMultiOrderResponse
|
||||
for x := range response {
|
||||
cancelledOrdersSlice, ok := response[x].([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for y := range cancelledOrdersSlice {
|
||||
cancelledOrderFields, ok := cancelledOrdersSlice[y].([]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
var cancelledOrder CancelMultiOrderResponse
|
||||
for z := range cancelledOrderFields {
|
||||
switch z {
|
||||
case 0:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "ID")
|
||||
}
|
||||
cancelledOrder.OrderID = strconv.FormatFloat(f, 'f', -1, 64)
|
||||
case 1:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "GID")
|
||||
}
|
||||
cancelledOrder.GroupOrderID = strconv.FormatFloat(f, 'f', -1, 64)
|
||||
case 2:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "CID")
|
||||
}
|
||||
cancelledOrder.ClientOrderID = strconv.FormatFloat(f, 'f', -1, 64)
|
||||
case 3:
|
||||
f, ok := cancelledOrderFields[z].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", cancelledOrderFields[z], "SYMBOL")
|
||||
}
|
||||
cancelledOrder.Symbol = f
|
||||
case 4:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "MTS_CREATE")
|
||||
}
|
||||
cancelledOrder.CreatedTime = time.UnixMilli(int64(f))
|
||||
case 5:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "MTS_UPDATE")
|
||||
}
|
||||
cancelledOrder.UpdatedTime = time.UnixMilli(int64(f))
|
||||
case 6:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "AMOUNT")
|
||||
}
|
||||
cancelledOrder.Amount = f
|
||||
case 7:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "AMOUNT_ORIG")
|
||||
}
|
||||
cancelledOrder.OriginalAmount = f
|
||||
case 8:
|
||||
f, ok := cancelledOrderFields[z].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", cancelledOrderFields[z], "TYPE")
|
||||
}
|
||||
cancelledOrder.OrderType = f
|
||||
case 9:
|
||||
f, ok := cancelledOrderFields[z].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", cancelledOrderFields[z], "TYPE_PREV")
|
||||
}
|
||||
cancelledOrder.OriginalOrderType = f
|
||||
case 12:
|
||||
f, ok := cancelledOrderFields[z].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", cancelledOrderFields[z], "FLAGS")
|
||||
}
|
||||
cancelledOrder.OrderFlags = f
|
||||
case 13:
|
||||
f, ok := cancelledOrderFields[z].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", cancelledOrderFields[z], "ORDER_STATUS")
|
||||
}
|
||||
cancelledOrder.OrderStatus = f
|
||||
case 16:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "PRICE")
|
||||
}
|
||||
cancelledOrder.Price = f
|
||||
case 17:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "PRICE_AVG")
|
||||
}
|
||||
cancelledOrder.AveragePrice = f
|
||||
case 18:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "PRICE_TRAILING")
|
||||
}
|
||||
cancelledOrder.TrailingPrice = f
|
||||
case 19:
|
||||
f, ok := cancelledOrderFields[z].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", cancelledOrderFields[z], "PRICE_AUX_LIMIT")
|
||||
}
|
||||
cancelledOrder.AuxLimitPrice = f
|
||||
}
|
||||
}
|
||||
cancelledOrders[y] = cancelledOrder
|
||||
}
|
||||
}
|
||||
return cancelledOrders, nil
|
||||
}
|
||||
|
||||
// CancelAllExistingOrders cancels all active and open orders
|
||||
func (b *Bitfinex) CancelAllExistingOrders(ctx context.Context) (string, error) {
|
||||
response := GenericResponse{}
|
||||
@@ -1609,24 +1782,33 @@ func (b *Bitfinex) GetOrderStatus(ctx context.Context, orderID int64) (Order, er
|
||||
}
|
||||
|
||||
// GetInactiveOrders returns order status information
|
||||
func (b *Bitfinex) GetInactiveOrders(ctx context.Context) ([]Order, error) {
|
||||
func (b *Bitfinex) GetInactiveOrders(ctx context.Context, symbol string, ids ...int64) ([]Order, error) {
|
||||
var response []Order
|
||||
req := make(map[string]interface{})
|
||||
req["limit"] = "100"
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexInactiveOrders,
|
||||
req["limit"] = 2500
|
||||
if len(ids) > 0 {
|
||||
req["ids"] = ids
|
||||
}
|
||||
return response, b.SendAuthenticatedHTTPRequestV2(
|
||||
ctx,
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
bitfinexV2Auth+"r/"+bitfinexOrders+"/"+symbol+"/"+bitfinexInactiveOrders,
|
||||
req,
|
||||
&response,
|
||||
orderMulti)
|
||||
}
|
||||
|
||||
// GetOpenOrders returns all active orders and statuses
|
||||
func (b *Bitfinex) GetOpenOrders(ctx context.Context) ([]Order, error) {
|
||||
func (b *Bitfinex) GetOpenOrders(ctx context.Context, ids ...int64) ([]Order, error) {
|
||||
var response []Order
|
||||
req := make(map[string]interface{})
|
||||
if len(ids) > 0 {
|
||||
req["ids"] = ids
|
||||
}
|
||||
return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrders,
|
||||
nil,
|
||||
req,
|
||||
&response,
|
||||
orderMulti)
|
||||
}
|
||||
@@ -1683,7 +1865,7 @@ func (b *Bitfinex) GetBalanceHistory(ctx context.Context, symbol string, timeSin
|
||||
|
||||
// GetMovementHistory returns an array of past deposits and withdrawals
|
||||
func (b *Bitfinex) GetMovementHistory(ctx context.Context, symbol, method string, timeSince, timeUntil time.Time, limit int) ([]MovementHistory, error) {
|
||||
var response []MovementHistory
|
||||
var response [][]interface{}
|
||||
req := make(map[string]interface{})
|
||||
req["currency"] = symbol
|
||||
|
||||
@@ -1700,11 +1882,80 @@ func (b *Bitfinex) GetMovementHistory(ctx context.Context, symbol, method string
|
||||
req["limit"] = limit
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost,
|
||||
bitfinexHistoryMovements,
|
||||
err := b.SendAuthenticatedHTTPRequestV2(ctx, exchange.RestSpot, http.MethodPost,
|
||||
"auth/r/"+bitfinexHistoryMovements+"/"+symbol+"/"+bitfinexHistoryShort,
|
||||
req,
|
||||
&response,
|
||||
orderMulti)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp []MovementHistory //nolint:prealloc // its an array in an array
|
||||
var ok bool
|
||||
for i := range response {
|
||||
var move MovementHistory
|
||||
for j := range response[i] {
|
||||
if response[i][j] == nil {
|
||||
continue
|
||||
}
|
||||
switch j {
|
||||
case 0:
|
||||
var id float64
|
||||
id, ok = response[i][j].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", response[i][j], "ID")
|
||||
}
|
||||
move.ID = int64(id)
|
||||
case 1:
|
||||
move.Currency, ok = response[i][j].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", response[i][j], "CURRENCY")
|
||||
}
|
||||
case 5:
|
||||
move.TimestampCreated, ok = response[i][j].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", response[i][j], "MTS_STARTED")
|
||||
}
|
||||
case 6:
|
||||
move.Timestamp, ok = response[i][j].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", response[i][j], "MTS_UPDATED")
|
||||
}
|
||||
case 9:
|
||||
move.Status, ok = response[i][j].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", response[i][j], "STATUS")
|
||||
}
|
||||
case 12:
|
||||
move.Amount, ok = response[i][j].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", response[i][j], "AMOUNT")
|
||||
}
|
||||
case 13:
|
||||
move.Fee, ok = response[i][j].(float64)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("float64", response[i][j], "FEE")
|
||||
}
|
||||
case 16:
|
||||
move.Address, ok = response[i][j].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", response[i][j], "DESTINATION_ADDRESS")
|
||||
}
|
||||
case 20:
|
||||
move.TxID, ok = response[i][j].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", response[i][j], "TRANSACTION_ID")
|
||||
}
|
||||
case 21:
|
||||
move.Description, ok = response[i][j].(string)
|
||||
if !ok {
|
||||
return nil, common.GetTypeAssertError("string", response[i][j], "WITHDRAW_TRANSACTION_NOTE")
|
||||
}
|
||||
}
|
||||
}
|
||||
resp = append(resp, move)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetTradeHistory returns past executed trades
|
||||
@@ -1861,7 +2112,7 @@ func (b *Bitfinex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st
|
||||
|
||||
return b.SendPayload(ctx, e, func() (*request.Item, error) {
|
||||
return item, nil
|
||||
})
|
||||
}, request.UnauthenticatedRequest)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request and json
|
||||
@@ -1910,12 +2161,11 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange
|
||||
Path: fullPath,
|
||||
Headers: headers,
|
||||
Result: result,
|
||||
AuthRequest: true,
|
||||
NonceEnabled: true,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
HTTPRecording: b.HTTPRecording}, nil
|
||||
})
|
||||
}, request.AuthenticatedRequest)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequestV2 sends an authenticated http request and json
|
||||
@@ -1964,13 +2214,12 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchan
|
||||
Headers: headers,
|
||||
Body: body,
|
||||
Result: result,
|
||||
AuthRequest: true,
|
||||
NonceEnabled: true,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
HTTPRecording: b.HTTPRecording,
|
||||
}, nil
|
||||
})
|
||||
}, request.AuthenticatedRequest)
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
|
||||
@@ -277,7 +277,9 @@ func TestGetLends(t *testing.T) {
|
||||
|
||||
func TestGetCandles(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetCandles(context.Background(), "fUSD", "1m", 0, 0, 10, true)
|
||||
e := time.Now().Add(-time.Hour * 2).Truncate(time.Hour)
|
||||
s := e.Add(-time.Hour * 4)
|
||||
_, err := b.GetCandles(context.Background(), "fUST", "1D", s.UnixMilli(), e.UnixMilli(), 10000, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -343,8 +345,8 @@ func TestGetAccountSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetAccountSummary(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetAccountSummary() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,13 +354,13 @@ func TestNewDeposit(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.NewDeposit(context.Background(), "blabla", "testwallet", 0)
|
||||
if err == nil {
|
||||
t.Error("NewDeposit() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.NewDeposit(context.Background(), "bitcoin", "testwallet", 0)
|
||||
if err == nil {
|
||||
t.Error("NewDeposit() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.NewDeposit(context.Background(), "ripple", "", 0)
|
||||
@@ -407,8 +409,8 @@ func TestWalletTransfer(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.WalletTransfer(context.Background(), 0.01, "btc", "bla", "bla")
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,7 +424,7 @@ func TestNewOrder(t *testing.T) {
|
||||
2,
|
||||
false,
|
||||
true)
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
@@ -491,8 +493,8 @@ func TestNewOrderMulti(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err := b.NewOrderMulti(context.Background(), newOrder)
|
||||
if err == nil {
|
||||
t.Error("NewOrderMulti() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -500,8 +502,8 @@ func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.CancelExistingOrder(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("CancelExistingOrder() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -509,8 +511,8 @@ func TestCancelMultipleOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.CancelMultipleOrders(context.Background(), []int64{1337, 1336})
|
||||
if err == nil {
|
||||
t.Error("CancelMultipleOrders() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -518,8 +520,8 @@ func TestCancelAllOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.CancelAllExistingOrders(context.Background())
|
||||
if err == nil {
|
||||
t.Error("CancelAllExistingOrders() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,8 +530,8 @@ func TestReplaceOrder(t *testing.T) {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.ReplaceOrder(context.Background(), 1337, "BTCUSD",
|
||||
1, 1, true, order.Limit.Lower(), false)
|
||||
if err == nil {
|
||||
t.Error("ReplaceOrder() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,8 +539,8 @@ func TestGetOrderStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetOrderStatus(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("GetOrderStatus() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -546,8 +548,13 @@ func TestGetOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetOpenOrders(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetOpenOrders() Expectederror")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetOpenOrders(context.Background(), 1, 2, 3, 4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,8 +562,8 @@ func TestGetActivePositions(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetActivePositions(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetActivePositions() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,8 +571,8 @@ func TestClaimPosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.ClaimPosition(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("ClaimPosition() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,8 +581,8 @@ func TestGetBalanceHistory(t *testing.T) {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetBalanceHistory(context.Background(),
|
||||
"USD", time.Time{}, time.Time{}, 1, "deposit")
|
||||
if err == nil {
|
||||
t.Error("GetBalanceHistory() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,8 +590,8 @@ func TestGetMovementHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetMovementHistory(context.Background(), "USD", "bitcoin", time.Time{}, time.Time{}, 1)
|
||||
if err == nil {
|
||||
t.Error("GetMovementHistory() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -593,8 +600,8 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetTradeHistory(context.Background(),
|
||||
"BTCUSD", time.Time{}, time.Time{}, 1, 0)
|
||||
if err == nil {
|
||||
t.Error("GetTradeHistory() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,8 +609,8 @@ func TestNewOffer(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.NewOffer(context.Background(), "BTC", 1, 1, 1, "loan")
|
||||
if err == nil {
|
||||
t.Error("NewOffer() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,8 +618,17 @@ func TestCancelOffer(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.CancelOffer(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("CancelOffer() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetWithdrawalsHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetWithdrawalsHistory(context.Background(), currency.BTC, asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,8 +636,8 @@ func TestGetOfferStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetOfferStatus(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("NewOffer() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,8 +645,8 @@ func TestGetActiveCredits(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetActiveCredits(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetActiveCredits() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,8 +654,8 @@ func TestGetActiveOffers(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetActiveOffers(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetActiveOffers() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,8 +663,8 @@ func TestGetActiveMarginFunding(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetActiveMarginFunding(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetActiveMarginFunding() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -656,8 +672,8 @@ func TestGetUnusedMarginFunds(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetUnusedMarginFunds(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetUnusedMarginFunds() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -665,8 +681,8 @@ func TestGetMarginTotalTakenFunds(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetMarginTotalTakenFunds(context.Background())
|
||||
if err == nil {
|
||||
t.Error("GetMarginTotalTakenFunds() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,8 +690,8 @@ func TestCloseMarginFunding(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.CloseMarginFunding(context.Background(), 1337)
|
||||
if err == nil {
|
||||
t.Error("CloseMarginFunding() Expected error")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -781,7 +797,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
var getOrdersRequest = order.MultiOrderRequest{
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Side: order.AnySide,
|
||||
@@ -797,17 +814,15 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
var getOrdersRequest = order.MultiOrderRequest{
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Side: order.AnySide,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(context.Background(), &getOrdersRequest)
|
||||
if sharedtestvalues.AreAPICredentialsSet(b) && err != nil {
|
||||
t.Errorf("Could not get order history: %s", err)
|
||||
} else if !sharedtestvalues.AreAPICredentialsSet(b) && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -896,10 +911,15 @@ func TestCancelAllExchangeOrdera(t *testing.T) {
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
|
||||
_, err := b.ModifyOrder(context.Background(),
|
||||
&order.Modify{AssetType: asset.Spot})
|
||||
if err == nil {
|
||||
t.Error("ModifyOrder() Expected error")
|
||||
_, err := b.ModifyOrder(
|
||||
context.Background(),
|
||||
&order.Modify{
|
||||
OrderID: "1337",
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPair(currency.BTC, currency.USD),
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1538,7 +1558,10 @@ func Test_FormatExchangeKlineInterval(t *testing.T) {
|
||||
for x := range testCases {
|
||||
test := testCases[x]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
ret := b.FormatExchangeKlineInterval(test.interval)
|
||||
ret, err := b.FormatExchangeKlineInterval(test.interval)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if ret != test.output {
|
||||
t.Fatalf("unexpected result return expected: %v received: %v", test.output, ret)
|
||||
}
|
||||
@@ -1749,3 +1772,35 @@ func TestGetSiteListConfigData(t *testing.T) {
|
||||
t.Fatal("expected pairs")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
|
||||
_, err := b.OrderUpdate(context.Background(), "1234", "", "", 1, 1, 1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInactiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b)
|
||||
_, err := b.GetInactiveOrders(context.Background(), "tBTCUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetInactiveOrders(context.Background(), "tBTCUSD", 1, 2, 3, 4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelMultipleOrdersV2(t *testing.T) {
|
||||
t.Parallel()
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, b, canManipulateRealOrders)
|
||||
_, err := b.CancelMultipleOrdersV2(context.Background(), 1337, 0, 0, time.Time{}, false)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ type BalanceHistory struct {
|
||||
// MovementHistory holds deposit and withdrawal history data
|
||||
type MovementHistory struct {
|
||||
ID int64 `json:"id"`
|
||||
TxID int64 `json:"txid"`
|
||||
TxID string `json:"txid"`
|
||||
Currency string `json:"currency"`
|
||||
Method string `json:"method"`
|
||||
Type string `json:"withdrawal"`
|
||||
@@ -426,8 +426,8 @@ type MovementHistory struct {
|
||||
Description string `json:"description"`
|
||||
Address string `json:"address"`
|
||||
Status string `json:"status"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
TimestampCreated string `json:"timestamp_created"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
TimestampCreated float64 `json:"timestamp_created"`
|
||||
Fee float64 `json:"fee"`
|
||||
}
|
||||
|
||||
@@ -837,3 +837,23 @@ type WsCancelOfferRequest struct {
|
||||
type WsCancelAllOrdersRequest struct {
|
||||
All int64 `json:"all"`
|
||||
}
|
||||
|
||||
// CancelMultiOrderResponse holds v2 cancelled order data
|
||||
type CancelMultiOrderResponse struct {
|
||||
OrderID string
|
||||
ClientOrderID string
|
||||
GroupOrderID string
|
||||
Symbol string
|
||||
CreatedTime time.Time
|
||||
UpdatedTime time.Time
|
||||
Amount float64
|
||||
OriginalAmount float64
|
||||
OrderType string
|
||||
OriginalOrderType string
|
||||
OrderFlags string
|
||||
OrderStatus string
|
||||
Price float64
|
||||
AveragePrice float64
|
||||
TrailingPrice float64
|
||||
AuxLimitPrice float64
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ func (b *Bitfinex) UpdateTradablePairs(ctx context.Context, forceUpdate bool) er
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return b.EnsureOnePairEnabled()
|
||||
}
|
||||
|
||||
// UpdateTickers updates the ticker for all currency pairs of a given asset type
|
||||
@@ -372,9 +372,9 @@ func (b *Bitfinex) FetchTicker(ctx context.Context, p currency.Pair, a asset.Ite
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.appendOptionalDelimiter(&fPair)
|
||||
tick, err := ticker.GetTicker(b.Name, fPair, asset.Spot)
|
||||
DFPair := fPair
|
||||
b.appendOptionalDelimiter(&DFPair)
|
||||
tick, err := ticker.GetTicker(b.Name, DFPair, a)
|
||||
if err != nil {
|
||||
return b.UpdateTicker(ctx, fPair, a)
|
||||
}
|
||||
@@ -387,9 +387,9 @@ func (b *Bitfinex) FetchOrderbook(ctx context.Context, p currency.Pair, assetTyp
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.appendOptionalDelimiter(&fPair)
|
||||
ob, err := orderbook.Get(b.Name, fPair, assetType)
|
||||
DFPair := fPair
|
||||
b.appendOptionalDelimiter(&DFPair)
|
||||
ob, err := orderbook.Get(b.Name, DFPair, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateOrderbook(ctx, fPair, assetType)
|
||||
}
|
||||
@@ -398,6 +398,12 @@ func (b *Bitfinex) FetchOrderbook(ctx context.Context, p currency.Pair, assetTyp
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (b *Bitfinex) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
|
||||
if p.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
if err := b.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o := &orderbook.Base{
|
||||
Exchange: b.Name,
|
||||
Pair: p,
|
||||
@@ -411,7 +417,7 @@ func (b *Bitfinex) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTy
|
||||
return o, err
|
||||
}
|
||||
if assetType != asset.Spot && assetType != asset.Margin && assetType != asset.MarginFunding {
|
||||
return o, fmt.Errorf("assetType not supported: %v", assetType)
|
||||
return o, fmt.Errorf("%w %v", asset.ErrNotSupported, assetType)
|
||||
}
|
||||
b.appendOptionalDelimiter(&fPair)
|
||||
var prefix = "t"
|
||||
@@ -527,15 +533,34 @@ func (b *Bitfinex) FetchAccountInfo(ctx context.Context, assetType asset.Item) (
|
||||
return acc, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// GetAccountFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (b *Bitfinex) GetFundingHistory(_ context.Context) ([]exchange.FundHistory, error) {
|
||||
func (b *Bitfinex) GetAccountFundingHistory(_ context.Context) ([]exchange.FundingHistory, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetWithdrawalsHistory returns previous withdrawals data
|
||||
func (b *Bitfinex) GetWithdrawalsHistory(_ context.Context, _ currency.Code, _ asset.Item) (resp []exchange.WithdrawalHistory, err error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
func (b *Bitfinex) GetWithdrawalsHistory(ctx context.Context, c currency.Code, _ asset.Item) ([]exchange.WithdrawalHistory, error) {
|
||||
history, err := b.GetMovementHistory(ctx, c.String(), "", time.Date(2012, 0, 0, 0, 0, 0, 0, time.Local), time.Now(), 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]exchange.WithdrawalHistory, len(history))
|
||||
for i := range history {
|
||||
resp[i] = exchange.WithdrawalHistory{
|
||||
Status: history[i].Status,
|
||||
TransferID: strconv.FormatInt(history[i].ID, 10),
|
||||
Description: history[i].Description,
|
||||
Timestamp: time.UnixMilli(int64(history[i].Timestamp)),
|
||||
Currency: history[i].Currency,
|
||||
Amount: history[i].Amount,
|
||||
Fee: history[i].Fee,
|
||||
TransferType: history[i].Type,
|
||||
CryptoToAddress: history[i].Address,
|
||||
CryptoTxID: history[i].TxID,
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetRecentTrades returns the most recent trades for a currency and asset
|
||||
@@ -544,20 +569,20 @@ func (b *Bitfinex) GetRecentTrades(ctx context.Context, p currency.Pair, assetTy
|
||||
}
|
||||
|
||||
// GetHistoricTrades returns historic trade data within the timeframe provided
|
||||
func (b *Bitfinex) GetHistoricTrades(ctx context.Context, p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) {
|
||||
if assetType == asset.MarginFunding {
|
||||
return nil, fmt.Errorf("asset type '%v' not supported", assetType)
|
||||
func (b *Bitfinex) GetHistoricTrades(ctx context.Context, p currency.Pair, a asset.Item, timestampStart, timestampEnd time.Time) ([]trade.Data, error) {
|
||||
if a == asset.MarginFunding {
|
||||
return nil, fmt.Errorf("%w %v", asset.ErrNotSupported, a)
|
||||
}
|
||||
if err := common.StartEndTimeCheck(timestampStart, timestampEnd); err != nil {
|
||||
return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v %w", timestampStart, timestampEnd, err)
|
||||
}
|
||||
var err error
|
||||
p, err = b.FormatExchangeCurrency(p, assetType)
|
||||
p, err = b.FormatExchangeCurrency(p, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var currString string
|
||||
currString, err = b.fixCasing(p, assetType)
|
||||
currString, err = b.fixCasing(p, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -582,7 +607,7 @@ allTrades:
|
||||
TID: tID,
|
||||
Exchange: b.Name,
|
||||
CurrencyPair: p,
|
||||
AssetType: assetType,
|
||||
AssetType: a,
|
||||
Price: tradeData[i].Price,
|
||||
Amount: tradeData[i].Amount,
|
||||
Timestamp: time.UnixMilli(tradeData[i].Timestamp),
|
||||
@@ -616,7 +641,7 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fpair, err := b.FormatExchangeCurrency(o.Pair, o.AssetType)
|
||||
fPair, err := b.FormatExchangeCurrency(o.Pair, o.AssetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -627,7 +652,7 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub
|
||||
orderID, err = b.WsNewOrder(&WsNewOrderRequest{
|
||||
CustomID: b.Websocket.AuthConn.GenerateMessageID(false),
|
||||
Type: o.Type.String(),
|
||||
Symbol: fpair.String(),
|
||||
Symbol: fPair.String(),
|
||||
Amount: o.Amount,
|
||||
Price: o.Price,
|
||||
})
|
||||
@@ -636,13 +661,13 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub
|
||||
}
|
||||
} else {
|
||||
var response Order
|
||||
b.appendOptionalDelimiter(&fpair)
|
||||
b.appendOptionalDelimiter(&fPair)
|
||||
orderType := o.Type.Lower()
|
||||
if o.AssetType == asset.Spot {
|
||||
orderType = "exchange " + orderType
|
||||
}
|
||||
response, err = b.NewOrder(ctx,
|
||||
fpair.String(),
|
||||
fPair.String(),
|
||||
orderType,
|
||||
o.Amount,
|
||||
o.Price,
|
||||
@@ -667,29 +692,33 @@ func (b *Bitfinex) SubmitOrder(ctx context.Context, o *order.Submit) (*order.Sub
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (b *Bitfinex) ModifyOrder(_ context.Context, action *order.Modify) (*order.ModifyResponse, error) {
|
||||
if !b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
func (b *Bitfinex) ModifyOrder(ctx context.Context, action *order.Modify) (*order.ModifyResponse, error) {
|
||||
if err := action.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderIDInt, err := strconv.ParseInt(action.OrderID, 10, 64)
|
||||
if err != nil {
|
||||
return &order.ModifyResponse{OrderID: action.OrderID}, err
|
||||
if b.Websocket.IsEnabled() && b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
|
||||
orderIDInt, err := strconv.ParseInt(action.OrderID, 10, 64)
|
||||
if err != nil {
|
||||
return &order.ModifyResponse{OrderID: action.OrderID}, err
|
||||
}
|
||||
|
||||
wsRequest := WsUpdateOrderRequest{
|
||||
OrderID: orderIDInt,
|
||||
Price: action.Price,
|
||||
Amount: action.Amount,
|
||||
}
|
||||
if action.Side == order.Sell && action.Amount > 0 {
|
||||
wsRequest.Amount *= -1
|
||||
}
|
||||
err = b.WsModifyOrder(&wsRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return action.DeriveModifyResponse()
|
||||
}
|
||||
|
||||
wsRequest := WsUpdateOrderRequest{
|
||||
OrderID: orderIDInt,
|
||||
Price: action.Price,
|
||||
Amount: action.Amount,
|
||||
}
|
||||
if action.Side == order.Sell && action.Amount > 0 {
|
||||
wsRequest.Amount *= -1
|
||||
}
|
||||
err = b.WsModifyOrder(&wsRequest)
|
||||
_, err := b.OrderUpdate(ctx, action.OrderID, "", action.ClientOrderID, action.Amount, action.Price, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -715,8 +744,11 @@ func (b *Bitfinex) CancelOrder(ctx context.Context, o *order.Cancel) error {
|
||||
}
|
||||
|
||||
// CancelBatchOrders cancels an orders by their corresponding ID numbers
|
||||
func (b *Bitfinex) CancelBatchOrders(_ context.Context, _ []order.Cancel) (order.CancelBatchResponse, error) {
|
||||
return order.CancelBatchResponse{}, common.ErrNotYetImplemented
|
||||
func (b *Bitfinex) CancelBatchOrders(_ context.Context, _ []order.Cancel) (*order.CancelBatchResponse, error) {
|
||||
// While bitfinex supports cancelling multiple orders, it is
|
||||
// done in a way that is not helpful for GCT, and it would be better instead
|
||||
// to use CancelAllOrders or CancelOrder
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
@@ -730,10 +762,115 @@ func (b *Bitfinex) CancelAllOrders(ctx context.Context, _ *order.Cancel) (order.
|
||||
return order.CancelAllResponse{}, err
|
||||
}
|
||||
|
||||
func (b *Bitfinex) parseOrderToOrderDetail(o *Order) (*order.Detail, error) {
|
||||
side, err := order.StringToOrderSide(o.Side)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var timestamp float64
|
||||
timestamp, err = strconv.ParseFloat(o.Timestamp, 64)
|
||||
if err != nil {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s Unable to convert timestamp '%s', leaving blank",
|
||||
b.Name, o.Timestamp)
|
||||
}
|
||||
|
||||
var pair currency.Pair
|
||||
pair, err = currency.NewPairFromString(o.Symbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderDetail := &order.Detail{
|
||||
Amount: o.OriginalAmount,
|
||||
Date: time.Unix(int64(timestamp), 0),
|
||||
Exchange: b.Name,
|
||||
OrderID: strconv.FormatInt(o.ID, 10),
|
||||
Side: side,
|
||||
Price: o.Price,
|
||||
RemainingAmount: o.RemainingAmount,
|
||||
Pair: pair,
|
||||
ExecutedAmount: o.ExecutedAmount,
|
||||
}
|
||||
|
||||
switch {
|
||||
case o.IsLive:
|
||||
orderDetail.Status = order.Active
|
||||
case o.IsCancelled:
|
||||
orderDetail.Status = order.Cancelled
|
||||
case o.IsHidden:
|
||||
orderDetail.Status = order.Hidden
|
||||
default:
|
||||
orderDetail.Status = order.UnknownStatus
|
||||
}
|
||||
|
||||
// API docs discrepancy. Example contains prefixed "exchange "
|
||||
// Return type suggests “market” / “limit” / “stop” / “trailing-stop”
|
||||
orderType := strings.Replace(o.Type, "exchange ", "", 1)
|
||||
if orderType == "trailing-stop" {
|
||||
orderDetail.Type = order.TrailingStop
|
||||
} else {
|
||||
orderDetail.Type, err = order.StringToOrderType(orderType)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return orderDetail, nil
|
||||
}
|
||||
|
||||
// GetOrderInfo returns order information based on order ID
|
||||
func (b *Bitfinex) GetOrderInfo(_ context.Context, _ string, _ currency.Pair, _ asset.Item) (order.Detail, error) {
|
||||
var orderDetail order.Detail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
func (b *Bitfinex) GetOrderInfo(ctx context.Context, orderID string, pair currency.Pair, assetType asset.Item) (*order.Detail, error) {
|
||||
if pair.IsEmpty() {
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
if err := b.CurrencyPairs.IsAssetEnabled(assetType); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := strconv.ParseInt(orderID, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b.appendOptionalDelimiter(&pair)
|
||||
var cf string
|
||||
cf, err = b.fixCasing(pair, assetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.GetInactiveOrders(ctx, cf, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range resp {
|
||||
if resp[i].OrderID != id {
|
||||
continue
|
||||
}
|
||||
var o *order.Detail
|
||||
o, err = b.parseOrderToOrderDetail(&resp[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
resp, err = b.GetOpenOrders(ctx, id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := range resp {
|
||||
if resp[i].OrderID != id {
|
||||
continue
|
||||
}
|
||||
var o *order.Detail
|
||||
o, err = b.parseOrderToOrderDetail(&resp[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
return nil, fmt.Errorf("%w %v", order.ErrOrderNotFound, orderID)
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
@@ -753,7 +890,7 @@ func (b *Bitfinex) GetDepositAddress(ctx context.Context, c currency.Code, accou
|
||||
|
||||
methods := acceptableMethods.lookup(c)
|
||||
if len(methods) == 0 {
|
||||
return nil, errors.New("unsupported currency")
|
||||
return nil, currency.ErrCurrencyNotSupported
|
||||
}
|
||||
method := methods[0]
|
||||
if len(methods) > 1 && chain != "" {
|
||||
@@ -873,7 +1010,7 @@ func (b *Bitfinex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui
|
||||
}
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (b *Bitfinex) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest) (order.FilteredOrders, error) {
|
||||
func (b *Bitfinex) GetActiveOrders(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
err := req.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -886,141 +1023,49 @@ func (b *Bitfinex) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequ
|
||||
|
||||
orders := make([]order.Detail, len(resp))
|
||||
for i := range resp {
|
||||
var side order.Side
|
||||
side, err = order.StringToOrderSide(resp[i].Side)
|
||||
var orderDetail *order.Detail
|
||||
orderDetail, err = b.parseOrderToOrderDetail(&resp[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var timestamp float64
|
||||
timestamp, err = strconv.ParseFloat(resp[i].Timestamp, 64)
|
||||
if err != nil {
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"Unable to convert timestamp '%s', leaving blank",
|
||||
resp[i].Timestamp)
|
||||
}
|
||||
|
||||
var pair currency.Pair
|
||||
pair, err = currency.NewPairFromString(resp[i].Symbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderDetail := order.Detail{
|
||||
Amount: resp[i].OriginalAmount,
|
||||
Date: time.Unix(int64(timestamp), 0),
|
||||
Exchange: b.Name,
|
||||
OrderID: strconv.FormatInt(resp[i].ID, 10),
|
||||
Side: side,
|
||||
Price: resp[i].Price,
|
||||
RemainingAmount: resp[i].RemainingAmount,
|
||||
Pair: pair,
|
||||
ExecutedAmount: resp[i].ExecutedAmount,
|
||||
}
|
||||
|
||||
switch {
|
||||
case resp[i].IsLive:
|
||||
orderDetail.Status = order.Active
|
||||
case resp[i].IsCancelled:
|
||||
orderDetail.Status = order.Cancelled
|
||||
case resp[i].IsHidden:
|
||||
orderDetail.Status = order.Hidden
|
||||
default:
|
||||
orderDetail.Status = order.UnknownStatus
|
||||
}
|
||||
|
||||
// API docs discrepancy. Example contains prefixed "exchange "
|
||||
// Return type suggests “market” / “limit” / “stop” / “trailing-stop”
|
||||
orderType := strings.Replace(resp[i].Type, "exchange ", "", 1)
|
||||
if orderType == "trailing-stop" {
|
||||
orderDetail.Type = order.TrailingStop
|
||||
} else {
|
||||
orderDetail.Type, err = order.StringToOrderType(orderType)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
orders[i] = orderDetail
|
||||
orders[i] = *orderDetail
|
||||
}
|
||||
return req.Filter(b.Name, orders), nil
|
||||
}
|
||||
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (b *Bitfinex) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest) (order.FilteredOrders, error) {
|
||||
func (b *Bitfinex) GetOrderHistory(ctx context.Context, req *order.MultiOrderRequest) (order.FilteredOrders, error) {
|
||||
err := req.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.GetInactiveOrders(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orders := make([]order.Detail, len(resp))
|
||||
for i := range resp {
|
||||
var side order.Side
|
||||
side, err = order.StringToOrderSide(resp[i].Side)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var timestamp int64
|
||||
timestamp, err = strconv.ParseInt(resp[i].Timestamp, 10, 64)
|
||||
if err != nil {
|
||||
log.Warnf(log.ExchangeSys, "Unable to convert timestamp '%v', leaving blank", resp[i].Timestamp)
|
||||
}
|
||||
orderDate := time.Unix(timestamp, 0)
|
||||
|
||||
var pair currency.Pair
|
||||
pair, err = currency.NewPairFromString(resp[i].Symbol)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderDetail := order.Detail{
|
||||
Amount: resp[i].OriginalAmount,
|
||||
Date: orderDate,
|
||||
Exchange: b.Name,
|
||||
OrderID: strconv.FormatInt(resp[i].ID, 10),
|
||||
Side: side,
|
||||
Price: resp[i].Price,
|
||||
AverageExecutedPrice: resp[i].AverageExecutionPrice,
|
||||
RemainingAmount: resp[i].RemainingAmount,
|
||||
ExecutedAmount: resp[i].ExecutedAmount,
|
||||
Pair: pair,
|
||||
}
|
||||
orderDetail.InferCostsAndTimes()
|
||||
|
||||
switch {
|
||||
case resp[i].IsLive:
|
||||
orderDetail.Status = order.Active
|
||||
case resp[i].IsCancelled:
|
||||
orderDetail.Status = order.Cancelled
|
||||
case resp[i].IsHidden:
|
||||
orderDetail.Status = order.Hidden
|
||||
default:
|
||||
orderDetail.Status = order.UnknownStatus
|
||||
}
|
||||
|
||||
// API docs discrepancy. Example contains prefixed "exchange "
|
||||
// Return type suggests “market” / “limit” / “stop” / “trailing-stop”
|
||||
orderType := strings.Replace(resp[i].Type, "exchange ", "", 1)
|
||||
if orderType == "trailing-stop" {
|
||||
orderDetail.Type = order.TrailingStop
|
||||
} else {
|
||||
orderDetail.Type, err = order.StringToOrderType(orderType)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
orders[i] = orderDetail
|
||||
}
|
||||
|
||||
var orders []order.Detail
|
||||
for i := range req.Pairs {
|
||||
b.appendOptionalDelimiter(&req.Pairs[i])
|
||||
var cf string
|
||||
cf, err = b.fixCasing(req.Pairs[i], req.AssetType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp []Order
|
||||
resp, err = b.GetInactiveOrders(ctx, cf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for j := range resp {
|
||||
var orderDetail *order.Detail
|
||||
orderDetail, err = b.parseOrderToOrderDetail(&resp[j])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
orders = append(orders, *orderDetail)
|
||||
}
|
||||
}
|
||||
|
||||
return req.Filter(b.Name, orders), nil
|
||||
}
|
||||
|
||||
@@ -1045,16 +1090,34 @@ func (b *Bitfinex) ValidateAPICredentials(ctx context.Context, assetType asset.I
|
||||
}
|
||||
|
||||
// FormatExchangeKlineInterval returns Interval to exchange formatted string
|
||||
func (b *Bitfinex) FormatExchangeKlineInterval(in kline.Interval) string {
|
||||
func (b *Bitfinex) FormatExchangeKlineInterval(in kline.Interval) (string, error) {
|
||||
switch in {
|
||||
case kline.OneMin:
|
||||
return "1m", nil
|
||||
case kline.FiveMin:
|
||||
return "5m", nil
|
||||
case kline.FifteenMin:
|
||||
return "15m", nil
|
||||
case kline.ThirtyMin:
|
||||
return "30m", nil
|
||||
case kline.OneHour:
|
||||
return "1h", nil
|
||||
case kline.ThreeHour:
|
||||
return "3h", nil
|
||||
case kline.SixHour:
|
||||
return "6h", nil
|
||||
case kline.TwelveHour:
|
||||
return "12h", nil
|
||||
case kline.OneDay:
|
||||
return "1D"
|
||||
return "1D", nil
|
||||
case kline.OneWeek:
|
||||
return "7D"
|
||||
return "7D", nil
|
||||
case kline.OneWeek * 2:
|
||||
return "14D"
|
||||
return "14D", nil
|
||||
case kline.OneMonth:
|
||||
return "1M", nil
|
||||
default:
|
||||
return in.Short()
|
||||
return "", fmt.Errorf("%w %v", kline.ErrInvalidInterval, in)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1069,14 +1132,11 @@ func (b *Bitfinex) GetHistoricCandles(ctx context.Context, pair currency.Pair, a
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candles, err := b.GetCandles(ctx,
|
||||
cf,
|
||||
b.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
req.Start.UnixMilli(),
|
||||
req.End.UnixMilli(),
|
||||
uint32(req.RequestLimit),
|
||||
true)
|
||||
fInterval, err := b.FormatExchangeKlineInterval(req.ExchangeInterval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
candles, err := b.GetCandles(ctx, cf, fInterval, req.Start.UnixMilli(), req.End.UnixMilli(), uint32(req.RequestLimit), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1106,17 +1166,14 @@ func (b *Bitfinex) GetHistoricCandlesExtended(ctx context.Context, pair currency
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fInterval, err := b.FormatExchangeKlineInterval(req.ExchangeInterval)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
timeSeries := make([]kline.Candle, 0, req.Size())
|
||||
for x := range req.RangeHolder.Ranges {
|
||||
var candles []Candle
|
||||
candles, err = b.GetCandles(ctx,
|
||||
cf,
|
||||
b.FormatExchangeKlineInterval(req.ExchangeInterval),
|
||||
req.RangeHolder.Ranges[x].Start.Ticks*1000,
|
||||
req.RangeHolder.Ranges[x].End.Ticks*1000,
|
||||
uint32(req.RequestLimit),
|
||||
true)
|
||||
candles, err = b.GetCandles(ctx, cf, fInterval, req.RangeHolder.Ranges[x].Start.Time.UnixMilli(), req.RangeHolder.Ranges[x].End.Time.UnixMilli(), uint32(req.RequestLimit), true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1148,7 +1205,7 @@ func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) (string, error) {
|
||||
checkString[1] = 'F'
|
||||
}
|
||||
|
||||
fmt, err := b.FormatExchangeCurrency(in, a)
|
||||
cFmt, err := b.FormatExchangeCurrency(in, a)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1156,15 +1213,15 @@ func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) (string, error) {
|
||||
y := in.Base.String()
|
||||
if (y[0] != checkString[0] && y[0] != checkString[1]) ||
|
||||
(y[0] == checkString[1] && y[1] == checkString[1]) || in.Base == currency.TNB {
|
||||
if fmt.Quote.IsEmpty() {
|
||||
return string(checkString[0]) + fmt.Base.Upper().String(), nil
|
||||
if cFmt.Quote.IsEmpty() {
|
||||
return string(checkString[0]) + cFmt.Base.Upper().String(), nil
|
||||
}
|
||||
return string(checkString[0]) + fmt.Upper().String(), nil
|
||||
return string(checkString[0]) + cFmt.Upper().String(), nil
|
||||
}
|
||||
|
||||
runes := []rune(fmt.Upper().String())
|
||||
if fmt.Quote.IsEmpty() {
|
||||
runes = []rune(fmt.Base.Upper().String())
|
||||
runes := []rune(cFmt.Upper().String())
|
||||
if cFmt.Quote.IsEmpty() {
|
||||
runes = []rune(cFmt.Base.Upper().String())
|
||||
}
|
||||
runes[0] = unicode.ToLower(runes[0])
|
||||
return string(runes), nil
|
||||
@@ -1188,3 +1245,8 @@ func (b *Bitfinex) GetAvailableTransferChains(ctx context.Context, cryptocurrenc
|
||||
}
|
||||
return availChains, nil
|
||||
}
|
||||
|
||||
// GetServerTime returns the current exchange server time.
|
||||
func (b *Bitfinex) GetServerTime(_ context.Context, _ asset.Item) (time.Time, error) {
|
||||
return time.Time{}, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user