FTX: Various bug fixes (#631)

* FTX: Various bug fixes

* ImPrOvE CaSe SenSitVity

* Shazbert nitterinos

* "Rm newline"

* Switch from API specified timestamp values to valid FTTBTC ones for auth requests

* Move comment to specific test
This commit is contained in:
Adrian Gallagher
2021-02-16 10:17:47 +11:00
committed by GitHub
parent 504c2fad6d
commit e80091de35
3 changed files with 248 additions and 133 deletions

View File

@@ -13,6 +13,7 @@ import (
"strings"
"time"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
@@ -31,12 +32,12 @@ const (
getMarkets = "/markets"
getMarket = "/markets/"
getOrderbook = "/markets/%s/orderbook?depth=%s"
getTrades = "/markets/%s/trades?"
getHistoricalData = "/markets/%s/candles?"
getTrades = "/markets/%s/trades"
getHistoricalData = "/markets/%s/candles"
getFutures = "/futures"
getFuture = "/futures/"
getFutureStats = "/futures/%s/stats"
getFundingRates = "/funding_rates?"
getFundingRates = "/funding_rates"
getIndexWeights = "/indexes/%s/weights"
getAllWalletBalances = "/wallet/all_balances"
@@ -50,11 +51,11 @@ const (
getDepositHistory = "/wallet/deposits"
getWithdrawalHistory = "/wallet/withdrawals"
withdrawRequest = "/wallet/withdrawals"
getOpenOrders = "/orders?"
getOrderHistory = "/orders/history?"
getOpenTriggerOrders = "/conditional_orders?"
getOpenOrders = "/orders"
getOrderHistory = "/orders/history"
getOpenTriggerOrders = "/conditional_orders"
getTriggerOrderTriggers = "/conditional_orders/%s/triggers"
getTriggerOrderHistory = "/conditional_orders/history?"
getTriggerOrderHistory = "/conditional_orders/history"
placeOrder = "/orders"
placeTriggerOrder = "/conditional_orders"
modifyOrder = "/orders/%s/modify"
@@ -65,8 +66,8 @@ const (
deleteOrder = "/orders/"
deleteOrderByClientID = "/orders/by_client_id/"
cancelTriggerOrder = "/conditional_orders/"
getFills = "/fills?"
getFundingPayments = "/funding_payments?"
getFills = "/fills"
getFundingPayments = "/funding_payments"
getLeveragedTokens = "/lt/tokens"
getTokenInfo = "/lt/"
getLTBalances = "/lt/balances"
@@ -92,7 +93,7 @@ const (
// Margin Endpoints
marginBorrowRates = "/spot_margin/borrow_rates"
maringLendingRates = "/spot_margin/lending_rates"
marginLendingRates = "/spot_margin/lending_rates"
dailyBorrowedAmounts = "/spot_margin/borrow_summary"
marginMarketInfo = "/spot_margin/market_info?market=%s"
marginBorrowHistory = "/spot_margin/borrow_history"
@@ -112,6 +113,10 @@ const (
rateLimit = 30
)
var (
errStartTimeCannotBeAfterEndTime = errors.New("start timestamp cannot be after end timestamp")
)
// GetMarkets gets market data
func (f *FTX) GetMarkets() ([]MarketData, error) {
resp := struct {
@@ -164,28 +169,38 @@ func (f *FTX) GetOrderbook(marketName string, depth int64) (OrderbookData, error
// GetTrades gets trades based on the conditions specified
func (f *FTX) GetTrades(marketName string, startTime, endTime, limit int64) ([]TradeData, error) {
strLimit := strconv.FormatInt(limit, 10)
if marketName == "" {
return nil, errors.New("a market pair must be specified")
}
params := url.Values{}
params.Set("limit", strLimit)
resp := struct {
Data []TradeData `json:"result"`
}{}
if limit != 0 {
params.Set("limit", strconv.FormatInt(limit, 10))
}
if startTime > 0 && endTime > 0 {
if startTime >= (endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return nil, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime, 10))
params.Set("end_time", strconv.FormatInt(endTime, 10))
}
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getTrades, marketName)+params.Encode(),
&resp)
resp := struct {
Data []TradeData `json:"result"`
}{}
endpoint := common.EncodeURLValues(fmt.Sprintf(getTrades, marketName), params)
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, endpoint, &resp)
}
// GetHistoricalData gets historical OHLCV data for a given market pair
func (f *FTX) GetHistoricalData(marketName, timeInterval, limit string, startTime, endTime time.Time) ([]OHLCVData, error) {
resp := struct {
Data []OHLCVData `json:"result"`
}{}
if marketName == "" {
return nil, errors.New("a market pair must be specified")
}
if timeInterval == "" {
return nil, errors.New("a time interval must be specified")
}
params := url.Values{}
params.Set("resolution", timeInterval)
if limit != "" {
@@ -193,12 +208,16 @@ func (f *FTX) GetHistoricalData(marketName, timeInterval, limit string, startTim
}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return nil, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
}
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getHistoricalData, marketName)+params.Encode(), &resp)
resp := struct {
Data []OHLCVData `json:"result"`
}{}
endpoint := common.EncodeURLValues(fmt.Sprintf(getHistoricalData, marketName), params)
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, endpoint, &resp)
}
// GetFutures gets data on futures
@@ -233,7 +252,7 @@ func (f *FTX) GetFundingRates(startTime, endTime time.Time, future string) ([]Fu
params := url.Values{}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return resp.Data, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
@@ -241,7 +260,8 @@ func (f *FTX) GetFundingRates(startTime, endTime time.Time, future string) ([]Fu
if future != "" {
params.Set("future", future)
}
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getFundingRates+params.Encode(), &resp)
endpoint := common.EncodeURLValues(getFundingRates, params)
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, endpoint, &resp)
}
// GetIndexWeights gets index weights
@@ -279,15 +299,15 @@ func (f *FTX) GetMarginLendingRates() ([]MarginFundingData, error) {
r := struct {
Data []MarginFundingData `json:"result"`
}{}
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, maringLendingRates, nil, &r)
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendingRates, nil, &r)
}
// MarginDailyBorrowedAmounts gets daily borrowed amounts for margin
func (f *FTX) MarginDailyBorrowedAmounts() ([]MarginMarketInfo, error) {
func (f *FTX) MarginDailyBorrowedAmounts() ([]MarginDailyBorrowStats, error) {
r := struct {
Data []MarginMarketInfo `json:"result"`
Data []MarginDailyBorrowStats `json:"result"`
}{}
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, dailyBorrowedAmounts, nil, &r)
return r.Data, f.SendHTTPRequest(exchange.RestSpot, dailyBorrowedAmounts, &r)
}
// GetMarginMarketInfo gets margin market data
@@ -331,13 +351,24 @@ func (f *FTX) GetLendingInfo() ([]LendingInfoData, error) {
}
// SubmitLendingOffer submits an offer for margin lending
func (f *FTX) SubmitLendingOffer(coin string, size, rate float64) (interface{}, error) {
var resp interface{}
func (f *FTX) SubmitLendingOffer(coin string, size, rate float64) error {
resp := struct {
Result string `json:"result"`
Success bool `json:"success"`
}{}
req := make(map[string]interface{})
req["coin"] = coin
req["coin"] = strings.ToUpper(coin)
req["size"] = size
req["rate"] = rate
return resp, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendingInfo, req, &resp)
if err := f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, marginLendingOffers, req, &resp); err != nil {
return err
}
if !resp.Success {
return errors.New(resp.Result)
}
return nil
}
// GetAccountInfo gets account info
@@ -392,7 +423,7 @@ func (f *FTX) FetchDepositAddress(coin string) (DepositData, error) {
resp := struct {
Data DepositData `json:"result"`
}{}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getDepositAddress+coin, nil, &resp)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getDepositAddress+strings.ToUpper(coin), nil, &resp)
}
// FetchDepositHistory gets deposit history
@@ -414,7 +445,7 @@ func (f *FTX) FetchWithdrawalHistory() ([]TransactionData, error) {
// Withdraw sends a withdrawal request
func (f *FTX) Withdraw(coin, address, tag, password, code string, size float64) (TransactionData, error) {
req := make(map[string]interface{})
req["coin"] = coin
req["coin"] = strings.ToUpper(coin)
req["address"] = address
req["size"] = size
if code != "" {
@@ -441,7 +472,8 @@ func (f *FTX) GetOpenOrders(marketName string) ([]OrderData, error) {
resp := struct {
Data []OrderData `json:"result"`
}{}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOpenOrders+params.Encode(), nil, &resp)
endpoint := common.EncodeURLValues(getOpenOrders, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// FetchOrderHistory gets order history
@@ -455,7 +487,7 @@ func (f *FTX) FetchOrderHistory(marketName string, startTime, endTime time.Time,
}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return resp.Data, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
@@ -463,7 +495,8 @@ func (f *FTX) FetchOrderHistory(marketName string, startTime, endTime time.Time,
if limit != "" {
params.Set("limit", limit)
}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOrderHistory+params.Encode(), nil, &resp)
endpoint := common.EncodeURLValues(getOrderHistory, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// GetOpenTriggerOrders gets trigger orders that are currently open
@@ -478,7 +511,8 @@ func (f *FTX) GetOpenTriggerOrders(marketName, orderType string) ([]TriggerOrder
resp := struct {
Data []TriggerOrderData `json:"result"`
}{}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOpenTriggerOrders+params.Encode(), nil, &resp)
endpoint := common.EncodeURLValues(getOpenTriggerOrders, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// GetTriggerOrderTriggers gets trigger orders that are currently open
@@ -491,16 +525,13 @@ func (f *FTX) GetTriggerOrderTriggers(orderID string) ([]TriggerData, error) {
// GetTriggerOrderHistory gets trigger orders that are currently open
func (f *FTX) GetTriggerOrderHistory(marketName string, startTime, endTime time.Time, side, orderType, limit string) ([]TriggerOrderData, error) {
resp := struct {
Data []TriggerOrderData `json:"result"`
}{}
params := url.Values{}
if marketName != "" {
params.Set("market", marketName)
}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return nil, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
@@ -514,7 +545,11 @@ func (f *FTX) GetTriggerOrderHistory(marketName string, startTime, endTime time.
if limit != "" {
params.Set("limit", limit)
}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getTriggerOrderHistory+params.Encode(), nil, &resp)
resp := struct {
Data []TriggerOrderData `json:"result"`
}{}
endpoint := common.EncodeURLValues(getTriggerOrderHistory, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// Order places an order
@@ -700,12 +735,13 @@ func (f *FTX) GetFills(market, limit string, startTime, endTime time.Time) ([]Fi
}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return resp.Data, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getFills+params.Encode(), nil, &resp)
endpoint := common.EncodeURLValues(getFills, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// GetFundingPayments gets funding payments
@@ -716,7 +752,7 @@ func (f *FTX) GetFundingPayments(startTime, endTime time.Time, future string) ([
params := url.Values{}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return resp.Data, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
@@ -724,7 +760,8 @@ func (f *FTX) GetFundingPayments(startTime, endTime time.Time, future string) ([
if future != "" {
params.Set("future", future)
}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getFundingPayments+params.Encode(), nil, &resp)
endpoint := common.EncodeURLValues(getFundingPayments, params)
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, nil, &resp)
}
// ListLeveragedTokens lists leveraged tokens
@@ -806,7 +843,7 @@ func (f *FTX) GetYourQuoteRequests() ([]PersonalQuotesData, error) {
// CreateQuoteRequest sends a request to create a quote
func (f *FTX) CreateQuoteRequest(underlying, optionType, side string, expiry int64, requestExpiry string, strike, size, limitPrice, counterParyID float64, hideLimitPrice bool) (CreateQuoteRequestData, error) {
req := make(map[string]interface{})
req["underlying"] = underlying
req["underlying"] = strings.ToUpper(underlying)
req["type"] = optionType
req["side"] = side
req["strike"] = strike
@@ -894,21 +931,22 @@ func (f *FTX) GetOptionsPositions() ([]OptionsPositionsData, error) {
// GetPublicOptionsTrades gets options' trades from public
func (f *FTX) GetPublicOptionsTrades(startTime, endTime time.Time, limit string) ([]OptionsTradesData, error) {
params := url.Values{}
if !startTime.IsZero() && !endTime.IsZero() {
if startTime.After(endTime) {
return nil, errStartTimeCannotBeAfterEndTime
}
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
}
if limit != "" {
params.Set("limit", limit)
}
resp := struct {
Data []OptionsTradesData `json:"result"`
}{}
req := make(map[string]interface{})
if !startTime.IsZero() && !endTime.IsZero() {
req["start_time"] = strconv.FormatInt(startTime.Unix(), 10)
req["end_time"] = strconv.FormatInt(endTime.Unix(), 10)
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
}
}
if limit != "" {
req["limit"] = limit
}
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getPublicOptionsTrades, req, &resp)
endpoint := common.EncodeURLValues(getPublicOptionsTrades, params)
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, endpoint, &resp)
}
// GetOptionsFills gets fills data for options
@@ -921,7 +959,7 @@ func (f *FTX) GetOptionsFills(startTime, endTime time.Time, limit string) ([]Opt
req["start_time"] = strconv.FormatInt(startTime.Unix(), 10)
req["end_time"] = strconv.FormatInt(endTime.Unix(), 10)
if startTime.After(endTime) {
return resp.Data, errors.New("startTime cannot be after endTime")
return resp.Data, errStartTimeCannotBeAfterEndTime
}
}
if limit != "" {
@@ -1047,8 +1085,8 @@ func (f *FTX) RequestForQuotes(base, quote string, amount float64) (RequestQuote
Data RequestQuoteData `json:"result"`
}{}
req := make(map[string]interface{})
req["fromCoin"] = base
req["toCoin"] = quote
req["fromCoin"] = strings.ToUpper(base)
req["toCoin"] = strings.ToUpper(quote)
req["size"] = amount
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, requestOTCQuote, req, &resp)
}

View File

@@ -4,7 +4,6 @@ import (
"log"
"os"
"reflect"
"strings"
"testing"
"time"
@@ -26,8 +25,14 @@ const (
canManipulateRealOrders = false
spotPair = "FTT/BTC"
futuresPair = "DOGE-PERP"
testToken = "ADAMOON"
btcusd = "BTC/USD"
testLeverageToken = "ADAMOON"
validFTTBTCStartTime = 1565445600 // Sat Aug 10 2019 14:00:00 GMT+0000
validFTTBTCEndTime = 1565532000 // Sat Aug 10 2019 14:00:00 GMT+0000
invalidFTTBTCStartTime = 1559881511 // Fri Jun 07 2019 04:25:11 GMT+0000
invalidFTTBTCEndTime = 1559901511 // Fri Jun 07 2019 09:58:31 GMT+0000
authStartTime = validFTTBTCStartTime // Adjust these to test auth requests
authEndTime = validFTTBTCEndTime
)
var f FTX
@@ -91,34 +96,71 @@ func TestGetOrderbook(t *testing.T) {
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := f.GetTrades(spotPair, 0, 0, 200)
if err != nil {
t.Error(err)
}
_, err = f.GetTrades(spotPair, 0, 0, 5)
if err != nil {
t.Error(err)
}
_, err = f.GetTrades(spotPair, 1559901511, 1559881511, 5)
// test empty market
_, err := f.GetTrades("", 0, 0, 200)
if err == nil {
t.Error("empty market should return an error")
}
_, err = f.GetTrades(spotPair, validFTTBTCEndTime, validFTTBTCStartTime, 5)
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
// test optional params
var trades []TradeData
trades, err = f.GetTrades(spotPair, 0, 0, 0)
if err != nil {
t.Error(err)
}
if len(trades) != 20 {
t.Error("default limit should return 20 items")
}
trades, err = f.GetTrades(spotPair, validFTTBTCStartTime, validFTTBTCEndTime, 5)
if err != nil {
t.Error(err)
}
if len(trades) != 5 {
t.Error("limit of 5 should return 5 items")
}
trades, err = f.GetTrades(spotPair, invalidFTTBTCStartTime, invalidFTTBTCEndTime, 5)
if err != nil {
t.Error(err)
}
if len(trades) != 0 {
t.Error("invalid time range should return 0 items")
}
}
func TestGetHistoricalData(t *testing.T) {
t.Parallel()
_, err := f.GetHistoricalData(spotPair, "86400", "5", time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = f.GetHistoricalData(spotPair, "86400", "5", time.Unix(1559881511, 0), time.Unix(1559901511, 0))
if err != nil {
t.Error(err)
}
_, err = f.GetHistoricalData(spotPair, "86400", "5", time.Unix(1559901511, 0), time.Unix(1559881511, 0))
// test empty market
_, err := f.GetHistoricalData("", "86400", "5", time.Time{}, time.Time{})
if err == nil {
t.Error("empty market should return an error")
}
// test empty resolution
_, err = f.GetHistoricalData(spotPair, "", "5", time.Time{}, time.Time{})
if err == nil {
t.Error("empty resolution should return an error")
}
_, err = f.GetHistoricalData(spotPair, "86400", "5", time.Unix(validFTTBTCEndTime, 0), time.Unix(validFTTBTCStartTime, 0))
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
var o []OHLCVData
o, err = f.GetHistoricalData(spotPair, "86400", "5", time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
if len(o) != 5 {
t.Error("limit of 5 should return 5 items")
}
o, err = f.GetHistoricalData(spotPair, "86400", "5", time.Unix(invalidFTTBTCStartTime, 0), time.Unix(invalidFTTBTCEndTime, 0))
if err != nil {
t.Error(err)
}
if len(o) != 0 {
t.Error("invalid time range should return 0 items")
}
}
func TestGetFutures(t *testing.T) {
@@ -147,7 +189,12 @@ func TestGetFutureStats(t *testing.T) {
func TestGetFundingRates(t *testing.T) {
t.Parallel()
_, err := f.GetFundingRates(time.Now().Add(-time.Hour), time.Now(), "BTC-PERP")
// optional params
_, err := f.GetFundingRates(time.Time{}, time.Time{}, "")
if err != nil {
t.Error(err)
}
_, err = f.GetFundingRates(time.Now().Add(-time.Hour), time.Now(), "BTC-PERP")
if err != nil {
t.Error(err)
}
@@ -243,9 +290,6 @@ func TestGetMarginLendingRates(t *testing.T) {
func TestMarginDailyBorrowedAmounts(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.MarginDailyBorrowedAmounts()
if err != nil {
t.Error(err)
@@ -312,8 +356,7 @@ func TestSubmitLendingOffer(t *testing.T) {
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip()
}
_, err := f.SubmitLendingOffer("btc", 0.1, 500)
if err != nil {
if err := f.SubmitLendingOffer("bTc", 0.1, 500); err != nil {
t.Error(err)
}
}
@@ -323,7 +366,7 @@ func TestFetchDepositAddress(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.FetchDepositAddress("TUSD")
_, err := f.FetchDepositAddress("tUsD")
if err != nil {
t.Error(err)
}
@@ -356,7 +399,7 @@ func TestWithdraw(t *testing.T) {
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or canManipulateRealOrders isnt set correctly")
}
_, err := f.Withdraw("BTC", core.BitcoinDonationAddress, "", "", "957378", 0.0009)
_, err := f.Withdraw("BtC", core.BitcoinDonationAddress, "", "", "957378", 0.0009)
if err != nil {
t.Error(err)
}
@@ -367,7 +410,11 @@ func TestGetOpenOrders(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetOpenOrders(spotPair)
_, err := f.GetOpenOrders("")
if err != nil {
t.Error(err)
}
_, err = f.GetOpenOrders(spotPair)
if err != nil {
t.Error(err)
}
@@ -378,17 +425,17 @@ func TestFetchOrderHistory(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.FetchOrderHistory(spotPair, time.Time{}, time.Time{}, "2")
_, err := f.FetchOrderHistory("", time.Time{}, time.Time{}, "2")
if err != nil {
t.Error(err)
}
_, err = f.FetchOrderHistory(spotPair, time.Unix(1559881511, 0), time.Unix(1559901511, 0), "2")
_, err = f.FetchOrderHistory(spotPair, time.Unix(authStartTime, 0), time.Unix(authEndTime, 0), "2")
if err != nil {
t.Error(err)
}
_, err = f.FetchOrderHistory(spotPair, time.Unix(1559901511, 0), time.Unix(1559881511, 0), "2")
if err == nil {
t.Error(err)
_, err = f.FetchOrderHistory(spotPair, time.Unix(authEndTime, 0), time.Unix(authStartTime, 0), "2")
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
@@ -397,7 +444,12 @@ func TestGetOpenTriggerOrders(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetOpenTriggerOrders(spotPair, "")
// optional params
_, err := f.GetOpenTriggerOrders("", "")
if err != nil {
t.Error(err)
}
_, err = f.GetOpenTriggerOrders(spotPair, "")
if err != nil {
t.Error(err)
}
@@ -419,18 +471,22 @@ func TestGetTriggerOrderHistory(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetTriggerOrderHistory(spotPair, time.Time{}, time.Time{}, order.Buy.Lower(), "stop", "1")
_, err := f.GetTriggerOrderHistory("", time.Time{}, time.Time{}, "", "", "")
if err != nil {
t.Error(err)
}
_, err = f.GetTriggerOrderHistory(spotPair, time.Unix(1559881511, 0), time.Unix(1559901511, 0), order.Buy.Lower(), "stop", "1")
_, err = f.GetTriggerOrderHistory(spotPair, time.Time{}, time.Time{}, order.Buy.Lower(), "stop", "1")
if err != nil {
t.Error(err)
}
_, err = f.GetTriggerOrderHistory(spotPair, time.Unix(1559901511, 0), time.Unix(1559881511, 0), order.Buy.Lower(), "stop", "1")
if err == nil {
_, err = f.GetTriggerOrderHistory(spotPair, time.Unix(authStartTime, 0), time.Unix(authEndTime, 0), order.Buy.Lower(), "stop", "1")
if err != nil {
t.Error(err)
}
_, err = f.GetTriggerOrderHistory(spotPair, time.Unix(authEndTime, 0), time.Unix(authStartTime, 0), order.Buy.Lower(), "stop", "1")
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
func TestOrder(t *testing.T) {
@@ -546,18 +602,23 @@ func TestGetFills(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetFills(spotPair, "", time.Time{}, time.Time{})
// optional params
_, err := f.GetFills("", "", time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = f.GetFills(spotPair, "", time.Unix(1559881511, 0), time.Unix(1559901511, 0))
_, err = f.GetFills(spotPair, "", time.Time{}, time.Time{})
if err != nil {
t.Error(err)
}
_, err = f.GetFills(spotPair, "", time.Unix(1559901511, 0), time.Unix(1559881511, 0))
if err == nil {
_, err = f.GetFills(spotPair, "", time.Unix(authStartTime, 0), time.Unix(authEndTime, 0))
if err != nil {
t.Error(err)
}
_, err = f.GetFills(spotPair, "", time.Unix(authEndTime, 0), time.Unix(authStartTime, 0))
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
func TestGetFundingPayments(t *testing.T) {
@@ -565,14 +626,19 @@ func TestGetFundingPayments(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetFundingPayments(time.Unix(1559881511, 0), time.Unix(1559901511, 0), "")
// optional params
_, err := f.GetFundingPayments(time.Time{}, time.Time{}, "")
if err != nil {
t.Error(err)
}
_, err = f.GetFundingPayments(time.Unix(1559901511, 0), time.Unix(1559881511, 0), "")
if err == nil {
_, err = f.GetFundingPayments(time.Unix(authStartTime, 0), time.Unix(authEndTime, 0), futuresPair)
if err != nil {
t.Error(err)
}
_, err = f.GetFundingPayments(time.Unix(authEndTime, 0), time.Unix(authStartTime, 0), futuresPair)
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
func TestListLeveragedTokens(t *testing.T) {
@@ -624,7 +690,7 @@ func TestRequestLTCreation(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.RequestLTCreation(testToken, 1)
_, err := f.RequestLTCreation(testLeverageToken, 1)
if err != nil {
t.Error(err)
}
@@ -668,7 +734,7 @@ func TestCreateQuoteRequest(t *testing.T) {
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or canManipulateRealOrders isnt set correctly")
}
_, err := f.CreateQuoteRequest(strings.ToUpper(currency.BTC.String()), "call", order.Buy.Lower(), 1593140400, "", 10, 10, 5, 0, false)
_, err := f.CreateQuoteRequest(currency.BTC.String(), "call", order.Buy.Lower(), 1593140400, "", 10, 10, 5, 0, false)
if err != nil {
t.Error(err)
}
@@ -764,20 +830,25 @@ func TestGetOptionsPositions(t *testing.T) {
func TestGetPublicOptionsTrades(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip()
}
_, err := f.GetPublicOptionsTrades(time.Time{}, time.Time{}, "5")
// test optional params
result, err := f.GetPublicOptionsTrades(time.Time{}, time.Time{}, "")
if err != nil {
t.Error(err)
}
_, err = f.GetPublicOptionsTrades(time.Unix(1559881511, 0), time.Unix(1559901511, 0), "5")
if len(result) != 20 {
t.Error("default limit should have returned 20 items")
}
tmNow := time.Now()
result, err = f.GetPublicOptionsTrades(tmNow.AddDate(0, 0, -1), tmNow, "5")
if err != nil {
t.Error(err)
}
_, err = f.GetPublicOptionsTrades(time.Unix(1559901511, 0), time.Unix(1559881511, 0), "5")
if err == nil {
t.Error(err)
if len(result) != 5 {
t.Error("limit of 5 should return 5 items")
}
_, err = f.GetPublicOptionsTrades(time.Unix(validFTTBTCEndTime, 0), time.Unix(validFTTBTCStartTime, 0), "5")
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
@@ -790,13 +861,13 @@ func TestGetOptionsFills(t *testing.T) {
if err != nil {
t.Error(err)
}
_, err = f.GetOptionsFills(time.Unix(1559881511, 0), time.Unix(1559901511, 0), "5")
_, err = f.GetOptionsFills(time.Unix(authStartTime, 0), time.Unix(authEndTime, 0), "5")
if err != nil {
t.Error(err)
}
_, err = f.GetOptionsFills(time.Unix(1559901511, 0), time.Unix(1559881511, 0), "5")
if err == nil {
t.Error(err)
_, err = f.GetOptionsFills(time.Unix(authEndTime, 0), time.Unix(authStartTime, 0), "5")
if err != errStartTimeCannotBeAfterEndTime {
t.Errorf("should have thrown errStartTimeCannotBeAfterEndTime, got %v", err)
}
}
@@ -1223,7 +1294,7 @@ func TestGetOTCQuoteStatus(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := f.GetOTCQuoteStatus(btcusd, "1")
_, err := f.GetOTCQuoteStatus(spotPair, "1")
if err != nil {
t.Error(err)
}
@@ -1234,7 +1305,7 @@ func TestRequestForQuotes(t *testing.T) {
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or canManipulateRealOrders isnt set correctly")
}
_, err := f.RequestForQuotes("BTC", "USD", 0.5)
_, err := f.RequestForQuotes("BtC", "UsD", 0.5)
if err != nil {
t.Error(err)
}

View File

@@ -14,6 +14,12 @@ type MarginFundingData struct {
Previous float64 `json:"previous"`
}
// MarginDailyBorrowStats stores the daily borrowed amounts
type MarginDailyBorrowStats struct {
Coin string `json:"coin"`
Size float64 `json:"size"`
}
// MarginMarketInfo stores margin market info
type MarginMarketInfo struct {
Coin string `json:"coin"`
@@ -319,13 +325,13 @@ type FillsData struct {
Fee float64 `json:"fee"`
FeeRate float64 `json:"feeRate"`
Future string `json:"future"`
ID string `json:"id"`
ID int64 `json:"id"`
Liquidity string `json:"liquidity"`
Market string `json:"market"`
BaseCurrency string `json:"baseCurrency"`
QuoteCurrency string `json:"quoteCurrency"`
OrderID string `json:"orderID"`
TradeID string `json:"tradeID"`
OrderID int64 `json:"orderId"`
TradeID int64 `json:"tradeId"`
Price float64 `json:"price"`
Side string `json:"side"`
Size float64 `json:"size"`
@@ -336,7 +342,7 @@ type FillsData struct {
// FundingPaymentsData stores funding payments' data
type FundingPaymentsData struct {
Future string `json:"future"`
ID string `json:"id"`
ID int64 `json:"id"`
Payment float64 `json:"payment"`
Time time.Time `json:"time"`
Rate float64 `json:"rate"`
@@ -617,8 +623,8 @@ type WsFills struct {
ID int64 `json:"id"`
Liquidity string `json:"liquidity"`
Market string `json:"market"`
OrderID int64 `json:"int64"`
TradeID int64 `json:"tradeID"`
OrderID int64 `json:"orderId"`
TradeID int64 `json:"tradeId"`
Price float64 `json:"price"`
Side string `json:"side"`
Size float64 `json:"size"`