mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-21 07:26:48 +00:00
Feature: Implement funding rates, futures and coin margin (exchange API coverage) (#530)
* ALMOST THERE * more api wips * more api thingz * testing n more api wipz * more apiz * more wips * what is goin on * more wips * whip n testing * testing * testing no keys * remove log * kraken is broken ugh * still broken * fixing auth funcs + usdtm api docs * wip * api stuffs * whip * more wips * whip * more wip * api wip n testing * wip * wip * unsaved * wip n testing * wip * wip * wip * wip * wip * wip * wip * wip * wip * whip * wrapper authenticated functions * adding asset type and fixing dependencies * wip * binance auth wrapper start * wrapper functionality * wip * wip * wip * wrapper cancel functions * order submission for wrappers * wip * more error fixing and nits * websocket beginning n error fix * wip * WOW * glorious n shazzy nits * useless nits * wip * fixing things * merge stuffs * crapveyor * crapveyor rebuild * probably broke more things than he fixed * rm lns n other thangs * hope * please * stop it * done * ofcourse * rm vb * fix lbank * appveyor please * float lev * DONT ASK RYAN FOR HELP EVER * wip * wip * endpoint upgrades continued * path upgrade * NeeeNeeeNeeeNeeeNING * fix stuffs * fixing time issue * fixing broken funcs * glorious nits * shaz changes * fixing errors for fundmon * more error fixing for fundmon * test running past 30s * basic changes * THX AGAIN SHAZBERT * path system upgrade * config upgrade * unsaved stuffs * broken wip config upgrade * path system upgrade contd. * path system upgrade contd * path upgrade ready for review * testing verbose removed * linter stuffs * appveyor stuffs * appveyor stuff * fixed? * bugfix * wip * broken stuff * fix test * wierd hack fix * appveyor pls stop * error found * more useless nits * bitmex err * broken wip * broken wip path upgrade change to uint32 * changed url lookups to uint * WOW * ready4review * config fixed HOPEFULLY * config fix and glorious changes * efficient way of getting orders and open orders * binance wrapper logic fixing * testing, adding tests and fixing lot of errrrrs * merge master * appveyor stuffs * appveyor stuffs * fmt * test * octalLiteral issue fix? * octalLiteral fix? * rm vb * prnt ln to restart * adding testz * test fixzzz * READY FOR REVIEW * Actually ready now * FORMATTING * addressing shazzy n glorious nits * crapveyor * rm vb * small change * fixing err * shazbert nits * review changes * requested changes * more requested changes * noo * last nit fixes * restart appveyor * improving test cov * Update .golangci.yml * shazbert changes * moving pair formatting * format pair update wip * path upgrade complete * error fix * appveyor linters * more linters * remove testexch * more formatting changes * changes * shazbert changes * checking older requested changes to ensure completion * wip * fixing broken code * error fix * all fixed * additional changes * more changes * remove commented code * ftx margin api * appveyor fixes * more appveyor issues + test addition * more appveyor issues + test addition * remove unnecessary * testing * testing, fixing okex api, error fix * git merge fix * go sum * glorious changes and error fix * rm vb * more glorious changes and go mod tidy * fixed now * okex testing upgrade * old config migration and batch fetching fix * added test * glorious requested changes WIP * tested and fixed * go fmted * go fmt and test fix * additional funcs and tests for fundingRates * OKEX tested and fixed * appveyor fixes * ineff assign * 1 glorious change * error fix * typo * shazbert changes * glorious code changes and path fixing huobi WIP * adding assetType to accountinfo functions * fixing panic * panic fix and updating account info wrappers WIP * updateaccountinfo updated * testing WIP binance USDT n Coin Margined and Kraken Futures * auth functions tested and fixed * added test * config reverted * shazbert and glorious changes * shazbert and glorious changes * latest changes and portfolio update * go fmt change: * remove commented codes * improved error checking * index out of range fix * rm ln * critical nit * glorious latest changes * appveyor changes * shazbert change * easier readability * latest glorious changes * shadow dec * assetstore updated * last change * another last change * merge changes * go mod tidy * thrasher requested changes wip * improving struct layouts * appveyor go fmt * remove unnecessary code * shazbert changes * small change * oopsie * tidy * configtest reverted * error fix * oopsie * for what * test patch fix * insecurities * fixing tests * fix config
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -45,20 +46,29 @@ func Process(h *Holdings) error {
|
||||
}
|
||||
|
||||
// GetHoldings returns full holdings for an exchange
|
||||
func GetHoldings(exch string) (Holdings, error) {
|
||||
func GetHoldings(exch string, assetType asset.Item) (Holdings, error) {
|
||||
if exch == "" {
|
||||
return Holdings{}, errors.New("exchange name unset")
|
||||
}
|
||||
|
||||
exch = strings.ToLower(exch)
|
||||
|
||||
if !assetType.IsValid() {
|
||||
return Holdings{}, fmt.Errorf("assetType %v is invalid", assetType)
|
||||
}
|
||||
|
||||
service.Lock()
|
||||
defer service.Unlock()
|
||||
h, ok := service.accounts[exch]
|
||||
if !ok {
|
||||
return Holdings{}, errors.New("exchange account holdings not found")
|
||||
}
|
||||
return *h.h, nil
|
||||
for y := range h.h.Accounts {
|
||||
if h.h.Accounts[y].AssetType == assetType {
|
||||
return *h.h, nil
|
||||
}
|
||||
}
|
||||
return Holdings{}, fmt.Errorf("%v holdings data not found for %s", assetType, exch)
|
||||
}
|
||||
|
||||
// Update updates holdings with new account info
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
)
|
||||
|
||||
func TestHoldings(t *testing.T) {
|
||||
@@ -36,7 +37,8 @@ func TestHoldings(t *testing.T) {
|
||||
err = Process(&Holdings{
|
||||
Exchange: "Test",
|
||||
Accounts: []SubAccount{{
|
||||
ID: "1337",
|
||||
AssetType: asset.Spot,
|
||||
ID: "1337",
|
||||
Currencies: []Balance{
|
||||
{
|
||||
CurrencyName: currency.BTC,
|
||||
@@ -50,17 +52,22 @@ func TestHoldings(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = GetHoldings("")
|
||||
_, err = GetHoldings("", asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
_, err = GetHoldings("bla")
|
||||
_, err = GetHoldings("bla", asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil")
|
||||
}
|
||||
|
||||
u, err := GetHoldings("Test")
|
||||
_, err = GetHoldings("bla", asset.Item("hi"))
|
||||
if err == nil {
|
||||
t.Error("error cannot be nil since an invalid asset type is provided")
|
||||
}
|
||||
|
||||
u, err := GetHoldings("Test", asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
)
|
||||
|
||||
// Vars for the ticker package
|
||||
@@ -36,6 +37,7 @@ type Holdings struct {
|
||||
// SubAccount defines a singular account type with asocciated currency balances
|
||||
type SubAccount struct {
|
||||
ID string
|
||||
AssetType asset.Item
|
||||
Currencies []Balance
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ func (a *Alphapoint) GetTicker(currencyPair string) (Ticker, error) {
|
||||
req["productPair"] = currencyPair
|
||||
response := Ticker{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointTicker, req, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointTicker, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func (a *Alphapoint) GetTrades(currencyPair string, startIndex, count int) (Trad
|
||||
req["Count"] = count
|
||||
response := Trades{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointTrades, req, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointTrades, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -102,7 +102,7 @@ func (a *Alphapoint) GetTradesByDate(currencyPair string, startDate, endDate int
|
||||
req["endDate"] = endDate
|
||||
response := Trades{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointTradesByDate, req, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointTradesByDate, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -119,7 +119,7 @@ func (a *Alphapoint) GetOrderbook(currencyPair string) (Orderbook, error) {
|
||||
req["productPair"] = currencyPair
|
||||
response := Orderbook{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointOrderbook, req, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointOrderbook, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (a *Alphapoint) GetOrderbook(currencyPair string) (Orderbook, error) {
|
||||
func (a *Alphapoint) GetProductPairs() (ProductPairs, error) {
|
||||
response := ProductPairs{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointProductPairs, nil, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointProductPairs, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -147,7 +147,7 @@ func (a *Alphapoint) GetProductPairs() (ProductPairs, error) {
|
||||
func (a *Alphapoint) GetProducts() (Products, error) {
|
||||
response := Products{}
|
||||
|
||||
err := a.SendHTTPRequest(http.MethodPost, alphapointProducts, nil, &response)
|
||||
err := a.SendHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointProducts, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func (a *Alphapoint) CreateAccount(firstName, lastName, email, phone, password s
|
||||
req["password"] = password
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(http.MethodPost, alphapointCreateAccount, req, &response)
|
||||
err := a.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointCreateAccount, req, &response)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create account. Reason: %s", err)
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func (a *Alphapoint) CreateAccount(firstName, lastName, email, phone, password s
|
||||
func (a *Alphapoint) GetUserInfo() (UserInfo, error) {
|
||||
response := UserInfo{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(http.MethodPost, alphapointUserInfo, map[string]interface{}{}, &response)
|
||||
err := a.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointUserInfo, map[string]interface{}{}, &response)
|
||||
if err != nil {
|
||||
return UserInfo{}, err
|
||||
}
|
||||
@@ -245,6 +245,7 @@ func (a *Alphapoint) SetUserInfo(firstName, lastName, cell2FACountryCode, cell2F
|
||||
req["userInfoKVP"] = userInfoKVPs
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointUserInfo,
|
||||
req,
|
||||
@@ -264,6 +265,7 @@ func (a *Alphapoint) GetAccountInformation() (AccountInfo, error) {
|
||||
response := AccountInfo{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointAccountInfo,
|
||||
map[string]interface{}{},
|
||||
@@ -290,6 +292,7 @@ func (a *Alphapoint) GetAccountTrades(currencyPair string, startIndex, count int
|
||||
response := Trades{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointAccountTrades,
|
||||
req,
|
||||
@@ -308,7 +311,7 @@ func (a *Alphapoint) GetAccountTrades(currencyPair string, startIndex, count int
|
||||
func (a *Alphapoint) GetDepositAddresses() ([]DepositAddresses, error) {
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(http.MethodPost, alphapointDepositAddresses,
|
||||
err := a.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, alphapointDepositAddresses,
|
||||
map[string]interface{}{}, &response,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -334,6 +337,7 @@ func (a *Alphapoint) WithdrawCoins(symbol, product, address string, amount float
|
||||
|
||||
response := Response{}
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointWithdraw,
|
||||
req,
|
||||
@@ -373,6 +377,7 @@ func (a *Alphapoint) CreateOrder(symbol, side, orderType string, quantity, price
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointCreateOrder,
|
||||
req,
|
||||
@@ -403,6 +408,7 @@ func (a *Alphapoint) ModifyExistingOrder(symbol string, orderID, action int64) (
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointModifyOrder,
|
||||
req,
|
||||
@@ -427,6 +433,7 @@ func (a *Alphapoint) CancelExistingOrder(orderID int64, omsid string) (int64, er
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointCancelOrder,
|
||||
req,
|
||||
@@ -449,6 +456,7 @@ func (a *Alphapoint) CancelAllExistingOrders(omsid string) error {
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointCancelAllOrders,
|
||||
req,
|
||||
@@ -468,6 +476,7 @@ func (a *Alphapoint) GetOrders() ([]OpenOrders, error) {
|
||||
response := OrderInfo{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointOpenOrders,
|
||||
map[string]interface{}{},
|
||||
@@ -496,6 +505,7 @@ func (a *Alphapoint) GetOrderFee(symbol, side string, quantity, price float64) (
|
||||
response := Response{}
|
||||
|
||||
err := a.SendAuthenticatedHTTPRequest(
|
||||
exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
alphapointOrderFee,
|
||||
req,
|
||||
@@ -511,10 +521,14 @@ func (a *Alphapoint) GetOrderFee(symbol, side string, quantity, price float64) (
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (a *Alphapoint) SendHTTPRequest(method, path string, data map[string]interface{}, result interface{}) error {
|
||||
func (a *Alphapoint) SendHTTPRequest(ep exchange.URL, method, path string, data map[string]interface{}, result interface{}) error {
|
||||
endpoint, err := a.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
path = fmt.Sprintf("%s/ajax/v%s/%s", a.API.Endpoints.URL, alphapointAPIVersion, path)
|
||||
path = fmt.Sprintf("%s/ajax/v%s/%s", endpoint, alphapointAPIVersion, path)
|
||||
|
||||
PayloadJSON, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
@@ -533,11 +547,16 @@ func (a *Alphapoint) SendHTTPRequest(method, path string, data map[string]interf
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request
|
||||
func (a *Alphapoint) SendAuthenticatedHTTPRequest(method, path string, data map[string]interface{}, result interface{}) error {
|
||||
func (a *Alphapoint) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, data map[string]interface{}, result interface{}) error {
|
||||
if !a.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, a.Name)
|
||||
}
|
||||
|
||||
endpoint, err := a.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := a.Requester.GetNonce(true)
|
||||
|
||||
headers := make(map[string]string)
|
||||
@@ -548,7 +567,7 @@ func (a *Alphapoint) SendAuthenticatedHTTPRequest(method, path string, data map[
|
||||
[]byte(n.String()+a.API.Credentials.ClientID+a.API.Credentials.Key),
|
||||
[]byte(a.API.Credentials.Secret))
|
||||
data["apiSig"] = strings.ToUpper(crypto.HexEncodeToString(hmac))
|
||||
path = fmt.Sprintf("%s/ajax/v%s/%s", a.API.Endpoints.URL, alphapointAPIVersion, path)
|
||||
path = fmt.Sprintf("%s/ajax/v%s/%s", endpoint, alphapointAPIVersion, path)
|
||||
|
||||
PayloadJSON, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,7 +2,6 @@ package alphapoint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -30,12 +29,6 @@ func TestMain(m *testing.M) {
|
||||
a.API.Credentials.Key = apiKey
|
||||
a.API.Credentials.Secret = apiSecret
|
||||
a.API.AuthenticatedSupport = true
|
||||
if a.API.Endpoints.URL != "https://sim3.alphapoint.com:8400" {
|
||||
log.Fatal("SetDefaults: String Incorrect -", a.API.Endpoints.URL)
|
||||
}
|
||||
if a.API.Endpoints.WebsocketURL != "wss://sim3.alphapoint.com:8401/v1/GetTicker/" {
|
||||
log.Fatal("SetDefaults: String Incorrect -", a.API.Endpoints.WebsocketURL)
|
||||
}
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -327,7 +320,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
t.Skip("API keys not set, skipping")
|
||||
}
|
||||
|
||||
_, err := a.UpdateAccountInfo()
|
||||
_, err := a.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetUserInfo() Expected error")
|
||||
}
|
||||
@@ -441,7 +434,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := a.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -455,7 +449,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := a.GetOrderHistory(&getOrdersRequest)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
@@ -18,7 +19,11 @@ func (a *Alphapoint) WebsocketClient() {
|
||||
var dialer websocket.Dialer
|
||||
var err error
|
||||
var httpResp *http.Response
|
||||
a.WebsocketConn, httpResp, err = dialer.Dial(a.API.Endpoints.WebsocketURL, http.Header{})
|
||||
endpoint, err := a.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
log.Error(log.WebsocketMgr, err)
|
||||
}
|
||||
a.WebsocketConn, httpResp, err = dialer.Dial(endpoint, http.Header{})
|
||||
httpResp.Body.Close() // not used, so safely free the body
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/trade"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
|
||||
@@ -30,8 +31,14 @@ func (a *Alphapoint) SetDefaults() {
|
||||
a.Name = "Alphapoint"
|
||||
a.Enabled = true
|
||||
a.Verbose = true
|
||||
a.API.Endpoints.URL = alphapointDefaultAPIURL
|
||||
a.API.Endpoints.WebsocketURL = alphapointDefaultWebsocketURL
|
||||
a.API.Endpoints = a.NewEndpoints()
|
||||
err := a.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: alphapointDefaultAPIURL,
|
||||
exchange.WebsocketSpot: alphapointDefaultWebsocketURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
a.API.CredentialsValidator.RequiresKey = true
|
||||
a.API.CredentialsValidator.RequiresSecret = true
|
||||
|
||||
@@ -82,7 +89,7 @@ func (a *Alphapoint) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Alphapoint exchange
|
||||
func (a *Alphapoint) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (a *Alphapoint) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = a.Name
|
||||
acc, err := a.GetAccountInformation()
|
||||
@@ -114,10 +121,10 @@ func (a *Alphapoint) UpdateAccountInfo() (account.Holdings, error) {
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Alphapoint exchange
|
||||
func (a *Alphapoint) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(a.Name)
|
||||
func (a *Alphapoint) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(a.Name, assetType)
|
||||
if err != nil {
|
||||
return a.UpdateAccountInfo()
|
||||
return a.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -433,7 +440,7 @@ func (a *Alphapoint) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (a *Alphapoint) ValidateCredentials() error {
|
||||
_, err := a.UpdateAccountInfo()
|
||||
func (a *Alphapoint) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := a.UpdateAccountInfo(assetType)
|
||||
return a.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ const (
|
||||
Futures = Item("futures")
|
||||
UpsideProfitContract = Item("upsideprofitcontract")
|
||||
DownsideProfitContract = Item("downsideprofitcontract")
|
||||
CoinMarginedFutures = Item("coinmarginedfutures")
|
||||
USDTMarginedFutures = Item("usdtmarginedfutures")
|
||||
)
|
||||
|
||||
var supported = Items{
|
||||
@@ -36,6 +38,8 @@ var supported = Items{
|
||||
Futures,
|
||||
UpsideProfitContract,
|
||||
DownsideProfitContract,
|
||||
CoinMarginedFutures,
|
||||
USDTMarginedFutures,
|
||||
}
|
||||
|
||||
// Supported returns a list of supported asset types
|
||||
|
||||
@@ -17,18 +17,30 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
// Binance is the overarching type across the Binance package
|
||||
type Binance struct {
|
||||
exchange.Base
|
||||
// Valid string list that is required by the exchange
|
||||
validLimits []int
|
||||
|
||||
obm *orderbookManager
|
||||
}
|
||||
|
||||
const (
|
||||
apiURL = "https://api.binance.com"
|
||||
apiURL = "https://api.binance.com"
|
||||
spotAPIURL = "https://sapi.binance.com"
|
||||
cfuturesAPIURL = "https://dapi.binance.com"
|
||||
ufuturesAPIURL = "https://fapi.binance.com"
|
||||
|
||||
// Public endpoints
|
||||
exchangeInfo = "/api/v3/exchangeInfo"
|
||||
orderBookDepth = "/api/v3/depth"
|
||||
recentTrades = "/api/v3/trades"
|
||||
historicalTrades = "/api/v3/historicalTrades"
|
||||
aggregatedTrades = "/api/v3/aggTrades"
|
||||
candleStick = "/api/v3/klines"
|
||||
averagePrice = "/api/v3/avgPrice"
|
||||
@@ -37,45 +49,57 @@ const (
|
||||
bestPrice = "/api/v3/ticker/bookTicker"
|
||||
accountInfo = "/api/v3/account"
|
||||
userAccountStream = "/api/v3/userDataStream"
|
||||
perpExchangeInfo = "/fapi/v1/exchangeInfo"
|
||||
|
||||
// Authenticated endpoints
|
||||
newOrderTest = "/api/v3/order/test"
|
||||
newOrder = "/api/v3/order"
|
||||
cancelOrder = "/api/v3/order"
|
||||
queryOrder = "/api/v3/order"
|
||||
openOrders = "/api/v3/openOrders"
|
||||
allOrders = "/api/v3/allOrders"
|
||||
myTrades = "/api/v3/myTrades"
|
||||
newOrderTest = "/api/v3/order/test"
|
||||
orderEndpoint = "/api/v3/order"
|
||||
openOrders = "/api/v3/openOrders"
|
||||
allOrders = "/api/v3/allOrders"
|
||||
|
||||
// Withdraw API endpoints
|
||||
withdrawEndpoint = "/wapi/v3/withdraw.html"
|
||||
depositHistory = "/wapi/v3/depositHistory.html"
|
||||
withdrawalHistory = "/wapi/v3/withdrawHistory.html"
|
||||
depositAddress = "/wapi/v3/depositAddress.html"
|
||||
accountStatus = "/wapi/v3/accountStatus.html"
|
||||
systemStatus = "/wapi/v3/systemStatus.html"
|
||||
dustLog = "/wapi/v3/userAssetDribbletLog.html"
|
||||
tradeFee = "/wapi/v3/tradeFee.html"
|
||||
assetDetail = "/wapi/v3/assetDetail.html"
|
||||
withdrawEndpoint = "/wapi/v3/withdraw.html"
|
||||
depositHistory = "/wapi/v3/depositHistory.html"
|
||||
withdrawalHistory = "/wapi/v3/withdrawHistory.html"
|
||||
depositAddress = "/wapi/v3/depositAddress.html"
|
||||
accountStatus = "/wapi/v3/accountStatus.html"
|
||||
systemStatus = "/wapi/v3/systemStatus.html"
|
||||
dustLog = "/wapi/v3/userAssetDribbletLog.html"
|
||||
tradeFee = "/wapi/v3/tradeFee.html"
|
||||
assetDetail = "/wapi/v3/assetDetail.html"
|
||||
undocumentedInterestHistory = "/gateway-api/v1/public/isolated-margin/pair/vip-level"
|
||||
undocumentedCrossMarginInterestHistory = "/gateway-api/v1/friendly/margin/vip/spec/list-all"
|
||||
)
|
||||
|
||||
// Binance is the overarching type across the Bithumb package
|
||||
type Binance struct {
|
||||
exchange.Base
|
||||
// GetInterestHistory gets interest history for currency/currencies provided
|
||||
func (b *Binance) GetInterestHistory() (MarginInfoData, error) {
|
||||
var resp MarginInfoData
|
||||
if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedInterestHistory, limitDefault, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Valid string list that is required by the exchange
|
||||
validLimits []int
|
||||
// GetCrossMarginInterestHistory gets cross-margin interest history for currency/currencies provided
|
||||
func (b *Binance) GetCrossMarginInterestHistory() (CrossMarginInterestData, error) {
|
||||
var resp CrossMarginInterestData
|
||||
if err := b.SendHTTPRequest(exchange.EdgeCase1, undocumentedCrossMarginInterestHistory, limitDefault, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
obm *orderbookManager
|
||||
// GetMarginMarkets returns exchange information. Check binance_types for more information
|
||||
func (b *Binance) GetMarginMarkets() (PerpsExchangeInfo, error) {
|
||||
var resp PerpsExchangeInfo
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, perpExchangeInfo, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// GetExchangeInfo returns exchange information. Check binance_types for more
|
||||
// information
|
||||
func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) {
|
||||
var resp ExchangeInfo
|
||||
path := b.API.Endpoints.URL + exchangeInfo
|
||||
|
||||
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, exchangeInfo, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// GetOrderBook returns full orderbook information
|
||||
@@ -90,7 +114,7 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.formatSymbol(obd.Symbol)
|
||||
symbol, err := b.FormatSymbol(obd.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
}
|
||||
@@ -98,8 +122,7 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error
|
||||
params.Set("limit", fmt.Sprintf("%d", obd.Limit))
|
||||
|
||||
var resp OrderBookData
|
||||
path := common.EncodeURLValues(b.API.Endpoints.URL+orderBookDepth, params)
|
||||
if err := b.SendHTTPRequest(path, orderbookLimit(obd.Limit), &resp); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, orderBookDepth+"?"+params.Encode(), orderbookLimit(obd.Limit), &resp); err != nil {
|
||||
return orderbook, err
|
||||
}
|
||||
|
||||
@@ -147,16 +170,16 @@ func (b *Binance) GetMostRecentTrades(rtr RecentTradeRequestParams) ([]RecentTra
|
||||
var resp []RecentTrade
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.formatSymbol(rtr.Symbol)
|
||||
symbol, err := b.FormatSymbol(rtr.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("limit", fmt.Sprintf("%d", rtr.Limit))
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, recentTrades, params.Encode())
|
||||
path := recentTrades + "?" + params.Encode()
|
||||
|
||||
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// GetHistoricalTrades returns historical trade activity
|
||||
@@ -177,7 +200,7 @@ func (b *Binance) GetHistoricalTrades(symbol string, limit int, fromID int64) ([
|
||||
// https://binance-docs.github.io/apidocs/spot/en/#compressed-aggregate-trades-list
|
||||
func (b *Binance) GetAggregatedTrades(arg *AggregatedTradeRequestParams) ([]AggregatedTrade, error) {
|
||||
params := url.Values{}
|
||||
symbol, err := b.formatSymbol(arg.Symbol)
|
||||
symbol, err := b.FormatSymbol(arg.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -218,10 +241,9 @@ func (b *Binance) GetAggregatedTrades(arg *AggregatedTradeRequestParams) ([]Aggr
|
||||
// We would receive {"code":-1128,"msg":"Combination of optional parameters invalid."}
|
||||
return nil, errors.New("please set StartTime or FromId, but not both")
|
||||
}
|
||||
|
||||
var resp []AggregatedTrade
|
||||
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
|
||||
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
path := aggregatedTrades + "?" + params.Encode()
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// batchAggregateTrades fetches trades in multiple requests
|
||||
@@ -246,8 +268,8 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params
|
||||
}
|
||||
params.Set("startTime", timeString(start))
|
||||
params.Set("endTime", timeString(start.Add(time.Hour)))
|
||||
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
|
||||
err := b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
path := aggregatedTrades + "?" + params.Encode()
|
||||
err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
|
||||
if err != nil {
|
||||
log.Warn(log.ExchangeSys, err.Error())
|
||||
return resp, err
|
||||
@@ -263,9 +285,9 @@ func (b *Binance) batchAggregateTrades(arg *AggregatedTradeRequestParams, params
|
||||
for ; arg.Limit == 0 || len(resp) < arg.Limit; fromID = resp[len(resp)-1].ATradeID {
|
||||
// Keep requesting new data after last retrieved trade
|
||||
params.Set("fromId", strconv.FormatInt(fromID, 10))
|
||||
path := b.API.Endpoints.URL + aggregatedTrades + "?" + params.Encode()
|
||||
path := aggregatedTrades + "?" + params.Encode()
|
||||
var additionalTrades []AggregatedTrade
|
||||
err := b.SendHTTPRequest(path, limitDefault, &additionalTrades)
|
||||
err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &additionalTrades)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -304,7 +326,7 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
|
||||
var klineData []CandleStick
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.formatSymbol(arg.Symbol)
|
||||
symbol, err := b.FormatSymbol(arg.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -320,9 +342,9 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
|
||||
params.Set("endTime", timeString(arg.EndTime))
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, candleStick, params.Encode())
|
||||
path := candleStick + "?" + params.Encode()
|
||||
|
||||
if err := b.SendHTTPRequest(path, limitDefault, &resp); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp); err != nil {
|
||||
return klineData, err
|
||||
}
|
||||
|
||||
@@ -375,15 +397,15 @@ func (b *Binance) GetSpotKline(arg *KlinesRequestParams) ([]CandleStick, error)
|
||||
func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) {
|
||||
resp := AveragePrice{}
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, averagePrice, params.Encode())
|
||||
path := averagePrice + "?" + params.Encode()
|
||||
|
||||
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// GetPriceChangeStats returns price change statistics for the last 24 hours
|
||||
@@ -392,22 +414,21 @@ func (b *Binance) GetAveragePrice(symbol currency.Pair) (AveragePrice, error) {
|
||||
func (b *Binance) GetPriceChangeStats(symbol currency.Pair) (PriceChangeStats, error) {
|
||||
resp := PriceChangeStats{}
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, priceChange, params.Encode())
|
||||
path := priceChange + "?" + params.Encode()
|
||||
|
||||
return resp, b.SendHTTPRequest(path, limitDefault, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, limitDefault, &resp)
|
||||
}
|
||||
|
||||
// GetTickers returns the ticker data for the last 24 hrs
|
||||
func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
|
||||
var resp []PriceChangeStats
|
||||
path := b.API.Endpoints.URL + priceChange
|
||||
return resp, b.SendHTTPRequest(path, limitPriceChangeAll, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, priceChange, limitPriceChangeAll, &resp)
|
||||
}
|
||||
|
||||
// GetLatestSpotPrice returns latest spot price of symbol
|
||||
@@ -416,15 +437,15 @@ func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
|
||||
func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error) {
|
||||
resp := SymbolPrice{}
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, symbolPrice, params.Encode())
|
||||
path := symbolPrice + "?" + params.Encode()
|
||||
|
||||
return resp, b.SendHTTPRequest(path, symbolPriceLimit(symbolValue), &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, symbolPriceLimit(symbolValue), &resp)
|
||||
}
|
||||
|
||||
// GetBestPrice returns the latest best price for symbol
|
||||
@@ -433,21 +454,21 @@ func (b *Binance) GetLatestSpotPrice(symbol currency.Pair) (SymbolPrice, error)
|
||||
func (b *Binance) GetBestPrice(symbol currency.Pair) (BestPrice, error) {
|
||||
resp := BestPrice{}
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, bestPrice, params.Encode())
|
||||
path := bestPrice + "?" + params.Encode()
|
||||
|
||||
return resp, b.SendHTTPRequest(path, bestPriceLimit(symbolValue), &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpotSupplementary, path, bestPriceLimit(symbolValue), &resp)
|
||||
}
|
||||
|
||||
// NewOrder sends a new order to Binance
|
||||
func (b *Binance) NewOrder(o *NewOrderRequest) (NewOrderResponse, error) {
|
||||
var resp NewOrderResponse
|
||||
if err := b.newOrder(newOrder, o, &resp); err != nil {
|
||||
if err := b.newOrder(orderEndpoint, o, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -465,10 +486,8 @@ func (b *Binance) NewOrderTest(o *NewOrderRequest) error {
|
||||
}
|
||||
|
||||
func (b *Binance) newOrder(api string, o *NewOrderRequest, resp *NewOrderResponse) error {
|
||||
path := b.API.Endpoints.URL + api
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.formatSymbol(o.Symbol)
|
||||
symbol, err := b.FormatSymbol(o.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -502,16 +521,14 @@ func (b *Binance) newOrder(api string, o *NewOrderRequest, resp *NewOrderRespons
|
||||
if o.NewOrderRespType != "" {
|
||||
params.Set("newOrderRespType", o.NewOrderRespType)
|
||||
}
|
||||
return b.SendAuthHTTPRequest(http.MethodPost, path, params, limitOrder, resp)
|
||||
return b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, api, params, limitOrder, resp)
|
||||
}
|
||||
|
||||
// CancelExistingOrder sends a cancel order to Binance
|
||||
func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origClientOrderID string) (CancelOrderResponse, error) {
|
||||
var resp CancelOrderResponse
|
||||
|
||||
path := b.API.Endpoints.URL + cancelOrder
|
||||
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -525,8 +542,7 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC
|
||||
if origClientOrderID != "" {
|
||||
params.Set("origClientOrderId", origClientOrderID)
|
||||
}
|
||||
|
||||
return resp, b.SendAuthHTTPRequest(http.MethodDelete, path, params, limitOrder, &resp)
|
||||
return resp, b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodDelete, orderEndpoint, params, limitOrder, &resp)
|
||||
}
|
||||
|
||||
// OpenOrders Current open orders. Get all open orders on a symbol.
|
||||
@@ -535,14 +551,12 @@ func (b *Binance) CancelExistingOrder(symbol currency.Pair, orderID int64, origC
|
||||
func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
|
||||
var resp []QueryOrderData
|
||||
|
||||
path := b.API.Endpoints.URL + openOrders
|
||||
|
||||
params := url.Values{}
|
||||
|
||||
var symbol string
|
||||
if pair != nil {
|
||||
var err error
|
||||
symbol, err = b.formatSymbol(*pair)
|
||||
symbol, err = b.FormatSymbol(*pair, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -551,7 +565,7 @@ func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
|
||||
params.Set("symbol", symbol)
|
||||
}
|
||||
|
||||
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, openOrdersLimit(symbol), &resp); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, openOrders, params, openOrdersLimit(symbol), &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -564,10 +578,8 @@ func (b *Binance) OpenOrders(pair *currency.Pair) ([]QueryOrderData, error) {
|
||||
func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]QueryOrderData, error) {
|
||||
var resp []QueryOrderData
|
||||
|
||||
path := b.API.Endpoints.URL + allOrders
|
||||
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -578,7 +590,7 @@ func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]Quer
|
||||
if limit != "" {
|
||||
params.Set("limit", limit)
|
||||
}
|
||||
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, limitOrdersAll, &resp); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, allOrders, params, limitOrdersAll, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -589,10 +601,8 @@ func (b *Binance) AllOrders(symbol currency.Pair, orderID, limit string) ([]Quer
|
||||
func (b *Binance) QueryOrder(symbol currency.Pair, origClientOrderID string, orderID int64) (QueryOrderData, error) {
|
||||
var resp QueryOrderData
|
||||
|
||||
path := b.API.Endpoints.URL + queryOrder
|
||||
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.formatSymbol(symbol)
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -604,7 +614,7 @@ func (b *Binance) QueryOrder(symbol currency.Pair, origClientOrderID string, ord
|
||||
params.Set("orderId", strconv.FormatInt(orderID, 10))
|
||||
}
|
||||
|
||||
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, limitOrder, &resp); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, orderEndpoint, params, limitOrder, &resp); err != nil {
|
||||
return resp, err
|
||||
}
|
||||
|
||||
@@ -622,11 +632,9 @@ func (b *Binance) GetAccount() (*Account, error) {
|
||||
}
|
||||
|
||||
var resp response
|
||||
|
||||
path := b.API.Endpoints.URL + accountInfo
|
||||
params := url.Values{}
|
||||
|
||||
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &resp); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, accountInfo, params, request.Unset, &resp); err != nil {
|
||||
return &resp.Account, err
|
||||
}
|
||||
|
||||
@@ -638,10 +646,14 @@ func (b *Binance) GetAccount() (*Account, error) {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (b *Binance) SendHTTPRequest(path string, f request.EndpointLimit, result interface{}) error {
|
||||
func (b *Binance) SendHTTPRequest(ePath exchange.URL, path string, f request.EndpointLimit, result interface{}) error {
|
||||
endpointPath, err := b.API.Endpoints.GetURL(ePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpointPath + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -650,42 +662,41 @@ func (b *Binance) SendHTTPRequest(path string, f request.EndpointLimit, result i
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated HTTP request
|
||||
func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, f request.EndpointLimit, result interface{}) error {
|
||||
func (b *Binance) SendAuthHTTPRequest(ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result interface{}) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
||||
}
|
||||
|
||||
endpointPath, err := b.API.Endpoints.GetURL(ePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path = endpointPath + path
|
||||
if params == nil {
|
||||
params = url.Values{}
|
||||
}
|
||||
recvWindow := 5 * time.Second
|
||||
params.Set("recvWindow", strconv.FormatInt(convert.RecvWindow(recvWindow), 10))
|
||||
params.Set("timestamp", strconv.FormatInt(time.Now().Unix()*1000, 10))
|
||||
|
||||
signature := params.Encode()
|
||||
hmacSigned := crypto.GetHMAC(crypto.HashSHA256, []byte(signature), []byte(b.API.Credentials.Secret))
|
||||
hmacSignedStr := crypto.HexEncodeToString(hmacSigned)
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["X-MBX-APIKEY"] = b.API.Credentials.Key
|
||||
|
||||
if b.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "sent path: %s", path)
|
||||
}
|
||||
|
||||
path = common.EncodeURLValues(path, params)
|
||||
path += "&signature=" + hmacSignedStr
|
||||
|
||||
interim := json.RawMessage{}
|
||||
|
||||
errCap := struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"msg"`
|
||||
Code int64 `json:"code"`
|
||||
}{}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), recvWindow)
|
||||
defer cancel()
|
||||
err := b.SendPayload(ctx, &request.Item{
|
||||
err = b.SendPayload(ctx, &request.Item{
|
||||
Method: method,
|
||||
Path: path,
|
||||
Headers: headers,
|
||||
@@ -699,13 +710,11 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, f
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(interim, &errCap); err == nil {
|
||||
if !errCap.Success && errCap.Message != "" {
|
||||
if !errCap.Success && errCap.Message != "" && errCap.Code != 200 {
|
||||
return errors.New(errCap.Message)
|
||||
}
|
||||
}
|
||||
|
||||
return json.Unmarshal(interim, result)
|
||||
}
|
||||
|
||||
@@ -779,7 +788,6 @@ func getCryptocurrencyWithdrawalFee(c currency.Code) float64 {
|
||||
// WithdrawCrypto sends cryptocurrency to the address of your choosing
|
||||
func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string) (string, error) {
|
||||
var resp WithdrawResponse
|
||||
path := b.API.Endpoints.URL + withdrawEndpoint
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("asset", asset)
|
||||
@@ -792,7 +800,7 @@ func (b *Binance) WithdrawCrypto(asset, address, addressTag, name, amount string
|
||||
params.Set("addressTag", addressTag)
|
||||
}
|
||||
|
||||
if err := b.SendAuthHTTPRequest(http.MethodPost, path, params, request.Unset, &resp); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodPost, withdrawEndpoint, params, request.Unset, &resp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -811,7 +819,6 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
|
||||
WithdrawList []WithdrawStatusResponse `json:"withdrawList"`
|
||||
}
|
||||
|
||||
path := b.API.Endpoints.URL + withdrawalHistory
|
||||
params := url.Values{}
|
||||
params.Set("asset", c.String())
|
||||
|
||||
@@ -838,7 +845,7 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
|
||||
params.Set("endTime", strconv.FormatInt(endTime, 10))
|
||||
}
|
||||
|
||||
if err := b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &response); err != nil {
|
||||
if err := b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, withdrawalHistory, params, request.Unset, &response); err != nil {
|
||||
return response.WithdrawList, err
|
||||
}
|
||||
|
||||
@@ -847,8 +854,6 @@ func (b *Binance) WithdrawStatus(c currency.Code, status string, startTime, endT
|
||||
|
||||
// GetDepositAddressForCurrency retrieves the wallet address for a given currency
|
||||
func (b *Binance) GetDepositAddressForCurrency(currency string) (string, error) {
|
||||
path := b.API.Endpoints.URL + depositAddress
|
||||
|
||||
resp := struct {
|
||||
Address string `json:"address"`
|
||||
Success bool `json:"success"`
|
||||
@@ -860,16 +865,20 @@ func (b *Binance) GetDepositAddressForCurrency(currency string) (string, error)
|
||||
params.Set("status", "true")
|
||||
|
||||
return resp.Address,
|
||||
b.SendAuthHTTPRequest(http.MethodGet, path, params, request.Unset, &resp)
|
||||
b.SendAuthHTTPRequest(exchange.RestSpotSupplementary, http.MethodGet, depositAddress, params, request.Unset, &resp)
|
||||
}
|
||||
|
||||
// GetWsAuthStreamKey will retrieve a key to use for authorised WS streaming
|
||||
func (b *Binance) GetWsAuthStreamKey() (string, error) {
|
||||
endpointPath, err := b.API.Endpoints.GetURL(exchange.RestSpotSupplementary)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var resp UserAccountStream
|
||||
path := b.API.Endpoints.URL + userAccountStream
|
||||
path := endpointPath + userAccountStream
|
||||
headers := make(map[string]string)
|
||||
headers["X-MBX-APIKEY"] = b.API.Credentials.Key
|
||||
err := b.SendPayload(context.Background(), &request.Item{
|
||||
err = b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodPost,
|
||||
Path: path,
|
||||
Headers: headers,
|
||||
@@ -888,12 +897,15 @@ func (b *Binance) GetWsAuthStreamKey() (string, error) {
|
||||
|
||||
// MaintainWsAuthStreamKey will keep the key alive
|
||||
func (b *Binance) MaintainWsAuthStreamKey() error {
|
||||
var err error
|
||||
endpointPath, err := b.API.Endpoints.GetURL(exchange.RestSpotSupplementary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if listenKey == "" {
|
||||
listenKey, err = b.GetWsAuthStreamKey()
|
||||
return err
|
||||
}
|
||||
path := b.API.Endpoints.URL + userAccountStream
|
||||
path := endpointPath + userAccountStream
|
||||
params := url.Values{}
|
||||
params.Set("listenKey", listenKey)
|
||||
path = common.EncodeURLValues(path, params)
|
||||
|
||||
1397
exchanges/binance/binance_cfutures.go
Normal file
1397
exchanges/binance/binance_cfutures.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -36,6 +36,6 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
b.setupOrderbookManager()
|
||||
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name, b.API.Endpoints.URL)
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -45,9 +45,14 @@ func TestMain(m *testing.M) {
|
||||
if err != nil {
|
||||
log.Fatalf("Mock server error %s", err)
|
||||
}
|
||||
|
||||
b.HTTPClient = newClient
|
||||
b.API.Endpoints.URL = serverDetails
|
||||
log.Printf(sharedtestvalues.MockTesting, b.Name, b.API.Endpoints.URL)
|
||||
endpointMap := b.API.Endpoints.GetURLMap()
|
||||
for k := range endpointMap {
|
||||
err = b.API.Endpoints.SetRunning(k, serverDetails)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
log.Printf(sharedtestvalues.MockTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,12 +19,6 @@ const (
|
||||
Completed
|
||||
)
|
||||
|
||||
// Response holds basic binance api response data
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// ExchangeInfo holds the full exchange information type
|
||||
type ExchangeInfo struct {
|
||||
Code int `json:"code"`
|
||||
@@ -93,6 +87,7 @@ type OrderBookData struct {
|
||||
|
||||
// OrderBook actual structured data that can be used for orderbook
|
||||
type OrderBook struct {
|
||||
Symbol string
|
||||
LastUpdateID int64
|
||||
Code int
|
||||
Msg string
|
||||
@@ -237,6 +232,18 @@ type AggregatedTrade struct {
|
||||
BestMatchPrice bool `json:"M"`
|
||||
}
|
||||
|
||||
// IndexMarkPrice stores data for index and mark prices
|
||||
type IndexMarkPrice struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
IndexPrice float64 `json:"indexPrice,string"`
|
||||
EstimatedSettlePrice float64 `json:"estimatedSettlePrice,string"`
|
||||
LastFundingRate string `json:"lastFundingRate"`
|
||||
NextFundingTime int64 `json:"nextFundingTime"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// CandleStick holds kline data
|
||||
type CandleStick struct {
|
||||
OpenTime time.Time
|
||||
@@ -749,6 +756,22 @@ type WsPayload struct {
|
||||
ID int64 `json:"id"`
|
||||
}
|
||||
|
||||
// CrossMarginInterestData stores cross margin data for borrowing
|
||||
type CrossMarginInterestData struct {
|
||||
Code int64 `json:"code,string"`
|
||||
Message string `json:"message"`
|
||||
MessageDetail string `json:"messageDetail"`
|
||||
Data []struct {
|
||||
AssetName string `json:"assetName"`
|
||||
Specs []struct {
|
||||
VipLevel string `json:"vipLevel"`
|
||||
DailyInterestRate string `json:"dailyInterestRate"`
|
||||
BorrowLimit string `json:"borrowLimit"`
|
||||
} `json:"specs"`
|
||||
} `json:"data"`
|
||||
Success bool `json:"success"`
|
||||
}
|
||||
|
||||
// orderbookManager defines a way of managing and maintaining synchronisation
|
||||
// across connections and assets.
|
||||
type orderbookManager struct {
|
||||
|
||||
1087
exchanges/binance/binance_ufutures.go
Normal file
1087
exchanges/binance/binance_ufutures.go
Normal file
File diff suppressed because it is too large
Load Diff
@@ -525,20 +525,22 @@ func (b *Binance) GenerateSubscriptions() ([]stream.ChannelSubscription, error)
|
||||
var subscriptions []stream.ChannelSubscription
|
||||
assets := b.GetAssetTypes()
|
||||
for x := range assets {
|
||||
pairs, err := b.GetEnabledPairs(assets[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if assets[x] == asset.Spot {
|
||||
pairs, err := b.GetEnabledPairs(assets[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for y := range pairs {
|
||||
for z := range channels {
|
||||
lp := pairs[y].Lower()
|
||||
lp.Delimiter = ""
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: lp.String() + channels[z],
|
||||
Currency: pairs[y],
|
||||
Asset: assets[x],
|
||||
})
|
||||
for y := range pairs {
|
||||
for z := range channels {
|
||||
lp := pairs[y].Lower()
|
||||
lp.Delimiter = ""
|
||||
subscriptions = append(subscriptions, stream.ChannelSubscription{
|
||||
Channel: lp.String() + channels[z],
|
||||
Currency: pairs[y],
|
||||
Asset: assets[x],
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
608
exchanges/binance/cfutures_types.go
Normal file
608
exchanges/binance/cfutures_types.go
Normal file
@@ -0,0 +1,608 @@
|
||||
package binance
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
// Response holds basic binance api response data
|
||||
type Response struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// FuturesPublicTradesData stores recent public trades for futures
|
||||
type FuturesPublicTradesData struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
QuoteQty float64 `json:"quoteQty,string"`
|
||||
Time int64 `json:"time"`
|
||||
IsBuyerMaker bool `json:"isBuyerMaker"`
|
||||
}
|
||||
|
||||
// CompressedTradesData stores futures trades data in a compressed format
|
||||
type CompressedTradesData struct {
|
||||
TradeID int64 `json:"a"`
|
||||
Price float64 `json:"p"`
|
||||
Quantity float64 `json:"q"`
|
||||
FirstTradeID int64 `json:"f"`
|
||||
LastTradeID int64 `json:"l"`
|
||||
Timestamp int64 `json:"t"`
|
||||
BuyerMaker bool `json:"b"`
|
||||
}
|
||||
|
||||
// MarkPriceData stores mark price data for futures
|
||||
type MarkPriceData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
LastFundingRate float64 `json:"lastFundingRate"`
|
||||
NextFundingTime int64 `json:"nextFundingTime"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// SymbolPriceTicker stores ticker price stats
|
||||
type SymbolPriceTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// SymbolOrderBookTicker stores orderbook ticker data
|
||||
type SymbolOrderBookTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice float64 `json:"bidPrice,string"`
|
||||
AskPrice float64 `json:"askPrice,string"`
|
||||
BidQty float64 `json:"bidQty,string"`
|
||||
AskQty float64 `json:"askQty,string"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// FuturesCandleStick holds kline data
|
||||
type FuturesCandleStick struct {
|
||||
OpenTime time.Time
|
||||
Open float64
|
||||
High float64
|
||||
Low float64
|
||||
Close float64
|
||||
Volume float64
|
||||
CloseTime time.Time
|
||||
BaseAssetVolume float64
|
||||
NumberOfTrades int64
|
||||
TakerBuyVolume float64
|
||||
TakerBuyBaseAssetVolume float64
|
||||
}
|
||||
|
||||
// AllLiquidationOrders gets all liquidation orders
|
||||
type AllLiquidationOrders struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
AveragePrice float64 `json:"averagePrice,string"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// OpenInterestData stores open interest data
|
||||
type OpenInterestData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
OpenInterest float64 `json:"openInterest,string"`
|
||||
ContractType string `json:"contractType"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// OpenInterestStats stores stats for open interest data
|
||||
type OpenInterestStats struct {
|
||||
Pair string `json:"pair"`
|
||||
ContractType string `json:"contractType"`
|
||||
SumOpenInterest float64 `json:"sumOpenInterest,string"`
|
||||
SumOpenInterestValue float64 `json:"sumOpenInterestValue,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// TopTraderAccountRatio stores account ratio data for top traders
|
||||
type TopTraderAccountRatio struct {
|
||||
Pair string `json:"pair"`
|
||||
LongShortRatio float64 `json:"longShortRatio,string"`
|
||||
LongAccount float64 `json:"longAccount,string"`
|
||||
ShortAccount float64 `json:"shortAccount,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// TopTraderPositionRatio stores position ratio for top trader accounts
|
||||
type TopTraderPositionRatio struct {
|
||||
Pair string `json:"pair"`
|
||||
LongShortRatio float64 `json:"longShortRatio,string"`
|
||||
LongPosition float64 `json:"longPosition,string"`
|
||||
ShortPosition float64 `json:"shortPosition,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// GlobalLongShortRatio stores ratio data of all longs vs shorts
|
||||
type GlobalLongShortRatio struct {
|
||||
Symbol string `json:"symbol"`
|
||||
LongShortRatio float64 `json:"longShortRatio"`
|
||||
LongAccount float64 `json:"longAccount"`
|
||||
ShortAccount float64 `json:"shortAccount"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
}
|
||||
|
||||
// TakerBuySellVolume stores taker buy sell volume
|
||||
type TakerBuySellVolume struct {
|
||||
Pair string `json:"pair"`
|
||||
ContractType string `json:"contractType"`
|
||||
TakerBuyVolume float64 `json:"takerBuyVol,string"`
|
||||
BuySellRatio float64 `json:"takerSellVol,string"`
|
||||
BuyVol float64 `json:"takerBuyVolValue,string"`
|
||||
SellVol float64 `json:"takerSellVolValue,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// FuturesBasisData gets futures basis data
|
||||
type FuturesBasisData struct {
|
||||
Pair string `json:"pair"`
|
||||
ContractType string `json:"contractType"`
|
||||
FuturesPrice float64 `json:"futuresPrice,string"`
|
||||
IndexPrice float64 `json:"indexPrice,string"`
|
||||
Basis float64 `json:"basis,string"`
|
||||
BasisRate float64 `json:"basisRate,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// PlaceBatchOrderData stores batch order data for placing
|
||||
type PlaceBatchOrderData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide,omitempty"`
|
||||
OrderType string `json:"type"`
|
||||
TimeInForce string `json:"timeInForce,omitempty"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
ReduceOnly string `json:"reduceOnly,omitempty"`
|
||||
Price float64 `json:"price"`
|
||||
NewClientOrderID string `json:"newClientOrderId,omitempty"`
|
||||
StopPrice float64 `json:"stopPrice,omitempty"`
|
||||
ActivationPrice float64 `json:"activationPrice,omitempty"`
|
||||
CallbackRate float64 `json:"callbackRate,omitempty"`
|
||||
WorkingType string `json:"workingType,omitempty"`
|
||||
PriceProtect string `json:"priceProtect,omitempty"`
|
||||
NewOrderRespType string `json:"newOrderRespType,omitempty"`
|
||||
}
|
||||
|
||||
// BatchCancelOrderData stores batch cancel order data
|
||||
type BatchCancelOrderData struct {
|
||||
ClientOrderID string `json:"clientOrderID"`
|
||||
CumQty float64 `json:"cumQty,string"`
|
||||
CumBase float64 `json:"cumBase,string"`
|
||||
ExecuteQty float64 `json:"executeQty,string"`
|
||||
OrderID int64 `json:"orderID,string"`
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice int64 `json:"stopPrice"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
TimeInForce string `json:"TimeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
OrigType string `json:"origType"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect bool `json:"priceProtect"`
|
||||
Code int64 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// FuturesOrderPlaceData stores futures order data
|
||||
type FuturesOrderPlaceData struct {
|
||||
ClientOrderID string `json:"clientOrderID"`
|
||||
CumQty float64 `json:"cumQty,string"`
|
||||
CumBase float64 `json:"cumBase,string"`
|
||||
ExecuteQty float64 `json:"executeQty,string"`
|
||||
OrderID int64 `json:"orderID,string"`
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice int64 `json:"stopPrice"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
TimeInForce string `json:"TimeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
OrigType string `json:"origType"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect bool `json:"priceProtect"`
|
||||
}
|
||||
|
||||
// FuturesOrderGetData stores futures order data for get requests
|
||||
type FuturesOrderGetData struct {
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
ClientOrderID string `json:"clientOrderID"`
|
||||
CumQty float64 `json:"cumQty,string"`
|
||||
CumBase float64 `json:"cumBase,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
OrigType string `json:"origType"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"buy"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect bool `json:"priceProtect"`
|
||||
}
|
||||
|
||||
// FuturesOrderData stores order data for futures
|
||||
type FuturesOrderData struct {
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
CumBase string `json:"cumBase"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
OrigType string `json:"origType"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
Time int64 `json:"time"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect bool `json:"priceProtect"`
|
||||
}
|
||||
|
||||
// OrderVars stores side, status and type for any order/trade
|
||||
type OrderVars struct {
|
||||
Side order.Side
|
||||
Status order.Status
|
||||
OrderType order.Type
|
||||
Fee float64
|
||||
}
|
||||
|
||||
// AutoCancelAllOrdersData gives data of auto cancelling all open orders
|
||||
type AutoCancelAllOrdersData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
CountdownTime int64 `json:"countdownTime,string"`
|
||||
}
|
||||
|
||||
// LevelDetail stores level detail data
|
||||
type LevelDetail struct {
|
||||
Level string `json:"level"`
|
||||
MaxBorrowable float64 `json:"maxBorrowable,string"`
|
||||
InterestRate float64 `json:"interestRate,string"`
|
||||
}
|
||||
|
||||
// MarginInfoData stores margin info data
|
||||
type MarginInfoData struct {
|
||||
Data []struct {
|
||||
MarginRatio string `json:"marginRatio"`
|
||||
Base struct {
|
||||
AssetName string `json:"assetName"`
|
||||
LevelDetails []LevelDetail `json:"levelDetails"`
|
||||
} `json:"base"`
|
||||
Quote struct {
|
||||
AssetName string `json:"assetName"`
|
||||
LevelDetails []LevelDetail `json:"levelDetails"`
|
||||
} `json:"quote"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FuturesAccountBalanceData stores account balance data for futures
|
||||
type FuturesAccountBalanceData struct {
|
||||
AccountAlias string `json:"accountAlias"`
|
||||
Asset string `json:"asset"`
|
||||
Balance float64 `json:"balance,string"`
|
||||
WithdrawAvailable float64 `json:"withdrawAvailable,string"`
|
||||
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
|
||||
CrossUnPNL float64 `json:"crossUnPNL,string"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
}
|
||||
|
||||
// FuturesAccountInformation stores account information for futures account
|
||||
type FuturesAccountInformation struct {
|
||||
Assets []struct {
|
||||
Asset string `json:"asset"`
|
||||
WalletBalance float64 `json:"walletBalance,string"`
|
||||
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
|
||||
MarginBalance float64 `json:"marginBalance,string"`
|
||||
MaintMargin float64 `json:"maintMargin,string"`
|
||||
InitialMargin float64 `json:"initialMargin,string"`
|
||||
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
|
||||
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
Isolated bool `json:"isolated"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
MaxQty float64 `json:"maxQty,string"`
|
||||
} `json:"assets"`
|
||||
Positions []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
InitialMargin float64 `json:"initialMargin,string"`
|
||||
MaintMargin float64 `json:"maintMargin,string"`
|
||||
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
|
||||
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
|
||||
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
Isolated bool `json:"isolated"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
MaxQty float64 `json:"maxQty,string"`
|
||||
} `json:"positions"`
|
||||
CanDeposit bool `json:"canDeposit"`
|
||||
CanTrade bool `json:"canTrade"`
|
||||
CanWithdraw bool `json:"canWithdraw"`
|
||||
FeeTier int64 `json:"feeTier"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
}
|
||||
|
||||
// GenericAuthResponse is a general data response for a post auth request
|
||||
type GenericAuthResponse struct {
|
||||
Code int64 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// FuturesLeverageData stores leverage data for futures
|
||||
type FuturesLeverageData struct {
|
||||
Leverage int64 `json:"leverage"`
|
||||
MaxQty float64 `json:"maxQty,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// ModifyIsolatedMarginData stores margin modification data
|
||||
type ModifyIsolatedMarginData struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Code int64 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
ModType string `json:"modType"`
|
||||
}
|
||||
|
||||
// GetPositionMarginChangeHistoryData gets margin change history for positions
|
||||
type GetPositionMarginChangeHistoryData struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Asset string `json:"asset"`
|
||||
Symbol string `json:"symbol"`
|
||||
Timestamp int64 `json:"time"`
|
||||
MarginChangeType int64 `json:"type"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
}
|
||||
|
||||
// FuturesPositionInformation stores futures position info
|
||||
type FuturesPositionInformation struct {
|
||||
Symbol string `json:"symbol"`
|
||||
PositionAmount float64 `json:"positionAmt,string"`
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
UnrealizedProfit float64 `json:"unRealizedProfit,string"`
|
||||
LiquidationPrice float64 `json:"liquidation,string"`
|
||||
Leverage int64 `json:"leverage"`
|
||||
MaxQty float64 `json:"maxQty"`
|
||||
MarginType string `json:"marginType"`
|
||||
IsolatedMargin float64 `json:"isolatedMargin,string"`
|
||||
IsAutoAddMargin bool `json:"isAutoAddMargin"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
}
|
||||
|
||||
// FuturesAccountTradeList stores account trade list data
|
||||
type FuturesAccountTradeList struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ID int64 `json:"id"`
|
||||
OrderID int64 `json:"orderID"`
|
||||
Pair string `json:"pair"`
|
||||
Side string `json:"side"`
|
||||
Price string `json:"price"`
|
||||
Qty float64 `json:"qty"`
|
||||
RealizedPNL float64 `json:"realizedPNL"`
|
||||
MarginAsset string `json:"marginAsset"`
|
||||
BaseQty float64 `json:"baseQty"`
|
||||
Commission float64 `json:"commission"`
|
||||
CommissionAsset string `json:"commissionAsset"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Buyer bool `json:"buyer"`
|
||||
Maker bool `json:"maker"`
|
||||
}
|
||||
|
||||
// FuturesIncomeHistoryData stores futures income history data
|
||||
type FuturesIncomeHistoryData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
IncomeType string `json:"incomeType"`
|
||||
Income float64 `json:"income,string"`
|
||||
Asset string `json:"asset"`
|
||||
Info string `json:"info"`
|
||||
Timestamp int64 `json:"time"`
|
||||
}
|
||||
|
||||
// NotionalBracketData stores notional bracket data
|
||||
type NotionalBracketData struct {
|
||||
Pair string `json:"pair"`
|
||||
Brackets []struct {
|
||||
Bracket int64 `json:"bracket"`
|
||||
InitialLeverage float64 `json:"initialLeverage"`
|
||||
QtyCap float64 `json:"qtyCap"`
|
||||
QtylFloor float64 `json:"qtyFloor"`
|
||||
MaintMarginRatio float64 `json:"maintMarginRatio"`
|
||||
}
|
||||
}
|
||||
|
||||
// ForcedOrdersData stores forced orders data
|
||||
type ForcedOrdersData struct {
|
||||
OrderID int64 `json:"orderId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
Price float64 `json:"price,string"`
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
CumQuote float64 `json:"cumQuote,string"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"orderType"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect float64 `json:"priceProtect,string"`
|
||||
OrigType string `json:"origType"`
|
||||
Time int64 `json:"time"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
}
|
||||
|
||||
// ADLEstimateData stores data for ADL estimates
|
||||
type ADLEstimateData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ADLQuantile struct {
|
||||
Long float64 `json:"LONG"`
|
||||
Short float64 `json:"SHORT"`
|
||||
Hedge float64 `json:"HEDGE"`
|
||||
} `json:"adlQuantile"`
|
||||
}
|
||||
|
||||
// InterestHistoryData gets interest history data
|
||||
type InterestHistoryData struct {
|
||||
Asset string `json:"asset"`
|
||||
Interest float64 `json:"interest"`
|
||||
LendingType string `json:"lendingType"`
|
||||
ProductName string `json:"productName"`
|
||||
Time string `json:"time"`
|
||||
}
|
||||
|
||||
// FundingRateData stores funding rates data
|
||||
type FundingRateData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
FundingRate float64 `json:"fundingRate,string"`
|
||||
FundingTime int64 `json:"fundingTime"`
|
||||
}
|
||||
|
||||
// SymbolsData stores perp futures' symbols
|
||||
type SymbolsData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// PerpsExchangeInfo stores data for perps
|
||||
type PerpsExchangeInfo struct {
|
||||
Symbols []SymbolsData `json:"symbols"`
|
||||
}
|
||||
|
||||
// UFuturesExchangeInfo stores exchange info for ufutures
|
||||
type UFuturesExchangeInfo struct {
|
||||
RateLimits []struct {
|
||||
Interval string `json:"interval"`
|
||||
IntervalNum int64 `json:"intervalNum"`
|
||||
Limit int64 `json:"limit"`
|
||||
RateLimitType string `json:"rateLimitType"`
|
||||
} `json:"rateLimits"`
|
||||
ServerTime int64 `json:"serverTime"`
|
||||
Symbols []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
MaintenanceMarginPercent float64 `json:"maintMarginPercent,string"`
|
||||
RequiredMarginPercent float64 `json:"requiredMarginPercent,string"`
|
||||
BaseAsset string `json:"baseAsset"`
|
||||
QuoteAsset string `json:"quoteAsset"`
|
||||
PricePrecision int64 `json:"pricePrecision"`
|
||||
QuantityPrecision int64 `json:"quantityPrecision"`
|
||||
BaseAssetPrecision int64 `json:"baseAssetPrecision"`
|
||||
QuotePrecision int64 `json:"quotePrecision"`
|
||||
Filters []struct {
|
||||
MinPrice float64 `json:"minPrice,string"`
|
||||
MaxPrice float64 `json:"maxPrice,string"`
|
||||
FilterType string `json:"filterType"`
|
||||
TickSize float64 `json:"tickSize,string"`
|
||||
StepSize float64 `json:"stepSize,string"`
|
||||
MaxQty float64 `json:"maxQty,string"`
|
||||
MinQty float64 `json:"minQty,string"`
|
||||
Limit int64 `json:"limit"`
|
||||
MultiplierDown float64 `json:"multiplierDown,string"`
|
||||
MultiplierUp float64 `json:"multiplierUp,string"`
|
||||
MultiplierDecimal float64 `json:"multiplierDecimal,string"`
|
||||
} `json:"filters"`
|
||||
OrderTypes []string `json:"orderTypes"`
|
||||
TimeInForce []string `json:"timeInForce"`
|
||||
} `json:"symbols"`
|
||||
Timezone string `json:"timezone"`
|
||||
}
|
||||
|
||||
// CExchangeInfo stores exchange info for cfutures
|
||||
type CExchangeInfo struct {
|
||||
ExchangeFilters []interface{} `json:"exchangeFilters"`
|
||||
RateLimits []struct {
|
||||
Interval string `json:"interval"`
|
||||
IntervalNum int64 `json:"intervalNul"`
|
||||
Limit int64 `json:"limit"`
|
||||
RateLimitType string `json:"rateLimitType"`
|
||||
} `json:"rateLimits"`
|
||||
ServerTime int64 `json:"serverTime"`
|
||||
Symbols []struct {
|
||||
Filters []struct {
|
||||
FilterType string `json:"filterType"`
|
||||
MinPrice float64 `json:"minPrice,string"`
|
||||
MaxPrice float64 `json:"maxPrice,string"`
|
||||
StepSize float64 `json:"stepSize,string"`
|
||||
MaxQty float64 `json:"maxQty,string"`
|
||||
MinQty float64 `json:"minQty,string"`
|
||||
Limit int64 `json:"limit"`
|
||||
MultiplierDown float64 `json:"multiplierDown,string"`
|
||||
MultiplierUp float64 `json:"multiplierUp,string"`
|
||||
MultiplierDecimal float64 `json:"multiplierDecimal,string"`
|
||||
} `json:"filters"`
|
||||
OrderTypes []string `json:"orderType"`
|
||||
TimeInForce []string `json:"timeInForce"`
|
||||
Symbol string `json:"symbol"`
|
||||
Pair string `json:"pair"`
|
||||
ContractType string `json:"contractType"`
|
||||
DeliveryDate int64 `json:"deliveryDate"`
|
||||
OnboardDate int64 `json:"onboardDate"`
|
||||
ContractStatus string `json:"contractStatus"`
|
||||
ContractSize int64 `json:"contractSize"`
|
||||
QuoteAsset string `json:"quoteAsset"`
|
||||
BaseAsset string `json:"baseAsset"`
|
||||
MarginAsset string `json:"marginAsset"`
|
||||
PricePrecision int64 `json:"pricePrecision"`
|
||||
QuantityPrecision int64 `json:"quantityPrecision"`
|
||||
BaseAssetPrecision int64 `json:"baseAssetPrecision"`
|
||||
QuotePrecision int64 `json:"quotePrecision"`
|
||||
MaintMarginPercent float64 `json:"maintMarginPercent,string"`
|
||||
RequiredMarginPercent float64 `json:"requiredMarginPercent,string"`
|
||||
} `json:"symbols"`
|
||||
Timezone string `json:"timezone"`
|
||||
}
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
)
|
||||
|
||||
// binanceTime provides an internal conversion helper
|
||||
@@ -346,13 +344,3 @@ func (a *wsListStatus) UnmarshalJSON(data []byte) error {
|
||||
a.Data.TransactionTime = aux.Data.TransactionTime.Time()
|
||||
return nil
|
||||
}
|
||||
|
||||
// formatSymbol formats the given pair to a string suitable for exchange API requests
|
||||
// currently applicable to Spot and Margin assets
|
||||
func (b *Binance) formatSymbol(pair currency.Pair) (string, error) {
|
||||
pairFmt, err := b.GetPairFormat(asset.Spot, true)
|
||||
if err != nil {
|
||||
return pair.String(), err
|
||||
}
|
||||
return pairFmt.Format(pair), nil
|
||||
}
|
||||
|
||||
411
exchanges/binance/ufutures_types.go
Normal file
411
exchanges/binance/ufutures_types.go
Normal file
@@ -0,0 +1,411 @@
|
||||
package binance
|
||||
|
||||
var (
|
||||
validFuturesIntervals = []string{
|
||||
"1m", "3m", "5m", "15m", "30m",
|
||||
"1h", "2h", "4h", "6h", "8h",
|
||||
"12h", "1d", "3d", "1w", "1M",
|
||||
}
|
||||
|
||||
validContractType = []string{
|
||||
"ALL", "CURRENT_QUARTER", "NEXT_QUARTER",
|
||||
}
|
||||
|
||||
validOrderType = []string{
|
||||
"LIMIT", "MARKET", "STOP", "TAKE_PROFIT",
|
||||
"STOP_MARKET", "TAKE_PROFIT_MARKET", "TRAILING_STOP_MARKET",
|
||||
}
|
||||
|
||||
validNewOrderRespType = []string{"ACK", "RESULT"}
|
||||
|
||||
validWorkingType = []string{"MARK_PRICE", "CONTRACT_TYPE"}
|
||||
|
||||
validPositionSide = []string{"BOTH", "LONG", "SHORT"}
|
||||
|
||||
validMarginType = []string{"ISOLATED", "CROSSED"}
|
||||
|
||||
validIncomeType = []string{"TRANSFER", "WELCOME_BONUS", "REALIZED_PNL", "FUNDING_FEE", "COMMISSION", "INSURANCE_CLEAR"}
|
||||
|
||||
validAutoCloseTypes = []string{"LIQUIDATION", "ADL"}
|
||||
|
||||
validMarginChange = map[string]int64{
|
||||
"add": 1,
|
||||
"reduce": 2,
|
||||
}
|
||||
|
||||
uValidOBLimits = []string{"5", "10", "20", "50", "100", "500", "1000"}
|
||||
|
||||
uValidPeriods = []string{"5m", "15m", "30m", "1h", "2h", "4h", "6h", "12h", "1d"}
|
||||
)
|
||||
|
||||
// USDT Margined Futures
|
||||
|
||||
// OrderbookData stores ob data for umargined and cmargined futures
|
||||
type OrderbookData struct {
|
||||
LastUpdateID int64 `json:"lastUpdateID"`
|
||||
Timestamp int64 `json:"T"`
|
||||
Bids [][2]string `json:"bids"`
|
||||
Asks [][2]string `json:"asks"`
|
||||
}
|
||||
|
||||
// UPublicTradesData stores trade data
|
||||
type UPublicTradesData struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
QuoteQty float64 `json:"quoteQty,string"`
|
||||
Time int64 `json:"time"`
|
||||
IsBuyerMaker bool `json:"isBuyerMaker"`
|
||||
}
|
||||
|
||||
// UCompressedTradeData stores compressed trade data
|
||||
type UCompressedTradeData struct {
|
||||
AggregateTradeID int64 `json:"a"`
|
||||
Price float64 `json:"p,string"`
|
||||
Quantity float64 `json:"q,string"`
|
||||
FirstTradeID int64 `json:"f"`
|
||||
LastTradeID int64 `json:"l"`
|
||||
Timestamp int64 `json:"t"`
|
||||
IsBuyerMaker bool `json:"m"`
|
||||
}
|
||||
|
||||
// UMarkPrice stores mark price data
|
||||
type UMarkPrice struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
IndexPrice float64 `json:"indexPrice,string"`
|
||||
LastFundingRate float64 `json:"lastFundingRate,string"`
|
||||
NextFundingTime int64 `json:"nextFundingTime"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// FundingRateHistory stores funding rate history
|
||||
type FundingRateHistory struct {
|
||||
Symbol string `json:"symbol"`
|
||||
FundingRate float64 `json:"fundingRate,string"`
|
||||
FundingTime int64 `json:"fundingTime"`
|
||||
}
|
||||
|
||||
// U24HrPriceChangeStats stores price change stats data
|
||||
type U24HrPriceChangeStats struct {
|
||||
Symbol string `json:"symbol"`
|
||||
PriceChange float64 `json:"priceChange,string"`
|
||||
PriceChangePercent float64 `json:"priceChangePercent,string"`
|
||||
WeightedAvgPrice float64 `json:"weightedAvgPrice,string"`
|
||||
PrevClosePrice float64 `json:"prevClosePrice,string"`
|
||||
LastPrice float64 `json:"lastPrice,string"`
|
||||
LastQty float64 `json:"lastQty,string"`
|
||||
OpenPrice float64 `json:"openPrice,string"`
|
||||
HighPrice float64 `json:"highPrice,string"`
|
||||
LowPrice float64 `json:"lowPrice,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
QuoteVolume float64 `json:"quoteVolume,string"`
|
||||
OpenTime int64 `json:"openTime"`
|
||||
CloseTime int64 `json:"closeTime"`
|
||||
FirstID int64 `json:"firstId"`
|
||||
LastID int64 `json:"lastId"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// USymbolPriceTicker stores symbol price ticker data
|
||||
type USymbolPriceTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// USymbolOrderbookTicker stores symbol orderbook ticker data
|
||||
type USymbolOrderbookTicker struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BidPrice float64 `json:"bidPrice,string"`
|
||||
BidQty float64 `json:"bidQty,string"`
|
||||
AskPrice float64 `json:"askPrice,string"`
|
||||
AskQty float64 `json:"askQty,string"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// ULiquidationOrdersData stores liquidation orders data
|
||||
type ULiquidationOrdersData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
AveragePrice float64 `json:"averagePrice,string"`
|
||||
Status string `json:"status"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
Side string `json:"side"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// UOpenInterestData stores open interest data
|
||||
type UOpenInterestData struct {
|
||||
OpenInterest float64 `json:"openInterest,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// UOpenInterestStats stores open interest stats data
|
||||
type UOpenInterestStats struct {
|
||||
Symbol string `json:"symbol"`
|
||||
SumOpenInterest float64 `json:"sumOpenInterest,string"`
|
||||
SumOpenInterestValue float64 `json:"sumOpenInterestValue,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// ULongShortRatio stores top trader accounts' or positions' or global long/short ratio data
|
||||
type ULongShortRatio struct {
|
||||
Symbol string `json:"symbol"`
|
||||
LongShortRatio float64 `json:"longShortRatio,string"`
|
||||
LongAccount float64 `json:"longAccount,string"`
|
||||
ShortAccount float64 `json:"shortAccount,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// UTakerVolumeData stores volume data on buy/sell side from takers
|
||||
type UTakerVolumeData struct {
|
||||
BuySellRatio float64 `json:"buySellRatio,string"`
|
||||
BuyVol float64 `json:"buyVol,string"`
|
||||
SellVol float64 `json:"sellVol,string"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// UCompositeIndexInfoData stores composite index data for usdt margined futures
|
||||
type UCompositeIndexInfoData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Time int64 `json:"time"`
|
||||
BaseAssetList []struct {
|
||||
BaseAsset string `json:"baseAsset"`
|
||||
WeightInQuantity float64 `json:"weightInQuantity,string"`
|
||||
WeightInPercentage float64 `json:"weightInPercentage,string"`
|
||||
} `json:"baseAssetList"`
|
||||
}
|
||||
|
||||
// UOrderData stores order data
|
||||
type UOrderData struct {
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
CumQty float64 `json:"cumQty,string"`
|
||||
CumQuote float64 `json:"cumQuote,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
OrigType string `json:"origType"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
Code int64 `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
// UFuturesOrderData stores order data for ufutures
|
||||
type UFuturesOrderData struct {
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
CumQuote string `json:"cumQuote"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
OrigType string `json:"origType"`
|
||||
Price float64 `json:"price,string"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Status string `json:"status"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time int64 `json:"time"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
ActivatePrice float64 `json:"activatePrice,string"`
|
||||
PriceRate float64 `json:"priceRate,string"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
WorkingType string `json:"workingType"`
|
||||
}
|
||||
|
||||
// UAccountBalanceV2Data stores account balance data for ufutures
|
||||
type UAccountBalanceV2Data struct {
|
||||
AccountAlias string `json:"accountAlias"`
|
||||
Asset string `json:"asset"`
|
||||
Balance float64 `json:"balance,string"`
|
||||
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
|
||||
CrossUnrealizedPNL float64 `json:"crossUnPnl,string"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
|
||||
}
|
||||
|
||||
// UAccountInformationV2Data stores account info for ufutures
|
||||
type UAccountInformationV2Data struct {
|
||||
FeeTier int64 `json:"feeTier"`
|
||||
CanTrade bool `json:"canTrade"`
|
||||
CanDeposit bool `json:"canDeposit"`
|
||||
CanWithdraw bool `json:"canWithdraw"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
TotalInitialMargin float64 `json:"totalInitialMargin,string"`
|
||||
TotalMaintenance float64 `json:"totalMaintMargin,string"`
|
||||
TotalWalletBalance float64 `json:"totalWalletBalance,string"`
|
||||
TotalUnrealizedProfit float64 `json:"totalUnrealizedProfit,string"`
|
||||
TotalMarginBalance float64 `json:"totalMarginBalance,string"`
|
||||
TotalPositionInitialMargin float64 `json:"totalPositionInitialMargin,string"`
|
||||
TotalOpenOrderInitialMargin float64 `json:"totalOpenOrderInitialMargin,string"`
|
||||
TotalCrossWalletBalance float64 `json:"totalCrossWalletBalance,string"`
|
||||
TotalCrossUnrealizedPNL float64 `json:"totalCrossUnPnl,string"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
|
||||
Assets []struct {
|
||||
Asset string `json:"asset"`
|
||||
WalletBalance float64 `json:"walletBalance,string"`
|
||||
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
|
||||
MarginBalance float64 `json:"marginBalance,string"`
|
||||
MaintMargin float64 `json:"maintMargin,string"`
|
||||
InitialMargin float64 `json:"initialMargin,string"`
|
||||
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
|
||||
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
|
||||
CrossWalletBalance float64 `json:"crossWalletBalance,string"`
|
||||
CrossUnPnl float64 `json:"crossUnPnl,string"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
MaxWithdrawAmount float64 `json:"maxWithdrawAmount,string"`
|
||||
} `json:"assets"`
|
||||
Positions []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
InitialMargin float64 `json:"initialMargin,string"`
|
||||
MaintenanceMargin float64 `json:"maintMargin,string"`
|
||||
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
|
||||
PositionInitialMargin float64 `json:"positionInitialMargin,string"`
|
||||
OpenOrderInitialMargin float64 `json:"openOrderInitialMargin,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
Isolated bool `json:"isolated"`
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
MaxNotional float64 `json:"maxNotional,string"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
} `json:"positions"`
|
||||
}
|
||||
|
||||
// UChangeInitialLeverage stores leverage change data
|
||||
type UChangeInitialLeverage struct {
|
||||
Leverage int64 `json:"leverage"`
|
||||
MaxNotionalValue float64 `json:"maxNotionalValue,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// UModifyIsolatedPosMargin stores modified isolated margin positions' data
|
||||
type UModifyIsolatedPosMargin struct {
|
||||
Amount float64 `json:"amount,string"`
|
||||
MarginType int64 `json:"type"`
|
||||
}
|
||||
|
||||
// UPositionMarginChangeHistoryData gets position margin change history data
|
||||
type UPositionMarginChangeHistoryData struct {
|
||||
Amount float64 `json:"amount,string"`
|
||||
Asset string `json:"asset"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time int64 `json:"time"`
|
||||
MarginType int64 `json:"type"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
}
|
||||
|
||||
// UPositionInformationV2 stores positions data
|
||||
type UPositionInformationV2 struct {
|
||||
EntryPrice float64 `json:"entryPrice,string"`
|
||||
MarginType string `json:"marginType"`
|
||||
AutoAddMarginEnabled bool `json:"isAutoAddMargin,string"`
|
||||
IsolatedMargin float64 `json:"isolatedMargin,string"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
LiquidationPrice float64 `json:"liquidationPrice,string"`
|
||||
MarkPrice float64 `json:"markPrice,string"`
|
||||
MaxNotionalValue float64 `json:"maxNotionalValue,string"`
|
||||
PositionAmount float64 `json:"positionAmt,string"`
|
||||
Symbol string `json:"symbol"`
|
||||
UnrealizedProfit float64 `json:"unrealizedProfit,string"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
}
|
||||
|
||||
// UAccountTradeHistory stores trade data for the users account
|
||||
type UAccountTradeHistory struct {
|
||||
Buyer bool `json:"buyer"`
|
||||
Commission float64 `json:"commission,string"`
|
||||
CommissionAsset string `json:"commissionAsset"`
|
||||
ID int64 `json:"id"`
|
||||
Maker bool `json:"maker"`
|
||||
OrderID int64 `json:"orderId"`
|
||||
Price float64 `json:"price,string"`
|
||||
Qty float64 `json:"qty,string"`
|
||||
QuoteQty float64 `json:"quoteQty"`
|
||||
RealizedPNL float64 `json:"realizedPnl,string"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
Symbol string `json:"symbol"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
// UAccountIncomeHistory stores income history data
|
||||
type UAccountIncomeHistory struct {
|
||||
Symbol string `json:"symbol"`
|
||||
IncomeType string `json:"incomeType"`
|
||||
Income float64 `json:"income,string"`
|
||||
Asset string `json:"asset"`
|
||||
Info string `json:"info"`
|
||||
Time int64 `json:"time"`
|
||||
TranID int64 `json:"tranId"`
|
||||
TradeID string `json:"tradeId"`
|
||||
}
|
||||
|
||||
// UNotionalLeverageAndBrakcetsData stores notional and leverage brackets data for the account
|
||||
type UNotionalLeverageAndBrakcetsData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Brackets []struct {
|
||||
Bracket int64 `json:"bracket"`
|
||||
InitialLeverage float64 `json:"initialLeverage"`
|
||||
NotionalCap float64 `json:"notionalCap"`
|
||||
NotionalFloor float64 `json:"notionalFloor"`
|
||||
MaintenanceMarginRatio float64 `json:"maintMarginRatio"`
|
||||
Cumulative float64 `json:"cum"`
|
||||
} `json:"brackets"`
|
||||
}
|
||||
|
||||
// UPositionADLEstimationData stores ADL estimation data for a position
|
||||
type UPositionADLEstimationData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ADLQuantile struct {
|
||||
Long int64 `json:"LONG"`
|
||||
Short int64 `json:"SHORT"`
|
||||
Hedge int64 `json:"HEDGE"`
|
||||
} `json:"adlQuantile"`
|
||||
}
|
||||
|
||||
// UForceOrdersData stores liquidation orders data for the account
|
||||
type UForceOrdersData struct {
|
||||
OrderID int64 `json:"orderId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Status string `json:"status"`
|
||||
ClientOrderID string `json:"clientOrderId"`
|
||||
Price float64 `json:"price,string"`
|
||||
AvgPrice float64 `json:"avgPrice,string"`
|
||||
OrigQty float64 `json:"origQty,string"`
|
||||
ExecutedQty float64 `json:"executedQty,string"`
|
||||
CumQuote float64 `json:"cumQuote,string"`
|
||||
TimeInForce string `json:"timeInForce"`
|
||||
OrderType string `json:"type"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
ClosePosition bool `json:"closePosition"`
|
||||
Side string `json:"side"`
|
||||
PositionSide string `json:"positionSide"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
WorkingType string `json:"workingType"`
|
||||
PriceProtect bool `json:"priceProtect,string"`
|
||||
OrigType string `json:"origType"`
|
||||
Time int64 `json:"time"`
|
||||
UpdateTime int64 `json:"updateTime"`
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
package bitfinex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -60,17 +62,23 @@ const (
|
||||
bitfinexLeaderboard = "rankings"
|
||||
|
||||
// Version 2 API endpoints
|
||||
bitfinexAPIVersion2 = "/v2/"
|
||||
bitfinexPlatformStatus = "platform/status"
|
||||
bitfinexTickerBatch = "tickers"
|
||||
bitfinexTicker = "ticker/"
|
||||
bitfinexTrades = "trades/"
|
||||
bitfinexOrderbook = "book/"
|
||||
bitfinexStatistics = "stats1/"
|
||||
bitfinexCandles = "candles/trade"
|
||||
bitfinexKeyPermissions = "key_info"
|
||||
bitfinexMarginInfo = "margin_infos"
|
||||
bitfinexDepositMethod = "conf/pub:map:currency:label"
|
||||
bitfinexAPIVersion2 = "/v2/"
|
||||
bitfinexV2MarginFunding = "calc/trade/avg?"
|
||||
bitfinexV2Balances = "auth/r/wallets"
|
||||
bitfinexV2AccountInfo = "auth/r/info/user"
|
||||
bitfinexV2FundingInfo = "auth/r/info/funding/%s"
|
||||
bitfinexDerivativeData = "status/deriv?"
|
||||
bitfinexPlatformStatus = "platform/status"
|
||||
bitfinexTickerBatch = "tickers"
|
||||
bitfinexTicker = "ticker/"
|
||||
bitfinexTrades = "trades/"
|
||||
bitfinexOrderbook = "book/"
|
||||
bitfinexStatistics = "stats1/"
|
||||
bitfinexCandles = "candles/trade"
|
||||
bitfinexKeyPermissions = "key_info"
|
||||
bitfinexMarginInfo = "margin_infos"
|
||||
bitfinexDepositMethod = "conf/pub:map:currency:label"
|
||||
bitfinexMarginPairs = "conf/pub:list:pair:margin"
|
||||
|
||||
// Bitfinex platform status values
|
||||
// When the platform is marked in maintenance mode bots should stop trading
|
||||
@@ -91,9 +99,9 @@ type Bitfinex struct {
|
||||
// GetPlatformStatus returns the Bifinex platform status
|
||||
func (b *Bitfinex) GetPlatformStatus() (int, error) {
|
||||
var response []int
|
||||
err := b.SendHTTPRequest(b.API.Endpoints.URL+
|
||||
err := b.SendHTTPRequest(exchange.RestSpot,
|
||||
bitfinexAPIVersion2+
|
||||
bitfinexPlatformStatus,
|
||||
bitfinexPlatformStatus,
|
||||
&response,
|
||||
platformStatus)
|
||||
if err != nil {
|
||||
@@ -110,16 +118,271 @@ func (b *Bitfinex) GetPlatformStatus() (int, error) {
|
||||
return -1, fmt.Errorf("unexpected platform status value %d", response[0])
|
||||
}
|
||||
|
||||
// GetV2MarginFunding gets borrowing rates for margin trading
|
||||
func (b *Bitfinex) GetV2MarginFunding(symbol, amount string, period int32) (MarginV2FundingData, error) {
|
||||
var resp []interface{}
|
||||
var response MarginV2FundingData
|
||||
params := make(map[string]interface{})
|
||||
params["symbol"] = symbol
|
||||
params["period"] = period
|
||||
params["amount"] = amount
|
||||
err := b.SendAuthenticatedHTTPRequestV2(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexV2MarginFunding,
|
||||
params,
|
||||
&resp,
|
||||
getAccountFees)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if len(resp) != 2 {
|
||||
return response, errors.New("invalid data received")
|
||||
}
|
||||
avgRate, ok := resp[0].(float64)
|
||||
if !ok {
|
||||
return response, errors.New("failed type assertion for rate")
|
||||
}
|
||||
avgAmount, ok := resp[1].(float64)
|
||||
if !ok {
|
||||
return response, errors.New("failed type assertion for amount")
|
||||
}
|
||||
response.Symbol = symbol
|
||||
response.RateAverage = avgRate
|
||||
response.AmountAverage = avgAmount
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetV2FundingInfo gets funding info for margin pairs
|
||||
func (b *Bitfinex) GetV2FundingInfo(key string) (MarginFundingDataV2, error) {
|
||||
var resp []interface{}
|
||||
var response MarginFundingDataV2
|
||||
err := b.SendAuthenticatedHTTPRequestV2(exchange.RestSpot, http.MethodPost,
|
||||
fmt.Sprintf(bitfinexV2FundingInfo, key),
|
||||
nil,
|
||||
&resp,
|
||||
getAccountFees)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if len(resp) != 3 {
|
||||
return response, errors.New("invalid data received")
|
||||
}
|
||||
sym, ok := resp[0].(string)
|
||||
if !ok {
|
||||
return response, errors.New("failed type assertion for sym")
|
||||
}
|
||||
symbol, ok := resp[1].(string)
|
||||
if !ok {
|
||||
return response, errors.New("failed type assertion for symbol")
|
||||
}
|
||||
fundingData, ok := resp[2].([]interface{})
|
||||
if !ok {
|
||||
return response, errors.New("failed type assertion for fundingData")
|
||||
}
|
||||
response.Sym = sym
|
||||
response.Symbol = symbol
|
||||
if len(fundingData) < 4 {
|
||||
return response, errors.New("invalid length of fundingData")
|
||||
}
|
||||
for x := 0; x < 3; x++ {
|
||||
_, ok := fundingData[x].(float64)
|
||||
if !ok {
|
||||
return response, fmt.Errorf("type conversion failed for x = %d", x)
|
||||
}
|
||||
}
|
||||
response.Data.YieldLoan = fundingData[0].(float64)
|
||||
response.Data.YieldLend = fundingData[1].(float64)
|
||||
response.Data.DurationLoan = fundingData[2].(float64)
|
||||
response.Data.DurationLend = fundingData[3].(float64)
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetAccountInfoV2 gets V2 account data
|
||||
func (b *Bitfinex) GetAccountInfoV2() (AccountV2Data, error) {
|
||||
var resp AccountV2Data
|
||||
var data []interface{}
|
||||
err := b.SendAuthenticatedHTTPRequestV2(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexV2AccountInfo,
|
||||
nil,
|
||||
&data,
|
||||
getAccountFees)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if len(data) < 8 {
|
||||
return resp, errors.New("invalid length of data")
|
||||
}
|
||||
var ok bool
|
||||
var tempString string
|
||||
var tempFloat float64
|
||||
if tempFloat, ok = data[0].(float64); !ok {
|
||||
return resp, errors.New("type assertion failed for id, check for api updates")
|
||||
}
|
||||
resp.ID = int64(tempFloat)
|
||||
if tempString, ok = data[1].(string); !ok {
|
||||
return resp, errors.New("type assertion failed for email, check for api updates")
|
||||
}
|
||||
resp.Email = tempString
|
||||
if tempString, ok = data[2].(string); !ok {
|
||||
return resp, errors.New("type assertion failed for username, check for api updates")
|
||||
}
|
||||
resp.Username = tempString
|
||||
if tempFloat, ok = data[3].(float64); !ok {
|
||||
return resp, errors.New("type assertion failed for accountcreate, check for api updates")
|
||||
}
|
||||
resp.MTSAccountCreate = int64(tempFloat)
|
||||
if tempFloat, ok = data[4].(float64); !ok {
|
||||
return resp, errors.New("type assertion failed for verified, check for api updates")
|
||||
}
|
||||
resp.Verified = int64(tempFloat)
|
||||
if tempString, ok = data[7].(string); !ok {
|
||||
return resp, errors.New("type assertion failed for timezone, check for api updates")
|
||||
}
|
||||
resp.Timezone = tempString
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetV2Balances gets v2 balances
|
||||
func (b *Bitfinex) GetV2Balances() ([]WalletDataV2, error) {
|
||||
var resp []WalletDataV2
|
||||
var data [][4]interface{}
|
||||
err := b.SendAuthenticatedHTTPRequestV2(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexV2Balances,
|
||||
nil,
|
||||
&data,
|
||||
getAccountFees)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
for x := range data {
|
||||
wType, ok := data[x][0].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for walletType, check for api updates")
|
||||
}
|
||||
curr, ok := data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for currency, check for api updates")
|
||||
}
|
||||
bal, ok := data[x][2].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for balance, check for api updates")
|
||||
}
|
||||
unsettledInterest, ok := data[x][3].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for unsettledInterest, check for api updates")
|
||||
}
|
||||
resp = append(resp, WalletDataV2{
|
||||
WalletType: wType,
|
||||
Currency: curr,
|
||||
Balance: bal,
|
||||
UnsettledInterest: unsettledInterest,
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetMarginPairs gets pairs that allow margin trading
|
||||
func (b *Bitfinex) GetMarginPairs() ([]string, error) {
|
||||
var resp [][]string
|
||||
path := bitfinexAPIVersion2 + bitfinexMarginPairs
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &resp, status)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(resp) != 1 {
|
||||
return nil, errors.New("invalid response")
|
||||
}
|
||||
return resp[0], nil
|
||||
}
|
||||
|
||||
// GetDerivativeData gets data for the queried derivative
|
||||
func (b *Bitfinex) GetDerivativeData(keys, startTime, endTime string, sort, limit int64) (DerivativeDataResponse, error) {
|
||||
var result [][19]interface{}
|
||||
var response DerivativeDataResponse
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("keys", keys)
|
||||
if startTime != "" {
|
||||
params.Set("start", startTime)
|
||||
}
|
||||
if endTime != "" {
|
||||
params.Set("end", endTime)
|
||||
}
|
||||
if sort != 0 {
|
||||
params.Set("sort", strconv.FormatInt(sort, 10))
|
||||
}
|
||||
if limit != 0 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
path := bitfinexAPIVersion2 + bitfinexDerivativeData +
|
||||
params.Encode()
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &result, status)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if len(result) < 1 {
|
||||
return response, errors.New("invalid response, array length too small, check api docs for updates")
|
||||
}
|
||||
if len(result[0]) < 19 {
|
||||
return response, errors.New("invalid response, array length too small, check api docs for updates")
|
||||
}
|
||||
var floatData float64
|
||||
var stringData string
|
||||
var ok bool
|
||||
if stringData, ok = result[0][0].(string); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.Key = stringData
|
||||
if floatData, ok = result[0][1].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.MTS = floatData
|
||||
if floatData, ok = result[0][3].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.DerivPrice = floatData
|
||||
if floatData, ok = result[0][4].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.SpotPrice = floatData
|
||||
if floatData, ok = result[0][6].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.InsuranceFundBalance = floatData
|
||||
if floatData, ok = result[0][8].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.NextFundingEventTS = floatData
|
||||
if floatData, ok = result[0][9].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.NextFundingAccured = floatData
|
||||
if floatData, ok = result[0][10].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.NextFundingStep = floatData
|
||||
if floatData, ok = result[0][12].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.CurrentFunding = floatData
|
||||
if floatData, ok = result[0][15].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.MarkPrice = floatData
|
||||
if floatData, ok = result[0][18].(float64); !ok {
|
||||
return response, errors.New("type assertion failed, check for api updates")
|
||||
}
|
||||
response.OpenInterest = floatData
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetTickerBatch returns all supported ticker information
|
||||
func (b *Bitfinex) GetTickerBatch() (map[string]Ticker, error) {
|
||||
var response [][]interface{}
|
||||
|
||||
path := b.API.Endpoints.URL +
|
||||
bitfinexAPIVersion2 +
|
||||
bitfinexTickerBatch +
|
||||
path := bitfinexAPIVersion2 + bitfinexTickerBatch +
|
||||
"?symbols=ALL"
|
||||
|
||||
err := b.SendHTTPRequest(path, &response, tickerBatch)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response, tickerBatch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -165,12 +428,9 @@ func (b *Bitfinex) GetTickerBatch() (map[string]Ticker, error) {
|
||||
func (b *Bitfinex) GetTicker(symbol string) (Ticker, error) {
|
||||
var response []interface{}
|
||||
|
||||
path := b.API.Endpoints.URL +
|
||||
bitfinexAPIVersion2 +
|
||||
bitfinexTicker +
|
||||
symbol
|
||||
path := bitfinexAPIVersion2 + bitfinexTicker + symbol
|
||||
|
||||
err := b.SendHTTPRequest(path, &response, tickerFunction)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response, tickerFunction)
|
||||
if err != nil {
|
||||
return Ticker{}, err
|
||||
}
|
||||
@@ -232,16 +492,10 @@ func (b *Bitfinex) GetTrades(currencyPair string, limit, timestampStart, timesta
|
||||
}
|
||||
v.Set("sort", sortVal)
|
||||
|
||||
path := b.API.Endpoints.URL +
|
||||
bitfinexAPIVersion2 +
|
||||
bitfinexTrades +
|
||||
currencyPair +
|
||||
"/hist" +
|
||||
"?" +
|
||||
v.Encode()
|
||||
path := bitfinexAPIVersion2 + bitfinexTrades + currencyPair + "/hist" + "?" + v.Encode()
|
||||
|
||||
var resp [][]interface{}
|
||||
err := b.SendHTTPRequest(path, &resp, tradeRateLimit)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &resp, tradeRateLimit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -290,17 +544,10 @@ func (b *Bitfinex) GetOrderbook(symbol, precision string, limit int64) (Orderboo
|
||||
if limit > 0 {
|
||||
u.Set("len", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
path := b.API.Endpoints.URL +
|
||||
bitfinexAPIVersion2 +
|
||||
bitfinexOrderbook +
|
||||
symbol +
|
||||
"/" +
|
||||
precision +
|
||||
"?" +
|
||||
u.Encode()
|
||||
path := bitfinexAPIVersion2 + bitfinexOrderbook + symbol + "/" + precision + "?" + u.Encode()
|
||||
|
||||
var response [][]interface{}
|
||||
err := b.SendHTTPRequest(path, &response, orderbookFunction)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response, orderbookFunction)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -371,8 +618,8 @@ func (b *Bitfinex) GetOrderbook(symbol, precision string, limit int64) (Orderboo
|
||||
// GetStats returns various statistics about the requested pair
|
||||
func (b *Bitfinex) GetStats(symbol string) ([]Stat, error) {
|
||||
var response []Stat
|
||||
path := b.API.Endpoints.URL + bitfinexAPIVersion + bitfinexStats + symbol
|
||||
return response, b.SendHTTPRequest(path, &response, statsV1)
|
||||
path := bitfinexAPIVersion + bitfinexStats + symbol
|
||||
return response, b.SendHTTPRequest(exchange.RestSpot, path, &response, statsV1)
|
||||
}
|
||||
|
||||
// GetFundingBook the entire margin funding book for both bids and asks sides
|
||||
@@ -382,9 +629,9 @@ func (b *Bitfinex) GetStats(symbol string) ([]Stat, error) {
|
||||
// conversion to full V2 API update is done.
|
||||
func (b *Bitfinex) GetFundingBook(symbol string) (FundingBook, error) {
|
||||
response := FundingBook{}
|
||||
path := b.API.Endpoints.URL + bitfinexAPIVersion + bitfinexLendbook + symbol
|
||||
path := bitfinexAPIVersion + bitfinexLendbook + symbol
|
||||
|
||||
if err := b.SendHTTPRequest(path, &response, fundingbook); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, path, &response, fundingbook); err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
@@ -397,12 +644,11 @@ func (b *Bitfinex) GetFundingBook(symbol string) (FundingBook, error) {
|
||||
// Symbol - example "USD"
|
||||
func (b *Bitfinex) GetLends(symbol string, values url.Values) ([]Lends, error) {
|
||||
var response []Lends
|
||||
path := common.EncodeURLValues(b.API.Endpoints.URL+
|
||||
bitfinexAPIVersion+
|
||||
path := common.EncodeURLValues(bitfinexAPIVersion+
|
||||
bitfinexLends+
|
||||
symbol,
|
||||
values)
|
||||
return response, b.SendHTTPRequest(path, &response, lends)
|
||||
return response, b.SendHTTPRequest(exchange.RestSpot, path, &response, lends)
|
||||
}
|
||||
|
||||
// GetCandles returns candle chart data
|
||||
@@ -415,8 +661,7 @@ func (b *Bitfinex) GetCandles(symbol, timeFrame string, start, end int64, limit
|
||||
fundingPeriod = ":p30"
|
||||
}
|
||||
|
||||
var path = b.API.Endpoints.URL +
|
||||
bitfinexAPIVersion2 +
|
||||
var path = bitfinexAPIVersion2 +
|
||||
bitfinexCandles +
|
||||
":" +
|
||||
timeFrame +
|
||||
@@ -444,7 +689,7 @@ func (b *Bitfinex) GetCandles(symbol, timeFrame string, start, end int64, limit
|
||||
}
|
||||
|
||||
var response [][]interface{}
|
||||
err := b.SendHTTPRequest(path, &response, candle)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response, candle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -467,7 +712,7 @@ func (b *Bitfinex) GetCandles(symbol, timeFrame string, start, end int64, limit
|
||||
path += "/last"
|
||||
|
||||
var response []interface{}
|
||||
err := b.SendHTTPRequest(path, &response, candle)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response, candle)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -528,7 +773,7 @@ func (b *Bitfinex) GetLeaderboard(key, timeframe, symbol string, sort, limit int
|
||||
return nil, errors.New("invalid leaderboard key")
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/%s:%s:%s/hist", b.API.Endpoints.URL+bitfinexAPIVersion2+bitfinexLeaderboard,
|
||||
path := fmt.Sprintf("%s/%s:%s:%s/hist", bitfinexAPIVersion2+bitfinexLeaderboard,
|
||||
key,
|
||||
timeframe,
|
||||
symbol)
|
||||
@@ -547,7 +792,7 @@ func (b *Bitfinex) GetLeaderboard(key, timeframe, symbol string, sort, limit int
|
||||
}
|
||||
path = common.EncodeURLValues(path, vals)
|
||||
var resp []interface{}
|
||||
if err := b.SendHTTPRequest(path, &resp, leaderBoardReqRate); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, path, &resp, leaderBoardReqRate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -587,7 +832,7 @@ func (b *Bitfinex) GetForeignExchangeRate() error {
|
||||
// GetAccountFees returns information about your account trading fees
|
||||
func (b *Bitfinex) GetAccountFees() ([]AccountInfo, error) {
|
||||
var responses []AccountInfo
|
||||
return responses, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return responses, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexAccountInfo,
|
||||
nil,
|
||||
&responses,
|
||||
@@ -597,7 +842,7 @@ func (b *Bitfinex) GetAccountFees() ([]AccountInfo, error) {
|
||||
// GetWithdrawalFees - Gets all fee rates for withdrawals
|
||||
func (b *Bitfinex) GetWithdrawalFees() (AccountFees, error) {
|
||||
response := AccountFees{}
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexAccountFees,
|
||||
nil,
|
||||
&response,
|
||||
@@ -609,7 +854,7 @@ func (b *Bitfinex) GetWithdrawalFees() (AccountFees, error) {
|
||||
func (b *Bitfinex) GetAccountSummary() (AccountSummary, error) {
|
||||
response := AccountSummary{}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexAccountSummary,
|
||||
nil,
|
||||
&response,
|
||||
@@ -635,7 +880,7 @@ func (b *Bitfinex) NewDeposit(method, walletName string, renew int) (DepositResp
|
||||
req["wallet_name"] = walletName
|
||||
req["renew"] = renew
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexDeposit,
|
||||
req,
|
||||
&response,
|
||||
@@ -646,7 +891,7 @@ func (b *Bitfinex) NewDeposit(method, walletName string, renew int) (DepositResp
|
||||
// this request.
|
||||
func (b *Bitfinex) GetKeyPermissions() (KeyPermissions, error) {
|
||||
response := KeyPermissions{}
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexKeyPermissions,
|
||||
nil,
|
||||
&response,
|
||||
@@ -656,7 +901,7 @@ func (b *Bitfinex) GetKeyPermissions() (KeyPermissions, error) {
|
||||
// GetMarginInfo shows your trading wallet information for margin trading
|
||||
func (b *Bitfinex) GetMarginInfo() ([]MarginInfo, error) {
|
||||
var response []MarginInfo
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexMarginInfo,
|
||||
nil,
|
||||
&response,
|
||||
@@ -666,7 +911,7 @@ func (b *Bitfinex) GetMarginInfo() ([]MarginInfo, error) {
|
||||
// GetAccountBalance returns full wallet balance information
|
||||
func (b *Bitfinex) GetAccountBalance() ([]Balance, error) {
|
||||
var response []Balance
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexBalances,
|
||||
nil,
|
||||
&response,
|
||||
@@ -686,7 +931,7 @@ func (b *Bitfinex) WalletTransfer(amount float64, currency, walletFrom, walletTo
|
||||
req["walletfrom"] = walletFrom
|
||||
req["walletto"] = walletTo
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexTransfer,
|
||||
req,
|
||||
&response,
|
||||
@@ -714,7 +959,7 @@ func (b *Bitfinex) WithdrawCryptocurrency(wallet, address, paymentID string, amo
|
||||
req["payment_id"] = paymentID
|
||||
}
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexWithdrawal,
|
||||
req,
|
||||
&response,
|
||||
@@ -759,7 +1004,7 @@ func (b *Bitfinex) WithdrawFIAT(withdrawalType, walletType string, withdrawReque
|
||||
req["intermediary_bank_swift"] = withdrawRequest.Fiat.IntermediarySwiftCode
|
||||
}
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexWithdrawal,
|
||||
req,
|
||||
&response,
|
||||
@@ -794,7 +1039,7 @@ func (b *Bitfinex) NewOrder(currencyPair, orderType string, amount, price float6
|
||||
req["side"] = order.Buy.Lower()
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderNew,
|
||||
req,
|
||||
&response,
|
||||
@@ -807,7 +1052,7 @@ func (b *Bitfinex) NewOrderMulti(orders []PlaceOrder) (OrderMultiResponse, error
|
||||
req := make(map[string]interface{})
|
||||
req["orders"] = orders
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderNewMulti,
|
||||
req,
|
||||
&response,
|
||||
@@ -820,7 +1065,7 @@ func (b *Bitfinex) CancelExistingOrder(orderID int64) (Order, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["order_id"] = orderID
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancel,
|
||||
req,
|
||||
&response,
|
||||
@@ -833,7 +1078,7 @@ func (b *Bitfinex) CancelMultipleOrders(orderIDs []int64) (string, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["order_ids"] = orderIDs
|
||||
|
||||
return response.Result, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response.Result, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancelMulti,
|
||||
req,
|
||||
nil,
|
||||
@@ -844,7 +1089,7 @@ func (b *Bitfinex) CancelMultipleOrders(orderIDs []int64) (string, error) {
|
||||
func (b *Bitfinex) CancelAllExistingOrders() (string, error) {
|
||||
response := GenericResponse{}
|
||||
|
||||
return response.Result, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response.Result, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancelAll,
|
||||
nil,
|
||||
nil,
|
||||
@@ -869,7 +1114,7 @@ func (b *Bitfinex) ReplaceOrder(orderID int64, symbol string, amount, price floa
|
||||
req["side"] = order.Sell.Lower()
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderCancelReplace,
|
||||
req,
|
||||
&response,
|
||||
@@ -882,7 +1127,7 @@ func (b *Bitfinex) GetOrderStatus(orderID int64) (Order, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["order_id"] = orderID
|
||||
|
||||
return orderStatus, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return orderStatus, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderStatus,
|
||||
req,
|
||||
&orderStatus,
|
||||
@@ -895,7 +1140,7 @@ func (b *Bitfinex) GetInactiveOrders() ([]Order, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["limit"] = "100"
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexInactiveOrders,
|
||||
req,
|
||||
&response,
|
||||
@@ -905,7 +1150,7 @@ func (b *Bitfinex) GetInactiveOrders() ([]Order, error) {
|
||||
// GetOpenOrders returns all active orders and statuses
|
||||
func (b *Bitfinex) GetOpenOrders() ([]Order, error) {
|
||||
var response []Order
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrders,
|
||||
nil,
|
||||
&response,
|
||||
@@ -916,7 +1161,7 @@ func (b *Bitfinex) GetOpenOrders() ([]Order, error) {
|
||||
func (b *Bitfinex) GetActivePositions() ([]Position, error) {
|
||||
var response []Position
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexPositions,
|
||||
nil,
|
||||
&response,
|
||||
@@ -929,7 +1174,7 @@ func (b *Bitfinex) ClaimPosition(positionID int) (Position, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["position_id"] = positionID
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexClaimPosition,
|
||||
nil,
|
||||
nil,
|
||||
@@ -955,7 +1200,7 @@ func (b *Bitfinex) GetBalanceHistory(symbol string, timeSince, timeUntil time.Ti
|
||||
req["wallet"] = wallet
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexHistory,
|
||||
req,
|
||||
&response,
|
||||
@@ -981,7 +1226,7 @@ func (b *Bitfinex) GetMovementHistory(symbol, method string, timeSince, timeUnti
|
||||
req["limit"] = limit
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexHistoryMovements,
|
||||
req,
|
||||
&response,
|
||||
@@ -1005,7 +1250,7 @@ func (b *Bitfinex) GetTradeHistory(currencyPair string, timestamp, until time.Ti
|
||||
req["reverse"] = reverse
|
||||
}
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexTradeHistory,
|
||||
req,
|
||||
&response,
|
||||
@@ -1022,7 +1267,7 @@ func (b *Bitfinex) NewOffer(symbol string, amount, rate float64, period int64, d
|
||||
req["period"] = period
|
||||
req["direction"] = direction
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOfferNew,
|
||||
req,
|
||||
&response,
|
||||
@@ -1035,7 +1280,7 @@ func (b *Bitfinex) CancelOffer(offerID int64) (Offer, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["offer_id"] = offerID
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOfferCancel,
|
||||
req,
|
||||
&response,
|
||||
@@ -1049,7 +1294,7 @@ func (b *Bitfinex) GetOfferStatus(offerID int64) (Offer, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["offer_id"] = offerID
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOrderStatus,
|
||||
req,
|
||||
&response,
|
||||
@@ -1060,7 +1305,7 @@ func (b *Bitfinex) GetOfferStatus(offerID int64) (Offer, error) {
|
||||
func (b *Bitfinex) GetActiveCredits() ([]Offer, error) {
|
||||
var response []Offer
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexActiveCredits,
|
||||
nil,
|
||||
&response,
|
||||
@@ -1071,7 +1316,7 @@ func (b *Bitfinex) GetActiveCredits() ([]Offer, error) {
|
||||
func (b *Bitfinex) GetActiveOffers() ([]Offer, error) {
|
||||
var response []Offer
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexOffers,
|
||||
nil,
|
||||
&response,
|
||||
@@ -1082,7 +1327,7 @@ func (b *Bitfinex) GetActiveOffers() ([]Offer, error) {
|
||||
func (b *Bitfinex) GetActiveMarginFunding() ([]MarginFunds, error) {
|
||||
var response []MarginFunds
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexMarginActiveFunds,
|
||||
nil,
|
||||
&response,
|
||||
@@ -1094,7 +1339,7 @@ func (b *Bitfinex) GetActiveMarginFunding() ([]MarginFunds, error) {
|
||||
func (b *Bitfinex) GetUnusedMarginFunds() ([]MarginFunds, error) {
|
||||
var response []MarginFunds
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexMarginUnusedFunds,
|
||||
nil,
|
||||
&response,
|
||||
@@ -1106,7 +1351,7 @@ func (b *Bitfinex) GetUnusedMarginFunds() ([]MarginFunds, error) {
|
||||
func (b *Bitfinex) GetMarginTotalTakenFunds() ([]MarginTotalTakenFunds, error) {
|
||||
var response []MarginTotalTakenFunds
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexMarginTotalFunds,
|
||||
nil,
|
||||
&response,
|
||||
@@ -1119,7 +1364,7 @@ func (b *Bitfinex) CloseMarginFunding(swapID int64) (Offer, error) {
|
||||
req := make(map[string]interface{})
|
||||
req["swap_id"] = swapID
|
||||
|
||||
return response, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return response, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitfinexMarginClose,
|
||||
req,
|
||||
&response,
|
||||
@@ -1127,10 +1372,14 @@ func (b *Bitfinex) CloseMarginFunding(swapID int64) (Offer, error) {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (b *Bitfinex) SendHTTPRequest(path string, result interface{}, e request.EndpointLimit) error {
|
||||
func (b *Bitfinex) SendHTTPRequest(ep exchange.URL, path string, result interface{}, e request.EndpointLimit) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -1140,12 +1389,17 @@ func (b *Bitfinex) SendHTTPRequest(path string, result interface{}, e request.En
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an autheticated http request and json
|
||||
// unmarshals result to a supplied variable
|
||||
func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error {
|
||||
func (b *Bitfinex) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
b.Name)
|
||||
}
|
||||
|
||||
ePoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := b.Requester.GetNonce(true)
|
||||
|
||||
req := make(map[string]interface{})
|
||||
@@ -1175,7 +1429,7 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
|
||||
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: b.API.Endpoints.URL + bitfinexAPIVersion + path,
|
||||
Path: ePoint + bitfinexAPIVersion + path,
|
||||
Headers: headers,
|
||||
Result: result,
|
||||
AuthRequest: true,
|
||||
@@ -1186,6 +1440,58 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
|
||||
Endpoint: endpoint})
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequestV2 sends an autheticated http request and json
|
||||
// unmarshals result to a supplied variable
|
||||
func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
b.Name)
|
||||
}
|
||||
ePoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var body io.Reader
|
||||
var payload []byte
|
||||
if len(params) != 0 {
|
||||
payload, err = json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body = bytes.NewBuffer(payload)
|
||||
}
|
||||
|
||||
// This is done in a weird way because bitfinex doesn't accept unixnano
|
||||
n := strconv.FormatInt(int64(b.Requester.GetNonce(false))*1e9, 10)
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
headers["Accept"] = "application/json"
|
||||
headers["bfx-apikey"] = b.API.Credentials.Key
|
||||
headers["bfx-nonce"] = n
|
||||
strPath := "/api" + bitfinexAPIVersion2 + path + string(payload)
|
||||
signStr := strPath + n
|
||||
hmac := crypto.GetHMAC(
|
||||
crypto.HashSHA512_384,
|
||||
[]byte(signStr),
|
||||
[]byte(b.API.Credentials.Secret),
|
||||
)
|
||||
headers["bfx-signature"] = crypto.HexEncodeToString(hmac)
|
||||
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: ePoint + bitfinexAPIVersion2 + path,
|
||||
Headers: headers,
|
||||
Body: body,
|
||||
Result: result,
|
||||
AuthRequest: true,
|
||||
NonceEnabled: true,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
HTTPRecording: b.HTTPRecording,
|
||||
Endpoint: endpoint,
|
||||
})
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
func (b *Bitfinex) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
var fee float64
|
||||
@@ -1343,9 +1649,8 @@ func (b *Bitfinex) ConvertSymbolToDepositMethod(c currency.Code) (string, error)
|
||||
func (b *Bitfinex) PopulateAcceptableMethods() error {
|
||||
if len(AcceptableMethods) == 0 {
|
||||
var response [][][2]string
|
||||
err := b.SendHTTPRequest(b.API.Endpoints.URL+
|
||||
bitfinexAPIVersion2+
|
||||
bitfinexDepositMethod,
|
||||
err := b.SendHTTPRequest(exchange.RestSpot,
|
||||
bitfinexAPIVersion2+bitfinexDepositMethod,
|
||||
&response,
|
||||
configs)
|
||||
if err != nil {
|
||||
|
||||
@@ -61,6 +61,64 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
func TestGetV2MarginFunding(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.SkipNow()
|
||||
}
|
||||
_, err := b.GetV2MarginFunding("fUSD", "2", 2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountInfoV2(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.SkipNow()
|
||||
}
|
||||
_, err := b.GetAccountInfoV2()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetV2FundingInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.SkipNow()
|
||||
}
|
||||
_, err := b.GetV2FundingInfo("fUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetV2Balances(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.SkipNow()
|
||||
}
|
||||
_, err := b.GetV2Balances()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDerivativeData(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetDerivativeData("tBTCF0:USTF0", "", "", 0, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginPairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetMarginPairs()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppendOptionalDelimiter(t *testing.T) {
|
||||
t.Parallel()
|
||||
curr1, err := currency.NewPairFromString("BTCUSD")
|
||||
@@ -222,7 +280,7 @@ func TestGetAccountFees(t *testing.T) {
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.UpdateAccountInfo()
|
||||
_, err := b.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo error", err)
|
||||
}
|
||||
@@ -233,7 +291,6 @@ func TestGetWithdrawalFee(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetWithdrawalFees()
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo error", err)
|
||||
@@ -315,7 +372,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.FetchAccountInfo()
|
||||
_, err := b.FetchAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -487,7 +544,6 @@ func TestGetBalanceHistory(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetBalanceHistory("USD", time.Time{}, time.Time{}, 1, "deposit")
|
||||
if err == nil {
|
||||
t.Error("GetBalanceHistory() Expected error")
|
||||
@@ -511,7 +567,6 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetTradeHistory("BTCUSD", time.Time{}, time.Time{}, 1, 0)
|
||||
if err == nil {
|
||||
t.Error("GetTradeHistory() Expected error")
|
||||
@@ -734,7 +789,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -748,7 +804,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -1470,7 +1527,7 @@ func TestGetHistoricTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
// longer term test
|
||||
_, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Hour*24*100), time.Now().Add(-time.Hour*24*99))
|
||||
_, err = b.GetHistoricTrades(currencyPair, asset.Spot, time.Now().Add(-time.Hour*100), time.Now().Add(-time.Hour*99))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,24 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
// AccountV2Data stores account v2 data
|
||||
type AccountV2Data struct {
|
||||
ID int64
|
||||
Email string
|
||||
Username string
|
||||
MTSAccountCreate int64
|
||||
Verified int64
|
||||
Timezone string
|
||||
}
|
||||
|
||||
// WalletDataV2 stores wallet data for v2
|
||||
type WalletDataV2 struct {
|
||||
WalletType string
|
||||
Currency string
|
||||
Balance float64
|
||||
UnsettledInterest float64
|
||||
}
|
||||
|
||||
// AcceptedOrderType defines the accepted market types, exchange strings denote non-contract order types.
|
||||
var AcceptedOrderType = []string{"market", "limit", "stop", "trailing-stop",
|
||||
"fill-or-kill", "exchange market", "exchange limit", "exchange stop",
|
||||
@@ -18,6 +36,42 @@ var AcceptedWalletNames = []string{"trading", "exchange", "deposit", "margin",
|
||||
// AcceptableMethods defines a map of currency codes to methods
|
||||
var AcceptableMethods = make(map[string]string)
|
||||
|
||||
// MarginV2FundingData stores margin funding data
|
||||
type MarginV2FundingData struct {
|
||||
Symbol string
|
||||
RateAverage float64
|
||||
AmountAverage float64
|
||||
}
|
||||
|
||||
// MarginFundingDataV2 stores margin funding data
|
||||
type MarginFundingDataV2 struct {
|
||||
Sym string
|
||||
Symbol string
|
||||
Data struct {
|
||||
YieldLoan float64
|
||||
YieldLend float64
|
||||
DurationLoan float64
|
||||
DurationLend float64
|
||||
}
|
||||
}
|
||||
|
||||
// MarginFundingData stores data for margin funding
|
||||
type MarginFundingData struct {
|
||||
ID int64
|
||||
Symbol string
|
||||
MTSCreated int64
|
||||
MTSUpdated int64
|
||||
Amount float64
|
||||
AmountOrig float64
|
||||
OrderType string
|
||||
OfferStatus string
|
||||
Active string
|
||||
Rate float64
|
||||
Period float64
|
||||
Notify bool
|
||||
Renew bool
|
||||
}
|
||||
|
||||
// Ticker holds ticker information
|
||||
type Ticker struct {
|
||||
FlashReturnRate float64
|
||||
@@ -36,6 +90,21 @@ type Ticker struct {
|
||||
FFRAmountAvailable float64
|
||||
}
|
||||
|
||||
// DerivativeDataResponse stores data for queried derivative
|
||||
type DerivativeDataResponse struct {
|
||||
Key string
|
||||
MTS float64
|
||||
DerivPrice float64
|
||||
SpotPrice float64
|
||||
MarkPrice float64
|
||||
InsuranceFundBalance float64
|
||||
NextFundingEventTS float64
|
||||
NextFundingAccured float64
|
||||
NextFundingStep float64
|
||||
CurrentFunding float64
|
||||
OpenInterest float64
|
||||
}
|
||||
|
||||
// Stat holds individual statistics from exchange
|
||||
type Stat struct {
|
||||
Period int64 `json:"period"`
|
||||
|
||||
@@ -163,10 +163,14 @@ func (b *Bitfinex) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.URLDefault = bitfinexAPIURLBase
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = publicBitfinexWebsocketEndpoint
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bitfinexAPIURLBase,
|
||||
exchange.WebsocketSpot: publicBitfinexWebsocketEndpoint,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = stream.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -184,6 +188,10 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wsEndpoint, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
@@ -192,7 +200,7 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: publicBitfinexWebsocketEndpoint,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsEndpoint,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
UnSubscriber: b.Unsubscribe,
|
||||
@@ -398,17 +406,19 @@ func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
if err != nil {
|
||||
return o, err
|
||||
}
|
||||
if assetType != asset.Spot && assetType != asset.Margin && assetType != asset.MarginFunding {
|
||||
return o, fmt.Errorf("assetType not supported: %v", assetType)
|
||||
}
|
||||
b.appendOptionalDelimiter(&fPair)
|
||||
var prefix = "t"
|
||||
if assetType == asset.MarginFunding {
|
||||
prefix = "f"
|
||||
}
|
||||
|
||||
orderbookNew, err := b.GetOrderbook(prefix+fPair.String(), "R0", 100)
|
||||
var orderbookNew Orderbook
|
||||
orderbookNew, err = b.GetOrderbook(prefix+fPair.String(), "R0", 100)
|
||||
if err != nil {
|
||||
return o, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if assetType == asset.MarginFunding {
|
||||
o.IsFundingRate = true
|
||||
for x := range orderbookNew.Asks {
|
||||
@@ -443,18 +453,16 @@ func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = o.Process()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return orderbook.Get(b.Name, fPair, assetType)
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Bitfinex exchange
|
||||
func (b *Bitfinex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bitfinex) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
|
||||
@@ -494,10 +502,10 @@ func (b *Bitfinex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitfinex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bitfinex) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -945,8 +953,8 @@ func (b *Bitfinex) appendOptionalDelimiter(p *currency.Pair) {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitfinex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bitfinex) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package bitflyer
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -76,51 +75,41 @@ type Bitflyer struct {
|
||||
// analysis system
|
||||
func (b *Bitflyer) GetLatestBlockCA() (ChainAnalysisBlock, error) {
|
||||
var resp ChainAnalysisBlock
|
||||
path := b.API.Endpoints.URLSecondary + latestBlock
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.ChainAnalysis, latestBlock, &resp)
|
||||
}
|
||||
|
||||
// GetBlockCA returns block information by blockhash from bitflyer chain
|
||||
// analysis system
|
||||
func (b *Bitflyer) GetBlockCA(blockhash string) (ChainAnalysisBlock, error) {
|
||||
var resp ChainAnalysisBlock
|
||||
path := b.API.Endpoints.URLSecondary + blockByBlockHash + blockhash
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.ChainAnalysis, blockByBlockHash+blockhash, &resp)
|
||||
}
|
||||
|
||||
// GetBlockbyHeightCA returns the block information by height from bitflyer chain
|
||||
// analysis system
|
||||
func (b *Bitflyer) GetBlockbyHeightCA(height int64) (ChainAnalysisBlock, error) {
|
||||
var resp ChainAnalysisBlock
|
||||
path := b.API.Endpoints.URLSecondary +
|
||||
blockByBlockHeight +
|
||||
strconv.FormatInt(height, 10)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.ChainAnalysis, blockByBlockHeight+strconv.FormatInt(height, 10), &resp)
|
||||
}
|
||||
|
||||
// GetTransactionByHashCA returns transaction information by txHash from
|
||||
// bitflyer chain analysis system
|
||||
func (b *Bitflyer) GetTransactionByHashCA(txHash string) (ChainAnalysisTransaction, error) {
|
||||
var resp ChainAnalysisTransaction
|
||||
path := b.API.Endpoints.URLSecondary + transaction + txHash
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.ChainAnalysis, transaction+txHash, &resp)
|
||||
}
|
||||
|
||||
// GetAddressInfoCA returns balance information for address by addressln string
|
||||
// from bitflyer chain analysis system
|
||||
func (b *Bitflyer) GetAddressInfoCA(addressln string) (ChainAnalysisAddress, error) {
|
||||
var resp ChainAnalysisAddress
|
||||
path := b.API.Endpoints.URLSecondary + address + addressln
|
||||
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.ChainAnalysis, address+addressln, &resp)
|
||||
}
|
||||
|
||||
// GetMarkets returns market information
|
||||
func (b *Bitflyer) GetMarkets() ([]MarketInfo, error) {
|
||||
var resp []MarketInfo
|
||||
path := b.API.Endpoints.URL + pubGetMarkets
|
||||
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, pubGetMarkets, &resp)
|
||||
}
|
||||
|
||||
// GetOrderBook returns market orderbook depth
|
||||
@@ -128,9 +117,8 @@ func (b *Bitflyer) GetOrderBook(symbol string) (Orderbook, error) {
|
||||
var resp Orderbook
|
||||
v := url.Values{}
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, pubGetBoard, v.Encode())
|
||||
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, pubGetBoard+"?"+v.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
@@ -138,8 +126,7 @@ func (b *Bitflyer) GetTicker(symbol string) (Ticker, error) {
|
||||
var resp Ticker
|
||||
v := url.Values{}
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, pubGetTicker, v.Encode())
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, pubGetTicker+"?"+v.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetExecutionHistory returns past trades that were executed on the market
|
||||
@@ -147,18 +134,14 @@ func (b *Bitflyer) GetExecutionHistory(symbol string) ([]ExecutedTrade, error) {
|
||||
var resp []ExecutedTrade
|
||||
v := url.Values{}
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, pubGetExecutionHistory, v.Encode())
|
||||
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, pubGetExecutionHistory+"?"+v.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetExchangeStatus returns exchange status information
|
||||
func (b *Bitflyer) GetExchangeStatus() (string, error) {
|
||||
resp := make(map[string]string)
|
||||
|
||||
path := b.API.Endpoints.URL + pubGetHealth
|
||||
|
||||
err := b.SendHTTPRequest(path, &resp)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, pubGetHealth, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -183,8 +166,7 @@ func (b *Bitflyer) GetChats(fromDate string) ([]ChatLog, error) {
|
||||
var resp []ChatLog
|
||||
v := url.Values{}
|
||||
v.Set("from_date", fromDate)
|
||||
path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, pubGetChats, v.Encode())
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, pubGetChats+"?"+v.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetPermissions returns current permissions for associated with your API
|
||||
@@ -304,10 +286,14 @@ func (b *Bitflyer) GetTradingCommission() {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (b *Bitflyer) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (b *Bitflyer) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
|
||||
@@ -283,7 +283,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -297,7 +298,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
|
||||
@@ -94,11 +94,14 @@ func (b *Bitflyer) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.URLDefault = japanURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.URLSecondaryDefault = chainAnalysis
|
||||
b.API.Endpoints.URLSecondary = b.API.Endpoints.URLSecondaryDefault
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: japanURL,
|
||||
exchange.ChainAnalysis: chainAnalysis,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -289,15 +292,15 @@ func (b *Bitflyer) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies on the
|
||||
// Bitflyer exchange
|
||||
func (b *Bitflyer) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bitflyer) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
return account.Holdings{}, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitflyer) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bitflyer) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -442,8 +445,8 @@ func (b *Bitflyer) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitflyer) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bitflyer) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -68,10 +68,7 @@ func (b *Bithumb) GetTradablePairs() ([]string, error) {
|
||||
// symbol e.g. "btc"
|
||||
func (b *Bithumb) GetTicker(symbol string) (Ticker, error) {
|
||||
var response TickerResponse
|
||||
path := b.API.Endpoints.URL +
|
||||
publicTicker +
|
||||
strings.ToUpper(symbol)
|
||||
err := b.SendHTTPRequest(path, &response)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, publicTicker+strings.ToUpper(symbol), &response)
|
||||
if err != nil {
|
||||
return response.Data, err
|
||||
}
|
||||
@@ -86,8 +83,7 @@ func (b *Bithumb) GetTicker(symbol string) (Ticker, error) {
|
||||
// GetAllTickers returns all ticker information
|
||||
func (b *Bithumb) GetAllTickers() (map[string]Ticker, error) {
|
||||
var response TickersResponse
|
||||
path := b.API.Endpoints.URL + publicTicker + "all"
|
||||
err := b.SendHTTPRequest(path, &response)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, publicTicker+"all", &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -116,9 +112,7 @@ func (b *Bithumb) GetAllTickers() (map[string]Ticker, error) {
|
||||
// symbol e.g. "btc"
|
||||
func (b *Bithumb) GetOrderBook(symbol string) (Orderbook, error) {
|
||||
response := Orderbook{}
|
||||
path := b.API.Endpoints.URL + publicOrderBook + strings.ToUpper(symbol)
|
||||
|
||||
err := b.SendHTTPRequest(path, &response)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, publicOrderBook+strings.ToUpper(symbol), &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -135,11 +129,10 @@ func (b *Bithumb) GetOrderBook(symbol string) (Orderbook, error) {
|
||||
// symbol e.g. "btc"
|
||||
func (b *Bithumb) GetTransactionHistory(symbol string) (TransactionHistory, error) {
|
||||
response := TransactionHistory{}
|
||||
path := b.API.Endpoints.URL +
|
||||
publicTransactionHistory +
|
||||
path := publicTransactionHistory +
|
||||
strings.ToUpper(symbol)
|
||||
|
||||
err := b.SendHTTPRequest(path, &response)
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -166,7 +159,7 @@ func (b *Bithumb) GetAccountInformation(orderCurrency, paymentCurrency string) (
|
||||
}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateAccInfo, val, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateAccInfo, val, &response)
|
||||
}
|
||||
|
||||
// GetAccountBalance returns customer wallet information
|
||||
@@ -185,7 +178,7 @@ func (b *Bithumb) GetAccountBalance(c string) (FullBalance, error) {
|
||||
vals.Set("currency", c)
|
||||
}
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequest(privateAccBalance, vals, &response)
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateAccBalance, vals, &response)
|
||||
if err != nil {
|
||||
return fullBalance, err
|
||||
}
|
||||
@@ -238,7 +231,7 @@ func (b *Bithumb) GetWalletAddress(currency string) (WalletAddressRes, error) {
|
||||
params := url.Values{}
|
||||
params.Set("currency", strings.ToUpper(currency))
|
||||
|
||||
err := b.SendAuthenticatedHTTPRequest(privateWalletAdd, params, &response)
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateWalletAdd, params, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -257,7 +250,7 @@ func (b *Bithumb) GetLastTransaction() (LastTransactionTicker, error) {
|
||||
response := LastTransactionTicker{}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateTicker, nil, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateTicker, nil, &response)
|
||||
}
|
||||
|
||||
// GetOrders returns order list
|
||||
@@ -292,7 +285,7 @@ func (b *Bithumb) GetOrders(orderID, transactionType, count, after, currency str
|
||||
}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateOrders, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateOrders, params, &response)
|
||||
}
|
||||
|
||||
// GetUserTransactions returns customer transactions
|
||||
@@ -300,7 +293,7 @@ func (b *Bithumb) GetUserTransactions() (UserTransactions, error) {
|
||||
response := UserTransactions{}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateUserTrans, nil, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateUserTrans, nil, &response)
|
||||
}
|
||||
|
||||
// PlaceTrade executes a trade order
|
||||
@@ -321,7 +314,7 @@ func (b *Bithumb) PlaceTrade(orderCurrency, transactionType string, units float6
|
||||
params.Set("price", strconv.FormatInt(price, 10))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privatePlaceTrade, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privatePlaceTrade, params, &response)
|
||||
}
|
||||
|
||||
// ModifyTrade modifies an order already on the exchange books
|
||||
@@ -337,7 +330,7 @@ func (b *Bithumb) ModifyTrade(orderID, orderCurrency, transactionType string, un
|
||||
params.Set("order_id", orderID)
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privatePlaceTrade, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privatePlaceTrade, params, &response)
|
||||
}
|
||||
|
||||
// GetOrderDetails returns specific order details
|
||||
@@ -355,7 +348,7 @@ func (b *Bithumb) GetOrderDetails(orderID, transactionType, currency string) (Or
|
||||
params.Set("currency", strings.ToUpper(currency))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateOrderDetail, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateOrderDetail, params, &response)
|
||||
}
|
||||
|
||||
// CancelTrade cancels a customer purchase/sales transaction
|
||||
@@ -372,7 +365,7 @@ func (b *Bithumb) CancelTrade(transactionType, orderID, currency string) (Action
|
||||
params.Set("currency", strings.ToUpper(currency))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateCancelTrade, nil, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateCancelTrade, nil, &response)
|
||||
}
|
||||
|
||||
// WithdrawCrypto withdraws a customer currency to an address
|
||||
@@ -395,7 +388,7 @@ func (b *Bithumb) WithdrawCrypto(address, destination, currency string, units fl
|
||||
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateBTCWithdraw, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateBTCWithdraw, params, &response)
|
||||
}
|
||||
|
||||
// RequestKRWDepositDetails returns Bithumb banking details for deposit
|
||||
@@ -404,7 +397,7 @@ func (b *Bithumb) RequestKRWDepositDetails() (KRWDeposit, error) {
|
||||
response := KRWDeposit{}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateKRWDeposit, nil, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateKRWDeposit, nil, &response)
|
||||
}
|
||||
|
||||
// RequestKRWWithdraw allows a customer KRW withdrawal request
|
||||
@@ -421,7 +414,7 @@ func (b *Bithumb) RequestKRWWithdraw(bank, account string, price int64) (ActionS
|
||||
params.Set("price", strconv.FormatInt(price, 10))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateKRWWithdraw, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateKRWWithdraw, params, &response)
|
||||
}
|
||||
|
||||
// MarketBuyOrder initiates a buy order through available order books
|
||||
@@ -437,7 +430,7 @@ func (b *Bithumb) MarketBuyOrder(currency string, units float64) (MarketBuy, err
|
||||
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateMarketBuy, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateMarketBuy, params, &response)
|
||||
}
|
||||
|
||||
// MarketSellOrder initiates a sell order through available order books
|
||||
@@ -453,14 +446,18 @@ func (b *Bithumb) MarketSellOrder(currency string, units float64) (MarketSell, e
|
||||
params.Set("units", strconv.FormatFloat(units, 'f', -1, 64))
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(privateMarketSell, params, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, privateMarketSell, params, &response)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bithumb) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (b *Bithumb) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -469,11 +466,14 @@ func (b *Bithumb) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bithumb
|
||||
func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, result interface{}) error {
|
||||
func (b *Bithumb) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, params url.Values, result interface{}) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
||||
}
|
||||
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if params == nil {
|
||||
params = url.Values{}
|
||||
}
|
||||
@@ -501,9 +501,9 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, r
|
||||
Message string `json:"message"`
|
||||
}{}
|
||||
|
||||
err := b.SendPayload(context.Background(), &request.Item{
|
||||
err = b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodPost,
|
||||
Path: b.API.Endpoints.URL + path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: bytes.NewBufferString(payload),
|
||||
Result: &intermediary,
|
||||
@@ -608,7 +608,7 @@ var errCode = map[string]string{
|
||||
|
||||
// GetCandleStick returns candle stick data for requested pair
|
||||
func (b *Bithumb) GetCandleStick(symbol, interval string) (resp OHLCVResponse, err error) {
|
||||
path := b.API.Endpoints.URL + publicCandleStick + symbol + "/" + interval
|
||||
err = b.SendHTTPRequest(path, &resp)
|
||||
path := publicCandleStick + symbol + "/" + interval
|
||||
err = b.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -343,8 +343,9 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Side: order.Sell,
|
||||
Type: order.AnyType,
|
||||
Side: order.Sell,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -358,7 +359,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -457,12 +459,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
_, err := b.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("Bithumb GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
_, err := b.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("Bithumb GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ type Ticker struct {
|
||||
PreviousClosingPrice float64 `json:"prev_closing_price,string"`
|
||||
UnitsTraded24Hr float64 `json:"units_traded_24H,string"`
|
||||
AccumulatedTradeValue24hr float64 `json:"acc_trade_value_24H,string"`
|
||||
Fluctate24Hr string `json:"fluctate_24H"`
|
||||
FluctateRate24hr float64 `json:"fluctate_rate_24H,string"`
|
||||
Fluctuate24Hr float64 `json:"fluctate_24H,string"`
|
||||
FluctuateRate24hr float64 `json:"fluctate_rate_24H,string"`
|
||||
Date int64 `json:"date,string"`
|
||||
}
|
||||
|
||||
|
||||
@@ -116,9 +116,13 @@ func (b *Bithumb) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.URLDefault = apiURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: apiURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -204,7 +208,6 @@ func (b *Bithumb) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.P
|
||||
fmt.Errorf("enabled pair %s [%s] not found in returned ticker map %v",
|
||||
pairs[i], pairs, tickers)
|
||||
}
|
||||
|
||||
err = ticker.ProcessTicker(&ticker.Price{
|
||||
High: t.MaxPrice,
|
||||
Low: t.MinPrice,
|
||||
@@ -280,7 +283,7 @@ func (b *Bithumb) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*order
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bithumb exchange
|
||||
func (b *Bithumb) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bithumb) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
bal, err := b.GetAccountBalance("ALL")
|
||||
if err != nil {
|
||||
@@ -316,10 +319,10 @@ func (b *Bithumb) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bithumb) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bithumb) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -680,8 +683,8 @@ func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bithumb) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bithumb) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -33,7 +35,7 @@ const (
|
||||
bitmexEndpointTrollbox = "/chat"
|
||||
bitmexEndpointTrollboxChannels = "/chat/channels"
|
||||
bitmexEndpointTrollboxConnected = "/chat/connected"
|
||||
bitmexEndpointFundingHistory = "/funding"
|
||||
bitmexEndpointFundingHistory = "/funding?"
|
||||
bitmexEndpointInstruments = "/instrument"
|
||||
bitmexEndpointActiveInstruments = "/instrument/active"
|
||||
bitmexEndpointActiveAndIndexInstruments = "/instrument/activeAndIndices"
|
||||
@@ -106,7 +108,7 @@ const (
|
||||
func (b *Bitmex) GetAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendHTTPRequest(bitmexEndpointAnnouncement,
|
||||
return announcement, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointAnnouncement,
|
||||
nil,
|
||||
&announcement)
|
||||
}
|
||||
@@ -115,7 +117,7 @@ func (b *Bitmex) GetAnnouncement() ([]Announcement, error) {
|
||||
func (b *Bitmex) GetUrgentAnnouncement() ([]Announcement, error) {
|
||||
var announcement []Announcement
|
||||
|
||||
return announcement, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return announcement, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointAnnouncementUrgent,
|
||||
nil,
|
||||
&announcement)
|
||||
@@ -125,7 +127,7 @@ func (b *Bitmex) GetUrgentAnnouncement() ([]Announcement, error) {
|
||||
func (b *Bitmex) GetAPIKeys() ([]APIKey, error) {
|
||||
var keys []APIKey
|
||||
|
||||
return keys, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return keys, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointAPIkeys,
|
||||
nil,
|
||||
&keys)
|
||||
@@ -135,7 +137,7 @@ func (b *Bitmex) GetAPIKeys() ([]APIKey, error) {
|
||||
func (b *Bitmex) RemoveAPIKey(params APIKeyParams) (bool, error) {
|
||||
var keyDeleted bool
|
||||
|
||||
return keyDeleted, b.SendAuthenticatedHTTPRequest(http.MethodDelete,
|
||||
return keyDeleted, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete,
|
||||
bitmexEndpointAPIkeys,
|
||||
¶ms,
|
||||
&keyDeleted)
|
||||
@@ -145,7 +147,7 @@ func (b *Bitmex) RemoveAPIKey(params APIKeyParams) (bool, error) {
|
||||
func (b *Bitmex) DisableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointDisableAPIkey,
|
||||
¶ms,
|
||||
&keyInfo)
|
||||
@@ -155,7 +157,7 @@ func (b *Bitmex) DisableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
func (b *Bitmex) EnableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
var keyInfo APIKey
|
||||
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return keyInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointEnableAPIkey,
|
||||
¶ms,
|
||||
&keyInfo)
|
||||
@@ -165,14 +167,14 @@ func (b *Bitmex) EnableAPIKey(params APIKeyParams) (APIKey, error) {
|
||||
func (b *Bitmex) GetTrollboxMessages(params ChatGetParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendHTTPRequest(bitmexEndpointTrollbox, ¶ms, &messages)
|
||||
return messages, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointTrollbox, ¶ms, &messages)
|
||||
}
|
||||
|
||||
// SendTrollboxMessage sends a message to the bitmex trollbox
|
||||
func (b *Bitmex) SendTrollboxMessage(params ChatSendParams) ([]Chat, error) {
|
||||
var messages []Chat
|
||||
|
||||
return messages, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return messages, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointTrollboxSend,
|
||||
¶ms,
|
||||
&messages)
|
||||
@@ -182,7 +184,7 @@ func (b *Bitmex) SendTrollboxMessage(params ChatSendParams) ([]Chat, error) {
|
||||
func (b *Bitmex) GetTrollboxChannels() ([]ChatChannel, error) {
|
||||
var channels []ChatChannel
|
||||
|
||||
return channels, b.SendHTTPRequest(bitmexEndpointTrollboxChannels,
|
||||
return channels, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointTrollboxChannels,
|
||||
nil,
|
||||
&channels)
|
||||
}
|
||||
@@ -191,7 +193,7 @@ func (b *Bitmex) GetTrollboxChannels() ([]ChatChannel, error) {
|
||||
func (b *Bitmex) GetTrollboxConnectedUsers() (ConnectedUsers, error) {
|
||||
var users ConnectedUsers
|
||||
|
||||
return users, b.SendHTTPRequest(bitmexEndpointTrollboxConnected, nil, &users)
|
||||
return users, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointTrollboxConnected, nil, &users)
|
||||
}
|
||||
|
||||
// GetAccountExecutions returns all raw transactions, which includes order
|
||||
@@ -200,7 +202,7 @@ func (b *Bitmex) GetTrollboxConnectedUsers() (ConnectedUsers, error) {
|
||||
func (b *Bitmex) GetAccountExecutions(params *GenericRequestParams) ([]Execution, error) {
|
||||
var executionList []Execution
|
||||
|
||||
return executionList, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return executionList, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointExecution,
|
||||
params,
|
||||
&executionList)
|
||||
@@ -211,17 +213,33 @@ func (b *Bitmex) GetAccountExecutions(params *GenericRequestParams) ([]Execution
|
||||
func (b *Bitmex) GetAccountExecutionTradeHistory(params *GenericRequestParams) ([]Execution, error) {
|
||||
var tradeHistory []Execution
|
||||
|
||||
return tradeHistory, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return tradeHistory, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointExecutionTradeHistory,
|
||||
params,
|
||||
&tradeHistory)
|
||||
}
|
||||
|
||||
// GetFullFundingHistory returns funding history
|
||||
func (b *Bitmex) GetFullFundingHistory() ([]Funding, error) {
|
||||
func (b *Bitmex) GetFullFundingHistory(symbol, count, filter, columns, start string, reverse bool, startTime, endTime time.Time) ([]Funding, error) {
|
||||
var fundingHistory []Funding
|
||||
|
||||
return fundingHistory, b.SendHTTPRequest(bitmexEndpointFundingHistory,
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("count", count)
|
||||
params.Set("filter", filter)
|
||||
params.Set("columns", columns)
|
||||
params.Set("start", start)
|
||||
params.Set("reverse", "true")
|
||||
if !reverse {
|
||||
params.Set("reverse", "false")
|
||||
}
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("startTime", startTime.Format(time.RFC3339))
|
||||
params.Set("endTime", endTime.Format(time.RFC3339))
|
||||
}
|
||||
return fundingHistory, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointFundingHistory+params.Encode(),
|
||||
nil,
|
||||
&fundingHistory)
|
||||
}
|
||||
@@ -230,7 +248,7 @@ func (b *Bitmex) GetFullFundingHistory() ([]Funding, error) {
|
||||
func (b *Bitmex) GetInstruments(params *GenericRequestParams) ([]Instrument, error) {
|
||||
var instruments []Instrument
|
||||
|
||||
return instruments, b.SendHTTPRequest(bitmexEndpointInstruments,
|
||||
return instruments, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointInstruments,
|
||||
params,
|
||||
&instruments)
|
||||
}
|
||||
@@ -239,7 +257,7 @@ func (b *Bitmex) GetInstruments(params *GenericRequestParams) ([]Instrument, err
|
||||
func (b *Bitmex) GetActiveInstruments(params *GenericRequestParams) ([]Instrument, error) {
|
||||
var activeInstruments []Instrument
|
||||
|
||||
return activeInstruments, b.SendHTTPRequest(bitmexEndpointActiveInstruments,
|
||||
return activeInstruments, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointActiveInstruments,
|
||||
params,
|
||||
&activeInstruments)
|
||||
}
|
||||
@@ -249,7 +267,7 @@ func (b *Bitmex) GetActiveAndIndexInstruments() ([]Instrument, error) {
|
||||
var activeAndIndices []Instrument
|
||||
|
||||
return activeAndIndices,
|
||||
b.SendHTTPRequest(bitmexEndpointActiveAndIndexInstruments,
|
||||
b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointActiveAndIndexInstruments,
|
||||
nil,
|
||||
&activeAndIndices)
|
||||
}
|
||||
@@ -258,17 +276,40 @@ func (b *Bitmex) GetActiveAndIndexInstruments() ([]Instrument, error) {
|
||||
func (b *Bitmex) GetActiveIntervals() (InstrumentInterval, error) {
|
||||
var interval InstrumentInterval
|
||||
|
||||
return interval, b.SendHTTPRequest(bitmexEndpointActiveIntervals,
|
||||
return interval, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointActiveIntervals,
|
||||
nil,
|
||||
&interval)
|
||||
}
|
||||
|
||||
// GetCompositeIndex returns composite index
|
||||
func (b *Bitmex) GetCompositeIndex(params *GenericRequestParams) ([]IndexComposite, error) {
|
||||
func (b *Bitmex) GetCompositeIndex(symbol, count, filter, columns, start, reverse string, startTime, endTime time.Time) ([]IndexComposite, error) {
|
||||
var compositeIndices []IndexComposite
|
||||
|
||||
return compositeIndices, b.SendHTTPRequest(bitmexEndpointCompositeIndex,
|
||||
params,
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
if count != "" {
|
||||
params.Set("count", count)
|
||||
}
|
||||
if filter != "" {
|
||||
params.Set("filter", filter)
|
||||
}
|
||||
if columns != "" {
|
||||
params.Set("columns", columns)
|
||||
}
|
||||
if start != "" {
|
||||
params.Set("start", start)
|
||||
}
|
||||
if reverse != "" {
|
||||
params.Set("reverse", "true")
|
||||
}
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("startTime", startTime.Format(time.RFC3339))
|
||||
params.Set("endTime", endTime.Format(time.RFC3339))
|
||||
}
|
||||
return compositeIndices, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointCompositeIndex+"?"+params.Encode(),
|
||||
nil,
|
||||
&compositeIndices)
|
||||
}
|
||||
|
||||
@@ -276,35 +317,35 @@ func (b *Bitmex) GetCompositeIndex(params *GenericRequestParams) ([]IndexComposi
|
||||
func (b *Bitmex) GetIndices() ([]Instrument, error) {
|
||||
var indices []Instrument
|
||||
|
||||
return indices, b.SendHTTPRequest(bitmexEndpointIndices, nil, &indices)
|
||||
return indices, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointIndices, nil, &indices)
|
||||
}
|
||||
|
||||
// GetInsuranceFundHistory returns insurance fund history
|
||||
func (b *Bitmex) GetInsuranceFundHistory(params *GenericRequestParams) ([]Insurance, error) {
|
||||
var history []Insurance
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointIndices, params, &history)
|
||||
return history, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointIndices, params, &history)
|
||||
}
|
||||
|
||||
// GetLeaderboard returns leaderboard information
|
||||
func (b *Bitmex) GetLeaderboard(params LeaderboardGetParams) ([]Leaderboard, error) {
|
||||
var leader []Leaderboard
|
||||
|
||||
return leader, b.SendHTTPRequest(bitmexEndpointLeader, params, &leader)
|
||||
return leader, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointLeader, params, &leader)
|
||||
}
|
||||
|
||||
// GetAliasOnLeaderboard returns your alias on the leaderboard
|
||||
func (b *Bitmex) GetAliasOnLeaderboard() (Alias, error) {
|
||||
var alias Alias
|
||||
|
||||
return alias, b.SendHTTPRequest(bitmexEndpointAlias, nil, &alias)
|
||||
return alias, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointAlias, nil, &alias)
|
||||
}
|
||||
|
||||
// GetLiquidationOrders returns liquidation orders
|
||||
func (b *Bitmex) GetLiquidationOrders(params *GenericRequestParams) ([]Liquidation, error) {
|
||||
var orders []Liquidation
|
||||
|
||||
return orders, b.SendHTTPRequest(bitmexEndpointLiquidation,
|
||||
return orders, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointLiquidation,
|
||||
params,
|
||||
&orders)
|
||||
}
|
||||
@@ -313,7 +354,7 @@ func (b *Bitmex) GetLiquidationOrders(params *GenericRequestParams) ([]Liquidati
|
||||
func (b *Bitmex) GetCurrentNotifications() ([]Notification, error) {
|
||||
var notifications []Notification
|
||||
|
||||
return notifications, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return notifications, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointNotifications,
|
||||
nil,
|
||||
¬ifications)
|
||||
@@ -322,7 +363,7 @@ func (b *Bitmex) GetCurrentNotifications() ([]Notification, error) {
|
||||
// GetOrders returns all the orders, open and closed
|
||||
func (b *Bitmex) GetOrders(params *OrdersRequest) ([]Order, error) {
|
||||
var orders []Order
|
||||
return orders, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return orders, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&orders)
|
||||
@@ -332,7 +373,7 @@ func (b *Bitmex) GetOrders(params *OrdersRequest) ([]Order, error) {
|
||||
func (b *Bitmex) AmendOrder(params *OrderAmendParams) (Order, error) {
|
||||
var order Order
|
||||
|
||||
return order, b.SendAuthenticatedHTTPRequest(http.MethodPut,
|
||||
return order, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPut,
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&order)
|
||||
@@ -342,7 +383,7 @@ func (b *Bitmex) AmendOrder(params *OrderAmendParams) (Order, error) {
|
||||
func (b *Bitmex) CreateOrder(params *OrderNewParams) (Order, error) {
|
||||
var orderInfo Order
|
||||
|
||||
return orderInfo, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return orderInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&orderInfo)
|
||||
@@ -353,7 +394,7 @@ func (b *Bitmex) CreateOrder(params *OrderNewParams) (Order, error) {
|
||||
func (b *Bitmex) CancelOrders(params *OrderCancelParams) ([]Order, error) {
|
||||
var cancelledOrders []Order
|
||||
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest(http.MethodDelete,
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete,
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&cancelledOrders)
|
||||
@@ -363,7 +404,7 @@ func (b *Bitmex) CancelOrders(params *OrderCancelParams) ([]Order, error) {
|
||||
func (b *Bitmex) CancelAllExistingOrders(params OrderCancelAllParams) ([]Order, error) {
|
||||
var cancelledOrders []Order
|
||||
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest(http.MethodDelete,
|
||||
return cancelledOrders, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete,
|
||||
bitmexEndpointCancelAllOrders,
|
||||
params,
|
||||
&cancelledOrders)
|
||||
@@ -373,7 +414,7 @@ func (b *Bitmex) CancelAllExistingOrders(params OrderCancelAllParams) ([]Order,
|
||||
func (b *Bitmex) AmendBulkOrders(params OrderAmendBulkParams) ([]Order, error) {
|
||||
var amendedOrders []Order
|
||||
|
||||
return amendedOrders, b.SendAuthenticatedHTTPRequest(http.MethodPut,
|
||||
return amendedOrders, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPut,
|
||||
bitmexEndpointBulk,
|
||||
params,
|
||||
&amendedOrders)
|
||||
@@ -383,7 +424,7 @@ func (b *Bitmex) AmendBulkOrders(params OrderAmendBulkParams) ([]Order, error) {
|
||||
func (b *Bitmex) CreateBulkOrders(params OrderNewBulkParams) ([]Order, error) {
|
||||
var orders []Order
|
||||
|
||||
return orders, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return orders, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointBulk,
|
||||
params,
|
||||
&orders)
|
||||
@@ -393,7 +434,7 @@ func (b *Bitmex) CreateBulkOrders(params OrderNewBulkParams) ([]Order, error) {
|
||||
func (b *Bitmex) CancelAllOrdersAfterTime(params OrderCancelAllAfterParams) ([]Order, error) {
|
||||
var cancelledOrder []Order
|
||||
|
||||
return cancelledOrder, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return cancelledOrder, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointCancelOrderAfter,
|
||||
params,
|
||||
&cancelledOrder)
|
||||
@@ -403,7 +444,7 @@ func (b *Bitmex) CancelAllOrdersAfterTime(params OrderCancelAllAfterParams) ([]O
|
||||
func (b *Bitmex) ClosePosition(params OrderClosePositionParams) ([]Order, error) {
|
||||
var closedPositions []Order
|
||||
|
||||
return closedPositions, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return closedPositions, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointOrder,
|
||||
params,
|
||||
&closedPositions)
|
||||
@@ -413,7 +454,7 @@ func (b *Bitmex) ClosePosition(params OrderClosePositionParams) ([]Order, error)
|
||||
func (b *Bitmex) GetOrderbook(params OrderBookGetL2Params) ([]OrderBookL2, error) {
|
||||
var orderBooks []OrderBookL2
|
||||
|
||||
return orderBooks, b.SendHTTPRequest(bitmexEndpointOrderbookL2,
|
||||
return orderBooks, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointOrderbookL2,
|
||||
params,
|
||||
&orderBooks)
|
||||
}
|
||||
@@ -422,7 +463,7 @@ func (b *Bitmex) GetOrderbook(params OrderBookGetL2Params) ([]OrderBookL2, error
|
||||
func (b *Bitmex) GetPositions(params PositionGetParams) ([]Position, error) {
|
||||
var positions []Position
|
||||
|
||||
return positions, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return positions, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointPosition,
|
||||
params,
|
||||
&positions)
|
||||
@@ -432,7 +473,7 @@ func (b *Bitmex) GetPositions(params PositionGetParams) ([]Position, error) {
|
||||
func (b *Bitmex) IsolatePosition(params PositionIsolateMarginParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return position, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointIsolatePosition,
|
||||
params,
|
||||
&position)
|
||||
@@ -442,7 +483,7 @@ func (b *Bitmex) IsolatePosition(params PositionIsolateMarginParams) (Position,
|
||||
func (b *Bitmex) LeveragePosition(params PositionUpdateLeverageParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return position, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointLeveragePosition,
|
||||
params,
|
||||
&position)
|
||||
@@ -452,7 +493,7 @@ func (b *Bitmex) LeveragePosition(params PositionUpdateLeverageParams) (Position
|
||||
func (b *Bitmex) UpdateRiskLimit(params PositionUpdateRiskLimitParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return position, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointAdjustRiskLimit,
|
||||
params,
|
||||
&position)
|
||||
@@ -462,7 +503,7 @@ func (b *Bitmex) UpdateRiskLimit(params PositionUpdateRiskLimitParams) (Position
|
||||
func (b *Bitmex) TransferMargin(params PositionTransferIsolatedMarginParams) (Position, error) {
|
||||
var position Position
|
||||
|
||||
return position, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return position, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointTransferMargin,
|
||||
params,
|
||||
&position)
|
||||
@@ -472,7 +513,7 @@ func (b *Bitmex) TransferMargin(params PositionTransferIsolatedMarginParams) (Po
|
||||
func (b *Bitmex) GetQuotes(params *GenericRequestParams) ([]Quote, error) {
|
||||
var quotations []Quote
|
||||
|
||||
return quotations, b.SendHTTPRequest(bitmexEndpointQuote,
|
||||
return quotations, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointQuote,
|
||||
params,
|
||||
"ations)
|
||||
}
|
||||
@@ -481,7 +522,7 @@ func (b *Bitmex) GetQuotes(params *GenericRequestParams) ([]Quote, error) {
|
||||
func (b *Bitmex) GetQuotesByBuckets(params *QuoteGetBucketedParams) ([]Quote, error) {
|
||||
var quotations []Quote
|
||||
|
||||
return quotations, b.SendHTTPRequest(bitmexEndpointQuoteBucketed,
|
||||
return quotations, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointQuoteBucketed,
|
||||
params,
|
||||
"ations)
|
||||
}
|
||||
@@ -490,7 +531,7 @@ func (b *Bitmex) GetQuotesByBuckets(params *QuoteGetBucketedParams) ([]Quote, er
|
||||
func (b *Bitmex) GetSettlementHistory(params *GenericRequestParams) ([]Settlement, error) {
|
||||
var history []Settlement
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointSettlement,
|
||||
return history, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointSettlement,
|
||||
params,
|
||||
&history)
|
||||
}
|
||||
@@ -499,35 +540,35 @@ func (b *Bitmex) GetSettlementHistory(params *GenericRequestParams) ([]Settlemen
|
||||
func (b *Bitmex) GetStats() ([]Stats, error) {
|
||||
var stats []Stats
|
||||
|
||||
return stats, b.SendHTTPRequest(bitmexEndpointStats, nil, &stats)
|
||||
return stats, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointStats, nil, &stats)
|
||||
}
|
||||
|
||||
// GetStatsHistorical historic stats
|
||||
func (b *Bitmex) GetStatsHistorical() ([]StatsHistory, error) {
|
||||
var history []StatsHistory
|
||||
|
||||
return history, b.SendHTTPRequest(bitmexEndpointStatsHistory, nil, &history)
|
||||
return history, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointStatsHistory, nil, &history)
|
||||
}
|
||||
|
||||
// GetStatSummary returns the stats summary in USD terms
|
||||
func (b *Bitmex) GetStatSummary() ([]StatsUSD, error) {
|
||||
var summary []StatsUSD
|
||||
|
||||
return summary, b.SendHTTPRequest(bitmexEndpointStatsSummary, nil, &summary)
|
||||
return summary, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointStatsSummary, nil, &summary)
|
||||
}
|
||||
|
||||
// GetTrade returns executed trades on the desk
|
||||
func (b *Bitmex) GetTrade(params *GenericRequestParams) ([]Trade, error) {
|
||||
var trade []Trade
|
||||
|
||||
return trade, b.SendHTTPRequest(bitmexEndpointTrade, params, &trade)
|
||||
return trade, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointTrade, params, &trade)
|
||||
}
|
||||
|
||||
// GetPreviousTrades previous trade history in time buckets
|
||||
func (b *Bitmex) GetPreviousTrades(params *TradeGetBucketedParams) ([]Trade, error) {
|
||||
var trade []Trade
|
||||
|
||||
return trade, b.SendHTTPRequest(bitmexEndpointTradeBucketed,
|
||||
return trade, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointTradeBucketed,
|
||||
params,
|
||||
&trade)
|
||||
}
|
||||
@@ -536,7 +577,7 @@ func (b *Bitmex) GetPreviousTrades(params *TradeGetBucketedParams) ([]Trade, err
|
||||
func (b *Bitmex) GetUserInfo() (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUser,
|
||||
nil,
|
||||
&userInfo)
|
||||
@@ -546,7 +587,7 @@ func (b *Bitmex) GetUserInfo() (User, error) {
|
||||
func (b *Bitmex) UpdateUserInfo(params *UserUpdateParams) (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(http.MethodPut,
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPut,
|
||||
bitmexEndpointUser,
|
||||
params,
|
||||
&userInfo)
|
||||
@@ -556,7 +597,7 @@ func (b *Bitmex) UpdateUserInfo(params *UserUpdateParams) (User, error) {
|
||||
func (b *Bitmex) GetAffiliateStatus() (AffiliateStatus, error) {
|
||||
var status AffiliateStatus
|
||||
|
||||
return status, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return status, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserAffiliate,
|
||||
nil,
|
||||
&status)
|
||||
@@ -566,7 +607,7 @@ func (b *Bitmex) GetAffiliateStatus() (AffiliateStatus, error) {
|
||||
func (b *Bitmex) CancelWithdraw(token string) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserCancelWithdraw,
|
||||
UserTokenParams{Token: token},
|
||||
&info)
|
||||
@@ -577,7 +618,7 @@ func (b *Bitmex) CancelWithdraw(token string) (TransactionInfo, error) {
|
||||
func (b *Bitmex) CheckReferalCode(referralCode string) (float64, error) {
|
||||
var percentage float64
|
||||
|
||||
return percentage, b.SendHTTPRequest(bitmexEndpointUserCheckReferralCode,
|
||||
return percentage, b.SendHTTPRequest(exchange.RestSpot, bitmexEndpointUserCheckReferralCode,
|
||||
UserCheckReferralCodeParams{ReferralCode: referralCode},
|
||||
&percentage)
|
||||
}
|
||||
@@ -586,7 +627,7 @@ func (b *Bitmex) CheckReferalCode(referralCode string) (float64, error) {
|
||||
func (b *Bitmex) GetUserCommision() (UserCommission, error) {
|
||||
var commissionInfo UserCommission
|
||||
|
||||
return commissionInfo, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return commissionInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserCommision,
|
||||
nil,
|
||||
&commissionInfo)
|
||||
@@ -596,7 +637,7 @@ func (b *Bitmex) GetUserCommision() (UserCommission, error) {
|
||||
func (b *Bitmex) ConfirmEmail(token string) (ConfirmEmail, error) {
|
||||
var confirmation ConfirmEmail
|
||||
|
||||
return confirmation, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return confirmation, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserConfirmEmail,
|
||||
UserTokenParams{Token: token},
|
||||
&confirmation)
|
||||
@@ -606,7 +647,7 @@ func (b *Bitmex) ConfirmEmail(token string) (ConfirmEmail, error) {
|
||||
func (b *Bitmex) ConfirmTwoFactorAuth(token, typ string) (bool, error) {
|
||||
var working bool
|
||||
|
||||
return working, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return working, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserConfirmTFA,
|
||||
UserConfirmTFAParams{Token: token, Type: typ},
|
||||
&working)
|
||||
@@ -616,7 +657,7 @@ func (b *Bitmex) ConfirmTwoFactorAuth(token, typ string) (bool, error) {
|
||||
func (b *Bitmex) ConfirmWithdrawal(token string) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserCancelWithdraw,
|
||||
UserTokenParams{Token: token},
|
||||
&info)
|
||||
@@ -632,7 +673,7 @@ func (b *Bitmex) GetCryptoDepositAddress(cryptoCurrency string) (string, error)
|
||||
cryptoCurrency)
|
||||
}
|
||||
|
||||
return address, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return address, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserDepositAddress,
|
||||
UserCurrencyParams{Currency: "XBt"},
|
||||
&address)
|
||||
@@ -642,7 +683,7 @@ func (b *Bitmex) GetCryptoDepositAddress(cryptoCurrency string) (string, error)
|
||||
func (b *Bitmex) DisableTFA(token, typ string) (bool, error) {
|
||||
var disabled bool
|
||||
|
||||
return disabled, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return disabled, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserDisableTFA,
|
||||
UserConfirmTFAParams{Token: token, Type: typ},
|
||||
&disabled)
|
||||
@@ -650,7 +691,7 @@ func (b *Bitmex) DisableTFA(token, typ string) (bool, error) {
|
||||
|
||||
// UserLogOut logs you out of BitMEX
|
||||
func (b *Bitmex) UserLogOut() error {
|
||||
return b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserLogout,
|
||||
nil,
|
||||
nil)
|
||||
@@ -660,7 +701,7 @@ func (b *Bitmex) UserLogOut() error {
|
||||
func (b *Bitmex) UserLogOutAll() (int64, error) {
|
||||
var status int64
|
||||
|
||||
return status, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return status, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserLogoutAll,
|
||||
nil,
|
||||
&status)
|
||||
@@ -670,7 +711,7 @@ func (b *Bitmex) UserLogOutAll() (int64, error) {
|
||||
func (b *Bitmex) GetUserMargin(currency string) (UserMargin, error) {
|
||||
var info UserMargin
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserMargin,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
@@ -680,7 +721,7 @@ func (b *Bitmex) GetUserMargin(currency string) (UserMargin, error) {
|
||||
func (b *Bitmex) GetAllUserMargin() ([]UserMargin, error) {
|
||||
var info []UserMargin
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserMargin,
|
||||
UserCurrencyParams{Currency: "all"},
|
||||
&info)
|
||||
@@ -690,7 +731,7 @@ func (b *Bitmex) GetAllUserMargin() ([]UserMargin, error) {
|
||||
func (b *Bitmex) GetMinimumWithdrawalFee(currency string) (MinWithdrawalFee, error) {
|
||||
var fee MinWithdrawalFee
|
||||
|
||||
return fee, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return fee, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserMinWithdrawalFee,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&fee)
|
||||
@@ -700,7 +741,7 @@ func (b *Bitmex) GetMinimumWithdrawalFee(currency string) (MinWithdrawalFee, err
|
||||
func (b *Bitmex) GetUserPreferences(params UserPreferencesParams) (User, error) {
|
||||
var userInfo User
|
||||
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return userInfo, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserPreferences,
|
||||
params,
|
||||
&userInfo)
|
||||
@@ -710,7 +751,7 @@ func (b *Bitmex) GetUserPreferences(params UserPreferencesParams) (User, error)
|
||||
func (b *Bitmex) EnableTFA(typ string) (bool, error) {
|
||||
var enabled bool
|
||||
|
||||
return enabled, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return enabled, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserRequestTFA,
|
||||
UserConfirmTFAParams{Type: typ},
|
||||
&enabled)
|
||||
@@ -722,7 +763,7 @@ func (b *Bitmex) EnableTFA(typ string) (bool, error) {
|
||||
func (b *Bitmex) UserRequestWithdrawal(params UserRequestWithdrawalParams) (TransactionInfo, error) {
|
||||
var info TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
bitmexEndpointUserRequestWithdraw,
|
||||
params,
|
||||
&info)
|
||||
@@ -732,7 +773,7 @@ func (b *Bitmex) UserRequestWithdrawal(params UserRequestWithdrawalParams) (Tran
|
||||
func (b *Bitmex) GetWalletInfo(currency string) (WalletInfo, error) {
|
||||
var info WalletInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserWallet,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
@@ -742,7 +783,7 @@ func (b *Bitmex) GetWalletInfo(currency string) (WalletInfo, error) {
|
||||
func (b *Bitmex) GetWalletHistory(currency string) ([]TransactionInfo, error) {
|
||||
var info []TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserWalletHistory,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
@@ -752,19 +793,24 @@ func (b *Bitmex) GetWalletHistory(currency string) ([]TransactionInfo, error) {
|
||||
func (b *Bitmex) GetWalletSummary(currency string) ([]TransactionInfo, error) {
|
||||
var info []TransactionInfo
|
||||
|
||||
return info, b.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return info, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
bitmexEndpointUserWalletSummary,
|
||||
UserCurrencyParams{Currency: currency},
|
||||
&info)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bitmex) SendHTTPRequest(path string, params Parameter, result interface{}) error {
|
||||
func (b *Bitmex) SendHTTPRequest(ep exchange.URL, path string, params Parameter, result interface{}) error {
|
||||
var respCheck interface{}
|
||||
path = b.API.Endpoints.URL + path
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path = endpoint + path
|
||||
if params != nil {
|
||||
var encodedPath string
|
||||
if !params.IsNil() {
|
||||
encodedPath, err := params.ToURLVals(path)
|
||||
encodedPath, err = params.ToURLVals(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -782,7 +828,8 @@ func (b *Bitmex) SendHTTPRequest(path string, params Parameter, result interface
|
||||
return b.CaptureError(respCheck, result)
|
||||
}
|
||||
}
|
||||
err := b.SendPayload(context.Background(), &request.Item{
|
||||
|
||||
err = b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Result: &respCheck,
|
||||
@@ -793,16 +840,20 @@ func (b *Bitmex) SendHTTPRequest(path string, params Parameter, result interface
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.CaptureError(respCheck, result)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex
|
||||
func (b *Bitmex) SendAuthenticatedHTTPRequest(verb, path string, params Parameter, result interface{}) error {
|
||||
func (b *Bitmex) SendAuthenticatedHTTPRequest(ep exchange.URL, verb, path string, params Parameter, result interface{}) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
b.Name)
|
||||
}
|
||||
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
expires := time.Now().Add(time.Second * 10)
|
||||
timestamp := expires.UnixNano()
|
||||
timestampStr := strconv.FormatInt(timestamp, 10)
|
||||
@@ -815,11 +866,12 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(verb, path string, params Paramete
|
||||
|
||||
var payload string
|
||||
if params != nil {
|
||||
err := params.VerifyData()
|
||||
err = params.VerifyData()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.Marshal(params)
|
||||
var data []byte
|
||||
data, err = json.Marshal(params)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -836,9 +888,9 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(verb, path string, params Paramete
|
||||
|
||||
ctx, cancel := context.WithDeadline(context.Background(), expires)
|
||||
defer cancel()
|
||||
err := b.SendPayload(ctx, &request.Item{
|
||||
err = b.SendPayload(ctx, &request.Item{
|
||||
Method: verb,
|
||||
Path: b.API.Endpoints.URL + path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: bytes.NewBuffer([]byte(payload)),
|
||||
Result: &respCheck,
|
||||
|
||||
@@ -56,12 +56,32 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
t.Parallel()
|
||||
var testWg sync.WaitGroup
|
||||
b.Start(&testWg)
|
||||
testWg.Wait()
|
||||
}
|
||||
|
||||
func TestGetFullFundingHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetFullFundingHistory("", "", "", "", "", true, time.Time{}, time.Time{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetFullFundingHistory("", "", "", "", "", true, time.Now().Add(-time.Hour*8), time.Now())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
_, err = b.GetFullFundingHistory("LTCUSD", "1", "", "", "", true, time.Now().Add(time.Hour*-24), time.Now())
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUrgentAnnouncement(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetUrgentAnnouncement()
|
||||
if err == nil {
|
||||
t.Error("GetUrgentAnnouncement() Expected error")
|
||||
@@ -69,6 +89,7 @@ func TestGetUrgentAnnouncement(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAPIKeys(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAPIKeys()
|
||||
if err == nil {
|
||||
t.Error("GetAPIKeys() Expected error")
|
||||
@@ -76,6 +97,7 @@ func TestGetAPIKeys(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRemoveAPIKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.RemoveAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("RemoveAPIKey() Expected error")
|
||||
@@ -83,6 +105,7 @@ func TestRemoveAPIKey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDisableAPIKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.DisableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("DisableAPIKey() Expected error")
|
||||
@@ -90,6 +113,7 @@ func TestDisableAPIKey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestEnableAPIKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.EnableAPIKey(APIKeyParams{APIKeyID: "1337"})
|
||||
if err == nil {
|
||||
t.Error("EnableAPIKey() Expected error")
|
||||
@@ -97,6 +121,7 @@ func TestEnableAPIKey(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrollboxMessages(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTrollboxMessages(ChatGetParams{Count: 5})
|
||||
if err != nil {
|
||||
t.Error("GetTrollboxMessages() error", err)
|
||||
@@ -104,6 +129,7 @@ func TestGetTrollboxMessages(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSendTrollboxMessage(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.SendTrollboxMessage(ChatSendParams{
|
||||
ChannelID: 1337,
|
||||
Message: "Hello,World!"})
|
||||
@@ -113,6 +139,7 @@ func TestSendTrollboxMessage(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrollboxChannels(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTrollboxChannels()
|
||||
if err != nil {
|
||||
t.Error("GetTrollboxChannels() error", err)
|
||||
@@ -120,6 +147,7 @@ func TestGetTrollboxChannels(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrollboxConnectedUsers(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTrollboxConnectedUsers()
|
||||
if err == nil {
|
||||
t.Error("GetTrollboxConnectedUsers() Expected error")
|
||||
@@ -127,6 +155,7 @@ func TestGetTrollboxConnectedUsers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountExecutions(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAccountExecutions(&GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("GetAccountExecutions() Expected error")
|
||||
@@ -134,6 +163,7 @@ func TestGetAccountExecutions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountExecutionTradeHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAccountExecutionTradeHistory(&GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("GetAccountExecutionTradeHistory() Expected error")
|
||||
@@ -141,6 +171,7 @@ func TestGetAccountExecutionTradeHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFundingHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetFundingHistory()
|
||||
if err == nil {
|
||||
t.Error("GetFundingHistory() Expected error")
|
||||
@@ -148,6 +179,7 @@ func TestGetFundingHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetInstruments(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetInstruments(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("GetInstruments() error", err)
|
||||
@@ -155,6 +187,7 @@ func TestGetInstruments(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveInstruments(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetActiveInstruments(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("GetActiveInstruments() error", err)
|
||||
@@ -162,6 +195,7 @@ func TestGetActiveInstruments(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveAndIndexInstruments(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetActiveAndIndexInstruments()
|
||||
if err != nil {
|
||||
t.Error("GetActiveAndIndexInstruments() error", err)
|
||||
@@ -169,6 +203,7 @@ func TestGetActiveAndIndexInstruments(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveIntervals(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetActiveIntervals()
|
||||
if err == nil {
|
||||
t.Error("GetActiveIntervals() Expected error")
|
||||
@@ -176,13 +211,15 @@ func TestGetActiveIntervals(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCompositeIndex(t *testing.T) {
|
||||
_, err := b.GetCompositeIndex(&GenericRequestParams{})
|
||||
if err == nil {
|
||||
t.Error("GetCompositeIndex() Expected error")
|
||||
t.Parallel()
|
||||
_, err := b.GetCompositeIndex(".XBT", "", "", "", "", "", time.Time{}, time.Time{})
|
||||
if err != nil {
|
||||
t.Error("GetCompositeIndex() Expected error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetIndices(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetIndices()
|
||||
if err != nil {
|
||||
t.Error("GetIndices() error", err)
|
||||
@@ -190,6 +227,7 @@ func TestGetIndices(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetInsuranceFundHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetInsuranceFundHistory(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("GetInsuranceFundHistory() error", err)
|
||||
@@ -197,6 +235,7 @@ func TestGetInsuranceFundHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetLeaderboard(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetLeaderboard(LeaderboardGetParams{})
|
||||
if err != nil {
|
||||
t.Error("GetLeaderboard() error", err)
|
||||
@@ -204,6 +243,7 @@ func TestGetLeaderboard(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAliasOnLeaderboard(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetAliasOnLeaderboard()
|
||||
if err == nil {
|
||||
t.Error("GetAliasOnLeaderboard() Expected error")
|
||||
@@ -211,6 +251,7 @@ func TestGetAliasOnLeaderboard(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetLiquidationOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetLiquidationOrders(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("GetLiquidationOrders() error", err)
|
||||
@@ -218,6 +259,7 @@ func TestGetLiquidationOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetCurrentNotifications(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetCurrentNotifications()
|
||||
if err == nil {
|
||||
t.Error("GetCurrentNotifications() Expected error")
|
||||
@@ -225,6 +267,7 @@ func TestGetCurrentNotifications(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAmendOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.AmendOrder(&OrderAmendParams{})
|
||||
if err == nil {
|
||||
t.Error("AmendOrder() Expected error")
|
||||
@@ -232,6 +275,7 @@ func TestAmendOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CreateOrder(&OrderNewParams{Symbol: "XBTM15",
|
||||
Price: 219.0,
|
||||
ClientOrderID: "mm_bitmex_1a/oemUeQ4CAJZgP3fjHsA",
|
||||
@@ -242,6 +286,7 @@ func TestCreateOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CancelOrders(&OrderCancelParams{})
|
||||
if err == nil {
|
||||
t.Error("CancelOrders() Expected error")
|
||||
@@ -249,6 +294,7 @@ func TestCancelOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CancelAllExistingOrders(OrderCancelAllParams{})
|
||||
if err == nil {
|
||||
t.Error("CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error)", err)
|
||||
@@ -256,6 +302,7 @@ func TestCancelAllOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAmendBulkOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.AmendBulkOrders(OrderAmendBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("AmendBulkOrders() Expected error")
|
||||
@@ -263,6 +310,7 @@ func TestAmendBulkOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateBulkOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CreateBulkOrders(OrderNewBulkParams{})
|
||||
if err == nil {
|
||||
t.Error("CreateBulkOrders() Expected error")
|
||||
@@ -270,6 +318,7 @@ func TestCreateBulkOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllOrdersAfterTime(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.CancelAllOrdersAfterTime(OrderCancelAllAfterParams{})
|
||||
if err == nil {
|
||||
t.Error("CancelAllOrdersAfterTime() Expected error")
|
||||
@@ -277,6 +326,7 @@ func TestCancelAllOrdersAfterTime(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClosePosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.ClosePosition(OrderClosePositionParams{})
|
||||
if err == nil {
|
||||
t.Error("ClosePosition() Expected error")
|
||||
@@ -284,6 +334,7 @@ func TestClosePosition(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetOrderbook(OrderBookGetL2Params{Symbol: "XBT"})
|
||||
if err != nil {
|
||||
t.Error("GetOrderbook() error", err)
|
||||
@@ -291,6 +342,7 @@ func TestGetOrderbook(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetPositions(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetPositions(PositionGetParams{})
|
||||
if err == nil {
|
||||
t.Error("GetPositions() Expected error")
|
||||
@@ -298,6 +350,7 @@ func TestGetPositions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestIsolatePosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.IsolatePosition(PositionIsolateMarginParams{Symbol: "XBT"})
|
||||
if err == nil {
|
||||
t.Error("IsolatePosition() Expected error")
|
||||
@@ -305,6 +358,7 @@ func TestIsolatePosition(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLeveragePosition(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.LeveragePosition(PositionUpdateLeverageParams{})
|
||||
if err == nil {
|
||||
t.Error("LeveragePosition() Expected error")
|
||||
@@ -312,6 +366,7 @@ func TestLeveragePosition(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateRiskLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.UpdateRiskLimit(PositionUpdateRiskLimitParams{})
|
||||
if err == nil {
|
||||
t.Error("UpdateRiskLimit() Expected error")
|
||||
@@ -319,6 +374,7 @@ func TestUpdateRiskLimit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTransferMargin(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.TransferMargin(PositionTransferIsolatedMarginParams{})
|
||||
if err == nil {
|
||||
t.Error("TransferMargin() Expected error")
|
||||
@@ -326,6 +382,7 @@ func TestTransferMargin(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetQuotesByBuckets(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetQuotesByBuckets(&QuoteGetBucketedParams{})
|
||||
if err == nil {
|
||||
t.Error("GetQuotesByBuckets() Expected error")
|
||||
@@ -333,6 +390,7 @@ func TestGetQuotesByBuckets(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetSettlementHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetSettlementHistory(&GenericRequestParams{})
|
||||
if err != nil {
|
||||
t.Error("GetSettlementHistory() error", err)
|
||||
@@ -340,6 +398,7 @@ func TestGetSettlementHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetStats(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetStats()
|
||||
if err != nil {
|
||||
t.Error("GetStats() error", err)
|
||||
@@ -347,6 +406,7 @@ func TestGetStats(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetStatsHistorical(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetStatsHistorical()
|
||||
if err != nil {
|
||||
t.Error("GetStatsHistorical() error", err)
|
||||
@@ -354,6 +414,7 @@ func TestGetStatsHistorical(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetStatSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetStatSummary()
|
||||
if err != nil {
|
||||
t.Error("GetStatSummary() error", err)
|
||||
@@ -361,6 +422,7 @@ func TestGetStatSummary(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrade(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetTrade(&GenericRequestParams{
|
||||
Symbol: "XBT",
|
||||
Reverse: false,
|
||||
@@ -372,6 +434,7 @@ func TestGetTrade(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetPreviousTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetPreviousTrades(&TradeGetBucketedParams{
|
||||
Symbol: "XBTBTC",
|
||||
Start: int32(time.Now().Add(-time.Hour * 24).Unix()),
|
||||
@@ -393,6 +456,7 @@ func setFeeBuilder() *exchange.FeeBuilder {
|
||||
|
||||
// TestGetFeeByTypeOfflineTradeFee logic test
|
||||
func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
b.GetFeeByType(feeBuilder)
|
||||
if !areTestAPIKeysSet() {
|
||||
@@ -407,6 +471,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
var feeBuilder = setFeeBuilder()
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00075) || err != nil {
|
||||
@@ -475,6 +540,7 @@ func TestGetFee(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawCryptoWith2FAText +
|
||||
" & " + exchange.WithdrawCryptoWithEmailText + " & " + exchange.NoFiatWithdrawalsText
|
||||
withdrawPermissions := b.FormatWithdrawPermissions()
|
||||
@@ -484,8 +550,10 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -497,10 +565,12 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.LTC,
|
||||
currency.BTC)},
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -518,6 +588,7 @@ func areTestAPIKeysSet() bool {
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -543,6 +614,7 @@ func TestSubmitOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -566,6 +638,7 @@ func TestCancelExchangeOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -594,13 +667,14 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
_, err := b.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
_, err := b.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() error")
|
||||
}
|
||||
@@ -608,6 +682,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -618,6 +693,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
withdrawCryptoRequest := withdraw.Request{
|
||||
Crypto: withdraw.CryptoRequest{
|
||||
Address: core.BitcoinDonationAddress,
|
||||
@@ -642,6 +718,7 @@ func TestWithdraw(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -654,6 +731,7 @@ func TestWithdrawFiat(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
@@ -666,6 +744,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := b.GetDepositAddress(currency.BTC, "")
|
||||
if err != nil {
|
||||
@@ -681,6 +760,7 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
|
||||
t.Skip(stream.WebsocketNotEnabled)
|
||||
}
|
||||
@@ -708,6 +788,7 @@ func TestWsAuth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateTradablePairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := b.UpdateTradablePairs(true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -715,6 +796,7 @@ func TestUpdateTradablePairs(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsPositionUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"position",
|
||||
"action":"update",
|
||||
"data":[{
|
||||
@@ -731,6 +813,7 @@ func TestWsPositionUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsInsertExectuionUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"execution",
|
||||
"action":"insert",
|
||||
"data":[{
|
||||
@@ -754,6 +837,7 @@ func TestWsInsertExectuionUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSConnectionHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"info":"Welcome to the BitMEX Realtime API.","version":"1.1.0",
|
||||
"timestamp":"2015-01-18T10:14:06.802Z","docs":"https://www.bitmex.com/app/wsAPI","heartbeatEnabled":false}`)
|
||||
err := b.wsHandleData(pressXToJSON)
|
||||
@@ -763,6 +847,7 @@ func TestWSConnectionHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSSubscriptionHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"success":true,"subscribe":"trade:ETHUSD",
|
||||
"request":{"op":"subscribe","args":["trade:ETHUSD","instrument:ETHUSD"]}}`)
|
||||
err := b.wsHandleData(pressXToJSON)
|
||||
@@ -772,6 +857,7 @@ func TestWSSubscriptionHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSPositionUpdateHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"position",
|
||||
"action":"update",
|
||||
"data":[{
|
||||
@@ -804,6 +890,7 @@ func TestWSPositionUpdateHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSOrderbookHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{
|
||||
"table":"orderBookL2_25",
|
||||
"keys":["symbol","id","side"],
|
||||
@@ -877,6 +964,7 @@ func TestWSOrderbookHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSDeleveragePositionUpdateHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"position",
|
||||
"action":"update",
|
||||
"data":[{
|
||||
@@ -911,6 +999,7 @@ func TestWSDeleveragePositionUpdateHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWSDeleverageExecutionInsertHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"execution",
|
||||
"action":"insert",
|
||||
"data":[{
|
||||
@@ -934,6 +1023,7 @@ func TestWSDeleverageExecutionInsertHandling(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
pressXToJSON := []byte(`{"table":"trade","action":"insert","data":[{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"MinusTick","trdMatchID":"c427f7a0-6b26-1e10-5c4e-1bd74daf2a73","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"95eb9155-b58c-70e9-44b7-34efe50302e0","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"e607c187-f25c-86bc-cb39-8afff7aaf2d9","grossValue":2583000,"homeNotional":0.9904912836767037,"foreignNotional":255.84389857369254},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":17,"price":258.3,"tickDirection":"ZeroMinusTick","trdMatchID":"0f076814-a57d-9a59-8063-ad6b823a80ac","grossValue":439110,"homeNotional":0.1683835182250396,"foreignNotional":43.49346275752773},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"MinusTick","trdMatchID":"f4ef3dfd-51c4-538f-37c1-e5071ba1c75d","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"81ef136b-8f4a-b1cf-78a8-fffbfa89bf40","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"65a87e8c-7563-34a4-d040-94e8513c5401","grossValue":2582500,"homeNotional":0.9904912836767037,"foreignNotional":255.79437400950872},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":15,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"1d11a74e-a157-3f33-036d-35a101fba50b","grossValue":387375,"homeNotional":0.14857369255150554,"foreignNotional":38.369156101426306},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":1,"price":258.25,"tickDirection":"ZeroMinusTick","trdMatchID":"40d49df1-f018-f66f-4ca5-31d4997641d7","grossValue":25825,"homeNotional":0.009904912836767036,"foreignNotional":2.5579437400950873},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"MinusTick","trdMatchID":"36135b51-73e5-c007-362b-a55be5830c6b","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"6ee19edb-99aa-3030-ba63-933ffb347ade","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":100,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"d44be603-cdb8-d676-e3e2-f91fb12b2a70","grossValue":2582000,"homeNotional":0.9904912836767037,"foreignNotional":255.7448494453249},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":5,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"a14b43b3-50b4-c075-c54d-dfb0165de33d","grossValue":129100,"homeNotional":0.04952456418383518,"foreignNotional":12.787242472266245},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":8,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"3c30e175-5194-320c-8f8c-01636c2f4a32","grossValue":206560,"homeNotional":0.07923930269413629,"foreignNotional":20.45958795562599},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":50,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"5b803378-760b-4919-21fc-bfb275d39ace","grossValue":1291000,"homeNotional":0.49524564183835185,"foreignNotional":127.87242472266244},{"timestamp":"2020-02-17T01:35:36.442Z","symbol":"ETHUSD","side":"Sell","size":244,"price":258.2,"tickDirection":"ZeroMinusTick","trdMatchID":"cf57fec1-c444-b9e5-5e2d-4fb643f4fdb7","grossValue":6300080,"homeNotional":2.416798732171157,"foreignNotional":624.0174326465927}]}`)
|
||||
err := b.wsHandleData(pressXToJSON)
|
||||
if err != nil {
|
||||
|
||||
@@ -119,10 +119,14 @@ func (b *Bitmex) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.URLDefault = bitmexAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitmexWSURL
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bitmexAPIURL,
|
||||
exchange.WebsocketSpot: bitmexWSURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = stream.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -141,6 +145,11 @@ func (b *Bitmex) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsEndpoint, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -148,7 +157,7 @@ func (b *Bitmex) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: bitmexWSURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsEndpoint,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
UnSubscriber: b.Unsubscribe,
|
||||
@@ -161,7 +170,6 @@ func (b *Bitmex) Setup(exch *config.ExchangeConfig) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
|
||||
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
|
||||
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
|
||||
@@ -180,11 +188,15 @@ func (b *Bitmex) Start(wg *sync.WaitGroup) {
|
||||
// Run implements the Bitmex wrapper
|
||||
func (b *Bitmex) Run() {
|
||||
if b.Verbose {
|
||||
wsEndpoint, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
log.Error(log.ExchangeSys, err)
|
||||
}
|
||||
log.Debugf(log.ExchangeSys,
|
||||
"%s Websocket: %s. (url: %s).\n",
|
||||
b.Name,
|
||||
common.IsEnabled(b.Websocket.IsEnabled()),
|
||||
b.API.Endpoints.WebsocketURL)
|
||||
wsEndpoint)
|
||||
b.PrintEnabledPairs()
|
||||
}
|
||||
|
||||
@@ -383,7 +395,7 @@ func (b *Bitmex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitmex exchange
|
||||
func (b *Bitmex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bitmex) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
|
||||
bal, err := b.GetAllUserMargin()
|
||||
@@ -414,10 +426,10 @@ func (b *Bitmex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitmex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bitmex) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -786,8 +798,8 @@ func (b *Bitmex) AuthenticateWebsocket() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitmex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bitmex) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -147,15 +147,8 @@ func (b *Bitstamp) GetTicker(currency string, hourly bool) (*Ticker, error) {
|
||||
if hourly {
|
||||
tickerEndpoint = bitstampAPITickerHourly
|
||||
}
|
||||
|
||||
path := fmt.Sprintf(
|
||||
"%s/v%s/%s/%s/",
|
||||
b.API.Endpoints.URL,
|
||||
bitstampAPIVersion,
|
||||
tickerEndpoint,
|
||||
strings.ToLower(currency),
|
||||
)
|
||||
return &response, b.SendHTTPRequest(path, &response)
|
||||
path := "/v" + bitstampAPIVersion + "/" + tickerEndpoint + "/" + strings.ToLower(currency) + "/"
|
||||
return &response, b.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
}
|
||||
|
||||
// GetOrderbook Returns a JSON dictionary with "bids" and "asks". Each is a list
|
||||
@@ -168,16 +161,8 @@ func (b *Bitstamp) GetOrderbook(currency string) (Orderbook, error) {
|
||||
Asks [][]string `json:"asks"`
|
||||
}
|
||||
resp := response{}
|
||||
|
||||
path := fmt.Sprintf(
|
||||
"%s/v%s/%s/%s/",
|
||||
b.API.Endpoints.URL,
|
||||
bitstampAPIVersion,
|
||||
bitstampAPIOrderbook,
|
||||
strings.ToLower(currency),
|
||||
)
|
||||
|
||||
err := b.SendHTTPRequest(path, &resp)
|
||||
path := "/v" + bitstampAPIVersion + "/" + bitstampAPIOrderbook + "/" + strings.ToLower(currency) + "/"
|
||||
err := b.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -220,13 +205,8 @@ func (b *Bitstamp) GetOrderbook(currency string) (Orderbook, error) {
|
||||
// currently supports
|
||||
func (b *Bitstamp) GetTradingPairs() ([]TradingPair, error) {
|
||||
var result []TradingPair
|
||||
|
||||
path := fmt.Sprintf("%s/v%s/%s",
|
||||
b.API.Endpoints.URL,
|
||||
bitstampAPIVersion,
|
||||
bitstampAPITradingPairsInfo)
|
||||
|
||||
return result, b.SendHTTPRequest(path, &result)
|
||||
path := "/v" + bitstampAPIVersion + "/" + bitstampAPITradingPairsInfo
|
||||
return result, b.SendHTTPRequest(exchange.RestSpot, path, &result)
|
||||
}
|
||||
|
||||
// GetTransactions returns transaction information
|
||||
@@ -234,36 +214,27 @@ func (b *Bitstamp) GetTradingPairs() ([]TradingPair, error) {
|
||||
// response into time intervals.
|
||||
func (b *Bitstamp) GetTransactions(currencyPair, timePeriod string) ([]Transactions, error) {
|
||||
var transactions []Transactions
|
||||
requestURL := fmt.Sprintf(
|
||||
"%s/v%s/%s/%s/",
|
||||
b.API.Endpoints.URL,
|
||||
bitstampAPIVersion,
|
||||
bitstampAPITransactions,
|
||||
strings.ToLower(currencyPair),
|
||||
)
|
||||
requestURL := "/v" + bitstampAPIVersion + "/" + bitstampAPITransactions + "/" + strings.ToLower(currencyPair) + "/"
|
||||
if timePeriod != "" {
|
||||
requestURL += "?time=" + url.QueryEscape(timePeriod)
|
||||
}
|
||||
|
||||
return transactions, b.SendHTTPRequest(requestURL, &transactions)
|
||||
return transactions, b.SendHTTPRequest(exchange.RestSpot, requestURL, &transactions)
|
||||
}
|
||||
|
||||
// GetEURUSDConversionRate returns the conversion rate between Euro and USD
|
||||
func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) {
|
||||
rate := EURUSDConversionRate{}
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bitstampAPIEURUSD)
|
||||
|
||||
return rate, b.SendHTTPRequest(path, &rate)
|
||||
path := "/" + bitstampAPIEURUSD
|
||||
return rate, b.SendHTTPRequest(exchange.RestSpot, path, &rate)
|
||||
}
|
||||
|
||||
// GetBalance returns full balance of currency held on the exchange
|
||||
func (b *Bitstamp) GetBalance() (Balances, error) {
|
||||
var balance map[string]string
|
||||
err := b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, nil, &balance)
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIBalance, true, nil, &balance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balances := make(map[string]Balance)
|
||||
for k := range balance {
|
||||
curr := k[0:3]
|
||||
@@ -317,14 +288,14 @@ func (b *Bitstamp) GetUserTransactions(currencyPair string) ([]UserTransactions,
|
||||
var response []Response
|
||||
|
||||
if currencyPair == "" {
|
||||
if err := b.SendAuthenticatedHTTPRequest(bitstampAPIUserTransactions,
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIUserTransactions,
|
||||
true,
|
||||
url.Values{},
|
||||
&response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err := b.SendAuthenticatedHTTPRequest(bitstampAPIUserTransactions+"/"+currencyPair,
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIUserTransactions+"/"+currencyPair,
|
||||
true,
|
||||
url.Values{},
|
||||
&response); err != nil {
|
||||
@@ -366,11 +337,8 @@ func (b *Bitstamp) GetUserTransactions(currencyPair string) ([]UserTransactions,
|
||||
// GetOpenOrders returns all open orders on the exchange
|
||||
func (b *Bitstamp) GetOpenOrders(currencyPair string) ([]Order, error) {
|
||||
var resp []Order
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s", bitstampAPIOpenOrders, strings.ToLower(currencyPair),
|
||||
)
|
||||
|
||||
return resp, b.SendAuthenticatedHTTPRequest(path, true, nil, &resp)
|
||||
path := bitstampAPIOpenOrders + "/" + strings.ToLower(currencyPair)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, path, true, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatus returns an the status of an order by its ID
|
||||
@@ -380,7 +348,7 @@ func (b *Bitstamp) GetOrderStatus(orderID int64) (OrderStatus, error) {
|
||||
req.Add("id", strconv.FormatInt(orderID, 10))
|
||||
|
||||
return resp,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIOrderStatus, false, req, &resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIOrderStatus, false, req, &resp)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels order by ID
|
||||
@@ -389,7 +357,7 @@ func (b *Bitstamp) CancelExistingOrder(orderID int64) (CancelOrder, error) {
|
||||
req.Add("id", strconv.FormatInt(orderID, 10))
|
||||
|
||||
var result CancelOrder
|
||||
err := b.SendAuthenticatedHTTPRequest(bitstampAPICancelOrder, true, req, &result)
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPICancelOrder, true, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -402,7 +370,7 @@ func (b *Bitstamp) CancelAllExistingOrders() (bool, error) {
|
||||
result := false
|
||||
|
||||
return result,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPICancelAllOrders, false, nil, &result)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPICancelAllOrders, false, nil, &result)
|
||||
}
|
||||
|
||||
// PlaceOrder places an order on the exchange.
|
||||
@@ -419,13 +387,13 @@ func (b *Bitstamp) PlaceOrder(currencyPair string, price, amount float64, buy, m
|
||||
|
||||
var path string
|
||||
if market {
|
||||
path = fmt.Sprintf("%s/%s/%s", orderType, bitstampAPIMarket, strings.ToLower(currencyPair))
|
||||
path = orderType + "/" + bitstampAPIMarket + strings.ToLower(currencyPair)
|
||||
} else {
|
||||
path = fmt.Sprintf("%s/%s", orderType, strings.ToLower(currencyPair))
|
||||
path = orderType + "/" + orderType + strings.ToLower(currencyPair)
|
||||
}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(path, true, req, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, path, true, req, &response)
|
||||
}
|
||||
|
||||
// GetWithdrawalRequests returns withdrawal requests for the account
|
||||
@@ -445,7 +413,7 @@ func (b *Bitstamp) GetWithdrawalRequests(timedelta int64) ([]WithdrawalRequests,
|
||||
}
|
||||
|
||||
return resp,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIWithdrawalRequests, false, value, &resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIWithdrawalRequests, false, value, &resp)
|
||||
}
|
||||
|
||||
// CryptoWithdrawal withdraws a cryptocurrency into a supplied wallet, returns ID
|
||||
@@ -484,7 +452,7 @@ func (b *Bitstamp) CryptoWithdrawal(amount float64, address, symbol, destTag str
|
||||
return resp, errors.New("incorrect symbol")
|
||||
}
|
||||
|
||||
return resp, b.SendAuthenticatedHTTPRequest(endpoint, false, req, &resp)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, endpoint, false, req, &resp)
|
||||
}
|
||||
|
||||
// OpenBankWithdrawal Opens a bank withdrawal request (SEPA or international)
|
||||
@@ -505,7 +473,7 @@ func (b *Bitstamp) OpenBankWithdrawal(amount float64, currency,
|
||||
req.Add("comment", comment)
|
||||
|
||||
resp := FIATWithdrawalResponse{}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
}
|
||||
|
||||
// OpenInternationalBankWithdrawal Opens a bank withdrawal request (international)
|
||||
@@ -533,7 +501,7 @@ func (b *Bitstamp) OpenInternationalBankWithdrawal(amount float64, currency,
|
||||
req.Add("bank_country", bankCountry)
|
||||
|
||||
resp := FIATWithdrawalResponse{}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIOpenWithdrawal, true, req, &resp)
|
||||
}
|
||||
|
||||
// GetCryptoDepositAddress returns a depositing address by crypto
|
||||
@@ -547,23 +515,23 @@ func (b *Bitstamp) GetCryptoDepositAddress(crypto currency.Code) (string, error)
|
||||
switch crypto {
|
||||
case currency.BTC:
|
||||
return resp,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIBitcoinDeposit, false, nil, &resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIBitcoinDeposit, false, nil, &resp)
|
||||
|
||||
case currency.LTC:
|
||||
return v2Resp.Address,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPILitecoinDeposit, true, nil, &v2Resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPILitecoinDeposit, true, nil, &v2Resp)
|
||||
|
||||
case currency.ETH:
|
||||
return v2Resp.Address,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIEthereumDeposit, true, nil, &v2Resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIEthereumDeposit, true, nil, &v2Resp)
|
||||
|
||||
case currency.XRP:
|
||||
return v2Resp.Address,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIXrpDeposit, true, nil, &v2Resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIXrpDeposit, true, nil, &v2Resp)
|
||||
|
||||
case currency.BCH:
|
||||
return v2Resp.Address,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIBitcoinCashDeposit, true, nil, &v2Resp)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIBitcoinCashDeposit, true, nil, &v2Resp)
|
||||
|
||||
default:
|
||||
return resp, fmt.Errorf("unsupported cryptocurrency string %s", crypto)
|
||||
@@ -575,7 +543,7 @@ func (b *Bitstamp) GetUnconfirmedBitcoinDeposits() ([]UnconfirmedBTCTransactions
|
||||
var response []UnconfirmedBTCTransactions
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIUnconfirmedBitcoin, false, nil, &response)
|
||||
b.SendAuthenticatedHTTPRequest(exchange.RestSpot, bitstampAPIUnconfirmedBitcoin, false, nil, &response)
|
||||
}
|
||||
|
||||
// OHLC returns OHLCV data for step (interval)
|
||||
@@ -593,7 +561,7 @@ func (b *Bitstamp) OHLC(currency string, start, end time.Time, step, limit strin
|
||||
if !end.IsZero() {
|
||||
v.Add("end", strconv.FormatInt(end.Unix(), 10))
|
||||
}
|
||||
return resp, b.SendHTTPRequest(common.EncodeURLValues(b.API.Endpoints.URL+"/v"+bitstampAPIVersion+"/"+bitstampOHLC+"/"+currency, v), &resp)
|
||||
return resp, b.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/v"+bitstampAPIVersion+"/"+bitstampOHLC+"/"+currency, v), &resp)
|
||||
}
|
||||
|
||||
// TransferAccountBalance transfers funds from either a main or sub account
|
||||
@@ -621,14 +589,18 @@ func (b *Bitstamp) TransferAccountBalance(amount float64, currency, subAccount s
|
||||
|
||||
var resp interface{}
|
||||
|
||||
return b.SendAuthenticatedHTTPRequest(path, true, req, &resp)
|
||||
return b.SendAuthenticatedHTTPRequest(exchange.RestSpot, path, true, req, &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bitstamp) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (b *Bitstamp) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -637,11 +609,14 @@ func (b *Bitstamp) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request
|
||||
func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url.Values, result interface{}) error {
|
||||
func (b *Bitstamp) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, v2 bool, values url.Values, result interface{}) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
||||
}
|
||||
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n := b.Requester.GetNonce(true).String()
|
||||
|
||||
if values == nil {
|
||||
@@ -656,9 +631,9 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url
|
||||
values.Set("signature", strings.ToUpper(crypto.HexEncodeToString(hmac)))
|
||||
|
||||
if v2 {
|
||||
path = fmt.Sprintf("%s/v%s/%s/", b.API.Endpoints.URL, bitstampAPIVersion, path)
|
||||
path = endpoint + "/v" + bitstampAPIVersion + "/" + path + "/"
|
||||
} else {
|
||||
path = fmt.Sprintf("%s/%s/", b.API.Endpoints.URL, path)
|
||||
path = endpoint + "/" + path + "/"
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
@@ -679,7 +654,7 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url
|
||||
Reason interface{} `json:"reason"`
|
||||
}{}
|
||||
|
||||
err := b.SendPayload(context.Background(), &request.Item{
|
||||
err = b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodPost,
|
||||
Path: path,
|
||||
Headers: headers,
|
||||
|
||||
@@ -35,6 +35,6 @@ func TestMain(m *testing.M) {
|
||||
if err != nil {
|
||||
log.Fatal("Bitstamp setup error", err)
|
||||
}
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name, b.API.Endpoints.URL)
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -46,7 +46,13 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
b.HTTPClient = newClient
|
||||
b.API.Endpoints.URL = serverDetails + "/api"
|
||||
log.Printf(sharedtestvalues.MockTesting, b.Name, b.API.Endpoints.URL)
|
||||
endpointMap := b.API.Endpoints.GetURLMap()
|
||||
for k := range endpointMap {
|
||||
err = b.API.Endpoints.SetRunning(k, serverDetails+"/api")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
log.Printf(sharedtestvalues.MockTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -182,7 +182,6 @@ func TestGetTicker(t *testing.T) {
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetOrderbook(currency.BTC.String() + currency.USD.String())
|
||||
if err != nil {
|
||||
t.Error("GetOrderbook() error", err)
|
||||
@@ -217,7 +216,6 @@ func TestGetEURUSDConversionRate(t *testing.T) {
|
||||
|
||||
func TestGetBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetBalance()
|
||||
switch {
|
||||
case areTestAPIKeysSet() && err != nil && !mockTests:
|
||||
@@ -333,7 +331,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -351,7 +350,8 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
|
||||
@@ -33,7 +33,6 @@ func (b *Bitstamp) GetDefaultConfig() (*config.ExchangeConfig, error) {
|
||||
exchCfg.Name = b.Name
|
||||
exchCfg.HTTPTimeout = exchange.DefaultHTTPTimeout
|
||||
exchCfg.BaseCurrencies = b.BaseCurrencies
|
||||
|
||||
err := b.SetupDefaults(exchCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -57,7 +56,6 @@ func (b *Bitstamp) SetDefaults() {
|
||||
b.API.CredentialsValidator.RequiresKey = true
|
||||
b.API.CredentialsValidator.RequiresSecret = true
|
||||
b.API.CredentialsValidator.RequiresClientID = true
|
||||
|
||||
requestFmt := ¤cy.PairFormat{Uppercase: true}
|
||||
configFmt := ¤cy.PairFormat{Uppercase: true}
|
||||
err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
|
||||
@@ -129,10 +127,14 @@ func (b *Bitstamp) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(request.NewBasicRateLimit(bitstampRateInterval, bitstampRequestRate)))
|
||||
|
||||
b.API.Endpoints.URLDefault = bitstampAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints.WebsocketURL = bitstampWSURL
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bitstampAPIURL,
|
||||
exchange.WebsocketSpot: bitstampWSURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = stream.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -151,6 +153,11 @@ func (b *Bitstamp) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsURL, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -158,7 +165,7 @@ func (b *Bitstamp) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: bitstampWSURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsURL,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
UnSubscriber: b.Unsubscribe,
|
||||
@@ -354,7 +361,7 @@ func (b *Bitstamp) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Bitstamp exchange
|
||||
func (b *Bitstamp) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bitstamp) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
accountBalance, err := b.GetBalance()
|
||||
@@ -383,10 +390,10 @@ func (b *Bitstamp) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bitstamp) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bitstamp) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -775,8 +782,8 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bitstamp) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bitstamp) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
spotURL = "spotAPIURL"
|
||||
spotWSURL = "spotWSURL"
|
||||
bittrexAPIURL = "https://bittrex.com/api/v1.1"
|
||||
bittrexAPIVersion = "v1.1"
|
||||
bittrexMaxOpenOrders = 500
|
||||
@@ -68,9 +70,8 @@ type Bittrex struct {
|
||||
// along with other meta data.
|
||||
func (b *Bittrex) GetMarkets() (Market, error) {
|
||||
var markets Market
|
||||
path := fmt.Sprintf("%s/%s/", b.API.Endpoints.URL, bittrexAPIGetMarkets)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &markets); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetMarkets+"/", &markets); err != nil {
|
||||
return markets, err
|
||||
}
|
||||
|
||||
@@ -83,9 +84,8 @@ func (b *Bittrex) GetMarkets() (Market, error) {
|
||||
// GetCurrencies is used to get all supported currencies at Bittrex
|
||||
func (b *Bittrex) GetCurrencies() (Currency, error) {
|
||||
var currencies Currency
|
||||
path := fmt.Sprintf("%s/%s/", b.API.Endpoints.URL, bittrexAPIGetCurrencies)
|
||||
|
||||
if err := b.SendHTTPRequest(path, ¤cies); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetCurrencies+"/", ¤cies); err != nil {
|
||||
return currencies, err
|
||||
}
|
||||
|
||||
@@ -99,11 +99,9 @@ func (b *Bittrex) GetCurrencies() (Currency, error) {
|
||||
// on the supplied currency. Example currency input param "btc-ltc".
|
||||
func (b *Bittrex) GetTicker(currencyPair string) (Ticker, error) {
|
||||
tick := Ticker{}
|
||||
path := fmt.Sprintf("%s/%s?market=%s", b.API.Endpoints.URL, bittrexAPIGetTicker,
|
||||
strings.ToUpper(currencyPair),
|
||||
)
|
||||
path := "/" + bittrexAPIGetTicker + "?market=" + strings.ToUpper(currencyPair)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &tick); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, path, &tick); err != nil {
|
||||
return tick, err
|
||||
}
|
||||
|
||||
@@ -117,9 +115,8 @@ func (b *Bittrex) GetTicker(currencyPair string) (Ticker, error) {
|
||||
// exchanges
|
||||
func (b *Bittrex) GetMarketSummaries() (MarketSummary, error) {
|
||||
var summaries MarketSummary
|
||||
path := fmt.Sprintf("%s/%s/", b.API.Endpoints.URL, bittrexAPIGetMarketSummaries)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &summaries); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetMarketSummaries+"/", &summaries); err != nil {
|
||||
return summaries, err
|
||||
}
|
||||
|
||||
@@ -133,11 +130,7 @@ func (b *Bittrex) GetMarketSummaries() (MarketSummary, error) {
|
||||
// exchanges by currency pair (btc-ltc).
|
||||
func (b *Bittrex) GetMarketSummary(currencyPair string) (MarketSummary, error) {
|
||||
var summary MarketSummary
|
||||
path := fmt.Sprintf("%s/%s?market=%s", b.API.Endpoints.URL,
|
||||
bittrexAPIGetMarketSummary, strings.ToLower(currencyPair),
|
||||
)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &summary); err != nil {
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetMarketSummary+"?market="+strings.ToLower(currencyPair), &summary); err != nil {
|
||||
return summary, err
|
||||
}
|
||||
|
||||
@@ -156,11 +149,8 @@ func (b *Bittrex) GetMarketSummary(currencyPair string) (MarketSummary, error) {
|
||||
// it returns full depth. So depth default is 50.
|
||||
func (b *Bittrex) GetOrderbook(currencyPair string) (OrderBooks, error) {
|
||||
var orderbooks OrderBooks
|
||||
path := fmt.Sprintf("%s/%s?market=%s&type=both&depth=50", b.API.Endpoints.URL,
|
||||
bittrexAPIGetOrderbook, strings.ToUpper(currencyPair),
|
||||
)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &orderbooks); err != nil {
|
||||
path := "/" + bittrexAPIGetOrderbook + "?market=" + strings.ToLower(currencyPair) + "&type=both&depth=50"
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, path, &orderbooks); err != nil {
|
||||
return orderbooks, err
|
||||
}
|
||||
|
||||
@@ -174,11 +164,8 @@ func (b *Bittrex) GetOrderbook(currencyPair string) (OrderBooks, error) {
|
||||
// market
|
||||
func (b *Bittrex) GetMarketHistory(currencyPair string) (MarketHistory, error) {
|
||||
var marketHistoriae MarketHistory
|
||||
path := fmt.Sprintf("%s/%s?market=%s", b.API.Endpoints.URL,
|
||||
bittrexAPIGetMarketHistory, strings.ToUpper(currencyPair),
|
||||
)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &marketHistoriae); err != nil {
|
||||
path := "/" + bittrexAPIGetMarketHistory + "?market=" + strings.ToUpper(currencyPair)
|
||||
if err := b.SendHTTPRequest(exchange.RestSpot, path, &marketHistoriae); err != nil {
|
||||
return marketHistoriae, err
|
||||
}
|
||||
|
||||
@@ -200,9 +187,7 @@ func (b *Bittrex) PlaceBuyLimit(currencyPair string, quantity, rate float64) (UU
|
||||
values.Set("market", currencyPair)
|
||||
values.Set("quantity", strconv.FormatFloat(quantity, 'E', -1, 64))
|
||||
values.Set("rate", strconv.FormatFloat(rate, 'E', -1, 64))
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIBuyLimit)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIBuyLimit, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
@@ -224,9 +209,7 @@ func (b *Bittrex) PlaceSellLimit(currencyPair string, quantity, rate float64) (U
|
||||
values.Set("market", currencyPair)
|
||||
values.Set("quantity", strconv.FormatFloat(quantity, 'E', -1, 64))
|
||||
values.Set("rate", strconv.FormatFloat(rate, 'E', -1, 64))
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPISellLimit)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPISellLimit, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
@@ -244,9 +227,8 @@ func (b *Bittrex) GetOpenOrders(currencyPair string) (Order, error) {
|
||||
if !(currencyPair == "" || currencyPair == " ") {
|
||||
values.Set("market", currencyPair)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetOpenOrders)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &orders); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetOpenOrders, values, &orders); err != nil {
|
||||
return orders, err
|
||||
}
|
||||
|
||||
@@ -261,9 +243,8 @@ func (b *Bittrex) CancelExistingOrder(uuid string) (Balances, error) {
|
||||
var balances Balances
|
||||
values := url.Values{}
|
||||
values.Set("uuid", uuid)
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPICancel)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &balances); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPICancel, values, &balances); err != nil {
|
||||
return balances, err
|
||||
}
|
||||
|
||||
@@ -276,9 +257,8 @@ func (b *Bittrex) CancelExistingOrder(uuid string) (Balances, error) {
|
||||
// GetAccountBalances is used to retrieve all balances from your account
|
||||
func (b *Bittrex) GetAccountBalances() (Balances, error) {
|
||||
var balances Balances
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetBalances)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, url.Values{}, &balances); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetBalances, url.Values{}, &balances); err != nil {
|
||||
return balances, err
|
||||
}
|
||||
|
||||
@@ -294,9 +274,8 @@ func (b *Bittrex) GetAccountBalanceByCurrency(currency string) (Balance, error)
|
||||
var balance Balance
|
||||
values := url.Values{}
|
||||
values.Set("currency", currency)
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetBalance)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &balance); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetBalance, values, &balance); err != nil {
|
||||
return balance, err
|
||||
}
|
||||
|
||||
@@ -313,9 +292,8 @@ func (b *Bittrex) GetCryptoDepositAddress(currency string) (DepositAddress, erro
|
||||
var address DepositAddress
|
||||
values := url.Values{}
|
||||
values.Set("currency", currency)
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetDepositAddress)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &address); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetDepositAddress, values, &address); err != nil {
|
||||
return address, err
|
||||
}
|
||||
|
||||
@@ -337,9 +315,7 @@ func (b *Bittrex) Withdraw(currency, paymentID, address string, quantity float64
|
||||
values.Set("paymentid", paymentID)
|
||||
}
|
||||
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIWithdraw)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIWithdraw, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
@@ -354,9 +330,8 @@ func (b *Bittrex) GetOrder(uuid string) (Order, error) {
|
||||
var order Order
|
||||
values := url.Values{}
|
||||
values.Set("uuid", uuid)
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetOrder)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &order); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetOrder, values, &order); err != nil {
|
||||
return order, err
|
||||
}
|
||||
|
||||
@@ -375,9 +350,8 @@ func (b *Bittrex) GetOrderHistoryForCurrency(currencyPair string) (Order, error)
|
||||
if !(currencyPair == "" || currencyPair == " ") {
|
||||
values.Set("market", currencyPair)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetOrderHistory)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &orders); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetOrderHistory, values, &orders); err != nil {
|
||||
return orders, err
|
||||
}
|
||||
|
||||
@@ -396,9 +370,8 @@ func (b *Bittrex) GetWithdrawalHistory(currency string) (WithdrawalHistory, erro
|
||||
if !(currency == "" || currency == " ") {
|
||||
values.Set("currency", currency)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetWithdrawalHistory)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &history); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetWithdrawalHistory, values, &history); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
@@ -417,9 +390,8 @@ func (b *Bittrex) GetDepositHistory(currency string) (DepositHistory, error) {
|
||||
if !(currency == "" || currency == " ") {
|
||||
values.Set("currency", currency)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", b.API.Endpoints.URL, bittrexAPIGetDepositHistory)
|
||||
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &history); err != nil {
|
||||
if err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, "/"+bittrexAPIGetDepositHistory, values, &history); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
@@ -430,10 +402,14 @@ func (b *Bittrex) GetDepositHistory(currency string) (DepositHistory, error) {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bittrex) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (b *Bittrex) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -443,16 +419,19 @@ func (b *Bittrex) SendHTTPRequest(path string, result interface{}) error {
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request to a desired
|
||||
// path
|
||||
func (b *Bittrex) SendAuthenticatedHTTPRequest(path string, values url.Values, result interface{}) (err error) {
|
||||
func (b *Bittrex) SendAuthenticatedHTTPRequest(ep exchange.URL, path string, values url.Values, result interface{}) (err error) {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
||||
}
|
||||
|
||||
endpoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n := b.Requester.GetNonce(true).String()
|
||||
|
||||
values.Set("apikey", b.API.Credentials.Key)
|
||||
values.Set("nonce", n)
|
||||
rawQuery := path + "?" + values.Encode()
|
||||
rawQuery := endpoint + path + "?" + values.Encode()
|
||||
hmac := crypto.GetHMAC(
|
||||
crypto.HashSHA512, []byte(rawQuery), []byte(b.API.Credentials.Secret),
|
||||
)
|
||||
|
||||
@@ -351,8 +351,9 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{p},
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{p},
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
getOrdersRequest.Pairs[0].Delimiter = "-"
|
||||
@@ -367,7 +368,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
|
||||
@@ -96,9 +96,13 @@ func (b *Bittrex) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(request.NewBasicRateLimit(bittrexRateInterval, bittrexRequestRate)))
|
||||
|
||||
b.API.Endpoints.URLDefault = bittrexAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: bittrexAPIURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup method sets current configuration details if enabled
|
||||
@@ -224,7 +228,7 @@ func (b *Bittrex) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// Bittrex exchange
|
||||
func (b *Bittrex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *Bittrex) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = b.Name
|
||||
accountBalance, err := b.GetAccountBalances()
|
||||
@@ -254,10 +258,10 @@ func (b *Bittrex) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *Bittrex) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *Bittrex) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -702,8 +706,8 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *Bittrex) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *Bittrex) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestMain(m *testing.M) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = b.ValidateCredentials()
|
||||
err = b.ValidateCredentials(asset.Spot)
|
||||
if err != nil {
|
||||
fmt.Println("API credentials are invalid:", err)
|
||||
b.API.AuthenticatedSupport = false
|
||||
@@ -456,7 +456,7 @@ func TestFetchAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := b.FetchAccountInfo()
|
||||
_, err := b.FetchAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -469,7 +469,8 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
_, err := b.GetOrderHistory(&order.GetOrdersRequest{
|
||||
Side: order.Buy,
|
||||
Side: order.Buy,
|
||||
AssetType: asset.Spot,
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
@@ -500,7 +501,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&order.GetOrdersRequest{})
|
||||
_, err := b.GetActiveOrders(&order.GetOrdersRequest{AssetType: asset.Spot})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -58,9 +58,6 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
b.API.CredentialsValidator.RequiresKey = true
|
||||
b.API.CredentialsValidator.RequiresSecret = true
|
||||
b.API.CredentialsValidator.RequiresBase64DecodeSecret = true
|
||||
b.API.Endpoints.URLDefault = btcMarketsAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
|
||||
requestFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
|
||||
configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
|
||||
err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
|
||||
@@ -123,8 +120,14 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.WebsocketURL = btcMarketsWSURL
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: btcMarketsAPIURL,
|
||||
exchange.WebsocketSpot: btcMarketsWSURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = stream.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -143,6 +146,11 @@ func (b *BTCMarkets) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsURL, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -150,7 +158,7 @@ func (b *BTCMarkets) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: btcMarketsWSURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsURL,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
GenerateSubscriptions: b.generateDefaultSubscriptions,
|
||||
@@ -387,7 +395,7 @@ func (b *BTCMarkets) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*or
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTCMarkets) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *BTCMarkets) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var resp account.Holdings
|
||||
data, err := b.GetAccountBalance()
|
||||
if err != nil {
|
||||
@@ -415,10 +423,10 @@ func (b *BTCMarkets) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTCMarkets) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *BTCMarkets) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -856,8 +864,8 @@ func (b *BTCMarkets) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *BTCMarkets) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *BTCMarkets) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
if err != nil {
|
||||
if b.CheckTransientError(err) == nil {
|
||||
return nil
|
||||
|
||||
@@ -36,11 +36,13 @@ const (
|
||||
|
||||
// Public endpoints
|
||||
btseMarketOverview = "market_summary"
|
||||
btseMarkets = "markets"
|
||||
btseOrderbook = "orderbook"
|
||||
btseTrades = "trades"
|
||||
btseTime = "time"
|
||||
btseOHLCV = "ohlcv"
|
||||
btsePrice = "price"
|
||||
btseFuturesFunding = "funding_history"
|
||||
|
||||
// Authenticated endpoints
|
||||
btseWallet = "user/wallet"
|
||||
@@ -55,6 +57,16 @@ const (
|
||||
btseCancelAllAfter = "order/cancelAllAfter"
|
||||
)
|
||||
|
||||
// FetchFundingHistory gets funding history
|
||||
func (b *BTSE) FetchFundingHistory(symbol string) (map[string][]FundingHistoryData, error) {
|
||||
var resp map[string][]FundingHistoryData
|
||||
params := url.Values{}
|
||||
if symbol != "" {
|
||||
params.Set("symbol", symbol)
|
||||
}
|
||||
return resp, b.SendHTTPRequest(exchange.RestFutures, http.MethodGet, btseFuturesFunding+params.Encode(), &resp, false, queryFunc)
|
||||
}
|
||||
|
||||
// GetMarketSummary stores market summary data
|
||||
func (b *BTSE) GetMarketSummary(symbol string, spot bool) (MarketSummary, error) {
|
||||
var m MarketSummary
|
||||
@@ -62,7 +74,7 @@ func (b *BTSE) GetMarketSummary(symbol string, spot bool) (MarketSummary, error)
|
||||
if symbol != "" {
|
||||
path += "?symbol=" + url.QueryEscape(symbol)
|
||||
}
|
||||
return m, b.SendHTTPRequest(http.MethodGet, path, &m, spot, queryFunc)
|
||||
return m, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet, path, &m, spot, queryFunc)
|
||||
}
|
||||
|
||||
// FetchOrderBook gets orderbook data for a given pair
|
||||
@@ -79,7 +91,7 @@ func (b *BTSE) FetchOrderBook(symbol string, group, limitBids, limitAsks int, sp
|
||||
if group > 0 {
|
||||
urlValues.Add("group", strconv.Itoa(group))
|
||||
}
|
||||
return &o, b.SendHTTPRequest(http.MethodGet,
|
||||
return &o, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
common.EncodeURLValues(btseOrderbook, urlValues), &o, spot, queryFunc)
|
||||
}
|
||||
|
||||
@@ -90,7 +102,7 @@ func (b *BTSE) FetchOrderBookL2(symbol string, depth int) (*Orderbook, error) {
|
||||
urlValues.Add("symbol", symbol)
|
||||
urlValues.Add("depth", strconv.FormatInt(int64(depth), 10))
|
||||
endpoint := common.EncodeURLValues(btseOrderbook+"/L2", urlValues)
|
||||
return &o, b.SendHTTPRequest(http.MethodGet, endpoint, &o, true, queryFunc)
|
||||
return &o, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, &o, true, queryFunc)
|
||||
}
|
||||
|
||||
// GetTrades returns a list of trades for the specified symbol
|
||||
@@ -119,7 +131,7 @@ func (b *BTSE) GetTrades(symbol string, start, end time.Time, beforeSerialID, af
|
||||
if includeOld {
|
||||
urlValues.Add("includeOld", "true")
|
||||
}
|
||||
return t, b.SendHTTPRequest(http.MethodGet,
|
||||
return t, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
common.EncodeURLValues(btseTrades, urlValues), &t, spot, queryFunc)
|
||||
}
|
||||
|
||||
@@ -142,26 +154,26 @@ func (b *BTSE) OHLCV(symbol string, start, end time.Time, resolution int) (OHLCV
|
||||
}
|
||||
urlValues.Add("resolution", strconv.FormatInt(int64(res), 10))
|
||||
endpoint := common.EncodeURLValues(btseOHLCV, urlValues)
|
||||
return o, b.SendHTTPRequest(http.MethodGet, endpoint, &o, true, queryFunc)
|
||||
return o, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, &o, true, queryFunc)
|
||||
}
|
||||
|
||||
// GetPrice get current price for requested symbol
|
||||
func (b *BTSE) GetPrice(symbol string) (Price, error) {
|
||||
var p Price
|
||||
path := btsePrice + "?symbol=" + url.QueryEscape(symbol)
|
||||
return p, b.SendHTTPRequest(http.MethodGet, path, &p, true, queryFunc)
|
||||
return p, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet, path, &p, true, queryFunc)
|
||||
}
|
||||
|
||||
// GetServerTime returns the exchanges server time
|
||||
func (b *BTSE) GetServerTime() (*ServerTime, error) {
|
||||
var s ServerTime
|
||||
return &s, b.SendHTTPRequest(http.MethodGet, btseTime, &s, true, queryFunc)
|
||||
return &s, b.SendHTTPRequest(exchange.RestSpot, http.MethodGet, btseTime, &s, true, queryFunc)
|
||||
}
|
||||
|
||||
// GetWalletInformation returns the users account balance
|
||||
func (b *BTSE) GetWalletInformation() ([]CurrencyBalance, error) {
|
||||
var a []CurrencyBalance
|
||||
return a, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseWallet, true, nil, nil, &a, queryFunc)
|
||||
return a, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btseWallet, true, nil, nil, &a, queryFunc)
|
||||
}
|
||||
|
||||
// GetFeeInformation retrieve fee's (maker/taker) for requested symbol
|
||||
@@ -171,7 +183,7 @@ func (b *BTSE) GetFeeInformation(symbol string) ([]AccountFees, error) {
|
||||
if symbol != "" {
|
||||
urlValues.Add("symbol", symbol)
|
||||
}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseUserFee, true, urlValues, nil, &resp, queryFunc)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btseUserFee, true, urlValues, nil, &resp, queryFunc)
|
||||
}
|
||||
|
||||
// GetWalletHistory returns the users account balance
|
||||
@@ -192,7 +204,7 @@ func (b *BTSE) GetWalletHistory(symbol string, start, end time.Time, count int)
|
||||
if count > 0 {
|
||||
urlValues.Add("count", strconv.Itoa(count))
|
||||
}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseWalletHistory, true, urlValues, nil, &resp, queryFunc)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btseWalletHistory, true, urlValues, nil, &resp, queryFunc)
|
||||
}
|
||||
|
||||
// GetWalletAddress returns the users account balance
|
||||
@@ -204,7 +216,7 @@ func (b *BTSE) GetWalletAddress(currency string) (WalletAddress, error) {
|
||||
urlValues.Add("currency", currency)
|
||||
}
|
||||
|
||||
return resp, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseWalletAddress, true, urlValues, nil, &resp, queryFunc)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btseWalletAddress, true, urlValues, nil, &resp, queryFunc)
|
||||
}
|
||||
|
||||
// CreateWalletAddress create new deposit address for requested currency
|
||||
@@ -212,7 +224,7 @@ func (b *BTSE) CreateWalletAddress(currency string) (WalletAddress, error) {
|
||||
var resp WalletAddress
|
||||
req := make(map[string]interface{}, 1)
|
||||
req["currency"] = currency
|
||||
err := b.SendAuthenticatedHTTPRequest(http.MethodPost, btseWalletAddress, true, nil, req, &resp, queryFunc)
|
||||
err := b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, btseWalletAddress, true, nil, req, &resp, queryFunc)
|
||||
if err != nil {
|
||||
errResp := ErrorResponse{}
|
||||
errResponseStr := strings.Split(err.Error(), "raw response: ")
|
||||
@@ -242,7 +254,7 @@ func (b *BTSE) WalletWithdrawal(currency, address, tag, amount string) (Withdraw
|
||||
req["address"] = address
|
||||
req["tag"] = tag
|
||||
req["amount"] = amount
|
||||
return resp, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseWalletWithdrawal, true, nil, req, &resp, queryFunc)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, btseWalletWithdrawal, true, nil, req, &resp, queryFunc)
|
||||
}
|
||||
|
||||
// CreateOrder creates an order
|
||||
@@ -292,7 +304,7 @@ func (b *BTSE) CreateOrder(clOrderID string, deviation float64, postOnly bool, p
|
||||
}
|
||||
|
||||
var r []Order
|
||||
return r, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseOrder, true, url.Values{}, req, &r, orderFunc)
|
||||
return r, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, btseOrder, true, url.Values{}, req, &r, orderFunc)
|
||||
}
|
||||
|
||||
// GetOrders returns all pending orders
|
||||
@@ -306,7 +318,7 @@ func (b *BTSE) GetOrders(symbol, orderID, clOrderID string) ([]OpenOrder, error)
|
||||
req.Add("clOrderID", clOrderID)
|
||||
}
|
||||
var o []OpenOrder
|
||||
return o, b.SendAuthenticatedHTTPRequest(http.MethodGet, btsePendingOrders, true, req, nil, &o, orderFunc)
|
||||
return o, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btsePendingOrders, true, req, nil, &o, orderFunc)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels an order
|
||||
@@ -321,14 +333,14 @@ func (b *BTSE) CancelExistingOrder(orderID, symbol, clOrderID string) (CancelOrd
|
||||
req.Add("clOrderID", clOrderID)
|
||||
}
|
||||
|
||||
return c, b.SendAuthenticatedHTTPRequest(http.MethodDelete, btseOrder, true, req, nil, &c, orderFunc)
|
||||
return c, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete, btseOrder, true, req, nil, &c, orderFunc)
|
||||
}
|
||||
|
||||
// CancelAllAfter cancels all orders after timeout
|
||||
func (b *BTSE) CancelAllAfter(timeout int) error {
|
||||
req := make(map[string]interface{})
|
||||
req["timeout"] = timeout
|
||||
return b.SendAuthenticatedHTTPRequest(http.MethodPost, btseCancelAllAfter, true, url.Values{}, req, nil, orderFunc)
|
||||
return b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, btseCancelAllAfter, true, url.Values{}, req, nil, orderFunc)
|
||||
}
|
||||
|
||||
// IndexOrderPeg create peg order that will track a certain percentage above/below the index price
|
||||
@@ -378,7 +390,7 @@ func (b *BTSE) IndexOrderPeg(clOrderID string, deviation float64, postOnly bool,
|
||||
req["type"] = orderType
|
||||
}
|
||||
|
||||
return o, b.SendAuthenticatedHTTPRequest(http.MethodPost, btsePegOrder, true, url.Values{}, req, nil, orderFunc)
|
||||
return o, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, btsePegOrder, true, url.Values{}, req, nil, orderFunc)
|
||||
}
|
||||
|
||||
// TradeHistory returns previous trades on exchange
|
||||
@@ -413,18 +425,22 @@ func (b *BTSE) TradeHistory(symbol string, start, end time.Time, beforeSerialID,
|
||||
if orderID != "" {
|
||||
urlValues.Add("orderID", orderID)
|
||||
}
|
||||
return resp, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseExchangeHistory, true, urlValues, nil, &resp, queryFunc)
|
||||
return resp, b.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, btseExchangeHistory, true, urlValues, nil, &resp, queryFunc)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an HTTP request to the desired endpoint
|
||||
func (b *BTSE) SendHTTPRequest(method, endpoint string, result interface{}, spotEndpoint bool, f request.EndpointLimit) error {
|
||||
func (b *BTSE) SendHTTPRequest(ep exchange.URL, method, endpoint string, result interface{}, spotEndpoint bool, f request.EndpointLimit) error {
|
||||
ePoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p := btseSPOTPath + btseSPOTAPIPath
|
||||
if !spotEndpoint {
|
||||
p = btseFuturesPath + btseFuturesAPIPath
|
||||
}
|
||||
return b.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: b.API.Endpoints.URL + p + endpoint,
|
||||
Path: ePoint + p + endpoint,
|
||||
Result: result,
|
||||
Verbose: b.Verbose,
|
||||
HTTPDebugging: b.HTTPDebugging,
|
||||
@@ -434,16 +450,21 @@ func (b *BTSE) SendHTTPRequest(method, endpoint string, result interface{}, spot
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the desired endpoint
|
||||
func (b *BTSE) SendAuthenticatedHTTPRequest(method, endpoint string, isSpot bool, values url.Values, req map[string]interface{}, result interface{}, f request.EndpointLimit) error {
|
||||
func (b *BTSE) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint string, isSpot bool, values url.Values, req map[string]interface{}, result interface{}, f request.EndpointLimit) error {
|
||||
if !b.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
b.Name)
|
||||
}
|
||||
|
||||
ePoint, err := b.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// The concatenation is done this way because BTSE expect endpoint+nonce or endpoint+nonce+body
|
||||
// when signing the data but the full path of the request is /spot/api/v3.2/<endpoint>
|
||||
// its messy but it works and supports futures as well
|
||||
host := b.API.Endpoints.URL
|
||||
host := ePoint
|
||||
if isSpot {
|
||||
host += btseSPOTPath + btseSPOTAPIPath + endpoint
|
||||
endpoint = btseSPOTAPIPath + endpoint
|
||||
|
||||
@@ -57,6 +57,13 @@ func areTestAPIKeysSet() bool {
|
||||
return b.ValidateAPICredentials()
|
||||
}
|
||||
|
||||
func TestFetchFundingHistory(t *testing.T) {
|
||||
_, err := b.FetchFundingHistory("")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarketsSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := b.GetMarketSummary("", true)
|
||||
@@ -103,7 +110,7 @@ func TestUpdateOrderbook(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
f, err := currency.NewPairFromString("BTC-PFC")
|
||||
f, err := currency.NewPairFromString(testFUTURESPair)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -386,7 +393,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
Quote: currency.USD,
|
||||
},
|
||||
},
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := b.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -401,7 +409,8 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
t.Skip("API keys not set, skipping test")
|
||||
}
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
_, err := b.GetOrderHistory(&getOrdersRequest)
|
||||
if err != nil {
|
||||
|
||||
@@ -13,6 +13,13 @@ const (
|
||||
orderCancelled = 6
|
||||
)
|
||||
|
||||
// FundingHistoryData stores funding history data
|
||||
type FundingHistoryData struct {
|
||||
Time int64 `json:"time"`
|
||||
Rate float64 `json:"rate"`
|
||||
Symbol string `json:"symbol"`
|
||||
}
|
||||
|
||||
// MarketSummary response data
|
||||
type MarketSummary []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
|
||||
@@ -28,6 +28,11 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
|
||||
)
|
||||
|
||||
const (
|
||||
spotURL = "spotURL"
|
||||
spotWSURL = "websocketURL"
|
||||
)
|
||||
|
||||
// GetDefaultConfig returns a default exchange config
|
||||
func (b *BTSE) GetDefaultConfig() (*config.ExchangeConfig, error) {
|
||||
b.SetDefaults()
|
||||
@@ -150,9 +155,15 @@ func (b *BTSE) SetDefaults() {
|
||||
b.Requester = request.New(b.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
b.API.Endpoints.URLDefault = btseAPIURL
|
||||
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: btseAPIURL,
|
||||
exchange.RestFutures: btseAPIURL,
|
||||
exchange.WebsocketSpot: btseWebsocket,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
b.Websocket = stream.New()
|
||||
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -171,6 +182,11 @@ func (b *BTSE) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := b.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = b.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -178,7 +194,7 @@ func (b *BTSE) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: btseWebsocket,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: b.WsConnect,
|
||||
Subscriber: b.Subscribe,
|
||||
UnSubscriber: b.Unsubscribe,
|
||||
@@ -363,7 +379,7 @@ func (b *BTSE) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// BTSE exchange
|
||||
func (b *BTSE) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (b *BTSE) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var a account.Holdings
|
||||
balance, err := b.GetWalletInformation()
|
||||
if err != nil {
|
||||
@@ -396,10 +412,10 @@ func (b *BTSE) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (b *BTSE) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name)
|
||||
func (b *BTSE) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(b.Name, assetType)
|
||||
if err != nil {
|
||||
return b.UpdateAccountInfo()
|
||||
return b.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -881,8 +897,8 @@ func (b *BTSE) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (b *BTSE) ValidateCredentials() error {
|
||||
_, err := b.UpdateAccountInfo()
|
||||
func (b *BTSE) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := b.UpdateAccountInfo(assetType)
|
||||
return b.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -63,20 +63,20 @@ type CoinbasePro struct {
|
||||
func (c *CoinbasePro) GetProducts() ([]Product, error) {
|
||||
var products []Product
|
||||
|
||||
return products, c.SendHTTPRequest(c.API.Endpoints.URL+coinbaseproProducts, &products)
|
||||
return products, c.SendHTTPRequest(exchange.RestSpot, coinbaseproProducts, &products)
|
||||
}
|
||||
|
||||
// GetOrderbook returns orderbook by currency pair and level
|
||||
func (c *CoinbasePro) GetOrderbook(symbol string, level int) (interface{}, error) {
|
||||
orderbook := OrderbookResponse{}
|
||||
|
||||
path := fmt.Sprintf("%s/%s/%s", c.API.Endpoints.URL+coinbaseproProducts, symbol, coinbaseproOrderbook)
|
||||
path := fmt.Sprintf("%s/%s/%s", coinbaseproProducts, symbol, coinbaseproOrderbook)
|
||||
if level > 0 {
|
||||
levelStr := strconv.Itoa(level)
|
||||
path = fmt.Sprintf("%s/%s/%s?level=%s", c.API.Endpoints.URL+coinbaseproProducts, symbol, coinbaseproOrderbook, levelStr)
|
||||
path = fmt.Sprintf("%s/%s/%s?level=%s", coinbaseproProducts, symbol, coinbaseproOrderbook, levelStr)
|
||||
}
|
||||
|
||||
if err := c.SendHTTPRequest(path, &orderbook); err != nil {
|
||||
if err := c.SendHTTPRequest(exchange.RestSpot, path, &orderbook); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -143,8 +143,8 @@ func (c *CoinbasePro) GetOrderbook(symbol string, level int) (interface{}, error
|
||||
func (c *CoinbasePro) GetTicker(currencyPair string) (Ticker, error) {
|
||||
tick := Ticker{}
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", c.API.Endpoints.URL+coinbaseproProducts, currencyPair, coinbaseproTicker)
|
||||
return tick, c.SendHTTPRequest(path, &tick)
|
||||
"%s/%s/%s", coinbaseproProducts, currencyPair, coinbaseproTicker)
|
||||
return tick, c.SendHTTPRequest(exchange.RestSpot, path, &tick)
|
||||
}
|
||||
|
||||
// GetTrades listd the latest trades for a product
|
||||
@@ -152,8 +152,8 @@ func (c *CoinbasePro) GetTicker(currencyPair string) (Ticker, error) {
|
||||
func (c *CoinbasePro) GetTrades(currencyPair string) ([]Trade, error) {
|
||||
var trades []Trade
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", c.API.Endpoints.URL+coinbaseproProducts, currencyPair, coinbaseproTrades)
|
||||
return trades, c.SendHTTPRequest(path, &trades)
|
||||
"%s/%s/%s", coinbaseproProducts, currencyPair, coinbaseproTrades)
|
||||
return trades, c.SendHTTPRequest(exchange.RestSpot, path, &trades)
|
||||
}
|
||||
|
||||
// GetHistoricRates returns historic rates for a product. Rates are returned in
|
||||
@@ -185,10 +185,10 @@ func (c *CoinbasePro) GetHistoricRates(currencyPair, start, end string, granular
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(
|
||||
fmt.Sprintf("%s/%s/%s", c.API.Endpoints.URL+coinbaseproProducts, currencyPair, coinbaseproHistory),
|
||||
fmt.Sprintf("%s/%s/%s", coinbaseproProducts, currencyPair, coinbaseproHistory),
|
||||
values)
|
||||
|
||||
if err := c.SendHTTPRequest(path, &resp); err != nil {
|
||||
if err := c.SendHTTPRequest(exchange.RestSpot, path, &resp); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
@@ -217,9 +217,9 @@ func (c *CoinbasePro) GetHistoricRates(currencyPair, start, end string, granular
|
||||
func (c *CoinbasePro) GetStats(currencyPair string) (Stats, error) {
|
||||
stats := Stats{}
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", c.API.Endpoints.URL+coinbaseproProducts, currencyPair, coinbaseproStats)
|
||||
"%s/%s/%s", coinbaseproProducts, currencyPair, coinbaseproStats)
|
||||
|
||||
return stats, c.SendHTTPRequest(path, &stats)
|
||||
return stats, c.SendHTTPRequest(exchange.RestSpot, path, &stats)
|
||||
}
|
||||
|
||||
// GetCurrencies returns a list of supported currency on the exchange
|
||||
@@ -227,14 +227,14 @@ func (c *CoinbasePro) GetStats(currencyPair string) (Stats, error) {
|
||||
func (c *CoinbasePro) GetCurrencies() ([]Currency, error) {
|
||||
var currencies []Currency
|
||||
|
||||
return currencies, c.SendHTTPRequest(c.API.Endpoints.URL+coinbaseproCurrencies, ¤cies)
|
||||
return currencies, c.SendHTTPRequest(exchange.RestSpot, coinbaseproCurrencies, ¤cies)
|
||||
}
|
||||
|
||||
// GetServerTime returns the API server time
|
||||
func (c *CoinbasePro) GetServerTime() (ServerTime, error) {
|
||||
serverTime := ServerTime{}
|
||||
|
||||
return serverTime, c.SendHTTPRequest(c.API.Endpoints.URL+coinbaseproTime, &serverTime)
|
||||
return serverTime, c.SendHTTPRequest(exchange.RestSpot, coinbaseproTime, &serverTime)
|
||||
}
|
||||
|
||||
// GetAccounts returns a list of trading accounts associated with the APIKEYS
|
||||
@@ -242,7 +242,7 @@ func (c *CoinbasePro) GetAccounts() ([]AccountResponse, error) {
|
||||
var resp []AccountResponse
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, coinbaseproAccounts, nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, coinbaseproAccounts, nil, &resp)
|
||||
}
|
||||
|
||||
// GetAccount returns information for a single account. Use this endpoint when
|
||||
@@ -251,7 +251,7 @@ func (c *CoinbasePro) GetAccount(accountID string) (AccountResponse, error) {
|
||||
resp := AccountResponse{}
|
||||
path := fmt.Sprintf("%s/%s", coinbaseproAccounts, accountID)
|
||||
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// GetAccountHistory returns a list of account activity. Account activity either
|
||||
@@ -261,7 +261,7 @@ func (c *CoinbasePro) GetAccountHistory(accountID string) ([]AccountLedgerRespon
|
||||
var resp []AccountLedgerResponse
|
||||
path := fmt.Sprintf("%s/%s/%s", coinbaseproAccounts, accountID, coinbaseproLedger)
|
||||
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// GetHolds returns the holds that are placed on an account for any active
|
||||
@@ -272,7 +272,7 @@ func (c *CoinbasePro) GetHolds(accountID string) ([]AccountHolds, error) {
|
||||
var resp []AccountHolds
|
||||
path := fmt.Sprintf("%s/%s/%s", coinbaseproAccounts, accountID, coinbaseproHolds)
|
||||
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// PlaceLimitOrder places a new limit order. Orders can only be placed if the
|
||||
@@ -317,7 +317,7 @@ func (c *CoinbasePro) PlaceLimitOrder(clientRef string, price, amount float64, s
|
||||
req["post_only"] = postOnly
|
||||
}
|
||||
|
||||
err := c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
err := c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -361,7 +361,7 @@ func (c *CoinbasePro) PlaceMarketOrder(clientRef string, size, funds float64, si
|
||||
req["stp"] = stp
|
||||
}
|
||||
|
||||
err := c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
err := c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -404,7 +404,7 @@ func (c *CoinbasePro) PlaceMarginOrder(clientRef string, size, funds float64, si
|
||||
req["stp"] = stp
|
||||
}
|
||||
|
||||
err := c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
err := c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproOrders, req, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -416,7 +416,7 @@ func (c *CoinbasePro) PlaceMarginOrder(clientRef string, size, funds float64, si
|
||||
func (c *CoinbasePro) CancelExistingOrder(orderID string) error {
|
||||
path := fmt.Sprintf("%s/%s", coinbaseproOrders, orderID)
|
||||
|
||||
return c.SendAuthenticatedHTTPRequest(http.MethodDelete, path, nil, nil)
|
||||
return c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete, path, nil, nil)
|
||||
}
|
||||
|
||||
// CancelAllExistingOrders cancels all open orders on the exchange and returns
|
||||
@@ -430,7 +430,7 @@ func (c *CoinbasePro) CancelAllExistingOrders(currencyPair string) ([]string, er
|
||||
if len(currencyPair) > 0 {
|
||||
req["product_id"] = currencyPair
|
||||
}
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodDelete, coinbaseproOrders, req, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete, coinbaseproOrders, req, &resp)
|
||||
}
|
||||
|
||||
// GetOrders lists current open orders. Only open or un-settled orders are
|
||||
@@ -449,11 +449,11 @@ func (c *CoinbasePro) GetOrders(status []string, currencyPair string) ([]General
|
||||
params.Set("product_id", currencyPair)
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbaseproOrders, params)
|
||||
path := common.EncodeURLValues(coinbaseproOrders, params)
|
||||
path = common.GetURIPath(path)
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, path[1:], nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path[1:], nil, &resp)
|
||||
}
|
||||
|
||||
// GetOrder returns a single order by order id.
|
||||
@@ -461,7 +461,7 @@ func (c *CoinbasePro) GetOrder(orderID string) (GeneralizedOrderResponse, error)
|
||||
resp := GeneralizedOrderResponse{}
|
||||
path := fmt.Sprintf("%s/%s", coinbaseproOrders, orderID)
|
||||
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// GetFills returns a list of recent fills
|
||||
@@ -479,11 +479,11 @@ func (c *CoinbasePro) GetFills(orderID, currencyPair string) ([]FillResponse, er
|
||||
return resp, errors.New("no parameters set")
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbaseproFills, params)
|
||||
path := common.EncodeURLValues(coinbaseproFills, params)
|
||||
uri := common.GetURIPath(path)
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, uri[1:], nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, uri[1:], nil, &resp)
|
||||
}
|
||||
|
||||
// MarginTransfer sends funds between a standard/default profile and a margin
|
||||
@@ -506,7 +506,7 @@ func (c *CoinbasePro) MarginTransfer(amount float64, transferType, profileID, cu
|
||||
req["margin_profile_id"] = profileID
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproMarginTransfer, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproMarginTransfer, req, &resp)
|
||||
}
|
||||
|
||||
// GetPosition returns an overview of account profile.
|
||||
@@ -514,7 +514,7 @@ func (c *CoinbasePro) GetPosition() (AccountOverview, error) {
|
||||
resp := AccountOverview{}
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, coinbaseproPosition, nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, coinbaseproPosition, nil, &resp)
|
||||
}
|
||||
|
||||
// ClosePosition closes a position and allowing you to repay position as well
|
||||
@@ -525,7 +525,7 @@ func (c *CoinbasePro) ClosePosition(repayOnly bool) (AccountOverview, error) {
|
||||
req["repay_only"] = repayOnly
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproPositionClose, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproPositionClose, req, &resp)
|
||||
}
|
||||
|
||||
// GetPayMethods returns a full list of payment methods
|
||||
@@ -533,7 +533,7 @@ func (c *CoinbasePro) GetPayMethods() ([]PaymentMethod, error) {
|
||||
var resp []PaymentMethod
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, coinbaseproPaymentMethod, nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, coinbaseproPaymentMethod, nil, &resp)
|
||||
}
|
||||
|
||||
// DepositViaPaymentMethod deposits funds from a payment method. See the Payment
|
||||
@@ -550,7 +550,7 @@ func (c *CoinbasePro) DepositViaPaymentMethod(amount float64, currency, paymentI
|
||||
req["payment_method_id"] = paymentID
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproPaymentMethodDeposit, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproPaymentMethodDeposit, req, &resp)
|
||||
}
|
||||
|
||||
// DepositViaCoinbase deposits funds from a coinbase account. Move funds between
|
||||
@@ -569,7 +569,7 @@ func (c *CoinbasePro) DepositViaCoinbase(amount float64, currency, accountID str
|
||||
req["coinbase_account_id"] = accountID
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproDepositCoinbase, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproDepositCoinbase, req, &resp)
|
||||
}
|
||||
|
||||
// WithdrawViaPaymentMethod withdraws funds to a payment method
|
||||
@@ -585,7 +585,7 @@ func (c *CoinbasePro) WithdrawViaPaymentMethod(amount float64, currency, payment
|
||||
req["payment_method_id"] = paymentID
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproWithdrawalPaymentMethod, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproWithdrawalPaymentMethod, req, &resp)
|
||||
}
|
||||
|
||||
// /////////////////////// NO ROUTE FOUND ERROR ////////////////////////////////
|
||||
@@ -618,7 +618,7 @@ func (c *CoinbasePro) WithdrawCrypto(amount float64, currency, cryptoAddress str
|
||||
req["crypto_address"] = cryptoAddress
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproWithdrawalCrypto, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproWithdrawalCrypto, req, &resp)
|
||||
}
|
||||
|
||||
// GetCoinbaseAccounts returns a list of coinbase accounts
|
||||
@@ -626,7 +626,7 @@ func (c *CoinbasePro) GetCoinbaseAccounts() ([]CoinbaseAccounts, error) {
|
||||
var resp []CoinbaseAccounts
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, coinbaseproCoinbaseAccounts, nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, coinbaseproCoinbaseAccounts, nil, &resp)
|
||||
}
|
||||
|
||||
// GetReport returns batches of historic information about your account in
|
||||
@@ -663,7 +663,7 @@ func (c *CoinbasePro) GetReport(reportType, startDate, endDate, currencyPair, ac
|
||||
}
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodPost, coinbaseproReports, req, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, coinbaseproReports, req, &resp)
|
||||
}
|
||||
|
||||
// GetReportStatus once a report request has been accepted for processing, the
|
||||
@@ -672,7 +672,7 @@ func (c *CoinbasePro) GetReportStatus(reportID string) (Report, error) {
|
||||
resp := Report{}
|
||||
path := fmt.Sprintf("%s/%s", coinbaseproReports, reportID)
|
||||
|
||||
return resp, c.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// GetTrailingVolume this request will return your 30-day trailing volume for
|
||||
@@ -681,14 +681,18 @@ func (c *CoinbasePro) GetTrailingVolume() ([]Volume, error) {
|
||||
var resp []Volume
|
||||
|
||||
return resp,
|
||||
c.SendAuthenticatedHTTPRequest(http.MethodGet, coinbaseproTrailingVolume, nil, &resp)
|
||||
c.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, coinbaseproTrailingVolume, nil, &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (c *CoinbasePro) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (c *CoinbasePro) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := c.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: c.Verbose,
|
||||
HTTPDebugging: c.HTTPDebugging,
|
||||
@@ -697,12 +701,15 @@ func (c *CoinbasePro) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (c *CoinbasePro) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
if !c.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
c.Name)
|
||||
}
|
||||
|
||||
endpoint, err := c.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
payload := []byte("")
|
||||
|
||||
if params != nil {
|
||||
@@ -732,7 +739,7 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(method, path string, params m
|
||||
defer cancel()
|
||||
return c.SendPayload(ctx, &request.Item{
|
||||
Method: method,
|
||||
Path: c.API.Endpoints.URL + path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: bytes.NewBuffer(payload),
|
||||
Result: result,
|
||||
|
||||
@@ -394,7 +394,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
currency.LTC)},
|
||||
}
|
||||
@@ -409,7 +410,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
currency.LTC)},
|
||||
}
|
||||
|
||||
@@ -131,10 +131,15 @@ func (c *CoinbasePro) SetDefaults() {
|
||||
c.Requester = request.New(c.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
c.API.Endpoints.URLDefault = coinbaseproAPIURL
|
||||
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
|
||||
c.API.Endpoints.WebsocketURL = coinbaseproWebsocketURL
|
||||
c.API.Endpoints = c.NewEndpoints()
|
||||
err = c.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: coinbaseproAPIURL,
|
||||
exchange.RestSandbox: coinbaseproSandboxAPIURL,
|
||||
exchange.WebsocketSpot: coinbaseproWebsocketURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
c.Websocket = stream.New()
|
||||
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -153,6 +158,11 @@ func (c *CoinbasePro) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := c.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -160,7 +170,7 @@ func (c *CoinbasePro) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: coinbaseproWebsocketURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: c.WsConnect,
|
||||
Subscriber: c.Subscribe,
|
||||
UnSubscriber: c.Unsubscribe,
|
||||
@@ -303,7 +313,7 @@ func (c *CoinbasePro) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// coinbasepro exchange
|
||||
func (c *CoinbasePro) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (c *CoinbasePro) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = c.Name
|
||||
accountBalance, err := c.GetAccounts()
|
||||
@@ -334,10 +344,10 @@ func (c *CoinbasePro) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *CoinbasePro) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
func (c *CoinbasePro) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name, assetType)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
return c.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -934,7 +944,7 @@ func (c *CoinbasePro) GetHistoricCandlesExtended(p currency.Pair, a asset.Item,
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *CoinbasePro) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
func (c *CoinbasePro) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := c.UpdateAccountInfo(assetType)
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
@@ -80,8 +80,8 @@ func (c *Coinbene) GetAllPairs() ([]PairData, error) {
|
||||
resp := struct {
|
||||
Data []PairData `json:"data"`
|
||||
}{}
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneGetAllPairs
|
||||
return resp.Data, c.SendHTTPRequest(path, spotPairs, &resp)
|
||||
path := coinbeneAPIVersion + coinbeneGetAllPairs
|
||||
return resp.Data, c.SendHTTPRequest(exchange.RestSpot, path, spotPairs, &resp)
|
||||
}
|
||||
|
||||
// GetPairInfo gets info about a single pair
|
||||
@@ -91,8 +91,8 @@ func (c *Coinbene) GetPairInfo(symbol string) (PairData, error) {
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbeneAPIVersion+coinbenePairInfo, params)
|
||||
return resp.Data, c.SendHTTPRequest(path, spotPairInfo, &resp)
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbenePairInfo, params)
|
||||
return resp.Data, c.SendHTTPRequest(exchange.RestSpot, path, spotPairInfo, &resp)
|
||||
}
|
||||
|
||||
// GetOrderbook gets and stores orderbook data for given pair
|
||||
@@ -108,8 +108,8 @@ func (c *Coinbene) GetOrderbook(symbol string, size int64) (Orderbook, error) {
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("depth", strconv.FormatInt(size, 10))
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbeneAPIVersion+coinbeneGetOrderBook, params)
|
||||
err := c.SendHTTPRequest(path, spotOrderbook, &resp)
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetOrderBook, params)
|
||||
err := c.SendHTTPRequest(exchange.RestSpot, path, spotOrderbook, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -154,8 +154,8 @@ func (c *Coinbene) GetTicker(symbol string) (TickerData, error) {
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbeneAPIVersion+coinbeneGetTicker, params)
|
||||
return resp.TickerData, c.SendHTTPRequest(path, spotSpecificTicker, &resp)
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetTicker, params)
|
||||
return resp.TickerData, c.SendHTTPRequest(exchange.RestSpot, path, spotSpecificTicker, &resp)
|
||||
}
|
||||
|
||||
// GetTickers gets and all spot tickers supported by the exchange
|
||||
@@ -164,8 +164,8 @@ func (c *Coinbene) GetTickers() ([]TickerData, error) {
|
||||
TickerData []TickerData `json:"data"`
|
||||
}{}
|
||||
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneGetTickersSpot
|
||||
return resp.TickerData, c.SendHTTPRequest(path, spotTickerList, &resp)
|
||||
path := coinbeneAPIVersion + coinbeneGetTickersSpot
|
||||
return resp.TickerData, c.SendHTTPRequest(exchange.RestSpot, path, spotTickerList, &resp)
|
||||
}
|
||||
|
||||
// GetTrades gets recent trades from the exchange
|
||||
@@ -177,8 +177,8 @@ func (c *Coinbene) GetTrades(symbol string, limit int64) (Trades, error) {
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
path := common.EncodeURLValues(c.API.Endpoints.URL+coinbeneAPIVersion+coinbeneGetTrades, params)
|
||||
err := c.SendHTTPRequest(path, spotMarketTrades, &resp)
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetTrades, params)
|
||||
err := c.SendHTTPRequest(exchange.RestSpot, path, spotMarketTrades, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -213,8 +213,8 @@ func (c *Coinbene) GetAccountBalances() ([]UserBalanceData, error) {
|
||||
resp := struct {
|
||||
Data []UserBalanceData `json:"data"`
|
||||
}{}
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneGetUserBalance
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneGetUserBalance
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneGetUserBalance,
|
||||
false,
|
||||
@@ -234,8 +234,8 @@ func (c *Coinbene) GetAccountAssetBalance(symbol string) (UserBalanceData, error
|
||||
resp := struct {
|
||||
Data UserBalanceData `json:"data"`
|
||||
}{}
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneAccountBalanceOne
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneAccountBalanceOne
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneAccountBalanceOne,
|
||||
false,
|
||||
@@ -289,8 +289,8 @@ func (c *Coinbene) PlaceSpotOrder(price, quantity float64, symbol, direction,
|
||||
if notional != 0 {
|
||||
params.Set("notional", strconv.Itoa(notional))
|
||||
}
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbenePlaceOrder
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbenePlaceOrder
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
path,
|
||||
coinbenePlaceOrder,
|
||||
false,
|
||||
@@ -359,8 +359,8 @@ func (c *Coinbene) PlaceSpotOrders(orders []PlaceOrderRequest) ([]OrderPlacement
|
||||
resp := struct {
|
||||
Data []OrderPlacementResponse `json:"data"`
|
||||
}{}
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneBatchPlaceOrder
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbeneBatchPlaceOrder
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
path,
|
||||
coinbeneBatchPlaceOrder,
|
||||
false,
|
||||
@@ -377,14 +377,14 @@ func (c *Coinbene) PlaceSpotOrders(orders []PlaceOrderRequest) ([]OrderPlacement
|
||||
func (c *Coinbene) FetchOpenSpotOrders(symbol string) (OrdersInfo, error) {
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneOpenOrders
|
||||
path := coinbeneAPIVersion + coinbeneOpenOrders
|
||||
var orders OrdersInfo
|
||||
for i := int64(1); ; i++ {
|
||||
temp := struct {
|
||||
Data OrdersInfo `json:"data"`
|
||||
}{}
|
||||
params.Set("pageNum", strconv.FormatInt(i, 10))
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneOpenOrders,
|
||||
false,
|
||||
@@ -410,14 +410,14 @@ func (c *Coinbene) FetchClosedOrders(symbol, latestID string) (OrdersInfo, error
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("latestOrderId", latestID)
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneClosedOrders
|
||||
path := coinbeneAPIVersion + coinbeneClosedOrders
|
||||
var orders OrdersInfo
|
||||
for i := int64(1); ; i++ {
|
||||
temp := struct {
|
||||
Data OrdersInfo `json:"data"`
|
||||
}{}
|
||||
params.Set("pageNum", strconv.FormatInt(i, 10))
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneClosedOrders,
|
||||
false,
|
||||
@@ -444,8 +444,8 @@ func (c *Coinbene) FetchSpotOrderInfo(orderID string) (OrderInfo, error) {
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("orderId", orderID)
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneOrderInfo
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneOrderInfo
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneOrderInfo,
|
||||
false,
|
||||
@@ -469,8 +469,8 @@ func (c *Coinbene) GetSpotOrderFills(orderID string) ([]OrderFills, error) {
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("orderId", orderID)
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneTradeFills
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneTradeFills
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
path,
|
||||
coinbeneTradeFills,
|
||||
false,
|
||||
@@ -490,8 +490,8 @@ func (c *Coinbene) CancelSpotOrder(orderID string) (string, error) {
|
||||
}{}
|
||||
req := make(map[string]interface{})
|
||||
req["orderId"] = orderID
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneCancelOrder
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbeneCancelOrder
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
path,
|
||||
coinbeneCancelOrder,
|
||||
false,
|
||||
@@ -513,8 +513,8 @@ func (c *Coinbene) CancelSpotOrders(orderIDs []string) ([]OrderCancellationRespo
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneBatchCancel
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbeneBatchCancel
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
path,
|
||||
coinbeneBatchCancel,
|
||||
false,
|
||||
@@ -533,8 +533,8 @@ func (c *Coinbene) GetSwapTickers() (SwapTickers, error) {
|
||||
Data SwapTickers `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneGetTickers
|
||||
err := c.SendHTTPRequest(path, contractTickers, &r)
|
||||
path := coinbeneAPIVersion + coinbeneGetTickers
|
||||
err := c.SendHTTPRequest(exchange.RestSwap, path, contractTickers, &r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -578,8 +578,8 @@ func (c *Coinbene) GetSwapOrderbook(symbol string, size int64) (Orderbook, error
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := common.EncodeURLValues(coinbeneSwapAPIURL+coinbeneAPIVersion+coinbeneGetOrderBook, v)
|
||||
err := c.SendHTTPRequest(path, contractOrderbook, &r)
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetOrderBook, v)
|
||||
err := c.SendHTTPRequest(exchange.RestSwap, path, contractOrderbook, &r)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
@@ -634,8 +634,8 @@ func (c *Coinbene) GetKlines(pair string, start, end time.Time, period string) (
|
||||
}
|
||||
v.Add("period", period)
|
||||
|
||||
path := common.EncodeURLValues(coinbeneAPIURL+coinbeneAPIVersion+coinbeneSpotKlines, v)
|
||||
if err = c.SendHTTPRequest(path, contractKline, &resp); err != nil {
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneSpotKlines, v)
|
||||
if err = c.SendHTTPRequest(exchange.RestSpot, path, contractKline, &resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -658,8 +658,8 @@ func (c *Coinbene) GetSwapKlines(symbol string, start, end time.Time, resolution
|
||||
}
|
||||
v.Set("resolution", resolution)
|
||||
|
||||
path := common.EncodeURLValues(coinbeneSwapAPIURL+coinbeneAPIVersion+coinbeneGetKlines, v)
|
||||
if err = c.SendHTTPRequest(path, contractKline, &resp); err != nil {
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetKlines, v)
|
||||
if err = c.SendHTTPRequest(exchange.RestSwap, path, contractKline, &resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -677,8 +677,8 @@ func (c *Coinbene) GetSwapTrades(symbol string, limit int) (SwapTrades, error) {
|
||||
Data [][]string `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := common.EncodeURLValues(coinbeneSwapAPIURL+coinbeneAPIVersion+coinbeneGetTrades, v)
|
||||
if err := c.SendHTTPRequest(path, contractTrades, &r); err != nil {
|
||||
path := common.EncodeURLValues(coinbeneAPIVersion+coinbeneGetTrades, v)
|
||||
if err := c.SendHTTPRequest(exchange.RestSwap, path, contractTrades, &r); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -716,8 +716,8 @@ func (c *Coinbene) GetSwapAccountInfo() (SwapAccountInfo, error) {
|
||||
Data SwapAccountInfo `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneAccountInfo
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneAccountInfo
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneAccountInfo,
|
||||
true,
|
||||
@@ -738,8 +738,8 @@ func (c *Coinbene) GetSwapPositions(symbol string) (SwapPositions, error) {
|
||||
Data SwapPositions `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneListSwapPositions
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneListSwapPositions
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneListSwapPositions,
|
||||
true,
|
||||
@@ -793,8 +793,8 @@ func (c *Coinbene) PlaceSwapOrder(symbol, direction, orderType, marginMode,
|
||||
Data SwapPlaceOrderResponse `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbenePlaceOrder
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbenePlaceOrder
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodPost,
|
||||
path,
|
||||
coinbenePlaceOrder,
|
||||
true,
|
||||
@@ -815,8 +815,8 @@ func (c *Coinbene) CancelSwapOrder(orderID string) (string, error) {
|
||||
Data string `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneCancelOrder
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbeneCancelOrder
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodPost,
|
||||
path,
|
||||
coinbeneCancelOrder,
|
||||
true,
|
||||
@@ -843,8 +843,8 @@ func (c *Coinbene) GetSwapOpenOrders(symbol string, pageNum, pageSize int) (Swap
|
||||
Data SwapOrders `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneOpenOrders
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneOpenOrders
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneOpenOrders,
|
||||
true,
|
||||
@@ -870,8 +870,8 @@ func (c *Coinbene) GetSwapOpenOrdersByPage(symbol string, latestOrderID int64) (
|
||||
Data SwapOrders `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneOpenOrdersByPage
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneOpenOrdersByPage
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneOpenOrdersByPage,
|
||||
true,
|
||||
@@ -892,8 +892,8 @@ func (c *Coinbene) GetSwapOrderInfo(orderID string) (SwapOrder, error) {
|
||||
Data SwapOrder `json:"data"`
|
||||
}
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneOrderInfo
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneOrderInfo
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneOrderInfo,
|
||||
true,
|
||||
@@ -935,8 +935,8 @@ func (c *Coinbene) GetSwapOrderHistory(beginTime, endTime, symbol string, pageNu
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneClosedOrders
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneClosedOrders
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneClosedOrders,
|
||||
true,
|
||||
@@ -973,8 +973,8 @@ func (c *Coinbene) GetSwapOrderHistoryByOrderID(beginTime, endTime, symbol, stat
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneClosedOrdersByPage
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneClosedOrdersByPage
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneClosedOrdersByPage,
|
||||
true,
|
||||
@@ -999,8 +999,8 @@ func (c *Coinbene) CancelSwapOrders(orderIDs []string) ([]OrderCancellationRespo
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneBatchCancel
|
||||
err := c.SendAuthHTTPRequest(http.MethodPost,
|
||||
path := coinbeneAPIVersion + coinbeneBatchCancel
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodPost,
|
||||
path,
|
||||
coinbeneBatchCancel,
|
||||
true,
|
||||
@@ -1030,8 +1030,8 @@ func (c *Coinbene) GetSwapOrderFills(symbol, orderID string, lastTradeID int64)
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbeneOrderFills
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbeneOrderFills
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbeneOrderFills,
|
||||
true,
|
||||
@@ -1058,8 +1058,8 @@ func (c *Coinbene) GetSwapFundingRates(pageNum, pageSize int) ([]SwapFundingRate
|
||||
}
|
||||
|
||||
var r resp
|
||||
path := coinbeneSwapAPIURL + coinbeneAPIVersion + coinbenePositionFeeRate
|
||||
err := c.SendAuthHTTPRequest(http.MethodGet,
|
||||
path := coinbeneAPIVersion + coinbenePositionFeeRate
|
||||
err := c.SendAuthHTTPRequest(exchange.RestSwap, http.MethodGet,
|
||||
path,
|
||||
coinbenePositionFeeRate,
|
||||
true,
|
||||
@@ -1073,7 +1073,11 @@ func (c *Coinbene) GetSwapFundingRates(pageNum, pageSize int) ([]SwapFundingRate
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (c *Coinbene) SendHTTPRequest(path string, f request.EndpointLimit, result interface{}) error {
|
||||
func (c *Coinbene) SendHTTPRequest(ep exchange.URL, path string, f request.EndpointLimit, result interface{}) error {
|
||||
endpoint, err := c.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var resp json.RawMessage
|
||||
errCap := struct {
|
||||
Code int `json:"code"`
|
||||
@@ -1082,7 +1086,7 @@ func (c *Coinbene) SendHTTPRequest(path string, f request.EndpointLimit, result
|
||||
|
||||
if err := c.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: &resp,
|
||||
Verbose: c.Verbose,
|
||||
HTTPDebugging: c.HTTPDebugging,
|
||||
@@ -1101,13 +1105,16 @@ func (c *Coinbene) SendHTTPRequest(path string, f request.EndpointLimit, result
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated HTTP request
|
||||
func (c *Coinbene) SendAuthHTTPRequest(method, path, epPath string, isSwap bool,
|
||||
func (c *Coinbene) SendAuthHTTPRequest(ep exchange.URL, method, path, epPath string, isSwap bool,
|
||||
params, result interface{}, f request.EndpointLimit) error {
|
||||
if !c.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
c.Name)
|
||||
}
|
||||
|
||||
endpoint, err := c.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
authPath := coinbeneAuthPath
|
||||
if isSwap {
|
||||
authPath = coinbeneSwapAuthPath
|
||||
@@ -1165,7 +1172,7 @@ func (c *Coinbene) SendAuthHTTPRequest(method, path, epPath string, isSwap bool,
|
||||
defer cancel()
|
||||
if err := c.SendPayload(ctx, &request.Item{
|
||||
Method: method,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: finalBody,
|
||||
Result: &resp,
|
||||
|
||||
@@ -242,7 +242,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := c.UpdateAccountInfo()
|
||||
_, err := c.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
|
||||
Status: oStatus,
|
||||
AssetType: assetType,
|
||||
Date: orders.Data[i].OrderTime,
|
||||
Leverage: strconv.FormatInt(orders.Data[i].Leverage, 10),
|
||||
Leverage: float64(orders.Data[i].Leverage),
|
||||
Pair: newPair,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,10 +146,15 @@ func (c *Coinbene) SetDefaults() {
|
||||
c.Requester = request.New(c.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
c.API.Endpoints.URLDefault = coinbeneAPIURL
|
||||
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
|
||||
c.API.Endpoints.WebsocketURL = wsContractURL
|
||||
c.API.Endpoints = c.NewEndpoints()
|
||||
err = c.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: coinbeneAPIURL,
|
||||
exchange.RestSwap: coinbeneSwapAPIURL,
|
||||
exchange.WebsocketSpot: wsContractURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
c.Websocket = stream.New()
|
||||
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -168,6 +173,11 @@ func (c *Coinbene) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := c.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -175,7 +185,7 @@ func (c *Coinbene) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: wsContractURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: c.WsConnect,
|
||||
Subscriber: c.Subscribe,
|
||||
UnSubscriber: c.Unsubscribe,
|
||||
@@ -464,7 +474,7 @@ func (c *Coinbene) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Coinbene exchange
|
||||
func (c *Coinbene) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (c *Coinbene) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
balance, err := c.GetAccountBalances()
|
||||
if err != nil {
|
||||
@@ -494,10 +504,10 @@ func (c *Coinbene) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *Coinbene) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
func (c *Coinbene) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name, assetType)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
return c.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -820,8 +830,8 @@ func (c *Coinbene) AuthenticateWebsocket() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *Coinbene) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
func (c *Coinbene) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := c.UpdateAccountInfo(assetType)
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ func (c *COINUT) GetInstruments() (Instruments, error) {
|
||||
var result Instruments
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = strings.ToUpper(asset.Spot.String())
|
||||
return result, c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutInstruments, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentTicker returns a ticker for a specific instrument
|
||||
@@ -82,7 +82,7 @@ func (c *COINUT) GetInstrumentTicker(instrumentID int64) (Ticker, error) {
|
||||
var result Ticker
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
return result, c.SendHTTPRequest(coinutTicker, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutTicker, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentOrderbook returns the orderbooks for a specific instrument
|
||||
@@ -94,7 +94,7 @@ func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int64) (Orderbook, e
|
||||
params["top_n"] = limit
|
||||
}
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrderbook, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutOrderbook, params, false, &result)
|
||||
}
|
||||
|
||||
// GetTrades returns trade information
|
||||
@@ -103,13 +103,13 @@ func (c *COINUT) GetTrades(instrumentID int64) (Trades, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTrades, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutTrades, params, false, &result)
|
||||
}
|
||||
|
||||
// GetUserBalance returns the full user balance
|
||||
func (c *COINUT) GetUserBalance() (*UserBalance, error) {
|
||||
var result *UserBalance
|
||||
return result, c.SendHTTPRequest(coinutBalance, nil, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutBalance, nil, true, &result)
|
||||
}
|
||||
|
||||
// NewOrder places a new order on the exchange
|
||||
@@ -127,7 +127,7 @@ func (c *COINUT) NewOrder(instrumentID int64, quantity, price float64, buy bool,
|
||||
}
|
||||
params["client_ord_id"] = orderID
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrder, params, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutOrder, params, true, &result)
|
||||
}
|
||||
|
||||
// NewOrders places multiple orders on the exchange
|
||||
@@ -136,7 +136,7 @@ func (c *COINUT) NewOrders(orders []Order) ([]OrdersBase, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["orders"] = orders
|
||||
|
||||
return result.Data, c.SendHTTPRequest(coinutOrders, params, true, &result.Data)
|
||||
return result.Data, c.SendHTTPRequest(exchange.RestSpot, coinutOrders, params, true, &result.Data)
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of open order and relevant information
|
||||
@@ -144,7 +144,7 @@ func (c *COINUT) GetOpenOrders(instrumentID int64) (GetOpenOrdersResponse, error
|
||||
var result GetOpenOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
return result, c.SendHTTPRequest(coinutOrdersOpen, params, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutOrdersOpen, params, true, &result)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels a specific order and returns if it was actioned
|
||||
@@ -164,7 +164,7 @@ func (c *COINUT) CancelExistingOrder(instrumentID, orderID int64) (bool, error)
|
||||
entries := []Request{entry}
|
||||
params["entries"] = entries
|
||||
|
||||
err := c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
|
||||
err := c.SendHTTPRequest(exchange.RestSpot, coinutOrdersCancel, params, true, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -184,7 +184,7 @@ func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, erro
|
||||
entries = append(entries, orders...)
|
||||
params["entries"] = entries
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutOrdersCancel, params, true, &result)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns trade history for a specific instrument.
|
||||
@@ -199,7 +199,7 @@ func (c *COINUT) GetTradeHistory(instrumentID, start, limit int64) (TradeHistory
|
||||
params["limit"] = limit
|
||||
}
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTradeHistory, params, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutTradeHistory, params, true, &result)
|
||||
}
|
||||
|
||||
// GetIndexTicker returns the index ticker for an asset
|
||||
@@ -208,7 +208,7 @@ func (c *COINUT) GetIndexTicker(asset string) (IndexTicker, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["asset"] = asset
|
||||
|
||||
return result, c.SendHTTPRequest(coinutIndexTicker, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutIndexTicker, params, false, &result)
|
||||
}
|
||||
|
||||
// GetDerivativeInstruments returns a list of derivative instruments
|
||||
@@ -217,7 +217,7 @@ func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = secType
|
||||
|
||||
return result, c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutInstruments, params, false, &result)
|
||||
}
|
||||
|
||||
// GetOptionChain returns option chain
|
||||
@@ -227,7 +227,7 @@ func (c *COINUT) GetOptionChain(asset, secType string) (OptionChainResponse, err
|
||||
params["asset"] = asset
|
||||
params["sec_type"] = secType
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOptionChain, params, false, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutOptionChain, params, false, &result)
|
||||
}
|
||||
|
||||
// GetPositionHistory returns position history
|
||||
@@ -242,7 +242,7 @@ func (c *COINUT) GetPositionHistory(secType string, start, limit int) (PositionH
|
||||
params["limit"] = limit
|
||||
}
|
||||
|
||||
return result, c.SendHTTPRequest(coinutPositionHistory, params, true, &result)
|
||||
return result, c.SendHTTPRequest(exchange.RestSpot, coinutPositionHistory, params, true, &result)
|
||||
}
|
||||
|
||||
// GetOpenPositions returns all your current opened positions
|
||||
@@ -255,17 +255,22 @@ func (c *COINUT) GetOpenPositions(instrumentID int) ([]OpenPosition, error) {
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
return result.Positions,
|
||||
c.SendHTTPRequest(coinutPositionOpen, params, true, &result)
|
||||
c.SendHTTPRequest(exchange.RestSpot, coinutPositionOpen, params, true, &result)
|
||||
}
|
||||
|
||||
// to-do: user position update via websocket
|
||||
|
||||
// SendHTTPRequest sends either an authenticated or unauthenticated HTTP request
|
||||
func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) {
|
||||
func (c *COINUT) SendHTTPRequest(ep exchange.URL, apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) {
|
||||
if !c.API.AuthenticatedSupport && authenticated {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, c.Name)
|
||||
}
|
||||
|
||||
endpoint, err := c.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if params == nil {
|
||||
params = map[string]interface{}{}
|
||||
}
|
||||
@@ -293,7 +298,7 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
|
||||
var rawMsg json.RawMessage
|
||||
err = c.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodPost,
|
||||
Path: c.API.Endpoints.URL,
|
||||
Path: endpoint,
|
||||
Headers: headers,
|
||||
Body: bytes.NewBuffer(payload),
|
||||
Result: &rawMsg,
|
||||
|
||||
@@ -253,7 +253,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
_, err := c.GetActiveOrders(&getOrdersRequest)
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
@@ -264,7 +265,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistoryWrapper(t *testing.T) {
|
||||
setupWSTestAuth(t)
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.BTC,
|
||||
currency.USD)},
|
||||
}
|
||||
@@ -358,12 +360,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiKey != "" || clientID != "" {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
_, err := c.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
_, err := c.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -113,10 +113,14 @@ func (c *COINUT) SetDefaults() {
|
||||
|
||||
c.Requester = request.New(c.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
|
||||
c.API.Endpoints.URLDefault = coinutAPIURL
|
||||
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
|
||||
c.API.Endpoints.WebsocketURL = coinutWebsocketURL
|
||||
c.API.Endpoints = c.NewEndpoints()
|
||||
err = c.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: coinutAPIURL,
|
||||
exchange.WebsocketSpot: coinutWebsocketURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
c.Websocket = stream.New()
|
||||
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -136,6 +140,11 @@ func (c *COINUT) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := c.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -143,7 +152,7 @@ func (c *COINUT) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: coinutWebsocketURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: c.WsConnect,
|
||||
Subscriber: c.Subscribe,
|
||||
UnSubscriber: c.Unsubscribe,
|
||||
@@ -294,7 +303,7 @@ func (c *COINUT) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// COINUT exchange
|
||||
func (c *COINUT) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (c *COINUT) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
var bal *UserBalance
|
||||
var err error
|
||||
@@ -384,10 +393,10 @@ func (c *COINUT) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (c *COINUT) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name)
|
||||
func (c *COINUT) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(c.Name, assetType)
|
||||
if err != nil {
|
||||
return c.UpdateAccountInfo()
|
||||
return c.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -1054,8 +1063,8 @@ func (c *COINUT) loadInstrumentsIfNotLoaded() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (c *COINUT) ValidateCredentials() error {
|
||||
_, err := c.UpdateAccountInfo()
|
||||
func (c *COINUT) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := c.UpdateAccountInfo(assetType)
|
||||
return c.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
@@ -578,6 +579,11 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
|
||||
}
|
||||
|
||||
e.SetFeatureDefaults()
|
||||
|
||||
if e.API.Endpoints == nil {
|
||||
e.API.Endpoints = e.NewEndpoints()
|
||||
}
|
||||
|
||||
err = e.SetAPIURL()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -767,7 +773,6 @@ func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item
|
||||
e.Name,
|
||||
strings.ToUpper(assetType.String()),
|
||||
remove)
|
||||
|
||||
e.Config.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
|
||||
e.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
|
||||
}
|
||||
@@ -778,52 +783,59 @@ func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item
|
||||
|
||||
// SetAPIURL sets configuration API URL for an exchange
|
||||
func (e *Base) SetAPIURL() error {
|
||||
if e.Config.API.Endpoints.URL == "" || e.Config.API.Endpoints.URLSecondary == "" {
|
||||
return fmt.Errorf("exchange %s: SetAPIURL error. URL vals are empty", e.Name)
|
||||
}
|
||||
|
||||
checkInsecureEndpoint := func(endpoint string) {
|
||||
if strings.Contains(endpoint, "https") {
|
||||
if strings.Contains(endpoint, "https") || strings.Contains(endpoint, "wss") {
|
||||
return
|
||||
}
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"%s is using HTTP instead of HTTPS [%s] for API functionality, an"+
|
||||
"%s is using HTTP instead of HTTPS or WS instead of WSS [%s] for API functionality, an"+
|
||||
" attacker could eavesdrop on this connection. Use at your"+
|
||||
" own risk.",
|
||||
e.Name, endpoint)
|
||||
}
|
||||
|
||||
if e.Config.API.Endpoints.URL != config.APIURLNonDefaultMessage {
|
||||
e.API.Endpoints.URL = e.Config.API.Endpoints.URL
|
||||
checkInsecureEndpoint(e.API.Endpoints.URL)
|
||||
}
|
||||
if e.Config.API.Endpoints.URLSecondary != config.APIURLNonDefaultMessage {
|
||||
e.API.Endpoints.URLSecondary = e.Config.API.Endpoints.URLSecondary
|
||||
checkInsecureEndpoint(e.API.Endpoints.URLSecondary)
|
||||
var err error
|
||||
if e.Config.API.OldEndPoints != nil {
|
||||
if e.Config.API.OldEndPoints.URL != "" && e.Config.API.OldEndPoints.URL != config.APIURLNonDefaultMessage {
|
||||
err = e.API.Endpoints.SetRunning(RestSpot.String(), e.Config.API.OldEndPoints.URL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checkInsecureEndpoint(e.Config.API.OldEndPoints.URL)
|
||||
}
|
||||
if e.Config.API.OldEndPoints.URLSecondary != "" && e.Config.API.OldEndPoints.URLSecondary != config.APIURLNonDefaultMessage {
|
||||
err = e.API.Endpoints.SetRunning(RestSpotSupplementary.String(), e.Config.API.OldEndPoints.URLSecondary)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checkInsecureEndpoint(e.Config.API.OldEndPoints.URLSecondary)
|
||||
}
|
||||
if e.Config.API.OldEndPoints.WebsocketURL != "" && e.Config.API.OldEndPoints.WebsocketURL != config.WebsocketURLNonDefaultMessage {
|
||||
err = e.API.Endpoints.SetRunning(WebsocketSpot.String(), e.Config.API.OldEndPoints.WebsocketURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checkInsecureEndpoint(e.Config.API.OldEndPoints.WebsocketURL)
|
||||
}
|
||||
e.Config.API.OldEndPoints = nil
|
||||
} else if e.Config.API.Endpoints != nil {
|
||||
for key, val := range e.Config.API.Endpoints {
|
||||
if val == "" ||
|
||||
val == config.APIURLNonDefaultMessage ||
|
||||
val == config.WebsocketURLNonDefaultMessage {
|
||||
continue
|
||||
}
|
||||
checkInsecureEndpoint(val)
|
||||
err = e.API.Endpoints.SetRunning(key, val)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
runningMap := e.API.Endpoints.GetURLMap()
|
||||
e.Config.API.Endpoints = runningMap
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAPIURL returns the set API URL
|
||||
func (e *Base) GetAPIURL() string {
|
||||
return e.API.Endpoints.URL
|
||||
}
|
||||
|
||||
// GetSecondaryAPIURL returns the set Secondary API URL
|
||||
func (e *Base) GetSecondaryAPIURL() string {
|
||||
return e.API.Endpoints.URLSecondary
|
||||
}
|
||||
|
||||
// GetAPIURLDefault returns exchange default URL
|
||||
func (e *Base) GetAPIURLDefault() string {
|
||||
return e.API.Endpoints.URLDefault
|
||||
}
|
||||
|
||||
// GetAPIURLSecondaryDefault returns exchange default secondary URL
|
||||
func (e *Base) GetAPIURLSecondaryDefault() string {
|
||||
return e.API.Endpoints.URLSecondaryDefault
|
||||
}
|
||||
|
||||
// SupportsREST returns whether or not the exchange supports
|
||||
// REST
|
||||
func (e *Base) SupportsREST() bool {
|
||||
@@ -946,6 +958,10 @@ func (e *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
|
||||
e.Name)
|
||||
}
|
||||
|
||||
if f.AssetEnabled == nil {
|
||||
f.AssetEnabled = convert.BoolPtr(true)
|
||||
}
|
||||
|
||||
if f.RequestFormat == nil {
|
||||
return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided",
|
||||
e.Name)
|
||||
@@ -1136,3 +1152,112 @@ func (e *Base) SetSaveTradeDataStatus(enabled bool) {
|
||||
log.Debugf(log.Trade, "Set %v 'SaveTradeData' to %v", e.Name, enabled)
|
||||
}
|
||||
}
|
||||
|
||||
// NewEndpoints declares default and running URLs maps
|
||||
func (e *Base) NewEndpoints() *Endpoints {
|
||||
return &Endpoints{
|
||||
Exchange: e.Name,
|
||||
defaults: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaultEndpoints declares and sets the default URLs map
|
||||
func (e *Endpoints) SetDefaultEndpoints(m map[URL]string) error {
|
||||
for k, v := range m {
|
||||
err := e.SetRunning(k.String(), v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRunning populates running URLs map
|
||||
func (e *Endpoints) SetRunning(key, val string) error {
|
||||
e.Lock()
|
||||
defer e.Unlock()
|
||||
err := validateKey(key)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = url.ParseRequestURI(val)
|
||||
if err != nil {
|
||||
log.Warnf(log.ExchangeSys, "Could not set custom URL for %s to %s for exchange %s. invalid URI for request.", key, val, e.Exchange)
|
||||
return nil
|
||||
}
|
||||
e.defaults[key] = val
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateKey(keyVal string) error {
|
||||
for x := range keyURLs {
|
||||
if keyURLs[x].String() == keyVal {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("keyVal invalid")
|
||||
}
|
||||
|
||||
// GetURL gets default url from URLs map
|
||||
func (e *Endpoints) GetURL(key URL) (string, error) {
|
||||
e.RLock()
|
||||
defer e.RUnlock()
|
||||
val, ok := e.defaults[key.String()]
|
||||
if !ok {
|
||||
return "", fmt.Errorf("no endpoint path found for the given key: %v", key)
|
||||
}
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// GetURLMap gets all urls for either running or default map based on the bool value supplied
|
||||
func (e *Endpoints) GetURLMap() map[string]string {
|
||||
e.RLock()
|
||||
var urlMap = make(map[string]string)
|
||||
for k, v := range e.defaults {
|
||||
urlMap[k] = v
|
||||
}
|
||||
e.RUnlock()
|
||||
return urlMap
|
||||
}
|
||||
|
||||
// FormatSymbol formats the given pair to a string suitable for exchange API requests
|
||||
func (e *Base) FormatSymbol(pair currency.Pair, assetType asset.Item) (string, error) {
|
||||
pairFmt, err := e.GetPairFormat(assetType, true)
|
||||
if err != nil {
|
||||
return pair.String(), err
|
||||
}
|
||||
return pairFmt.Format(pair), nil
|
||||
}
|
||||
|
||||
func (u URL) String() string {
|
||||
switch u {
|
||||
case RestSpot:
|
||||
return "RestSpotURL"
|
||||
case RestSpotSupplementary:
|
||||
return "RestSpotSupplementaryURL"
|
||||
case RestUSDTMargined:
|
||||
return "RestUSDTMarginedFuturesURL"
|
||||
case RestCoinMargined:
|
||||
return "RestCoinMarginedFuturesURL"
|
||||
case RestFutures:
|
||||
return "RestFuturesURL"
|
||||
case RestSandbox:
|
||||
return "RestSandboxURL"
|
||||
case RestSwap:
|
||||
return "RestSwapURL"
|
||||
case WebsocketSpot:
|
||||
return "WebsocketSpotURL"
|
||||
case WebsocketSpotSupplementary:
|
||||
return "WebsocketSpotSupplementaryURL"
|
||||
case ChainAnalysis:
|
||||
return "ChainAnalysisURL"
|
||||
case EdgeCase1:
|
||||
return "EdgeCase1URL"
|
||||
case EdgeCase2:
|
||||
return "EdgeCase2URL"
|
||||
case EdgeCase3:
|
||||
return "EdgeCase3URL"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,9 +56,138 @@ func TestSupportsRESTTickerBatchUpdates(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateMap(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "HELOOOOOOOO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "http://test1url.com/",
|
||||
EdgeCase2: "http://test2url.com/",
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
val, ok := b.API.Endpoints.defaults[EdgeCase1.String()]
|
||||
if !ok || val != "http://test1url.com/" {
|
||||
t.Errorf("CreateMap failed, incorrect value received for the given key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSet(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "HELOOOOOOOO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "http://test1url.com/",
|
||||
EdgeCase2: "http://test2url.com/",
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
err = b.API.Endpoints.SetRunning(EdgeCase2.String(), "http://google.com/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
val, ok := b.API.Endpoints.defaults[EdgeCase2.String()]
|
||||
if !ok {
|
||||
t.Error("set method or createmap failed")
|
||||
}
|
||||
if val != "http://google.com/" {
|
||||
t.Errorf("vals didnt match. expecting: %s, got: %s\n", "http://google.com/", val)
|
||||
}
|
||||
err = b.API.Endpoints.SetRunning(EdgeCase3.String(), "Added Edgecase3")
|
||||
if err != nil {
|
||||
t.Errorf("not expecting an error since invalid url val err should be logged but received: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "HELAAAAAOOOOOOOOO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "http://test1.com/",
|
||||
EdgeCase2: "http://test2.com/",
|
||||
})
|
||||
getVal, err := b.API.Endpoints.GetURL(EdgeCase1)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if getVal != "http://test1.com/" {
|
||||
t.Errorf("getVal failed")
|
||||
}
|
||||
err = b.API.Endpoints.SetRunning(EdgeCase2.String(), "http://OVERWRITTENBRO.com.au/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
getChangedVal, err := b.API.Endpoints.GetURL(EdgeCase2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if getChangedVal != "http://OVERWRITTENBRO.com.au/" {
|
||||
t.Error("couldnt get changed val")
|
||||
}
|
||||
_, err = b.API.Endpoints.GetURL(URL(100))
|
||||
if err == nil {
|
||||
t.Error("expecting error due to invalid URL key parsed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAll(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "HELLLLLLO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "http://test1.com.au/",
|
||||
EdgeCase2: "http://test2.com.au/",
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
allRunning := b.API.Endpoints.GetURLMap()
|
||||
if len(allRunning) != 2 {
|
||||
t.Error("invalid running map received")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultEndpoints(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Base{
|
||||
Name: "HELLLLLLO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "http://test1.com.au/",
|
||||
EdgeCase2: "http://test2.com.au/",
|
||||
})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
URL(15): "http://test2.com.au/",
|
||||
})
|
||||
if err == nil {
|
||||
t.Error("expecting an error due to invalid url key")
|
||||
}
|
||||
err = b.API.Endpoints.SetDefaultEndpoints(map[URL]string{
|
||||
EdgeCase1: "",
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("expecting a warning due due to invalid url val but got an error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPClient(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
r := Base{Name: "asdf"}
|
||||
r.SetHTTPClientTimeout(time.Second * 5)
|
||||
|
||||
@@ -1116,14 +1245,21 @@ func TestSetupDefaults(t *testing.T) {
|
||||
AuthenticatedSupport: true,
|
||||
},
|
||||
}
|
||||
b.SetupDefaults(&cfg)
|
||||
|
||||
err := b.SetupDefaults(&cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cfg.HTTPTimeout.String() != "15s" {
|
||||
t.Error("HTTP timeout should be set to 15s")
|
||||
}
|
||||
|
||||
// Test custom HTTP timeout is set
|
||||
cfg.HTTPTimeout = time.Second * 30
|
||||
b.SetupDefaults(&cfg)
|
||||
err = b.SetupDefaults(&cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cfg.HTTPTimeout.String() != "30s" {
|
||||
t.Error("HTTP timeout should be set to 30s")
|
||||
}
|
||||
@@ -1458,78 +1594,6 @@ func TestUpdatePairs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAPIURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
testURL := "https://api.something.com"
|
||||
testURLSecondary := "https://api.somethingelse.com"
|
||||
testURLDefault := "https://api.defaultsomething.com"
|
||||
testURLSecondaryDefault := "https://api.defaultsomethingelse.com"
|
||||
|
||||
tester := Base{Name: "test"}
|
||||
tester.Config = new(config.ExchangeConfig)
|
||||
|
||||
err := tester.SetAPIURL()
|
||||
if err == nil {
|
||||
t.Error("setting zero value config")
|
||||
}
|
||||
|
||||
tester.Config.API.Endpoints.URL = testURL
|
||||
tester.Config.API.Endpoints.URLSecondary = testURLSecondary
|
||||
|
||||
tester.API.Endpoints.URLDefault = testURLDefault
|
||||
tester.API.Endpoints.URLSecondaryDefault = testURLSecondaryDefault
|
||||
|
||||
err = tester.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if tester.GetAPIURL() != testURL {
|
||||
t.Error("incorrect return URL")
|
||||
}
|
||||
|
||||
if tester.GetSecondaryAPIURL() != testURLSecondary {
|
||||
t.Error("incorrect return URL")
|
||||
}
|
||||
|
||||
if tester.GetAPIURLDefault() != testURLDefault {
|
||||
t.Error("incorrect return URL")
|
||||
}
|
||||
|
||||
if tester.GetAPIURLSecondaryDefault() != testURLSecondaryDefault {
|
||||
t.Error("incorrect return URL")
|
||||
}
|
||||
|
||||
tester.Config.API.Endpoints.URL = "http://insecureino.com"
|
||||
tester.Config.API.Endpoints.URLSecondary = tester.Config.API.Endpoints.URL
|
||||
err = tester.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSetAPIURL(b *testing.B) {
|
||||
tester := Base{Name: "test"}
|
||||
|
||||
test := config.ExchangeConfig{}
|
||||
|
||||
test.API.Endpoints.URL = "https://api.something.com"
|
||||
test.API.Endpoints.URLSecondary = "https://api.somethingelse.com"
|
||||
|
||||
tester.API.Endpoints.URLDefault = "https://api.defaultsomething.com"
|
||||
tester.API.Endpoints.URLDefault = "https://api.defaultsomethingelse.com"
|
||||
|
||||
tester.Config = &test
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
err := tester.SetAPIURL()
|
||||
if err != nil {
|
||||
b.Errorf("Benchmark failed %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSupportsWebsocket(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -2107,3 +2171,155 @@ func TestAddTradesToBuffer(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestString(t *testing.T) {
|
||||
if RestSpot.String() != "RestSpotURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestSpotSupplementary.String() != "RestSpotSupplementaryURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestUSDTMargined.String() != "RestUSDTMarginedFuturesURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestCoinMargined.String() != "RestCoinMarginedFuturesURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestFutures.String() != "RestFuturesURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestSandbox.String() != "RestSandboxURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if RestSwap.String() != "RestSwapURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if WebsocketSpot.String() != "WebsocketSpotURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if WebsocketSpotSupplementary.String() != "WebsocketSpotSupplementaryURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if ChainAnalysis.String() != "ChainAnalysisURL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if EdgeCase1.String() != "EdgeCase1URL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if EdgeCase2.String() != "EdgeCase2URL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
if EdgeCase3.String() != "EdgeCase3URL" {
|
||||
t.Errorf("invalid string conversion")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatSymbol(t *testing.T) {
|
||||
b := Base{}
|
||||
spotStore := currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{Uppercase: true},
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Uppercase: true,
|
||||
},
|
||||
}
|
||||
err := b.StoreAssetPairFormat(asset.Spot, spotStore)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
pair, err := currency.NewPairFromString("BTC-USD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
sym, err := b.FormatSymbol(pair, asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if sym != "BTCUSD" {
|
||||
t.Error("formatting failed")
|
||||
}
|
||||
_, err = b.FormatSymbol(pair, asset.Futures)
|
||||
if err == nil {
|
||||
t.Error("expecting an error since asset pair format has not been set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetAPIURL(t *testing.T) {
|
||||
b := Base{
|
||||
Name: "SomeExchange",
|
||||
}
|
||||
b.Config = &config.ExchangeConfig{}
|
||||
var mappy struct {
|
||||
Mappymap map[string]string `json:"urlEndpoints"`
|
||||
}
|
||||
mappy.Mappymap = make(map[string]string)
|
||||
mappy.Mappymap["hi"] = "http://google.com/"
|
||||
b.Config.API.Endpoints = mappy.Mappymap
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.SetAPIURL()
|
||||
if err == nil {
|
||||
t.Error("expecting an error since the key provided is invalid")
|
||||
}
|
||||
mappy.Mappymap = make(map[string]string)
|
||||
b.Config.API.Endpoints = mappy.Mappymap
|
||||
mappy.Mappymap["RestSpotURL"] = "hi"
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Errorf("expecting no error since invalid url value should be logged but received the following error: %v", err)
|
||||
}
|
||||
mappy.Mappymap = make(map[string]string)
|
||||
b.Config.API.Endpoints = mappy.Mappymap
|
||||
mappy.Mappymap["RestSpotURL"] = "http://google.com/"
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err = b.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
mappy.Mappymap = make(map[string]string)
|
||||
b.Config.API.OldEndPoints = &config.APIEndpointsConfig{}
|
||||
b.Config.API.Endpoints = mappy.Mappymap
|
||||
mappy.Mappymap["RestSpotURL"] = "http://google.com/"
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
b.Config.API.OldEndPoints.URL = "heloo"
|
||||
err = b.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Errorf("expecting a warning since invalid oldendpoints url but got an error: %v", err)
|
||||
}
|
||||
mappy.Mappymap = make(map[string]string)
|
||||
b.Config.API.OldEndPoints = &config.APIEndpointsConfig{}
|
||||
b.Config.API.Endpoints = mappy.Mappymap
|
||||
mappy.Mappymap["RestSpotURL"] = "http://google.com/"
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
b.Config.API.OldEndPoints.URL = "https://www.bitstamp.net/"
|
||||
b.Config.API.OldEndPoints.URLSecondary = "https://www.secondary.net/"
|
||||
b.Config.API.OldEndPoints.WebsocketURL = "https://www.websocket.net/"
|
||||
err = b.SetAPIURL()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
var urlLookup URL
|
||||
for x := range keyURLs {
|
||||
if keyURLs[x].String() == "RestSpotURL" {
|
||||
urlLookup = keyURLs[x]
|
||||
}
|
||||
}
|
||||
urlData, err := b.API.Endpoints.GetURL(urlLookup)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if urlData != "https://www.bitstamp.net/" {
|
||||
t.Error("oldendpoints url setting failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetRunning(t *testing.T) {
|
||||
b := Base{
|
||||
Name: "HELOOOOOOOO",
|
||||
}
|
||||
b.API.Endpoints = b.NewEndpoints()
|
||||
err := b.API.Endpoints.SetRunning(EdgeCase1.String(), "http://google.com/")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,19 +166,20 @@ type FeaturesSupported struct {
|
||||
Kline kline.ExchangeCapabilitiesSupported
|
||||
}
|
||||
|
||||
// Endpoints stores running url endpoints for exchanges
|
||||
type Endpoints struct {
|
||||
Exchange string
|
||||
defaults map[string]string
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// API stores the exchange API settings
|
||||
type API struct {
|
||||
AuthenticatedSupport bool
|
||||
AuthenticatedWebsocketSupport bool
|
||||
PEMKeySupport bool
|
||||
|
||||
Endpoints struct {
|
||||
URL string
|
||||
URLDefault string
|
||||
URLSecondary string
|
||||
URLSecondaryDefault string
|
||||
WebsocketURL string
|
||||
}
|
||||
Endpoints *Endpoints
|
||||
|
||||
Credentials struct {
|
||||
Key string
|
||||
@@ -222,3 +223,37 @@ type Base struct {
|
||||
settingsMutex sync.RWMutex
|
||||
OrderbookVerificationBypass bool
|
||||
}
|
||||
|
||||
// url lookup consts
|
||||
const (
|
||||
RestSpot URL = iota
|
||||
RestSpotSupplementary
|
||||
RestUSDTMargined
|
||||
RestCoinMargined
|
||||
RestFutures
|
||||
RestSwap
|
||||
RestSandbox
|
||||
WebsocketSpot
|
||||
WebsocketSpotSupplementary
|
||||
ChainAnalysis
|
||||
EdgeCase1
|
||||
EdgeCase2
|
||||
EdgeCase3
|
||||
)
|
||||
|
||||
var keyURLs = []URL{RestSpot,
|
||||
RestSpotSupplementary,
|
||||
RestUSDTMargined,
|
||||
RestCoinMargined,
|
||||
RestFutures,
|
||||
RestSwap,
|
||||
RestSandbox,
|
||||
WebsocketSpot,
|
||||
WebsocketSpotSupplementary,
|
||||
ChainAnalysis,
|
||||
EdgeCase1,
|
||||
EdgeCase2,
|
||||
EdgeCase3}
|
||||
|
||||
// URL stores uint conversions
|
||||
type URL uint16
|
||||
|
||||
@@ -57,8 +57,8 @@ func (e *EXMO) GetTrades(symbol string) (map[string][]Trades, error) {
|
||||
v := url.Values{}
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string][]Trades)
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoTrades)
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(urlPath, v), &result)
|
||||
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoTrades)
|
||||
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
|
||||
}
|
||||
|
||||
// GetOrderbook returns the orderbook for a symbol or symbols
|
||||
@@ -66,36 +66,36 @@ func (e *EXMO) GetOrderbook(symbol string) (map[string]Orderbook, error) {
|
||||
v := url.Values{}
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string]Orderbook)
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoOrderbook)
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(urlPath, v), &result)
|
||||
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoOrderbook)
|
||||
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
|
||||
}
|
||||
|
||||
// GetTicker returns the ticker for a symbol or symbols
|
||||
func (e *EXMO) GetTicker() (map[string]Ticker, error) {
|
||||
v := url.Values{}
|
||||
result := make(map[string]Ticker)
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoTicker)
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(urlPath, v), &result)
|
||||
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoTicker)
|
||||
return result, e.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues(urlPath, v), &result)
|
||||
}
|
||||
|
||||
// GetPairSettings returns the pair settings for a symbol or symbols
|
||||
func (e *EXMO) GetPairSettings() (map[string]PairSettings, error) {
|
||||
result := make(map[string]PairSettings)
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoPairSettings)
|
||||
return result, e.SendHTTPRequest(urlPath, &result)
|
||||
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoPairSettings)
|
||||
return result, e.SendHTTPRequest(exchange.RestSpot, urlPath, &result)
|
||||
}
|
||||
|
||||
// GetCurrency returns a list of currencies
|
||||
func (e *EXMO) GetCurrency() ([]string, error) {
|
||||
var result []string
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, exmoCurrency)
|
||||
return result, e.SendHTTPRequest(urlPath, &result)
|
||||
urlPath := fmt.Sprintf("/v%s/%s", exmoAPIVersion, exmoCurrency)
|
||||
return result, e.SendHTTPRequest(exchange.RestSpot, urlPath, &result)
|
||||
}
|
||||
|
||||
// GetUserInfo returns the user info
|
||||
func (e *EXMO) GetUserInfo() (UserInfo, error) {
|
||||
var result UserInfo
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoUserInfo, url.Values{}, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoUserInfo, url.Values{}, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func (e *EXMO) CreateOrder(pair, orderType string, price, amount float64) (int64
|
||||
v.Set("quantity", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
|
||||
var resp response
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoOrderCreate, v, &resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderCreate, v, &resp)
|
||||
if !resp.Result {
|
||||
return -1, errors.New(resp.Error)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ func (e *EXMO) CancelExistingOrder(orderID int64) error {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
var resp response
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoOrderCancel, v, &resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderCancel, v, &resp)
|
||||
if !resp.Result {
|
||||
return errors.New(resp.Error)
|
||||
}
|
||||
@@ -142,7 +142,7 @@ func (e *EXMO) CancelExistingOrder(orderID int64) error {
|
||||
// GetOpenOrders returns the users open orders
|
||||
func (e *EXMO) GetOpenOrders() (map[string]OpenOrders, error) {
|
||||
result := make(map[string]OpenOrders)
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoOpenOrders, url.Values{}, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOpenOrders, url.Values{}, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ func (e *EXMO) GetUserTrades(pair, offset, limit string) (map[string][]UserTrade
|
||||
v.Set("limit", limit)
|
||||
}
|
||||
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoUserTrades, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoUserTrades, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ func (e *EXMO) GetCancelledOrders(offset, limit string) ([]CancelledOrder, error
|
||||
v.Set("limit", limit)
|
||||
}
|
||||
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoCancelledOrders, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoCancelledOrders, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ func (e *EXMO) GetOrderTrades(orderID int64) (OrderTrades, error) {
|
||||
v := url.Values{}
|
||||
v.Set("order_id", strconv.FormatInt(orderID, 10))
|
||||
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoOrderTrades, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoOrderTrades, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -198,14 +198,14 @@ func (e *EXMO) GetRequiredAmount(pair string, amount float64) (RequiredAmount, e
|
||||
v.Set("pair", pair)
|
||||
v.Set("quantity", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
var result RequiredAmount
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoRequiredAmount, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoRequiredAmount, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetCryptoDepositAddress returns a list of addresses for cryptocurrency deposits
|
||||
func (e *EXMO) GetCryptoDepositAddress() (map[string]string, error) {
|
||||
var result interface{}
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoDepositAddress, url.Values{}, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoDepositAddress, url.Values{}, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -243,7 +243,7 @@ func (e *EXMO) WithdrawCryptocurrency(currency, address, invoice string, amount
|
||||
|
||||
v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
var resp response
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoWithdrawCrypt, v, &resp)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoWithdrawCrypt, v, &resp)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
@@ -264,7 +264,7 @@ func (e *EXMO) GetWithdrawTXID(taskID int64) (string, error) {
|
||||
v.Set("task_id", strconv.FormatInt(taskID, 10))
|
||||
|
||||
var result response
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoGetWithdrawTXID, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoGetWithdrawTXID, v, &result)
|
||||
return result.TXID, err
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ func (e *EXMO) ExcodeCreate(currency string, amount float64) (ExcodeCreate, erro
|
||||
v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
|
||||
var result ExcodeCreate
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoExcodeCreate, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoExcodeCreate, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ func (e *EXMO) ExcodeLoad(excode string) (ExcodeLoad, error) {
|
||||
v.Set("code", excode)
|
||||
|
||||
var result ExcodeLoad
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoExcodeLoad, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoExcodeLoad, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
@@ -295,15 +295,19 @@ func (e *EXMO) GetWalletHistory(date int64) (WalletHistory, error) {
|
||||
v.Set("date", strconv.FormatInt(date, 10))
|
||||
|
||||
var result WalletHistory
|
||||
err := e.SendAuthenticatedHTTPRequest(http.MethodPost, exmoWalletHistory, v, &result)
|
||||
err := e.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, exmoWalletHistory, v, &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (e *EXMO) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (e *EXMO) SendHTTPRequest(endpoint exchange.URL, path string, result interface{}) error {
|
||||
urlPath, err := e.API.Endpoints.GetURL(endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return e.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: urlPath + path,
|
||||
Result: result,
|
||||
Verbose: e.Verbose,
|
||||
HTTPDebugging: e.HTTPDebugging,
|
||||
@@ -312,12 +316,17 @@ func (e *EXMO) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (e *EXMO) SendAuthenticatedHTTPRequest(method, endpoint string, vals url.Values, result interface{}) error {
|
||||
func (e *EXMO) SendAuthenticatedHTTPRequest(epath exchange.URL, method, endpoint string, vals url.Values, result interface{}) error {
|
||||
if !e.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
e.Name)
|
||||
}
|
||||
|
||||
urlPath, err := e.API.Endpoints.GetURL(epath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
n := e.Requester.GetNonce(true).String()
|
||||
vals.Set("nonce", n)
|
||||
|
||||
@@ -338,11 +347,11 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(method, endpoint string, vals url.Va
|
||||
headers["Sign"] = crypto.HexEncodeToString(hash)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
path := fmt.Sprintf("%s/v%s/%s", e.API.Endpoints.URL, exmoAPIVersion, endpoint)
|
||||
path := fmt.Sprintf("/v%s/%s", exmoAPIVersion, endpoint)
|
||||
|
||||
return e.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: path,
|
||||
Path: urlPath + path,
|
||||
Headers: headers,
|
||||
Body: strings.NewReader(payload),
|
||||
Result: result,
|
||||
|
||||
@@ -264,7 +264,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := e.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -277,7 +278,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
currPair := currency.NewPair(currency.BTC, currency.USD)
|
||||
currPair.Delimiter = "_"
|
||||
|
||||
@@ -108,9 +108,13 @@ func (e *EXMO) SetDefaults() {
|
||||
e.Requester = request.New(e.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(request.NewBasicRateLimit(exmoRateInterval, exmoRequestRate)))
|
||||
|
||||
e.API.Endpoints.URLDefault = exmoAPIURL
|
||||
e.API.Endpoints.URL = e.API.Endpoints.URLDefault
|
||||
e.API.Endpoints = e.NewEndpoints()
|
||||
err = e.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: exmoAPIURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -320,7 +324,7 @@ func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Exmo exchange
|
||||
func (e *EXMO) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (e *EXMO) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = e.Name
|
||||
result, err := e.GetUserInfo()
|
||||
@@ -356,10 +360,10 @@ func (e *EXMO) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (e *EXMO) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(e.Name)
|
||||
func (e *EXMO) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(e.Name, assetType)
|
||||
if err != nil {
|
||||
return e.UpdateAccountInfo()
|
||||
return e.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -655,8 +659,8 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (e *EXMO) ValidateCredentials() error {
|
||||
_, err := e.UpdateAccountInfo()
|
||||
func (e *EXMO) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := e.UpdateAccountInfo(assetType)
|
||||
return e.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ const (
|
||||
getFutures = "/futures"
|
||||
getFuture = "/futures/"
|
||||
getFutureStats = "/futures/%s/stats"
|
||||
getFundingRates = "/funding_rates"
|
||||
getFundingRates = "/funding_rates?"
|
||||
getIndexWeights = "/indexes/%s/weights"
|
||||
getAllWalletBalances = "/wallet/all_balances"
|
||||
|
||||
@@ -90,6 +90,17 @@ const (
|
||||
getOTCQuoteStatus = "/otc/quotes/"
|
||||
acceptOTCQuote = "/otc/quotes/%s/accept"
|
||||
|
||||
// Margin Endpoints
|
||||
marginBorrowRates = "/spot_margin/borrow_rates"
|
||||
maringLendingRates = "/spot_margin/lending_rates"
|
||||
dailyBorrowedAmounts = "/spot_margin/borrow_summary"
|
||||
marginMarketInfo = "/spot_margin/market_info?market=%s"
|
||||
marginBorrowHistory = "/spot_margin/borrow_history"
|
||||
marginLendHistory = "/spot_margin/lending_history"
|
||||
marginLendingOffers = "/spot_margin/offers"
|
||||
marginLendingInfo = "/spot_margin/lending_info"
|
||||
submitLendingOrder = "/spot_margin/offers"
|
||||
|
||||
// Other Consts
|
||||
trailingStopOrderType = "trailingStop"
|
||||
takeProfitOrderType = "takeProfit"
|
||||
@@ -106,7 +117,7 @@ func (f *FTX) GetMarkets() ([]MarketData, error) {
|
||||
resp := struct {
|
||||
Data []MarketData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(ftxAPIURL+getMarkets, &resp)
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getMarkets, &resp)
|
||||
}
|
||||
|
||||
// GetMarket gets market data for a provided asset type
|
||||
@@ -114,7 +125,7 @@ func (f *FTX) GetMarket(marketName string) (MarketData, error) {
|
||||
resp := struct {
|
||||
Data MarketData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(ftxAPIURL+getMarket+marketName,
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getMarket+marketName,
|
||||
&resp)
|
||||
}
|
||||
|
||||
@@ -131,7 +142,7 @@ func (f *FTX) GetOrderbook(marketName string, depth int64) (OrderbookData, error
|
||||
}
|
||||
|
||||
var resp OrderbookData
|
||||
err := f.SendHTTPRequest(fmt.Sprintf(ftxAPIURL+getOrderbook, marketName, strDepth), &result)
|
||||
err := f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getOrderbook, marketName, strDepth), &result)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -166,7 +177,7 @@ func (f *FTX) GetTrades(marketName string, startTime, endTime, limit int64) ([]T
|
||||
params.Set("start_time", strconv.FormatInt(startTime, 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime, 10))
|
||||
}
|
||||
return resp.Data, f.SendHTTPRequest(fmt.Sprintf(ftxAPIURL+getTrades, marketName)+params.Encode(),
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getTrades, marketName)+params.Encode(),
|
||||
&resp)
|
||||
}
|
||||
|
||||
@@ -187,7 +198,7 @@ func (f *FTX) GetHistoricalData(marketName, timeInterval, limit string, startTim
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
return resp.Data, f.SendHTTPRequest(fmt.Sprintf(ftxAPIURL+getHistoricalData, marketName)+params.Encode(), &resp)
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getHistoricalData, marketName)+params.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetFutures gets data on futures
|
||||
@@ -195,7 +206,7 @@ func (f *FTX) GetFutures() ([]FuturesData, error) {
|
||||
resp := struct {
|
||||
Data []FuturesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(ftxAPIURL+getFutures, &resp)
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getFutures, &resp)
|
||||
}
|
||||
|
||||
// GetFuture gets data on a given future
|
||||
@@ -203,7 +214,7 @@ func (f *FTX) GetFuture(futureName string) (FuturesData, error) {
|
||||
resp := struct {
|
||||
Data FuturesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(ftxAPIURL+getFuture+futureName, &resp)
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getFuture+futureName, &resp)
|
||||
}
|
||||
|
||||
// GetFutureStats gets data on a given future's stats
|
||||
@@ -211,28 +222,43 @@ func (f *FTX) GetFutureStats(futureName string) (FutureStatsData, error) {
|
||||
resp := struct {
|
||||
Data FutureStatsData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(fmt.Sprintf(ftxAPIURL+getFutureStats, futureName), &resp)
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getFutureStats, futureName), &resp)
|
||||
}
|
||||
|
||||
// GetFundingRates gets data on funding rates
|
||||
func (f *FTX) GetFundingRates() ([]FundingRatesData, error) {
|
||||
func (f *FTX) GetFundingRates(startTime, endTime time.Time, future string) ([]FundingRatesData, error) {
|
||||
resp := struct {
|
||||
Data []FundingRatesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendHTTPRequest(ftxAPIURL+getFundingRates, &resp)
|
||||
params := url.Values{}
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp.Data, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
if future != "" {
|
||||
params.Set("future", future)
|
||||
}
|
||||
return resp.Data, f.SendHTTPRequest(exchange.RestSpot, getFundingRates+params.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetIndexWeights gets index weights
|
||||
func (f *FTX) GetIndexWeights(index string) (IndexWeights, error) {
|
||||
var resp IndexWeights
|
||||
return resp, f.SendHTTPRequest(ftxAPIURL+fmt.Sprintf(getIndexWeights, index), &resp)
|
||||
return resp, f.SendHTTPRequest(exchange.RestSpot, fmt.Sprintf(getIndexWeights, index), &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (f *FTX) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (f *FTX) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := f.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return f.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: f.Verbose,
|
||||
HTTPDebugging: f.HTTPDebugging,
|
||||
@@ -240,12 +266,86 @@ func (f *FTX) SendHTTPRequest(path string, result interface{}) error {
|
||||
})
|
||||
}
|
||||
|
||||
// GetMarginBorrowRates gets borrowing rates for margin trading
|
||||
func (f *FTX) GetMarginBorrowRates() ([]MarginFundingData, error) {
|
||||
r := struct {
|
||||
Data []MarginFundingData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginBorrowRates, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingRates gets lending rates for margin trading
|
||||
func (f *FTX) GetMarginLendingRates() ([]MarginFundingData, error) {
|
||||
r := struct {
|
||||
Data []MarginFundingData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, maringLendingRates, nil, &r)
|
||||
}
|
||||
|
||||
// MarginDailyBorrowedAmounts gets daily borrowed amounts for margin
|
||||
func (f *FTX) MarginDailyBorrowedAmounts() ([]MarginMarketInfo, error) {
|
||||
r := struct {
|
||||
Data []MarginMarketInfo `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, dailyBorrowedAmounts, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginMarketInfo gets margin market data
|
||||
func (f *FTX) GetMarginMarketInfo(market string) ([]MarginMarketInfo, error) {
|
||||
r := struct {
|
||||
Data []MarginMarketInfo `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, fmt.Sprintf(marginMarketInfo, market), nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginBorrowHistory gets margin borrowing history
|
||||
func (f *FTX) GetMarginBorrowHistory() ([]MarginTransactionHistoryData, error) {
|
||||
r := struct {
|
||||
Data []MarginTransactionHistoryData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginBorrowHistory, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingHistory gets margin lending history
|
||||
func (f *FTX) GetMarginLendingHistory() ([]MarginTransactionHistoryData, error) {
|
||||
r := struct {
|
||||
Data []MarginTransactionHistoryData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendHistory, nil, &r)
|
||||
}
|
||||
|
||||
// GetMarginLendingOffers gets margin lending offers
|
||||
func (f *FTX) GetMarginLendingOffers() ([]LendingOffersData, error) {
|
||||
r := struct {
|
||||
Data []LendingOffersData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendingOffers, nil, &r)
|
||||
}
|
||||
|
||||
// GetLendingInfo gets margin lending info
|
||||
func (f *FTX) GetLendingInfo() ([]LendingInfoData, error) {
|
||||
r := struct {
|
||||
Data []LendingInfoData `json:"result"`
|
||||
}{}
|
||||
return r.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendingInfo, nil, &r)
|
||||
}
|
||||
|
||||
// SubmitLendingOffer submits an offer for margin lending
|
||||
func (f *FTX) SubmitLendingOffer(coin string, size, rate float64) (interface{}, error) {
|
||||
var resp interface{}
|
||||
req := make(map[string]interface{})
|
||||
req["coin"] = coin
|
||||
req["size"] = size
|
||||
req["rate"] = rate
|
||||
return resp, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, marginLendingInfo, req, &resp)
|
||||
}
|
||||
|
||||
// GetAccountInfo gets account info
|
||||
func (f *FTX) GetAccountInfo() (AccountInfoData, error) {
|
||||
resp := struct {
|
||||
Data AccountInfoData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getAccountInfo, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getAccountInfo, nil, &resp)
|
||||
}
|
||||
|
||||
// GetPositions gets the users positions
|
||||
@@ -253,14 +353,14 @@ func (f *FTX) GetPositions() ([]PositionData, error) {
|
||||
resp := struct {
|
||||
Data []PositionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getPositions, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getPositions, nil, &resp)
|
||||
}
|
||||
|
||||
// ChangeAccountLeverage changes default leverage used by account
|
||||
func (f *FTX) ChangeAccountLeverage(leverage float64) error {
|
||||
req := make(map[string]interface{})
|
||||
req["leverage"] = leverage
|
||||
return f.SendAuthHTTPRequest(http.MethodPost, setLeverage, req, nil)
|
||||
return f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, setLeverage, req, nil)
|
||||
}
|
||||
|
||||
// GetCoins gets coins' data in the account wallet
|
||||
@@ -268,7 +368,7 @@ func (f *FTX) GetCoins() ([]WalletCoinsData, error) {
|
||||
resp := struct {
|
||||
Data []WalletCoinsData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getCoins, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getCoins, nil, &resp)
|
||||
}
|
||||
|
||||
// GetBalances gets balances of the account
|
||||
@@ -276,7 +376,7 @@ func (f *FTX) GetBalances() ([]BalancesData, error) {
|
||||
resp := struct {
|
||||
Data []BalancesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getBalances, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// GetAllWalletBalances gets all wallets' balances
|
||||
@@ -284,7 +384,7 @@ func (f *FTX) GetAllWalletBalances() (AllWalletAccountData, error) {
|
||||
resp := struct {
|
||||
Data AllWalletAccountData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getAllWalletBalances, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getAllWalletBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchDepositAddress gets deposit address for a given coin
|
||||
@@ -292,7 +392,7 @@ func (f *FTX) FetchDepositAddress(coin string) (DepositData, error) {
|
||||
resp := struct {
|
||||
Data DepositData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getDepositAddress+coin, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getDepositAddress+coin, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchDepositHistory gets deposit history
|
||||
@@ -300,7 +400,7 @@ func (f *FTX) FetchDepositHistory() ([]TransactionData, error) {
|
||||
resp := struct {
|
||||
Data []TransactionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getDepositHistory, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getDepositHistory, nil, &resp)
|
||||
}
|
||||
|
||||
// FetchWithdrawalHistory gets withdrawal history
|
||||
@@ -308,7 +408,7 @@ func (f *FTX) FetchWithdrawalHistory() ([]TransactionData, error) {
|
||||
resp := struct {
|
||||
Data []TransactionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getWithdrawalHistory, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getWithdrawalHistory, nil, &resp)
|
||||
}
|
||||
|
||||
// Withdraw sends a withdrawal request
|
||||
@@ -329,7 +429,7 @@ func (f *FTX) Withdraw(coin, address, tag, password, code string, size float64)
|
||||
resp := struct {
|
||||
Data TransactionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, withdrawRequest, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, withdrawRequest, req, &resp)
|
||||
}
|
||||
|
||||
// GetOpenOrders gets open orders
|
||||
@@ -341,7 +441,7 @@ func (f *FTX) GetOpenOrders(marketName string) ([]OrderData, error) {
|
||||
resp := struct {
|
||||
Data []OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOpenOrders+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOpenOrders+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// FetchOrderHistory gets order history
|
||||
@@ -363,7 +463,7 @@ func (f *FTX) FetchOrderHistory(marketName string, startTime, endTime time.Time,
|
||||
if limit != "" {
|
||||
params.Set("limit", limit)
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOrderHistory+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOrderHistory+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// GetOpenTriggerOrders gets trigger orders that are currently open
|
||||
@@ -378,7 +478,7 @@ func (f *FTX) GetOpenTriggerOrders(marketName, orderType string) ([]TriggerOrder
|
||||
resp := struct {
|
||||
Data []TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOpenTriggerOrders+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOpenTriggerOrders+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// GetTriggerOrderTriggers gets trigger orders that are currently open
|
||||
@@ -386,7 +486,7 @@ func (f *FTX) GetTriggerOrderTriggers(orderID string) ([]TriggerData, error) {
|
||||
resp := struct {
|
||||
Data []TriggerData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), nil, &resp)
|
||||
}
|
||||
|
||||
// GetTriggerOrderHistory gets trigger orders that are currently open
|
||||
@@ -414,7 +514,7 @@ func (f *FTX) GetTriggerOrderHistory(marketName string, startTime, endTime time.
|
||||
if limit != "" {
|
||||
params.Set("limit", limit)
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getTriggerOrderHistory+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getTriggerOrderHistory+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// Order places an order
|
||||
@@ -440,7 +540,7 @@ func (f *FTX) Order(marketName, side, orderType, reduceOnly, ioc, postOnly, clie
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, placeOrder, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, placeOrder, req, &resp)
|
||||
}
|
||||
|
||||
// TriggerOrder places an order
|
||||
@@ -470,7 +570,7 @@ func (f *FTX) TriggerOrder(marketName, side, orderType, reduceOnly, retryUntilFi
|
||||
resp := struct {
|
||||
Data TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, placeTriggerOrder, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, placeTriggerOrder, req, &resp)
|
||||
}
|
||||
|
||||
// ModifyPlacedOrder modifies a placed order
|
||||
@@ -484,7 +584,7 @@ func (f *FTX) ModifyPlacedOrder(orderID, clientID string, price, size float64) (
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(modifyOrder, orderID), req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrder, orderID), req, &resp)
|
||||
}
|
||||
|
||||
// ModifyOrderByClientID modifies a placed order via clientOrderID
|
||||
@@ -498,7 +598,7 @@ func (f *FTX) ModifyOrderByClientID(clientOrderID, clientID string, price, size
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), req, &resp)
|
||||
}
|
||||
|
||||
// ModifyTriggerOrder modifies an existing trigger order
|
||||
@@ -520,7 +620,7 @@ func (f *FTX) ModifyTriggerOrder(orderID, orderType string, size, triggerPrice,
|
||||
resp := struct {
|
||||
Data TriggerOrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), req, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatus gets the order status of a given orderID
|
||||
@@ -528,7 +628,7 @@ func (f *FTX) GetOrderStatus(orderID string) (OrderData, error) {
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOrderStatus+orderID, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOrderStatus+orderID, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOrderStatusByClientID gets the order status of a given clientOrderID
|
||||
@@ -536,7 +636,7 @@ func (f *FTX) GetOrderStatusByClientID(clientOrderID string) (OrderData, error)
|
||||
resp := struct {
|
||||
Data OrderData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOrderStatusByClientID+clientOrderID, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOrderStatusByClientID+clientOrderID, nil, &resp)
|
||||
}
|
||||
|
||||
// DeleteOrder deletes an order
|
||||
@@ -545,7 +645,7 @@ func (f *FTX) DeleteOrder(orderID string) (string, error) {
|
||||
Result string `json:"result"`
|
||||
Success bool `json:"success"`
|
||||
}{}
|
||||
if err := f.SendAuthHTTPRequest(http.MethodDelete, deleteOrder+orderID, nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodDelete, deleteOrder+orderID, nil, &resp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !resp.Success {
|
||||
@@ -561,7 +661,7 @@ func (f *FTX) DeleteOrderByClientID(clientID string) (string, error) {
|
||||
Success bool `json:"success"`
|
||||
}{}
|
||||
|
||||
if err := f.SendAuthHTTPRequest(http.MethodDelete, deleteOrderByClientID+clientID, nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodDelete, deleteOrderByClientID+clientID, nil, &resp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !resp.Success {
|
||||
@@ -577,7 +677,7 @@ func (f *FTX) DeleteTriggerOrder(orderID string) (string, error) {
|
||||
Success bool `json:"success"`
|
||||
}{}
|
||||
|
||||
if err := f.SendAuthHTTPRequest(http.MethodDelete, cancelTriggerOrder+orderID, nil, &resp); err != nil {
|
||||
if err := f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodDelete, cancelTriggerOrder+orderID, nil, &resp); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if !resp.Success {
|
||||
@@ -605,7 +705,7 @@ func (f *FTX) GetFills(market, limit string, startTime, endTime time.Time) ([]Fi
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getFills+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getFills+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// GetFundingPayments gets funding payments
|
||||
@@ -624,7 +724,7 @@ func (f *FTX) GetFundingPayments(startTime, endTime time.Time, future string) ([
|
||||
if future != "" {
|
||||
params.Set("future", future)
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getFundingPayments+params.Encode(), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getFundingPayments+params.Encode(), nil, &resp)
|
||||
}
|
||||
|
||||
// ListLeveragedTokens lists leveraged tokens
|
||||
@@ -632,7 +732,7 @@ func (f *FTX) ListLeveragedTokens() ([]LeveragedTokensData, error) {
|
||||
resp := struct {
|
||||
Data []LeveragedTokensData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getLeveragedTokens, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getLeveragedTokens, nil, &resp)
|
||||
}
|
||||
|
||||
// GetTokenInfo gets token info
|
||||
@@ -640,7 +740,7 @@ func (f *FTX) GetTokenInfo(tokenName string) ([]LeveragedTokensData, error) {
|
||||
resp := struct {
|
||||
Data []LeveragedTokensData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getTokenInfo+tokenName, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getTokenInfo+tokenName, nil, &resp)
|
||||
}
|
||||
|
||||
// ListLTBalances gets leveraged tokens' balances
|
||||
@@ -648,7 +748,7 @@ func (f *FTX) ListLTBalances() ([]LTBalanceData, error) {
|
||||
resp := struct {
|
||||
Data []LTBalanceData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getLTBalances, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getLTBalances, nil, &resp)
|
||||
}
|
||||
|
||||
// ListLTCreations lists the leveraged tokens' creation requests
|
||||
@@ -656,7 +756,7 @@ func (f *FTX) ListLTCreations() ([]LTCreationData, error) {
|
||||
resp := struct {
|
||||
Data []LTCreationData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getLTCreations, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getLTCreations, nil, &resp)
|
||||
}
|
||||
|
||||
// RequestLTCreation sends a request to create a leveraged token
|
||||
@@ -666,7 +766,7 @@ func (f *FTX) RequestLTCreation(tokenName string, size float64) (RequestTokenCre
|
||||
resp := struct {
|
||||
Data RequestTokenCreationData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), req, &resp)
|
||||
}
|
||||
|
||||
// ListLTRedemptions lists the leveraged tokens' redemption requests
|
||||
@@ -674,7 +774,7 @@ func (f *FTX) ListLTRedemptions() ([]LTRedemptionData, error) {
|
||||
resp := struct {
|
||||
Data []LTRedemptionData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getLTRedemptions, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getLTRedemptions, nil, &resp)
|
||||
}
|
||||
|
||||
// RequestLTRedemption sends a request to redeem a leveraged token
|
||||
@@ -684,7 +784,7 @@ func (f *FTX) RequestLTRedemption(tokenName string, size float64) (LTRedemptionR
|
||||
resp := struct {
|
||||
Data LTRedemptionRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), req, &resp)
|
||||
}
|
||||
|
||||
// GetQuoteRequests gets a list of quote requests
|
||||
@@ -692,7 +792,7 @@ func (f *FTX) GetQuoteRequests() ([]QuoteRequestData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getListQuotes, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getListQuotes, nil, &resp)
|
||||
}
|
||||
|
||||
// GetYourQuoteRequests gets a list of your quote requests
|
||||
@@ -700,7 +800,7 @@ func (f *FTX) GetYourQuoteRequests() ([]PersonalQuotesData, error) {
|
||||
resp := struct {
|
||||
Data []PersonalQuotesData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getMyQuotesRequests, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getMyQuotesRequests, nil, &resp)
|
||||
}
|
||||
|
||||
// CreateQuoteRequest sends a request to create a quote
|
||||
@@ -725,7 +825,7 @@ func (f *FTX) CreateQuoteRequest(underlying, optionType, side string, expiry int
|
||||
resp := struct {
|
||||
Data CreateQuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, createQuoteRequest, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, createQuoteRequest, req, &resp)
|
||||
}
|
||||
|
||||
// DeleteQuote sends request to cancel a quote
|
||||
@@ -733,13 +833,13 @@ func (f *FTX) DeleteQuote(requestID string) (CancelQuoteRequestData, error) {
|
||||
resp := struct {
|
||||
Data CancelQuoteRequestData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodDelete, deleteQuote+requestID, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodDelete, deleteQuote+requestID, nil, &resp)
|
||||
}
|
||||
|
||||
// GetQuotesForYourQuote gets a list of quotes for your quote
|
||||
func (f *FTX) GetQuotesForYourQuote(requestID string) (QuoteForQuoteData, error) {
|
||||
var resp QuoteForQuoteData
|
||||
return resp, f.SendAuthHTTPRequest(http.MethodGet, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
return resp, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
}
|
||||
|
||||
// MakeQuote makes a quote for a quote
|
||||
@@ -749,7 +849,7 @@ func (f *FTX) MakeQuote(requestID, price string) ([]QuoteForQuoteData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(endpointQuote, requestID), nil, &resp)
|
||||
}
|
||||
|
||||
// MyQuotes gets a list of my quotes for quotes
|
||||
@@ -757,7 +857,7 @@ func (f *FTX) MyQuotes() ([]QuoteForQuoteData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getMyQuotes, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getMyQuotes, nil, &resp)
|
||||
}
|
||||
|
||||
// DeleteMyQuote deletes my quote for quotes
|
||||
@@ -765,7 +865,7 @@ func (f *FTX) DeleteMyQuote(quoteID string) ([]QuoteForQuoteData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodDelete, deleteMyQuote+quoteID, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodDelete, deleteMyQuote+quoteID, nil, &resp)
|
||||
}
|
||||
|
||||
// AcceptQuote accepts the quote for quote
|
||||
@@ -773,7 +873,7 @@ func (f *FTX) AcceptQuote(quoteID string) ([]QuoteForQuoteData, error) {
|
||||
resp := struct {
|
||||
Data []QuoteForQuoteData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), nil, &resp)
|
||||
}
|
||||
|
||||
// GetAccountOptionsInfo gets account's options' info
|
||||
@@ -781,7 +881,7 @@ func (f *FTX) GetAccountOptionsInfo() (AccountOptionsInfoData, error) {
|
||||
resp := struct {
|
||||
Data AccountOptionsInfoData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOptionsInfo, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOptionsInfo, nil, &resp)
|
||||
}
|
||||
|
||||
// GetOptionsPositions gets options' positions
|
||||
@@ -789,7 +889,7 @@ func (f *FTX) GetOptionsPositions() ([]OptionsPositionsData, error) {
|
||||
resp := struct {
|
||||
Data []OptionsPositionsData `json:"result"`
|
||||
}{}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOptionsPositions, nil, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOptionsPositions, nil, &resp)
|
||||
}
|
||||
|
||||
// GetPublicOptionsTrades gets options' trades from public
|
||||
@@ -808,7 +908,7 @@ func (f *FTX) GetPublicOptionsTrades(startTime, endTime time.Time, limit string)
|
||||
if limit != "" {
|
||||
req["limit"] = limit
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getPublicOptionsTrades, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getPublicOptionsTrades, req, &resp)
|
||||
}
|
||||
|
||||
// GetOptionsFills gets fills data for options
|
||||
@@ -827,15 +927,18 @@ func (f *FTX) GetOptionsFills(startTime, endTime time.Time, limit string) ([]Opt
|
||||
if limit != "" {
|
||||
req["limit"] = limit
|
||||
}
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOptionsFills, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOptionsFills, req, &resp)
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated request
|
||||
func (f *FTX) SendAuthHTTPRequest(method, path string, data, result interface{}) error {
|
||||
func (f *FTX) SendAuthHTTPRequest(ep exchange.URL, method, path string, data, result interface{}) error {
|
||||
endpoint, err := f.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ts := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
var body io.Reader
|
||||
var hmac, payload []byte
|
||||
var err error
|
||||
if data != nil {
|
||||
payload, err = json.Marshal(data)
|
||||
if err != nil {
|
||||
@@ -855,7 +958,7 @@ func (f *FTX) SendAuthHTTPRequest(method, path string, data, result interface{})
|
||||
headers["Content-Type"] = "application/json"
|
||||
return f.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: ftxAPIURL + path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: body,
|
||||
Result: result,
|
||||
@@ -947,7 +1050,7 @@ func (f *FTX) RequestForQuotes(base, quote string, amount float64) (RequestQuote
|
||||
req["fromCoin"] = base
|
||||
req["toCoin"] = quote
|
||||
req["size"] = amount
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodPost, requestOTCQuote, req, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, requestOTCQuote, req, &resp)
|
||||
}
|
||||
|
||||
// GetOTCQuoteStatus gets quote status of a quote
|
||||
@@ -957,10 +1060,10 @@ func (f *FTX) GetOTCQuoteStatus(marketName, quoteID string) ([]QuoteStatusData,
|
||||
}{}
|
||||
params := url.Values{}
|
||||
params.Set("market", marketName)
|
||||
return resp.Data, f.SendAuthHTTPRequest(http.MethodGet, getOTCQuoteStatus+quoteID, params, &resp)
|
||||
return resp.Data, f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodGet, getOTCQuoteStatus+quoteID, params, &resp)
|
||||
}
|
||||
|
||||
// AcceptOTCQuote requests for otc quotes
|
||||
func (f *FTX) AcceptOTCQuote(quoteID string) error {
|
||||
return f.SendAuthHTTPRequest(http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), nil, nil)
|
||||
return f.SendAuthHTTPRequest(exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), nil, nil)
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func TestGetFutureStats(t *testing.T) {
|
||||
|
||||
func TestGetFundingRates(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := f.GetFundingRates()
|
||||
_, err := f.GetFundingRates(time.Now().Add(-time.Hour), time.Now(), "BTC-PERP")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -175,6 +175,28 @@ func TestGetPositions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetBalances()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllWalletBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetAllWalletBalances()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChangeAccountLeverage(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
@@ -197,23 +219,100 @@ func TestGetCoins(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBalances(t *testing.T) {
|
||||
func TestGetMarginBorrowRates(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetBalances()
|
||||
_, err := f.GetMarginBorrowRates()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAllWalletBalances(t *testing.T) {
|
||||
func TestGetMarginLendingRates(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetAllWalletBalances()
|
||||
_, err := f.GetMarginLendingRates()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarginDailyBorrowedAmounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.MarginDailyBorrowedAmounts()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginMarketInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetMarginMarketInfo("BTC_USD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginBorrowHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetMarginBorrowHistory()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginLendingHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetMarginLendingHistory()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarginLendingOffers(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetMarginLendingOffers()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLendingInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.GetLendingInfo()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubmitLendingOffer(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := f.SubmitLendingOffer("btc", 0.1, 500)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -727,6 +826,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
var orderReq order.GetOrdersRequest
|
||||
cp := currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "/")
|
||||
orderReq.Pairs = append(orderReq.Pairs, cp)
|
||||
orderReq.AssetType = asset.Spot
|
||||
_, err := f.GetActiveOrders(&orderReq)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -741,6 +841,7 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
var orderReq order.GetOrdersRequest
|
||||
cp := currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "/")
|
||||
orderReq.Pairs = append(orderReq.Pairs, cp)
|
||||
orderReq.AssetType = asset.Spot
|
||||
_, err := f.GetOrderHistory(&orderReq)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -752,7 +853,7 @@ func TestUpdateAccountHoldings(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := f.UpdateAccountInfo()
|
||||
_, err := f.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -763,7 +864,7 @@ func TestFetchAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys required but not set, skipping test")
|
||||
}
|
||||
_, err := f.FetchAccountInfo()
|
||||
_, err := f.FetchAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,47 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
// MarginFundingData stores borrowing/lending data for margin trading
|
||||
type MarginFundingData struct {
|
||||
Coin string `json:"coin"`
|
||||
Estimate float64 `json:"estimate"`
|
||||
Previous float64 `json:"previous"`
|
||||
}
|
||||
|
||||
// MarginMarketInfo stores margin market info
|
||||
type MarginMarketInfo struct {
|
||||
Coin string `json:"coin"`
|
||||
Borrowed float64 `json:"borrowed"`
|
||||
Free float64 `json:"free"`
|
||||
EstimatedRate float64 `json:"estimatedRate"`
|
||||
PreviousRate float64 `json:"previousRate"`
|
||||
}
|
||||
|
||||
// MarginTransactionHistoryData stores margin borrowing/lending history
|
||||
type MarginTransactionHistoryData struct {
|
||||
Coin string `json:"coin"`
|
||||
Cost float64 `json:"cost"`
|
||||
Rate float64 `json:"rate"`
|
||||
Size float64 `json:"size"`
|
||||
Time time.Time `json:"time"`
|
||||
}
|
||||
|
||||
// LendingOffersData stores data for lending offers
|
||||
type LendingOffersData struct {
|
||||
Coin string `json:"coin"`
|
||||
Rate float64 `json:"rate"`
|
||||
Size float64 `json:"size"`
|
||||
}
|
||||
|
||||
// LendingInfoData stores margin lending info
|
||||
type LendingInfoData struct {
|
||||
Coin string `json:"coin"`
|
||||
Lendable float64 `json:"lendable"`
|
||||
Locked float64 `json:"locked"`
|
||||
MinRate float64 `json:"minRate"`
|
||||
Offered float64 `json:"offered"`
|
||||
}
|
||||
|
||||
// MarketData stores market data
|
||||
type MarketData struct {
|
||||
Name string `json:"name"`
|
||||
|
||||
@@ -142,9 +142,14 @@ func (f *FTX) SetDefaults() {
|
||||
f.Requester = request.New(f.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(request.NewBasicRateLimit(ratePeriod, rateLimit)))
|
||||
|
||||
f.API.Endpoints.URLDefault = ftxAPIURL
|
||||
f.API.Endpoints.URL = f.API.Endpoints.URLDefault
|
||||
f.API.Endpoints = f.NewEndpoints()
|
||||
err = f.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: ftxAPIURL,
|
||||
exchange.WebsocketSpot: ftxWSURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
f.Websocket = stream.New()
|
||||
f.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
f.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -163,6 +168,11 @@ func (f *FTX) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsEndpoint, err := f.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = f.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -170,7 +180,7 @@ func (f *FTX) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: ftxWSURL,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsEndpoint,
|
||||
Connector: f.WsConnect,
|
||||
Subscriber: f.Subscribe,
|
||||
UnSubscriber: f.Unsubscribe,
|
||||
@@ -365,7 +375,7 @@ func (f *FTX) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (f *FTX) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (f *FTX) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var resp account.Holdings
|
||||
data, err := f.GetBalances()
|
||||
if err != nil {
|
||||
@@ -393,10 +403,10 @@ func (f *FTX) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (f *FTX) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(f.Name)
|
||||
func (f *FTX) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(f.Name, assetType)
|
||||
if err != nil {
|
||||
return f.UpdateAccountInfo()
|
||||
return f.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -651,6 +661,8 @@ func (s *OrderData) GetCompatible(f *FTX) (OrderVars, error) {
|
||||
resp.Side = order.Buy
|
||||
case order.Sell.Lower():
|
||||
resp.Side = order.Sell
|
||||
default:
|
||||
resp.Side = order.UnknownSide
|
||||
}
|
||||
switch s.Status {
|
||||
case strings.ToLower(order.New.String()):
|
||||
@@ -667,6 +679,8 @@ func (s *OrderData) GetCompatible(f *FTX) (OrderVars, error) {
|
||||
if s.FilledSize == s.Size {
|
||||
resp.Status = order.Filled
|
||||
}
|
||||
default:
|
||||
resp.Status = order.AnyStatus
|
||||
}
|
||||
var feeBuilder exchange.FeeBuilder
|
||||
feeBuilder.PurchasePrice = s.AvgFillPrice
|
||||
@@ -991,8 +1005,8 @@ func (f *FTX) AuthenticateWebsocket() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (f *FTX) ValidateCredentials() error {
|
||||
_, err := f.UpdateAccountInfo()
|
||||
func (f *FTX) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := f.UpdateAccountInfo(assetType)
|
||||
return f.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ type Gateio struct {
|
||||
// GetSymbols returns all supported symbols
|
||||
func (g *Gateio) GetSymbols() ([]string, error) {
|
||||
var result []string
|
||||
urlPath := fmt.Sprintf("%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioSymbol)
|
||||
err := g.SendHTTPRequest(urlPath, &result)
|
||||
urlPath := fmt.Sprintf("/%s/%s", gateioAPIVersion, gateioSymbol)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &result)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -66,10 +66,10 @@ func (g *Gateio) GetMarketInfo() (MarketInfoResponse, error) {
|
||||
Pairs []interface{} `json:"pairs"`
|
||||
}
|
||||
|
||||
urlPath := fmt.Sprintf("%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioMarketInfo)
|
||||
urlPath := fmt.Sprintf("/%s/%s", gateioAPIVersion, gateioMarketInfo)
|
||||
var res response
|
||||
var result MarketInfoResponse
|
||||
err := g.SendHTTPRequest(urlPath, &res)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &res)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -106,16 +106,16 @@ func (g *Gateio) GetLatestSpotPrice(symbol string) (float64, error) {
|
||||
// GetTicker returns a ticker for the supplied symbol
|
||||
// updated every 10 seconds
|
||||
func (g *Gateio) GetTicker(symbol string) (TickerResponse, error) {
|
||||
urlPath := fmt.Sprintf("%s/%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioTicker, symbol)
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", gateioAPIVersion, gateioTicker, symbol)
|
||||
var res TickerResponse
|
||||
return res, g.SendHTTPRequest(urlPath, &res)
|
||||
return res, g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &res)
|
||||
}
|
||||
|
||||
// GetTickers returns tickers for all symbols
|
||||
func (g *Gateio) GetTickers() (map[string]TickerResponse, error) {
|
||||
urlPath := fmt.Sprintf("%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioTickers)
|
||||
urlPath := fmt.Sprintf("/%s/%s", gateioAPIVersion, gateioTickers)
|
||||
resp := make(map[string]TickerResponse)
|
||||
err := g.SendHTTPRequest(urlPath, &resp)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -124,9 +124,9 @@ func (g *Gateio) GetTickers() (map[string]TickerResponse, error) {
|
||||
|
||||
// GetTrades returns trades for symbols
|
||||
func (g *Gateio) GetTrades(symbol string) (TradeHistory, error) {
|
||||
urlPath := fmt.Sprintf("%s/%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioTrades, symbol)
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", gateioAPIVersion, gateioTrades, symbol)
|
||||
var resp TradeHistory
|
||||
err := g.SendHTTPRequest(urlPath, &resp)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &resp)
|
||||
if err != nil {
|
||||
return TradeHistory{}, err
|
||||
}
|
||||
@@ -135,9 +135,9 @@ func (g *Gateio) GetTrades(symbol string) (TradeHistory, error) {
|
||||
|
||||
// GetOrderbook returns the orderbook data for a suppled symbol
|
||||
func (g *Gateio) GetOrderbook(symbol string) (Orderbook, error) {
|
||||
urlPath := fmt.Sprintf("%s/%s/%s/%s", g.API.Endpoints.URLSecondary, gateioAPIVersion, gateioOrderbook, symbol)
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", gateioAPIVersion, gateioOrderbook, symbol)
|
||||
var resp OrderbookResponse
|
||||
err := g.SendHTTPRequest(urlPath, &resp)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -196,8 +196,7 @@ func (g *Gateio) GetOrderbook(symbol string) (Orderbook, error) {
|
||||
|
||||
// GetSpotKline returns kline data for the most recent time period
|
||||
func (g *Gateio) GetSpotKline(arg KlinesRequestParams) (kline.Item, error) {
|
||||
urlPath := fmt.Sprintf("%s/%s/%s/%s?group_sec=%s&range_hour=%d",
|
||||
g.API.Endpoints.URLSecondary,
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s?group_sec=%s&range_hour=%d",
|
||||
gateioAPIVersion,
|
||||
gateioKline,
|
||||
arg.Symbol,
|
||||
@@ -205,7 +204,7 @@ func (g *Gateio) GetSpotKline(arg KlinesRequestParams) (kline.Item, error) {
|
||||
arg.HourSize)
|
||||
|
||||
var rawKlines map[string]interface{}
|
||||
err := g.SendHTTPRequest(urlPath, &rawKlines)
|
||||
err := g.SendHTTPRequest(exchange.RestSpotSupplementary, urlPath, &rawKlines)
|
||||
if err != nil {
|
||||
return kline.Item{}, err
|
||||
}
|
||||
@@ -270,7 +269,7 @@ func (g *Gateio) GetBalances() (BalancesResponse, error) {
|
||||
var result BalancesResponse
|
||||
|
||||
return result,
|
||||
g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioBalances, "", &result)
|
||||
g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioBalances, "", &result)
|
||||
}
|
||||
|
||||
// SpotNewOrder places a new order
|
||||
@@ -285,7 +284,7 @@ func (g *Gateio) SpotNewOrder(arg SpotNewOrderRequestParams) (SpotNewOrderRespon
|
||||
)
|
||||
|
||||
urlPath := fmt.Sprintf("%s/%s", gateioOrder, arg.Type)
|
||||
return result, g.SendAuthenticatedHTTPRequest(http.MethodPost, urlPath, params, &result)
|
||||
return result, g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, urlPath, params, &result)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels an order given the supplied orderID and symbol
|
||||
@@ -304,7 +303,7 @@ func (g *Gateio) CancelExistingOrder(orderID int64, symbol string) (bool, error)
|
||||
orderID,
|
||||
symbol,
|
||||
)
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioCancelOrder, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioCancelOrder, params, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -316,10 +315,14 @@ func (g *Gateio) CancelExistingOrder(orderID int64, symbol string) (bool, error)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (g *Gateio) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (g *Gateio) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := g.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return g.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: g.Verbose,
|
||||
HTTPDebugging: g.HTTPDebugging,
|
||||
@@ -341,7 +344,7 @@ func (g *Gateio) CancelAllExistingOrders(orderType int64, symbol string) error {
|
||||
orderType,
|
||||
symbol,
|
||||
)
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioCancelAllOrders, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioCancelAllOrders, params, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -362,7 +365,7 @@ func (g *Gateio) GetOpenOrders(symbol string) (OpenOrdersResponse, error) {
|
||||
params = fmt.Sprintf("currencyPair=%s", symbol)
|
||||
}
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioOpenOrders, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioOpenOrders, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -380,7 +383,7 @@ func (g *Gateio) GetTradeHistory(symbol string) (TradHistoryResponse, error) {
|
||||
var result TradHistoryResponse
|
||||
params = fmt.Sprintf("currencyPair=%s", symbol)
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioTradeHistory, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioTradeHistory, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
@@ -400,12 +403,15 @@ func (g *Gateio) GenerateSignature(message string) []byte {
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends authenticated requests to the Gateio API
|
||||
// To use this you must setup an APIKey and APISecret from the exchange
|
||||
func (g *Gateio) SendAuthenticatedHTTPRequest(method, endpoint, param string, result interface{}) error {
|
||||
func (g *Gateio) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint, param string, result interface{}) error {
|
||||
if !g.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
g.Name)
|
||||
}
|
||||
|
||||
ePoint, err := g.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
headers["key"] = g.API.Credentials.Key
|
||||
@@ -413,10 +419,10 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(method, endpoint, param string, re
|
||||
hmac := g.GenerateSignature(param)
|
||||
headers["sign"] = crypto.HexEncodeToString(hmac)
|
||||
|
||||
urlPath := fmt.Sprintf("%s/%s/%s", g.API.Endpoints.URL, gateioAPIVersion, endpoint)
|
||||
urlPath := fmt.Sprintf("%s/%s/%s", ePoint, gateioAPIVersion, endpoint)
|
||||
|
||||
var intermidiary json.RawMessage
|
||||
err := g.SendPayload(context.Background(), &request.Item{
|
||||
err = g.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: urlPath,
|
||||
Headers: headers,
|
||||
@@ -518,7 +524,7 @@ func (g *Gateio) WithdrawCrypto(currency, address string, amount float64) (*with
|
||||
address,
|
||||
amount,
|
||||
)
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioWithdraw, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioWithdraw, params, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -544,7 +550,7 @@ func (g *Gateio) GetCryptoDepositAddress(currency string) (string, error) {
|
||||
params := fmt.Sprintf("currency=%s",
|
||||
currency)
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, gateioDepositAddress, params, &result)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, gateioDepositAddress, params, &result)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
@@ -285,7 +285,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := g.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -298,7 +299,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
currPair := currency.NewPair(currency.LTC, currency.BTC)
|
||||
@@ -398,12 +400,12 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if apiSecret == "" || apiKey == "" {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
_, err := g.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
} else {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
_, err := g.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
|
||||
@@ -127,12 +127,15 @@ func (g *Gateio) SetDefaults() {
|
||||
}
|
||||
g.Requester = request.New(g.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
|
||||
g.API.Endpoints.URLDefault = gateioTradeURL
|
||||
g.API.Endpoints.URL = g.API.Endpoints.URLDefault
|
||||
g.API.Endpoints.URLSecondaryDefault = gateioMarketURL
|
||||
g.API.Endpoints.URLSecondary = g.API.Endpoints.URLSecondaryDefault
|
||||
g.API.Endpoints.WebsocketURL = gateioWebsocketEndpoint
|
||||
g.API.Endpoints = g.NewEndpoints()
|
||||
err = g.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: gateioTradeURL,
|
||||
exchange.RestSpotSupplementary: gateioMarketURL,
|
||||
exchange.WebsocketSpot: gateioWebsocketEndpoint,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
g.Websocket = stream.New()
|
||||
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -151,6 +154,11 @@ func (g *Gateio) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := g.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = g.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -158,7 +166,7 @@ func (g *Gateio) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: gateioWebsocketEndpoint,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: g.WsConnect,
|
||||
Subscriber: g.Subscribe,
|
||||
GenerateSubscriptions: g.GenerateDefaultSubscriptions,
|
||||
@@ -316,7 +324,7 @@ func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// ZB exchange
|
||||
func (g *Gateio) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (g *Gateio) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
var balances []account.Balance
|
||||
|
||||
@@ -401,10 +409,10 @@ func (g *Gateio) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (g *Gateio) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name)
|
||||
func (g *Gateio) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name, assetType)
|
||||
if err != nil {
|
||||
return g.UpdateAccountInfo()
|
||||
return g.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -802,8 +810,8 @@ func (g *Gateio) AuthenticateWebsocket() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (g *Gateio) ValidateCredentials() error {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
func (g *Gateio) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := g.UpdateAccountInfo(assetType)
|
||||
return g.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -67,15 +67,15 @@ type Gemini struct {
|
||||
// GetSymbols returns all available symbols for trading
|
||||
func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
var symbols []string
|
||||
path := fmt.Sprintf("%s/v%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiSymbols)
|
||||
return symbols, g.SendHTTPRequest(path, &symbols)
|
||||
path := fmt.Sprintf("/v%s/%s", geminiAPIVersion, geminiSymbols)
|
||||
return symbols, g.SendHTTPRequest(exchange.RestSpot, path, &symbols)
|
||||
}
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(currencyPair string) (TickerV2, error) {
|
||||
ticker := TickerV2{}
|
||||
path := fmt.Sprintf("%s/v2/ticker/%s", g.API.Endpoints.URL, currencyPair)
|
||||
err := g.SendHTTPRequest(path, &ticker)
|
||||
path := fmt.Sprintf("/v2/ticker/%s", currencyPair)
|
||||
err := g.SendHTTPRequest(exchange.RestSpot, path, &ticker)
|
||||
if err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
@@ -96,15 +96,14 @@ func (g *Gemini) GetTicker(currencyPair string) (TickerV2, error) {
|
||||
// Type is an integer ie "params.Set("limit_asks", 30)"
|
||||
func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook, error) {
|
||||
path := common.EncodeURLValues(
|
||||
fmt.Sprintf("%s/v%s/%s/%s",
|
||||
g.API.Endpoints.URL,
|
||||
fmt.Sprintf("/v%s/%s/%s",
|
||||
geminiAPIVersion,
|
||||
geminiOrderbook,
|
||||
currencyPair),
|
||||
params)
|
||||
|
||||
var orderbook Orderbook
|
||||
return orderbook, g.SendHTTPRequest(path, &orderbook)
|
||||
return orderbook, g.SendHTTPRequest(exchange.RestSpot, path, &orderbook)
|
||||
}
|
||||
|
||||
// GetTrades return the trades that have executed since the specified timestamp.
|
||||
@@ -127,18 +126,18 @@ func (g *Gemini) GetTrades(currencyPair string, since, limit int64, includeBreak
|
||||
if includeBreaks {
|
||||
params.Add("include_breaks", strconv.FormatBool(true))
|
||||
}
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiTrades, currencyPair), params)
|
||||
path := common.EncodeURLValues(fmt.Sprintf("/v%s/%s/%s", geminiAPIVersion, geminiTrades, currencyPair), params)
|
||||
var trades []Trade
|
||||
|
||||
return trades, g.SendHTTPRequest(path, &trades)
|
||||
return trades, g.SendHTTPRequest(exchange.RestSpot, path, &trades)
|
||||
}
|
||||
|
||||
// GetAuction returns auction information
|
||||
func (g *Gemini) GetAuction(currencyPair string) (Auction, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiAuction, currencyPair)
|
||||
path := fmt.Sprintf("/v%s/%s/%s", geminiAPIVersion, geminiAuction, currencyPair)
|
||||
auction := Auction{}
|
||||
|
||||
return auction, g.SendHTTPRequest(path, &auction)
|
||||
return auction, g.SendHTTPRequest(exchange.RestSpot, path, &auction)
|
||||
}
|
||||
|
||||
// GetAuctionHistory returns the auction events, optionally including
|
||||
@@ -153,9 +152,9 @@ func (g *Gemini) GetAuction(currencyPair string) (Auction, error) {
|
||||
// include_indicative - [bool] Whether to include publication of
|
||||
// indicative prices and quantities.
|
||||
func (g *Gemini) GetAuctionHistory(currencyPair string, params url.Values) ([]AuctionHistory, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", g.API.Endpoints.URL, geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)
|
||||
path := common.EncodeURLValues(fmt.Sprintf("/v%s/%s/%s/%s", geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)
|
||||
var auctionHist []AuctionHistory
|
||||
return auctionHist, g.SendHTTPRequest(path, &auctionHist)
|
||||
return auctionHist, g.SendHTTPRequest(exchange.RestSpot, path, &auctionHist)
|
||||
}
|
||||
|
||||
// NewOrder Only limit orders are supported through the API at present.
|
||||
@@ -169,7 +168,7 @@ func (g *Gemini) NewOrder(symbol string, amount, price float64, side, orderType
|
||||
req["type"] = orderType
|
||||
|
||||
response := Order{}
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiOrderNew, req, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiOrderNew, req, &response)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -183,7 +182,7 @@ func (g *Gemini) CancelExistingOrder(orderID int64) (Order, error) {
|
||||
req["order_id"] = orderID
|
||||
|
||||
response := Order{}
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiOrderCancel, req, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiOrderCancel, req, &response)
|
||||
if err != nil {
|
||||
return Order{}, err
|
||||
}
|
||||
@@ -205,7 +204,7 @@ func (g *Gemini) CancelExistingOrders(cancelBySession bool) (OrderResult, error)
|
||||
}
|
||||
|
||||
var response OrderResult
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, path, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -222,7 +221,7 @@ func (g *Gemini) GetOrderStatus(orderID int64) (Order, error) {
|
||||
|
||||
response := Order{}
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiOrderStatus, req, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiOrderStatus, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -241,7 +240,7 @@ func (g *Gemini) GetOrders() ([]Order, error) {
|
||||
orders []Order
|
||||
}
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiOrders, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiOrders, nil, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -268,7 +267,7 @@ func (g *Gemini) GetTradeHistory(currencyPair string, timestamp int64) ([]TradeH
|
||||
}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiMyTrades, req, &response)
|
||||
g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiMyTrades, req, &response)
|
||||
}
|
||||
|
||||
// GetNotionalVolume returns the volume in price currency that has been traded across all pairs over a period of 30 days
|
||||
@@ -276,7 +275,7 @@ func (g *Gemini) GetNotionalVolume() (NotionalVolume, error) {
|
||||
response := NotionalVolume{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiVolume, nil, &response)
|
||||
g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiVolume, nil, &response)
|
||||
}
|
||||
|
||||
// GetTradeVolume returns a multi-arrayed volume response
|
||||
@@ -284,7 +283,7 @@ func (g *Gemini) GetTradeVolume() ([][]TradeVolume, error) {
|
||||
var response [][]TradeVolume
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiTradeVolume, nil, &response)
|
||||
g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiTradeVolume, nil, &response)
|
||||
}
|
||||
|
||||
// GetBalances returns available balances in the supported currencies
|
||||
@@ -292,7 +291,7 @@ func (g *Gemini) GetBalances() ([]Balance, error) {
|
||||
var response []Balance
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiBalances, nil, &response)
|
||||
g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiBalances, nil, &response)
|
||||
}
|
||||
|
||||
// GetCryptoDepositAddress returns a deposit address
|
||||
@@ -304,7 +303,7 @@ func (g *Gemini) GetCryptoDepositAddress(depositAddlabel, currency string) (Depo
|
||||
req["label"] = depositAddlabel
|
||||
}
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiDeposit+"/"+currency+"/"+geminiNewAddress, req, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiDeposit+"/"+currency+"/"+geminiNewAddress, req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -321,7 +320,7 @@ func (g *Gemini) WithdrawCrypto(address, currency string, amount float64) (Withd
|
||||
req["address"] = address
|
||||
req["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiWithdraw+strings.ToLower(currency), req, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiWithdraw+strings.ToLower(currency), req, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -340,7 +339,7 @@ func (g *Gemini) PostHeartbeat() (string, error) {
|
||||
}
|
||||
response := Response{}
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest(http.MethodPost, geminiHeartbeat, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, geminiHeartbeat, nil, &response)
|
||||
if err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
@@ -351,10 +350,14 @@ func (g *Gemini) PostHeartbeat() (string, error) {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (g *Gemini) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (g *Gemini) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := g.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return g.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: g.Verbose,
|
||||
HTTPDebugging: g.HTTPDebugging,
|
||||
@@ -364,11 +367,16 @@ func (g *Gemini) SendHTTPRequest(path string, result interface{}) error {
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the
|
||||
// exchange and returns an error
|
||||
func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
func (g *Gemini) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
if !g.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name)
|
||||
}
|
||||
|
||||
endpoint, err := g.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
req := make(map[string]interface{})
|
||||
req["request"] = fmt.Sprintf("/v%s/%s", geminiAPIVersion, path)
|
||||
req["nonce"] = g.Requester.GetNonce(true).String()
|
||||
@@ -399,7 +407,7 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
|
||||
|
||||
return g.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
Path: g.API.Endpoints.URL + "/v1/" + path,
|
||||
Path: endpoint + "/v1/" + path,
|
||||
Headers: headers,
|
||||
Result: result,
|
||||
AuthRequest: true,
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
)
|
||||
|
||||
@@ -34,7 +35,10 @@ func TestMain(m *testing.M) {
|
||||
if err != nil {
|
||||
log.Fatal("Gemini setup error", err)
|
||||
}
|
||||
g.API.Endpoints.URL = geminiSandboxAPIURL
|
||||
log.Printf(sharedtestvalues.LiveTesting, g.Name, g.API.Endpoints.URL)
|
||||
err = g.API.Endpoints.SetRunning(exchange.RestSpot.String(), geminiSandboxAPIURL)
|
||||
if err != nil {
|
||||
log.Fatalf("endpoint setting failed. key: %s, val: %s", exchange.RestSpot.String(), geminiSandboxAPIURL)
|
||||
}
|
||||
log.Printf(sharedtestvalues.LiveTesting, g.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -45,7 +45,13 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
|
||||
g.HTTPClient = newClient
|
||||
g.API.Endpoints.URL = serverDetails
|
||||
log.Printf(sharedtestvalues.MockTesting, g.Name, g.API.Endpoints.URL)
|
||||
endpointMap := g.API.Endpoints.GetURLMap()
|
||||
for k := range endpointMap {
|
||||
err = g.API.Endpoints.SetRunning(k, serverDetails)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
log.Printf(sharedtestvalues.MockTesting, g.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -354,6 +354,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
Pairs: []currency.Pair{
|
||||
currency.NewPair(currency.LTC, currency.BTC),
|
||||
},
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := g.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -370,8 +371,9 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.LTC, currency.BTC)},
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.LTC, currency.BTC)},
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := g.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -550,8 +552,10 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
// TestWsAuth dials websocket, sends login request.
|
||||
func TestWsAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
g.API.Endpoints.WebsocketURL = geminiWebsocketSandboxEndpoint
|
||||
|
||||
err := g.API.Endpoints.SetRunning(exchange.WebsocketSpot.String(), geminiWebsocketSandboxEndpoint)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if !g.Websocket.IsEnabled() &&
|
||||
!g.API.AuthenticatedWebsocketSupport ||
|
||||
!areTestAPIKeysSet() {
|
||||
@@ -559,7 +563,7 @@ func TestWsAuth(t *testing.T) {
|
||||
}
|
||||
var dialer websocket.Dialer
|
||||
go g.wsReadData()
|
||||
err := g.WsSecureSubscribe(&dialer, geminiWsOrderEvents)
|
||||
err = g.WsSecureSubscribe(&dialer, geminiWsOrderEvents)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -1133,8 +1137,8 @@ func TestGetHistoricTrades(t *testing.T) {
|
||||
tStart := time.Date(2020, 6, 6, 0, 0, 0, 0, time.UTC)
|
||||
tEnd := time.Date(2020, 6, 7, 0, 0, 0, 0, time.UTC)
|
||||
if !mockTests {
|
||||
tStart = time.Date(2020, time.Now().Month(), 6, 0, 0, 0, 0, time.UTC)
|
||||
tEnd = time.Date(2020, time.Now().Month(), 7, 0, 0, 0, 0, time.UTC)
|
||||
tStart = time.Date(time.Now().Year(), time.Now().Month(), 6, 0, 0, 0, 0, time.UTC)
|
||||
tEnd = time.Date(time.Now().Year(), time.Now().Month(), 7, 0, 0, 0, 0, time.UTC)
|
||||
}
|
||||
_, err = g.GetHistoricTrades(currencyPair, asset.Spot, tStart, tEnd)
|
||||
if err != nil {
|
||||
|
||||
@@ -72,8 +72,12 @@ func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
|
||||
val.Set("bids", "true")
|
||||
val.Set("offers", "true")
|
||||
val.Set("trades", "true")
|
||||
wsEndpoint, err := g.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint := fmt.Sprintf("%s%s/%s?%s",
|
||||
g.API.Endpoints.WebsocketURL,
|
||||
wsEndpoint,
|
||||
geminiWsMarketData,
|
||||
enabledCurrencies[i].String(),
|
||||
val.Encode())
|
||||
@@ -85,7 +89,7 @@ func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
|
||||
Traffic: g.Websocket.TrafficAlert,
|
||||
Match: g.Websocket.Match,
|
||||
}
|
||||
err := connection.Dial(dialer, http.Header{})
|
||||
err = connection.Dial(dialer, http.Header{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v Websocket connection %v error. Error %v",
|
||||
g.Name, endpoint, err)
|
||||
@@ -109,8 +113,11 @@ func (g *Gemini) WsSecureSubscribe(dialer *websocket.Dialer, url string) error {
|
||||
if err != nil {
|
||||
return fmt.Errorf("%v sendAuthenticatedHTTPRequest: Unable to JSON request", g.Name)
|
||||
}
|
||||
|
||||
endpoint := g.API.Endpoints.WebsocketURL + url
|
||||
wsEndpoint, err := g.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
endpoint := wsEndpoint + url
|
||||
PayloadBase64 := crypto.Base64Encode(PayloadJSON)
|
||||
hmac := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), []byte(g.API.Credentials.Secret))
|
||||
headers := http.Header{}
|
||||
|
||||
@@ -106,10 +106,14 @@ func (g *Gemini) SetDefaults() {
|
||||
g.Requester = request.New(g.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
g.API.Endpoints.URLDefault = geminiAPIURL
|
||||
g.API.Endpoints.URL = g.API.Endpoints.URLDefault
|
||||
g.API.Endpoints.WebsocketURL = geminiWebsocketEndpoint
|
||||
g.API.Endpoints = g.NewEndpoints()
|
||||
err = g.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: geminiAPIURL,
|
||||
exchange.WebsocketSpot: geminiWebsocketEndpoint,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
g.Websocket = stream.New()
|
||||
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -129,7 +133,15 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
|
||||
}
|
||||
|
||||
if exch.UseSandbox {
|
||||
g.API.Endpoints.URL = geminiSandboxAPIURL
|
||||
err = g.API.Endpoints.SetRunning(exchange.RestSpot.String(), geminiSandboxAPIURL)
|
||||
if err != nil {
|
||||
log.Error(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
wsRunningURL, err := g.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return g.Websocket.Setup(&stream.WebsocketSetup{
|
||||
@@ -139,7 +151,7 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: geminiWebsocketEndpoint,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: g.WsConnect,
|
||||
Features: &g.Features.Supports.WebsocketCapabilities,
|
||||
OrderbookBufferLimit: exch.OrderbookConfig.WebsocketBufferLimit,
|
||||
@@ -196,7 +208,7 @@ func (g *Gemini) UpdateTradablePairs(forceUpdate bool) error {
|
||||
|
||||
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
|
||||
// Gemini exchange
|
||||
func (g *Gemini) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (g *Gemini) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = g.Name
|
||||
accountBalance, err := g.GetBalances()
|
||||
@@ -226,10 +238,10 @@ func (g *Gemini) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (g *Gemini) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name)
|
||||
func (g *Gemini) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(g.Name, assetType)
|
||||
if err != nil {
|
||||
return g.UpdateAccountInfo()
|
||||
return g.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -655,8 +667,8 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (g *Gemini) ValidateCredentials() error {
|
||||
_, err := g.UpdateAccountInfo()
|
||||
func (g *Gemini) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := g.UpdateAccountInfo(assetType)
|
||||
return g.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,10 @@ func (h *HitBTC) GetCurrencies() (map[string]Currencies, error) {
|
||||
Data []Currencies
|
||||
}
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, apiV2Currency)
|
||||
path := fmt.Sprintf("/%s", apiV2Currency)
|
||||
|
||||
ret := make(map[string]Currencies)
|
||||
err := h.SendHTTPRequest(path, &resp.Data)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, path, &resp.Data)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -79,9 +79,9 @@ func (h *HitBTC) GetCurrency(currency string) (Currencies, error) {
|
||||
Data Currencies
|
||||
}
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s", h.API.Endpoints.URL, apiV2Currency, currency)
|
||||
path := fmt.Sprintf("/%s/%s", apiV2Currency, currency)
|
||||
|
||||
return resp.Data, h.SendHTTPRequest(path, &resp.Data)
|
||||
return resp.Data, h.SendHTTPRequest(exchange.RestSpot, path, &resp.Data)
|
||||
}
|
||||
|
||||
// GetSymbols Return the actual list of currency symbols (currency pairs) traded
|
||||
@@ -91,10 +91,10 @@ func (h *HitBTC) GetCurrency(currency string) (Currencies, error) {
|
||||
// of the base currency.
|
||||
func (h *HitBTC) GetSymbols(symbol string) ([]string, error) {
|
||||
var resp []Symbol
|
||||
path := fmt.Sprintf("%s/%s/%s", h.API.Endpoints.URL, apiV2Symbol, symbol)
|
||||
path := fmt.Sprintf("/%s/%s", apiV2Symbol, symbol)
|
||||
|
||||
ret := make([]string, 0, len(resp))
|
||||
err := h.SendHTTPRequest(path, &resp)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -109,22 +109,22 @@ func (h *HitBTC) GetSymbols(symbol string) ([]string, error) {
|
||||
// all their details.
|
||||
func (h *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
|
||||
var resp []Symbol
|
||||
path := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, apiV2Symbol)
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
path := fmt.Sprintf("/%s", apiV2Symbol)
|
||||
return resp, h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
func (h *HitBTC) GetTicker(symbol string) (TickerResponse, error) {
|
||||
var resp TickerResponse
|
||||
path := fmt.Sprintf("%s/%s/%s", h.API.Endpoints.URL, apiV2Ticker, symbol)
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
path := fmt.Sprintf("/%s/%s", apiV2Ticker, symbol)
|
||||
return resp, h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
}
|
||||
|
||||
// GetTickers returns ticker information
|
||||
func (h *HitBTC) GetTickers() ([]TickerResponse, error) {
|
||||
var resp []TickerResponse
|
||||
path := fmt.Sprintf("%s/%s/", h.API.Endpoints.URL, apiV2Ticker)
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
path := fmt.Sprintf("/%s/", apiV2Ticker)
|
||||
return resp, h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
}
|
||||
|
||||
// GetTrades returns trades from hitbtc
|
||||
@@ -150,12 +150,11 @@ func (h *HitBTC) GetTrades(currencyPair, by, sort string, from, till, limit, off
|
||||
}
|
||||
|
||||
var resp []TradeHistory
|
||||
path := fmt.Sprintf("%s/%s/%s?%s",
|
||||
h.API.Endpoints.URL,
|
||||
path := fmt.Sprintf("/%s/%s?%s",
|
||||
apiV2Trades,
|
||||
currencyPair,
|
||||
urlValues.Encode())
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
return resp, h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderbook an order book is an electronic list of buy and sell orders for a
|
||||
@@ -169,13 +168,12 @@ func (h *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error)
|
||||
}
|
||||
|
||||
resp := OrderbookResponse{}
|
||||
path := fmt.Sprintf("%s/%s/%s?%s",
|
||||
h.API.Endpoints.URL,
|
||||
path := fmt.Sprintf("/%s/%s?%s",
|
||||
apiV2Orderbook,
|
||||
currencyPair,
|
||||
vals.Encode())
|
||||
|
||||
err := h.SendHTTPRequest(path, &resp)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -213,8 +211,8 @@ func (h *HitBTC) GetCandles(currencyPair, limit, period string, start, end time.
|
||||
}
|
||||
|
||||
var resp []ChartData
|
||||
path := fmt.Sprintf("%s/%s/%s?%s", h.API.Endpoints.URL, apiV2Candles, currencyPair, vals.Encode())
|
||||
return resp, h.SendHTTPRequest(path, &resp)
|
||||
path := fmt.Sprintf("/%s/%s?%s", apiV2Candles, currencyPair, vals.Encode())
|
||||
return resp, h.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
}
|
||||
|
||||
// Authenticated Market Data
|
||||
@@ -223,7 +221,7 @@ func (h *HitBTC) GetCandles(currencyPair, limit, period string, start, end time.
|
||||
// GetBalances returns full balance for your account
|
||||
func (h *HitBTC) GetBalances() (map[string]Balance, error) {
|
||||
var result []Balance
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
apiV2Balance,
|
||||
url.Values{},
|
||||
otherRequests,
|
||||
@@ -246,7 +244,7 @@ func (h *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, e
|
||||
var resp DepositCryptoAddresses
|
||||
|
||||
return resp,
|
||||
h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
apiV2CryptoAddress+"/"+currency,
|
||||
url.Values{},
|
||||
otherRequests,
|
||||
@@ -256,7 +254,7 @@ func (h *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, e
|
||||
// GenerateNewAddress generates a new deposit address for a currency
|
||||
func (h *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, error) {
|
||||
resp := DepositCryptoAddresses{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
apiV2CryptoAddress+"/"+currency,
|
||||
url.Values{},
|
||||
otherRequests,
|
||||
@@ -268,7 +266,7 @@ func (h *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, er
|
||||
// GetActiveorders returns all your active orders
|
||||
func (h *HitBTC) GetActiveorders(currency string) ([]Order, error) {
|
||||
var resp []Order
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
orders+"?symbol="+currency,
|
||||
url.Values{},
|
||||
tradingRequests,
|
||||
@@ -292,7 +290,7 @@ func (h *HitBTC) GetTradeHistoryForCurrency(currency, start, end string) (Authen
|
||||
values.Set("currencyPair", currency)
|
||||
result := AuthenticatedTradeHistoryResponse{}
|
||||
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
apiV2TradeHistory,
|
||||
values,
|
||||
otherRequests,
|
||||
@@ -314,7 +312,7 @@ func (h *HitBTC) GetTradeHistoryForAllCurrencies(start, end string) (Authenticat
|
||||
values.Set("currencyPair", "all")
|
||||
result := AuthenticatedTradeHistoryAll{}
|
||||
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
apiV2TradeHistory,
|
||||
values,
|
||||
otherRequests,
|
||||
@@ -327,7 +325,7 @@ func (h *HitBTC) GetOrders(currency string) ([]OrderHistoryResponse, error) {
|
||||
values.Set("symbol", currency)
|
||||
var result []OrderHistoryResponse
|
||||
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
apiV2OrderHistory,
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -340,7 +338,7 @@ func (h *HitBTC) GetOpenOrders(currency string) ([]OrderHistoryResponse, error)
|
||||
values.Set("symbol", currency)
|
||||
var result []OrderHistoryResponse
|
||||
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
apiv2OpenOrders,
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -359,7 +357,7 @@ func (h *HitBTC) PlaceOrder(currency string, rate, amount float64, orderType, si
|
||||
values.Set("price", strconv.FormatFloat(rate, 'f', -1, 64))
|
||||
values.Set("type", orderType)
|
||||
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
apiOrder,
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -371,7 +369,7 @@ func (h *HitBTC) CancelExistingOrder(orderID int64) (bool, error) {
|
||||
result := GenericResponse{}
|
||||
values := url.Values{}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodDelete,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete,
|
||||
apiOrder+"/"+strconv.FormatInt(orderID, 10),
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -392,7 +390,7 @@ func (h *HitBTC) CancelExistingOrder(orderID int64) (bool, error) {
|
||||
func (h *HitBTC) CancelAllExistingOrders() ([]Order, error) {
|
||||
var result []Order
|
||||
values := url.Values{}
|
||||
return result, h.SendAuthenticatedHTTPRequest(http.MethodDelete,
|
||||
return result, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete,
|
||||
apiOrder,
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -410,7 +408,7 @@ func (h *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon
|
||||
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
orderMove,
|
||||
values,
|
||||
tradingRequests,
|
||||
@@ -436,7 +434,7 @@ func (h *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
|
||||
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
values.Set("address", address)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
apiV2CryptoWithdraw,
|
||||
values,
|
||||
otherRequests,
|
||||
@@ -456,7 +454,7 @@ func (h *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
|
||||
// GetFeeInfo returns current fee information
|
||||
func (h *HitBTC) GetFeeInfo(currencyPair string) (Fee, error) {
|
||||
result := Fee{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
apiV2FeeInfo+"/"+currencyPair,
|
||||
url.Values{},
|
||||
tradingRequests,
|
||||
@@ -472,7 +470,7 @@ func (h *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
|
||||
}
|
||||
result := Response{}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
tradableBalances,
|
||||
url.Values{},
|
||||
tradingRequests,
|
||||
@@ -504,7 +502,7 @@ func (h *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
|
||||
values.Set("fromAccount", from)
|
||||
values.Set("toAccount", to)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost,
|
||||
transferBalance,
|
||||
values,
|
||||
otherRequests,
|
||||
@@ -522,10 +520,14 @@ func (h *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (h *HitBTC) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (h *HitBTC) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := h.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return h.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: h.Verbose,
|
||||
HTTPDebugging: h.HTTPDebugging,
|
||||
@@ -535,15 +537,19 @@ func (h *HitBTC) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request
|
||||
func (h *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, f request.EndpointLimit, result interface{}) error {
|
||||
func (h *HitBTC) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint string, values url.Values, f request.EndpointLimit, result interface{}) error {
|
||||
if !h.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
h.Name)
|
||||
}
|
||||
ePoint, err := h.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
headers := make(map[string]string)
|
||||
headers["Authorization"] = "Basic " + crypto.Base64Encode([]byte(h.API.Credentials.Key+":"+h.API.Credentials.Secret))
|
||||
|
||||
path := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, endpoint)
|
||||
path := fmt.Sprintf("%s/%s", ePoint, endpoint)
|
||||
|
||||
return h.SendPayload(context.Background(), &request.Item{
|
||||
Method: method,
|
||||
|
||||
@@ -265,8 +265,9 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := h.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -279,8 +280,9 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Pairs: []currency.Pair{currency.NewPair(currency.ETH, currency.BTC)},
|
||||
}
|
||||
|
||||
_, err := h.GetOrderHistory(&getOrdersRequest)
|
||||
|
||||
@@ -130,10 +130,14 @@ func (h *HitBTC) SetDefaults() {
|
||||
h.Requester = request.New(h.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout),
|
||||
request.WithLimiter(SetRateLimit()))
|
||||
|
||||
h.API.Endpoints.URLDefault = apiURL
|
||||
h.API.Endpoints.URL = h.API.Endpoints.URLDefault
|
||||
h.API.Endpoints.WebsocketURL = hitbtcWebsocketAddress
|
||||
h.API.Endpoints = h.NewEndpoints()
|
||||
err = h.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: apiURL,
|
||||
exchange.WebsocketSpot: hitbtcWebsocketAddress,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
h.Websocket = stream.New()
|
||||
h.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
|
||||
h.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
|
||||
@@ -152,6 +156,11 @@ func (h *HitBTC) Setup(exch *config.ExchangeConfig) error {
|
||||
return err
|
||||
}
|
||||
|
||||
wsRunningURL, err := h.API.Endpoints.GetURL(exchange.WebsocketSpot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = h.Websocket.Setup(&stream.WebsocketSetup{
|
||||
Enabled: exch.Features.Enabled.Websocket,
|
||||
Verbose: exch.Verbose,
|
||||
@@ -159,7 +168,7 @@ func (h *HitBTC) Setup(exch *config.ExchangeConfig) error {
|
||||
WebsocketTimeout: exch.WebsocketTrafficTimeout,
|
||||
DefaultURL: hitbtcWebsocketAddress,
|
||||
ExchangeName: exch.Name,
|
||||
RunningURL: exch.API.Endpoints.WebsocketURL,
|
||||
RunningURL: wsRunningURL,
|
||||
Connector: h.WsConnect,
|
||||
Subscriber: h.Subscribe,
|
||||
UnSubscriber: h.Unsubscribe,
|
||||
@@ -404,7 +413,7 @@ func (h *HitBTC) UpdateOrderbook(c currency.Pair, assetType asset.Item) (*orderb
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// HitBTC exchange
|
||||
func (h *HitBTC) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (h *HitBTC) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = h.Name
|
||||
accountBalance, err := h.GetBalances()
|
||||
@@ -434,10 +443,10 @@ func (h *HitBTC) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (h *HitBTC) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(h.Name)
|
||||
func (h *HitBTC) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(h.Name, assetType)
|
||||
if err != nil {
|
||||
return h.UpdateAccountInfo()
|
||||
return h.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -772,8 +781,8 @@ func (h *HitBTC) AuthenticateWebsocket() error {
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (h *HitBTC) ValidateCredentials() error {
|
||||
_, err := h.UpdateAccountInfo()
|
||||
func (h *HitBTC) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := h.UpdateAccountInfo(assetType)
|
||||
return h.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
1195
exchanges/huobi/cfutures_types.go
Normal file
1195
exchanges/huobi/cfutures_types.go
Normal file
File diff suppressed because it is too large
Load Diff
845
exchanges/huobi/futures_types.go
Normal file
845
exchanges/huobi/futures_types.go
Normal file
@@ -0,0 +1,845 @@
|
||||
package huobi
|
||||
|
||||
// FContractInfoData gets contract info data for futures
|
||||
type FContractInfoData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractSize float64 `json:"contract_size"`
|
||||
PriceTick float64 `json:"price_tick"`
|
||||
DeliveryDate string `json:"delivery_date"`
|
||||
CreateDate string `json:"create_date"`
|
||||
ContractStatus int64 `json:"contract_status"`
|
||||
}
|
||||
}
|
||||
|
||||
// FContractIndexPriceInfo stores contract index price
|
||||
type FContractIndexPriceInfo struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
IndexPrice float64 `json:"index_price"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FContractPriceLimits gets limits for futures contracts
|
||||
type FContractPriceLimits struct {
|
||||
Data struct {
|
||||
Symbol string `json:"symbol"`
|
||||
HighLimit float64 `json:"high_limit"`
|
||||
LowLimit float64 `json:"low_limit"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FContractOIData stores open interest data for futures contracts
|
||||
type FContractOIData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
Amount float64 `json:"amount"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FEstimatedDeliveryPriceInfo stores estimated delivery price data for futures
|
||||
type FEstimatedDeliveryPriceInfo struct {
|
||||
Data struct {
|
||||
DeliveryPrice float64 `json:"delivery_price"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FMarketDepth gets orderbook data for futures
|
||||
type FMarketDepth struct {
|
||||
Ch string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
MRID int64 `json:"mrid"`
|
||||
ID int64 `json:"id"`
|
||||
Bids [][2]float64 `json:"bids"`
|
||||
Asks [][2]float64 `json:"asks"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Version int64 `json:"version"`
|
||||
Ch string `json:"ch"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// OBData stores market depth data
|
||||
type OBData struct {
|
||||
Symbol string
|
||||
Asks []obItem
|
||||
Bids []obItem
|
||||
}
|
||||
|
||||
type obItem struct {
|
||||
Price float64
|
||||
Quantity float64
|
||||
}
|
||||
|
||||
// FKlineData stores kline data for futures
|
||||
type FKlineData struct {
|
||||
Ch string `json:"ch"`
|
||||
Data []struct {
|
||||
Vol float64 `json:"vol"`
|
||||
Close float64 `json:"close"`
|
||||
Count float64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
ID int64 `json:"id"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FMarketOverviewData stores overview data for futures
|
||||
type FMarketOverviewData struct {
|
||||
Ch string `json:"ch"`
|
||||
Tick struct {
|
||||
Vol float64 `json:"vol,string"`
|
||||
Ask [2]float64
|
||||
Bid [2]float64
|
||||
Close float64 `json:"close,string"`
|
||||
Count float64 `json:"count"`
|
||||
High float64 `json:"high,string"`
|
||||
ID int64 `jso:"id"`
|
||||
Low float64 `json:"low,string"`
|
||||
Open float64 `json:"open,string"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
} `json:"tick"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FLastTradeData stores last trade's data for a contract
|
||||
type FLastTradeData struct {
|
||||
Ch string `json:"ch"`
|
||||
Tick struct {
|
||||
Data []struct {
|
||||
Amount float64 `json:"amount,string"`
|
||||
Direction string `json:"direction"`
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price,string"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"data"`
|
||||
ID int64 `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"tick"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FBatchTradesForContractData stores batch of trades data for a contract
|
||||
type FBatchTradesForContractData struct {
|
||||
Ch string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
ID int64 `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Direction string `json:"direction"`
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"data"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FClawbackRateAndInsuranceData stores clawback rate and insurance data for futures
|
||||
type FClawbackRateAndInsuranceData struct {
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
InsuranceFund float64 `json:"insurance_fund"`
|
||||
EstimatedClawback float64 `json:"estimated_clawback"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FHistoricalInsuranceRecordsData stores historical records of insurance fund balances for futures
|
||||
type FHistoricalInsuranceRecordsData struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Data struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Tick []struct {
|
||||
InsuranceFund float64 `json:"insurance_fund"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"tick"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FTieredAdjustmentFactorInfo stores info on adjustment factor for futures
|
||||
type FTieredAdjustmentFactorInfo struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
List []struct {
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
Ladders []struct {
|
||||
Ladder int64 `json:"ladder"`
|
||||
MinSize float64 `json:"min_size"`
|
||||
MaxSize float64 `json:"max_size"`
|
||||
AdjustFactor float64 `json:"adjust_factor"`
|
||||
} `json:"ladders"`
|
||||
} `json:"list"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FOIData gets oi data on futures
|
||||
type FOIData struct {
|
||||
Data struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Tick []struct {
|
||||
Volume float64 `json:"volume,string"`
|
||||
AmountType int64 `json:"amount_type"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"tick"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FInfoSystemStatusData stores system status info for futures
|
||||
type FInfoSystemStatusData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Open int64 `json:"open"`
|
||||
Close int64 `json:"close"`
|
||||
Cancel int64 `json:"cancel"`
|
||||
TransferIn int64 `json:"transfer_in"`
|
||||
TransferOut int64 `json:"transfer_out"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTopAccountsLongShortRatio stores long/short ratio for top futures accounts
|
||||
type FTopAccountsLongShortRatio struct {
|
||||
Data struct {
|
||||
List []struct {
|
||||
BuyRatio float64 `json:"buy_ratio"`
|
||||
SellRatio float64 `json:"sell_ratio"`
|
||||
LockedRatio float64 `json:"locked_ratio"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"list"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTopPositionsLongShortRatio stores long short ratio for top futures positions
|
||||
type FTopPositionsLongShortRatio struct {
|
||||
Data struct {
|
||||
Symbol string `json:"symbol"`
|
||||
List []struct {
|
||||
BuyRatio float64 `json:"buy_ratio"`
|
||||
SellRatio float64 `json:"sell_ratio"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
} `json:"list"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// FLiquidationOrdersInfo stores data of futures liquidation orders
|
||||
type FLiquidationOrdersInfo struct {
|
||||
Data struct {
|
||||
Orders []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
} `json:"orders"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FIndexKlineData stores index kline data for futures
|
||||
type FIndexKlineData struct {
|
||||
Ch string `json:"ch"`
|
||||
Data []struct {
|
||||
Vol float64 `json:"vol"`
|
||||
Close float64 `json:"close"`
|
||||
Count float64 `json:"count"`
|
||||
High float64 `json:"high"`
|
||||
ID int64 `json:"id"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FBasisData stores basis data for futures
|
||||
type FBasisData struct {
|
||||
Ch string `json:"ch"`
|
||||
Data []struct {
|
||||
Basis float64 `json:"basis,string"`
|
||||
BasisRate float64 `json:"basis_rate,string"`
|
||||
ContractPrice float64 `json:"contract_price,string"`
|
||||
ID int64 `json:"id"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FUserAccountData stores user account data info for futures
|
||||
type FUserAccountData struct {
|
||||
AccData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalance float64 `json:"margin_balance"`
|
||||
MarginPosition float64 `json:"margin_position"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
MarginAvailable float64 `json:"margin_available"`
|
||||
ProfitReal float64 `json:"profit_real"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
RiskRate float64 `json:"risk_rate"`
|
||||
LiquidationPrice float64 `json:"liquidation_price"`
|
||||
WithdrawAvailable float64 `json:"withdraw_available"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
AdjustFactor float64 `json:"adjust_factor"`
|
||||
MarginStatic float64 `json:"margin_static"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FUsersPositionsInfo stores positions data for futures
|
||||
type FUsersPositionsInfo struct {
|
||||
PosInfo []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
Available float64 `json:"available"`
|
||||
Frozen float64 `json:"frozen"`
|
||||
CostOpen float64 `json:"cost_open"`
|
||||
CostHold float64 `json:"cost_hold"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
ProfitRate float64 `json:"profit_rate"`
|
||||
Profit float64 `json:"profit"`
|
||||
PositionMargin float64 `json:"position_margin"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
Direction string `json:"direction"`
|
||||
LastPrice float64 `json:"last_price"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FSubAccountAssetsInfo gets subaccounts asset data
|
||||
type FSubAccountAssetsInfo struct {
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
SubUID int64 `json:"sub_uid"`
|
||||
List []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalance float64 `json:"margin_balance"`
|
||||
LiquidationPrice float64 `json:"liquidation_price"`
|
||||
RiskRate float64 `json:"risk_rate"`
|
||||
} `json:"list"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FSingleSubAccountAssetsInfo stores futures assets info for a single subaccount
|
||||
type FSingleSubAccountAssetsInfo struct {
|
||||
AssetsData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalance float64 `json:"margin_balance"`
|
||||
MarginPosition float64 `json:"margin_position"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
MarginAvailable float64 `json:"margin_available"`
|
||||
ProfitReal float64 `json:"profit_real"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
WithdrawAvailable float64 `json:"withdraw_available"`
|
||||
RiskRate float64 `json:"risk_rate"`
|
||||
LiquidationPrice float64 `json:"liquidation_price"`
|
||||
AdjustFactor float64 `json:"adjust_factor"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
MarginStatic float64 `json:"margin_static"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FSingleSubAccountPositionsInfo stores futures positions' info for a single subaccount
|
||||
type FSingleSubAccountPositionsInfo struct {
|
||||
PositionsData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
Available float64 `json:"available"`
|
||||
Frozen float64 `json:"frozen"`
|
||||
CostOpen float64 `json:"cost_open"`
|
||||
CostHold float64 `json:"cost_hold"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
ProfitRate float64 `json:"profit_rate"`
|
||||
Profit float64 `json:"profit"`
|
||||
PositionMargin float64 `json:"position_margin"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
Direction string `json:"direction"`
|
||||
LastPrice float64 `json:"last_price"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FFinancialRecords stores financial records data for futures
|
||||
type FFinancialRecords struct {
|
||||
Data struct {
|
||||
FinancialRecord []struct {
|
||||
ID int64 `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Symbol string `json:"symbol"`
|
||||
RecordType int64 `json:"type"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"financial_record"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FSettlementRecords stores user's futures settlement records
|
||||
type FSettlementRecords struct {
|
||||
Data struct {
|
||||
SettlementRecords []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalanceInit float64 `json:"margin_balance_init"`
|
||||
MarginBalance int64 `json:"margin_balance"`
|
||||
SettlementProfitReal float64 `json:"settlement_profit_real"`
|
||||
SettlementTime int64 `json:"settlement_time"`
|
||||
Clawback float64 `json:"clawback"`
|
||||
DeliveryFee float64 `json:"delivery_fee"`
|
||||
OffsetProfitLoss float64 `json:"offset_profitloss"`
|
||||
Fee float64 `json:"fee"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
Positions []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Direction string `json:"direction"`
|
||||
Volume float64 `json:"volume"`
|
||||
CostOpen float64 `json:"cost_open"`
|
||||
CostHoldPre float64 `json:"cost_hold_pre"`
|
||||
CostHold float64 `json:"cost_hold"`
|
||||
SettlementProfitUnreal float64 `json:"settlement_profit_unreal"`
|
||||
SettlementPrice float64 `json:"settlement_price"`
|
||||
SettlmentType string `json:"settlement_type"`
|
||||
} `json:"positions"`
|
||||
} `json:"settlement_records"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FContractInfoOnOrderLimit stores contract info on futures order limit
|
||||
type FContractInfoOnOrderLimit struct {
|
||||
ContractData []struct {
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
List []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractTypes []struct {
|
||||
ContractType string `json:"contract_type"`
|
||||
OpenLimit int64 `json:"open_limit"`
|
||||
CloseLimit int64 `json:"close_limit"`
|
||||
} `json:"types"`
|
||||
} `json:"list"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FContractTradingFeeData stores contract trading fee data
|
||||
type FContractTradingFeeData struct {
|
||||
ContractTradingFeeData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
OpenMakerFee float64 `json:"open_maker_fee,string"`
|
||||
OpenTakerFee float64 `json:"open_taker_fee,string"`
|
||||
CloseMakerFee float64 `json:"close_maker_fee,string"`
|
||||
CloseTakerFee float64 `json:"close_taker_fee,string"`
|
||||
DeliveryFee float64 `json:"delivery_fee,string"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTransferLimitData stores transfer limit data for futures
|
||||
type FTransferLimitData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MaxTransferIn float64 `json:"transfer_in_max_each"`
|
||||
MinTransferIn float64 `json:"transfer_in_min_each"`
|
||||
MaxTransferOut float64 `json:"transfer_out_max_each"`
|
||||
MinTransferOut float64 `json:"transfer_out_min_each"`
|
||||
MaxTransferInDaily float64 `json:"transfer_in_max_daily"`
|
||||
MaxTransferOutDaily float64 `json:"transfer_out_max_daily"`
|
||||
NetTransferInMaxDaily float64 `json:"net_transfer_in_max_daily"`
|
||||
NetTransferOutMaxDaily float64 `json:"net_transfer_out_max_daily"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FPositionLimitData stores information on futures positions limit
|
||||
type FPositionLimitData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
List []struct {
|
||||
ContractType string `json:"contract_type"`
|
||||
BuyLimit float64 `json:"buy_limit"`
|
||||
SellLimit float64 `json:"sell_limit"`
|
||||
} `json:"list"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FAssetsAndPositionsData stores assets and positions data for futures
|
||||
type FAssetsAndPositionsData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalance float64 `json:"margin_balance"`
|
||||
MarginPosition float64 `json:"margin_position"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
MarginAvailable float64 `json:"margin_available"`
|
||||
ProfitReal float64 `json:"profit_real"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
RiskRate float64 `json:"risk_rate"`
|
||||
WithdrawAvailable float64 `json:"withdraw_available"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FAccountTransferData stores internal transfer data for futures
|
||||
type FAccountTransferData struct {
|
||||
Status string `json:"status"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data struct {
|
||||
OrderID string `json:"order_id"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FTransferRecords gets transfer records data
|
||||
type FTransferRecords struct {
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data struct {
|
||||
TransferRecord []struct {
|
||||
ID int64 `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Symbol string `json:"symbol"`
|
||||
SubUID int64 `json:"sub_uid"`
|
||||
SubAccountName string `json:"sub_account_name"`
|
||||
TransferType int64 `json:"transfer_type"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"transfer_record"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FAvailableLeverageData stores available leverage data for futures
|
||||
type FAvailableLeverageData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
AvailableLeverageRate string `json:"available_level_rate"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// FOrderData stores order data for futures
|
||||
type FOrderData struct {
|
||||
Data struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDStr string `json:"order_id_str"`
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
type fBatchOrderData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ClientOrderID string `json:"client_order_id"`
|
||||
Price float64 `json:"price"`
|
||||
Volume float64 `json:"volume"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"leverRate"`
|
||||
OrderPriceType string `json:"orderPriceType"`
|
||||
}
|
||||
|
||||
// FBatchOrderResponse stores batch order data
|
||||
type FBatchOrderResponse struct {
|
||||
OrdersData []FOrderData `json:"orders_data"`
|
||||
}
|
||||
|
||||
// FCancelOrderData stores cancel order data
|
||||
type FCancelOrderData struct {
|
||||
Data struct {
|
||||
Errors []struct {
|
||||
OrderID int64 `json:"order_id,string"`
|
||||
ErrCode int64 `json:"err_code"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
} `json:"errors"`
|
||||
Successes string `json:"successes"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FOrderInfo stores order info
|
||||
type FOrderInfo struct {
|
||||
Data []struct {
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
CanceledAt int64 `json:"canceled_at"`
|
||||
Direction string `json:"direction"`
|
||||
Fee float64 `json:"fee"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
LeverRate int64 `json:"lever_rate"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
Offset string `json:"offset"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_string"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
OrderSource string `json:"order_source"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Price float64 `json:"price"`
|
||||
Profit float64 `json:"profit"`
|
||||
Status int64 `json:"status"`
|
||||
Symbol string `json:"symbol"`
|
||||
TradeAvgPrice float64 `json:"trade_avg_price"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
Volume float64 `json:"volume"`
|
||||
LiquidationType int64 `json:"liquidation_type"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// FOrderDetailsData stores order details for futures orders
|
||||
type FOrderDetailsData struct {
|
||||
Data struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
Profit float64 `json:"profit"`
|
||||
OrderSource string `json:"order_source"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Status int64 `json:"status"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradeTurnover int64 `json:"trade_turnover"`
|
||||
TradeAvgPrice float64 `json:"trade_avg_price"`
|
||||
Fee float64 `json:"fee"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
CanceledAt int64 `json:"canceled_at"`
|
||||
FinalInterest float64 `json:"final_interest"`
|
||||
AdjustValue int64 `json:"adjust_value"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
Trades []struct {
|
||||
ID string `json:"id"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
TradeFee float64 `json:"trade_fee"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
Role string `json:"role"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
} `json:"trades"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FOpenOrdersData stores open orders data for futures
|
||||
type FOpenOrdersData struct {
|
||||
Data struct {
|
||||
Orders []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_string"`
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
OrderSource string `json:"order_source"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
Fee float64 `json:"fee"`
|
||||
TradeAvgPrice float64 `json:"trade_avg_price"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
Profit float64 `json:"profit"`
|
||||
Status int64 `json:"status"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
} `json:"orders"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FOrderHistoryData stores order history data
|
||||
type FOrderHistoryData struct {
|
||||
Data struct {
|
||||
Orders []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
OrderSource string `json:"order_source"`
|
||||
CreateDate int64 `json:"create_date"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
Fee float64 `json:"fee"`
|
||||
TradeAvgPrice float64 `json:"trade_avg_price"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
Profit float64 `json:"profit"`
|
||||
Status int64 `json:"status"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
LiquidationType int64 `json:"liquidation_type"`
|
||||
} `json:"orders"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTradeHistoryData stores trade history data for futures
|
||||
type FTradeHistoryData struct {
|
||||
Data struct {
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
Trades []struct {
|
||||
ID string `json:"id"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
CreateDate int64 `json:"create_date"`
|
||||
Direction string `json:"direction"`
|
||||
MatchID int64 `json:"match_id"`
|
||||
Offset string `json:"offset"`
|
||||
OffsetPNL float64 `json:"offset_profitloss"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
Symbol string `json:"symbol"`
|
||||
OrderSource string `json:"order_source"`
|
||||
TradeFee float64 `json:"trade_fee"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
Role string `json:"role"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
} `json:"trades"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTriggerOrderData stores trigger order data
|
||||
type FTriggerOrderData struct {
|
||||
Data struct {
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDStr string `json:"order_id_str"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTriggerOpenOrders stores trigger open orders data
|
||||
type FTriggerOpenOrders struct {
|
||||
Data struct {
|
||||
Orders []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
TriggerType string `json:"trigger_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
OrderSource string `json:"order_source"`
|
||||
TriggerPrice float64 `json:"trigger_price"`
|
||||
OrderPrice float64 `json:"order_price"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Status int64 `json:"status"`
|
||||
} `json:"orders"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// FTriggerOrderHistoryData stores trigger order history for futures
|
||||
type FTriggerOrderHistoryData struct {
|
||||
Data struct {
|
||||
Orders []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
TriggerType string `json:"trigger_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
RelationOrderID string `json:"relation_order_id"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Status string `json:"status"`
|
||||
OrderSource string `json:"order_source"`
|
||||
TriggerPrice int64 `json:"trigger_price"`
|
||||
TriggeredPrice float64 `json:"triggered_price"`
|
||||
OrderPrice float64 `json:"order_price"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
TriggeredAt int64 `json:"triggered_at"`
|
||||
OrderInsertAt float64 `json:"order_insert_at"`
|
||||
CancelledAt int64 `json:"canceled_at"`
|
||||
FailCode int64 `json:"fail_code"`
|
||||
FailReason string `json:"fail_reason"`
|
||||
} `json:"orders"`
|
||||
TotalPage int64 `json:"total_page"`
|
||||
CurrentPage int64 `json:"current_page"`
|
||||
TotalSize int64 `json:"total_size"`
|
||||
} `json:"data"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
@@ -15,17 +15,22 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
const (
|
||||
huobiAPIURL = "https://api.huobi.pro"
|
||||
huobiURL = "https://api.hbdm.com/"
|
||||
huobiFuturesURL = "https://api.hbdm.com"
|
||||
huobiAPIVersion = "1"
|
||||
huobiAPIVersion2 = "2"
|
||||
|
||||
// Spot endpoints
|
||||
huobiMarketHistoryKline = "market/history/kline"
|
||||
huobiMarketDetail = "market/detail"
|
||||
huobiMarketDetailMerged = "market/detail/merged"
|
||||
huobi24HrMarketSummary = "/market/detail?"
|
||||
huobiMarketDepth = "market/depth"
|
||||
huobiMarketTrade = "market/trade"
|
||||
huobiMarketTickers = "market/tickers"
|
||||
@@ -56,6 +61,7 @@ const (
|
||||
huobiWithdrawCreate = "dw/withdraw/api/create"
|
||||
huobiWithdrawCancel = "dw/withdraw-virtual/%s/cancel"
|
||||
huobiStatusError = "error"
|
||||
huobiMarginRates = "margin/loan-info"
|
||||
)
|
||||
|
||||
// HUOBI is the overarching type across this package
|
||||
@@ -64,11 +70,29 @@ type HUOBI struct {
|
||||
AccountID string
|
||||
}
|
||||
|
||||
// GetMarginRates gets margin rates
|
||||
func (h *HUOBI) GetMarginRates(symbol currency.Pair) (MarginRatesData, error) {
|
||||
var resp MarginRatesData
|
||||
vals := url.Values{}
|
||||
if symbol != (currency.Pair{}) {
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
}
|
||||
return resp, h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiMarginRates, vals, nil, &resp, false)
|
||||
}
|
||||
|
||||
// GetSpotKline returns kline data
|
||||
// KlinesRequestParams contains symbol, period and size
|
||||
// KlinesRequestParams contains symbol currency.Pair, period and size
|
||||
func (h *HUOBI) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", arg.Symbol)
|
||||
symbolValue, err := h.FormatSymbol(arg.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
vals.Set("period", arg.Period)
|
||||
|
||||
if arg.Size != 0 {
|
||||
@@ -81,26 +105,40 @@ func (h *HUOBI) GetSpotKline(arg KlinesRequestParams) ([]KlineItem, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketHistoryKline)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketHistoryKline, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
return result.Data, err
|
||||
}
|
||||
|
||||
// Get24HrMarketSummary returns 24hr market summary for a given market symbol
|
||||
func (h *HUOBI) Get24HrMarketSummary(symbol currency.Pair) (MarketSummary24Hr, error) {
|
||||
var result MarketSummary24Hr
|
||||
params := url.Values{}
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
return result, h.SendHTTPRequest(exchange.RestSpot, huobi24HrMarketSummary+params.Encode(), &result)
|
||||
}
|
||||
|
||||
// GetTickers returns the ticker for the specified symbol
|
||||
func (h *HUOBI) GetTickers() (Tickers, error) {
|
||||
var result Tickers
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketTickers)
|
||||
return result, h.SendHTTPRequest(urlPath, &result)
|
||||
return result, h.SendHTTPRequest(exchange.RestSpot, "/"+huobiMarketTickers, &result)
|
||||
}
|
||||
|
||||
// GetMarketDetailMerged returns the ticker for the specified symbol
|
||||
func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) {
|
||||
func (h *HUOBI) GetMarketDetailMerged(symbol currency.Pair) (DetailMerged, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return DetailMerged{}, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
@@ -108,9 +146,8 @@ func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketDetailMerged)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketDetailMerged, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Tick, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -120,7 +157,11 @@ func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) {
|
||||
// GetDepth returns the depth for the specified symbol
|
||||
func (h *HUOBI) GetDepth(obd OrderBookDataRequestParams) (Orderbook, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", obd.Symbol)
|
||||
symbolValue, err := h.FormatSymbol(obd.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
if obd.Type != OrderBookDataRequestParamsTypeNone {
|
||||
vals.Set("type", string(obd.Type))
|
||||
@@ -132,9 +173,8 @@ func (h *HUOBI) GetDepth(obd OrderBookDataRequestParams) (Orderbook, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketDepth)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketDepth, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Depth, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -142,9 +182,13 @@ func (h *HUOBI) GetDepth(obd OrderBookDataRequestParams) (Orderbook, error) {
|
||||
}
|
||||
|
||||
// GetTrades returns the trades for the specified symbol
|
||||
func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
|
||||
func (h *HUOBI) GetTrades(symbol currency.Pair) ([]Trade, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
@@ -154,9 +198,8 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketTrade)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketTrade, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -166,7 +209,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
|
||||
// GetLatestSpotPrice returns latest spot price of symbol
|
||||
//
|
||||
// symbol: string of currency pair
|
||||
func (h *HUOBI) GetLatestSpotPrice(symbol string) (float64, error) {
|
||||
func (h *HUOBI) GetLatestSpotPrice(symbol currency.Pair) (float64, error) {
|
||||
list, err := h.GetTradeHistory(symbol, 1)
|
||||
|
||||
if err != nil {
|
||||
@@ -180,9 +223,13 @@ func (h *HUOBI) GetLatestSpotPrice(symbol string) (float64, error) {
|
||||
}
|
||||
|
||||
// GetTradeHistory returns the trades for the specified symbol
|
||||
func (h *HUOBI) GetTradeHistory(symbol string, size int64) ([]TradeHistory, error) {
|
||||
func (h *HUOBI) GetTradeHistory(symbol currency.Pair, size int64) ([]TradeHistory, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
if size > 0 {
|
||||
vals.Set("size", strconv.FormatInt(size, 10))
|
||||
@@ -194,9 +241,8 @@ func (h *HUOBI) GetTradeHistory(symbol string, size int64) ([]TradeHistory, erro
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketTradeHistory)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketTradeHistory, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -204,9 +250,13 @@ func (h *HUOBI) GetTradeHistory(symbol string, size int64) ([]TradeHistory, erro
|
||||
}
|
||||
|
||||
// GetMarketDetail returns the ticker for the specified symbol
|
||||
func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) {
|
||||
func (h *HUOBI) GetMarketDetail(symbol currency.Pair) (Detail, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return Detail{}, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
type response struct {
|
||||
Response
|
||||
@@ -214,9 +264,8 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/%s", h.API.Endpoints.URL, huobiMarketDetail)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(urlPath, vals), &result)
|
||||
err = h.SendHTTPRequest(exchange.RestSpot, common.EncodeURLValues("/"+huobiMarketDetail, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Tick, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -231,9 +280,8 @@ func (h *HUOBI) GetSymbols() ([]Symbol, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", h.API.Endpoints.URL, huobiAPIVersion, huobiSymbols)
|
||||
|
||||
err := h.SendHTTPRequest(urlPath, &result)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, "/v"+huobiAPIVersion+"/"+huobiSymbols, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -248,9 +296,8 @@ func (h *HUOBI) GetCurrencies() ([]string, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", h.API.Endpoints.URL, huobiAPIVersion, huobiCurrencies)
|
||||
|
||||
err := h.SendHTTPRequest(urlPath, &result)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, "/v"+huobiAPIVersion+"/"+huobiCurrencies, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -265,9 +312,8 @@ func (h *HUOBI) GetTimestamp() (int64, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
urlPath := fmt.Sprintf("%s/v%s/%s", h.API.Endpoints.URL, huobiAPIVersion, huobiTimestamp)
|
||||
|
||||
err := h.SendHTTPRequest(urlPath, &result)
|
||||
err := h.SendHTTPRequest(exchange.RestSpot, "/v"+huobiAPIVersion+"/"+huobiTimestamp, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -279,7 +325,7 @@ func (h *HUOBI) GetAccounts() ([]Account, error) {
|
||||
result := struct {
|
||||
Accounts []Account `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccounts, url.Values{}, nil, &result, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiAccounts, url.Values{}, nil, &result, false)
|
||||
return result.Accounts, err
|
||||
}
|
||||
|
||||
@@ -291,7 +337,7 @@ func (h *HUOBI) GetAccountBalance(accountID string) ([]AccountBalanceDetail, err
|
||||
endpoint := fmt.Sprintf(huobiAccountBalance, accountID)
|
||||
v := url.Values{}
|
||||
v.Set("account-id", accountID)
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, v, nil, &result, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, v, nil, &result, false)
|
||||
return result.AccountBalanceData.AccountBalanceDetails, err
|
||||
}
|
||||
|
||||
@@ -300,7 +346,7 @@ func (h *HUOBI) GetAggregatedBalance() ([]AggregatedBalance, error) {
|
||||
result := struct {
|
||||
AggregatedBalances []AggregatedBalance `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot,
|
||||
http.MethodGet,
|
||||
huobiAggregatedBalance,
|
||||
nil,
|
||||
@@ -312,7 +358,12 @@ func (h *HUOBI) GetAggregatedBalance() ([]AggregatedBalance, error) {
|
||||
}
|
||||
|
||||
// SpotNewOrder submits an order to Huobi
|
||||
func (h *HUOBI) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) {
|
||||
func (h *HUOBI) SpotNewOrder(arg *SpotNewOrderRequestParams) (int64, error) {
|
||||
symbolValue, err := h.FormatSymbol(arg.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
data := struct {
|
||||
AccountID int `json:"account-id,string"`
|
||||
Amount string `json:"amount"`
|
||||
@@ -323,7 +374,7 @@ func (h *HUOBI) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) {
|
||||
}{
|
||||
AccountID: arg.AccountID,
|
||||
Amount: strconv.FormatFloat(arg.Amount, 'f', -1, 64),
|
||||
Symbol: arg.Symbol,
|
||||
Symbol: symbolValue,
|
||||
Type: string(arg.Type),
|
||||
}
|
||||
|
||||
@@ -339,7 +390,7 @@ func (h *HUOBI) SpotNewOrder(arg SpotNewOrderRequestParams) (int64, error) {
|
||||
result := struct {
|
||||
OrderID int64 `json:"data,string"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
huobiOrderPlace,
|
||||
nil,
|
||||
@@ -356,7 +407,7 @@ func (h *HUOBI) CancelExistingOrder(orderID int64) (int64, error) {
|
||||
OrderID int64 `json:"data,string"`
|
||||
}{}
|
||||
endpoint := fmt.Sprintf(huobiOrderCancel, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, url.Values{}, nil, &resp, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, endpoint, url.Values{}, nil, &resp, false)
|
||||
return resp.OrderID, err
|
||||
}
|
||||
|
||||
@@ -368,7 +419,7 @@ func (h *HUOBI) CancelOrderBatch(_ []int64) ([]CancelOrderBatch, error) {
|
||||
}
|
||||
|
||||
var result response
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiOrderCancelBatch, url.Values{}, nil, &result, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, huobiOrderCancelBatch, url.Values{}, nil, &result, false)
|
||||
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
@@ -377,9 +428,12 @@ func (h *HUOBI) CancelOrderBatch(_ []int64) ([]CancelOrderBatch, error) {
|
||||
}
|
||||
|
||||
// CancelOpenOrdersBatch cancels a batch of orders -- to-do
|
||||
func (h *HUOBI) CancelOpenOrdersBatch(accountID, symbol string) (CancelOpenOrdersBatch, error) {
|
||||
func (h *HUOBI) CancelOpenOrdersBatch(accountID string, symbol currency.Pair) (CancelOpenOrdersBatch, error) {
|
||||
params := url.Values{}
|
||||
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return CancelOpenOrdersBatch{}, err
|
||||
}
|
||||
params.Set("account-id", accountID)
|
||||
var result CancelOpenOrdersBatch
|
||||
|
||||
@@ -388,10 +442,10 @@ func (h *HUOBI) CancelOpenOrdersBatch(accountID, symbol string) (CancelOpenOrder
|
||||
Symbol string `json:"symbol"`
|
||||
}{
|
||||
AccountID: accountID,
|
||||
Symbol: symbol,
|
||||
Symbol: symbolValue,
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiBatchCancelOpenOrders, url.Values{}, data, &result, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, huobiBatchCancelOpenOrders, url.Values{}, data, &result, false)
|
||||
if result.Data.FailedCount > 0 {
|
||||
return result, fmt.Errorf("there were %v failed order cancellations", result.Data.FailedCount)
|
||||
}
|
||||
@@ -406,7 +460,7 @@ func (h *HUOBI) GetOrder(orderID int64) (OrderInfo, error) {
|
||||
}{}
|
||||
urlVal := url.Values{}
|
||||
urlVal.Set("clientOrderId", strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet,
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet,
|
||||
huobiGetOrder,
|
||||
urlVal,
|
||||
nil,
|
||||
@@ -421,18 +475,22 @@ func (h *HUOBI) GetOrderMatchResults(orderID int64) ([]OrderMatchInfo, error) {
|
||||
Orders []OrderMatchInfo `json:"data"`
|
||||
}{}
|
||||
endpoint := fmt.Sprintf(huobiGetOrderMatch, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, endpoint, url.Values{}, nil, &resp, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, endpoint, url.Values{}, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOrders returns a list of orders
|
||||
func (h *HUOBI) GetOrders(symbol, types, start, end, states, from, direct, size string) ([]OrderInfo, error) {
|
||||
func (h *HUOBI) GetOrders(symbol currency.Pair, types, start, end, states, from, direct, size string) ([]OrderInfo, error) {
|
||||
resp := struct {
|
||||
Orders []OrderInfo `json:"data"`
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
vals.Set("states", states)
|
||||
|
||||
if types != "" {
|
||||
@@ -459,36 +517,44 @@ func (h *HUOBI) GetOrders(symbol, types, start, end, states, from, direct, size
|
||||
vals.Set("size", size)
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrders, vals, nil, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiGetOrders, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of orders
|
||||
func (h *HUOBI) GetOpenOrders(accountID, symbol, side string, size int64) ([]OrderInfo, error) {
|
||||
func (h *HUOBI) GetOpenOrders(symbol currency.Pair, accountID, side string, size int64) ([]OrderInfo, error) {
|
||||
resp := struct {
|
||||
Orders []OrderInfo `json:"data"`
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
vals.Set("accountID", accountID)
|
||||
if len(side) > 0 {
|
||||
vals.Set("side", side)
|
||||
}
|
||||
vals.Set("size", strconv.FormatInt(size, 10))
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOpenOrders, vals, nil, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiGetOpenOrders, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// GetOrdersMatch returns a list of matched orders
|
||||
func (h *HUOBI) GetOrdersMatch(symbol, types, start, end, from, direct, size string) ([]OrderMatchInfo, error) {
|
||||
func (h *HUOBI) GetOrdersMatch(symbol currency.Pair, types, start, end, from, direct, size string) ([]OrderMatchInfo, error) {
|
||||
resp := struct {
|
||||
Orders []OrderMatchInfo `json:"data"`
|
||||
}{}
|
||||
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
|
||||
if types != "" {
|
||||
vals.Set("types", types)
|
||||
@@ -514,18 +580,22 @@ func (h *HUOBI) GetOrdersMatch(symbol, types, start, end, from, direct, size str
|
||||
vals.Set("size", size)
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiGetOrdersMatch, vals, nil, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiGetOrdersMatch, vals, nil, &resp, false)
|
||||
return resp.Orders, err
|
||||
}
|
||||
|
||||
// MarginTransfer transfers assets into or out of the margin account
|
||||
func (h *HUOBI) MarginTransfer(symbol, currency string, amount float64, in bool) (int64, error) {
|
||||
func (h *HUOBI) MarginTransfer(symbol currency.Pair, currency string, amount float64, in bool) (int64, error) {
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
data := struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Currency string `json:"currency"`
|
||||
Amount string `json:"amount"`
|
||||
}{
|
||||
Symbol: symbol,
|
||||
Symbol: symbolValue,
|
||||
Currency: currency,
|
||||
Amount: strconv.FormatFloat(amount, 'f', -1, 64),
|
||||
}
|
||||
@@ -538,18 +608,22 @@ func (h *HUOBI) MarginTransfer(symbol, currency string, amount float64, in bool)
|
||||
resp := struct {
|
||||
TransferID int64 `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, path, nil, data, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, nil, data, &resp, false)
|
||||
return resp.TransferID, err
|
||||
}
|
||||
|
||||
// MarginOrder submits a margin order application
|
||||
func (h *HUOBI) MarginOrder(symbol, currency string, amount float64) (int64, error) {
|
||||
func (h *HUOBI) MarginOrder(symbol currency.Pair, currency string, amount float64) (int64, error) {
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
data := struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Currency string `json:"currency"`
|
||||
Amount string `json:"amount"`
|
||||
}{
|
||||
Symbol: symbol,
|
||||
Symbol: symbolValue,
|
||||
Currency: currency,
|
||||
Amount: strconv.FormatFloat(amount, 'f', -1, 64),
|
||||
}
|
||||
@@ -557,7 +631,7 @@ func (h *HUOBI) MarginOrder(symbol, currency string, amount float64) (int64, err
|
||||
resp := struct {
|
||||
MarginOrderID int64 `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiMarginOrders, nil, data, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, huobiMarginOrders, nil, data, &resp, false)
|
||||
return resp.MarginOrderID, err
|
||||
}
|
||||
|
||||
@@ -574,14 +648,18 @@ func (h *HUOBI) MarginRepayment(orderID int64, amount float64) (int64, error) {
|
||||
}{}
|
||||
|
||||
endpoint := fmt.Sprintf(huobiMarginRepay, strconv.FormatInt(orderID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, nil, data, &resp, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, endpoint, nil, data, &resp, false)
|
||||
return resp.MarginOrderID, err
|
||||
}
|
||||
|
||||
// GetMarginLoanOrders returns the margin loan orders
|
||||
func (h *HUOBI) GetMarginLoanOrders(symbol, currency, start, end, states, from, direct, size string) ([]MarginOrder, error) {
|
||||
func (h *HUOBI) GetMarginLoanOrders(symbol currency.Pair, currency, start, end, states, from, direct, size string) ([]MarginOrder, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
vals.Set("currency", currency)
|
||||
|
||||
if start != "" {
|
||||
@@ -611,20 +689,24 @@ func (h *HUOBI) GetMarginLoanOrders(symbol, currency, start, end, states, from,
|
||||
resp := struct {
|
||||
MarginLoanOrders []MarginOrder `json:"data"`
|
||||
}{}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginLoanOrders, vals, nil, &resp, false)
|
||||
err = h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiMarginLoanOrders, vals, nil, &resp, false)
|
||||
return resp.MarginLoanOrders, err
|
||||
}
|
||||
|
||||
// GetMarginAccountBalance returns the margin account balances
|
||||
func (h *HUOBI) GetMarginAccountBalance(symbol string) ([]MarginAccountBalance, error) {
|
||||
func (h *HUOBI) GetMarginAccountBalance(symbol currency.Pair) ([]MarginAccountBalance, error) {
|
||||
resp := struct {
|
||||
Balances []MarginAccountBalance `json:"data"`
|
||||
}{}
|
||||
vals := url.Values{}
|
||||
if symbol != "" {
|
||||
vals.Set("symbol", symbol)
|
||||
if symbol != (currency.Pair{}) {
|
||||
symbolValue, err := h.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return resp.Balances, err
|
||||
}
|
||||
vals.Set("symbol", symbolValue)
|
||||
}
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiMarginAccountBalance, vals, nil, &resp, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiMarginAccountBalance, vals, nil, &resp, false)
|
||||
return resp.Balances, err
|
||||
}
|
||||
|
||||
@@ -654,7 +736,7 @@ func (h *HUOBI) Withdraw(c currency.Code, address, addrTag string, amount, fee f
|
||||
data.AddrTag = addrTag
|
||||
}
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, huobiWithdrawCreate, nil, data, &resp.WithdrawID, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, huobiWithdrawCreate, nil, data, &resp.WithdrawID, false)
|
||||
return resp.WithdrawID, err
|
||||
}
|
||||
|
||||
@@ -667,7 +749,7 @@ func (h *HUOBI) CancelWithdraw(withdrawID int64) (int64, error) {
|
||||
vals.Set("withdraw-id", strconv.FormatInt(withdrawID, 10))
|
||||
|
||||
endpoint := fmt.Sprintf(huobiWithdrawCancel, strconv.FormatInt(withdrawID, 10))
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodPost, endpoint, vals, nil, &resp, false)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, endpoint, vals, nil, &resp, false)
|
||||
return resp.WithdrawID, err
|
||||
}
|
||||
|
||||
@@ -680,7 +762,7 @@ func (h *HUOBI) QueryDepositAddress(cryptocurrency string) (DepositAddress, erro
|
||||
vals := url.Values{}
|
||||
vals.Set("currency", cryptocurrency)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccountDepositAddress, vals, nil, &resp, true)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiAccountDepositAddress, vals, nil, &resp, true)
|
||||
if err != nil {
|
||||
return DepositAddress{}, err
|
||||
}
|
||||
@@ -699,7 +781,7 @@ func (h *HUOBI) QueryWithdrawQuotas(cryptocurrency string) (WithdrawQuota, error
|
||||
vals := url.Values{}
|
||||
vals.Set("currency", cryptocurrency)
|
||||
|
||||
err := h.SendAuthenticatedHTTPRequest(http.MethodGet, huobiAccountWithdrawQuota, vals, nil, &resp, true)
|
||||
err := h.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, huobiAccountWithdrawQuota, vals, nil, &resp, true)
|
||||
if err != nil {
|
||||
return WithdrawQuota{}, err
|
||||
}
|
||||
@@ -707,23 +789,41 @@ func (h *HUOBI) QueryWithdrawQuotas(cryptocurrency string) (WithdrawQuota, error
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (h *HUOBI) SendHTTPRequest(path string, result interface{}) error {
|
||||
return h.SendPayload(context.Background(), &request.Item{
|
||||
func (h *HUOBI) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := h.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var tempResp json.RawMessage
|
||||
var errCap errorCapture
|
||||
err = h.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Result: result,
|
||||
Path: endpoint + path,
|
||||
Result: &tempResp,
|
||||
Verbose: h.Verbose,
|
||||
HTTPDebugging: h.HTTPDebugging,
|
||||
HTTPRecording: h.HTTPRecording,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := json.Unmarshal(tempResp, &errCap); err == nil {
|
||||
if errCap.Code != 200 && errCap.ErrMsg != "" {
|
||||
return errors.New(errCap.ErrMsg)
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(tempResp, result)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API
|
||||
func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, data, result interface{}, isVersion2API bool) error {
|
||||
func (h *HUOBI) SendAuthenticatedHTTPRequest(ep exchange.URL, method, endpoint string, values url.Values, data, result interface{}, isVersion2API bool) error {
|
||||
if !h.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, h.Name)
|
||||
}
|
||||
|
||||
ePoint, err := h.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if values == nil {
|
||||
values = url.Values{}
|
||||
}
|
||||
@@ -735,9 +835,9 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
values.Set("Timestamp", now.UTC().Format("2006-01-02T15:04:05"))
|
||||
|
||||
if isVersion2API {
|
||||
endpoint = fmt.Sprintf("/v%s/%s", huobiAPIVersion2, endpoint)
|
||||
endpoint = "/v" + huobiAPIVersion2 + "/" + endpoint
|
||||
} else {
|
||||
endpoint = fmt.Sprintf("/v%s/%s", huobiAPIVersion, endpoint)
|
||||
endpoint = "/v" + huobiAPIVersion + "/" + endpoint
|
||||
}
|
||||
|
||||
payload := fmt.Sprintf("%s\napi.huobi.pro\n%s\n%s",
|
||||
@@ -753,22 +853,21 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
|
||||
hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(h.API.Credentials.Secret))
|
||||
values.Set("Signature", crypto.Base64Encode(hmac))
|
||||
urlPath := h.API.Endpoints.URL + common.EncodeURLValues(endpoint, values)
|
||||
urlPath := ePoint + common.EncodeURLValues(endpoint, values)
|
||||
|
||||
var body []byte
|
||||
if data != nil {
|
||||
encoded, err := json.Marshal(data)
|
||||
body, err = json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
body = encoded
|
||||
}
|
||||
|
||||
// Time difference between your timestamp and standard should be less than 1 minute.
|
||||
ctx, cancel := context.WithDeadline(context.Background(), now.Add(time.Minute))
|
||||
defer cancel()
|
||||
interim := json.RawMessage{}
|
||||
err := h.SendPayload(ctx, &request.Item{
|
||||
err = h.SendPayload(ctx, &request.Item{
|
||||
Method: method,
|
||||
Path: urlPath,
|
||||
Headers: headers,
|
||||
|
||||
1001
exchanges/huobi/huobi_cfutures.go
Normal file
1001
exchanges/huobi/huobi_cfutures.go
Normal file
File diff suppressed because it is too large
Load Diff
1182
exchanges/huobi/huobi_futures.go
Normal file
1182
exchanges/huobi/huobi_futures.go
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,416 @@
|
||||
package huobi
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
type errorCapture struct {
|
||||
Status string `json:"status"`
|
||||
Code int64 `json:"err_code"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// MarketSummary24Hr stores past 24hr market summary data of a given symbol
|
||||
type MarketSummary24Hr struct {
|
||||
Tick struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
High float64 `json:"high"`
|
||||
ID int64 `json:"id"`
|
||||
Count float64 `json:"count"`
|
||||
Low float64 `json:"low"`
|
||||
Version int64 `json:"version"`
|
||||
Volume float64 `json:"vol"`
|
||||
}
|
||||
}
|
||||
|
||||
// WsKlineData stores kline data for futures and swap websocket
|
||||
type WsKlineData struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
ID int64 `json:"id"`
|
||||
MRID int64 `json:"mrid"`
|
||||
Volume float64 `json:"vol"`
|
||||
Count float64 `json:"count"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
Low float64 `json:"low"`
|
||||
High float64 `json:"high"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsMarketDepth stores market depth data for futures and swap websocket
|
||||
type WsMarketDepth struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
MRID int64 `json:"mrid"`
|
||||
ID int64 `json:"id"`
|
||||
Bids [][2]float64 `json:"bids"`
|
||||
Asks [][2]float64 `json:"asks"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Version int64 `json:"version"`
|
||||
Channel string `json:"ch"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsIncrementalMarketDepth stores incremental market depth data for swap and futures websocket
|
||||
type WsIncrementalMarketDepth struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
MRID int64 `json:"mrid"`
|
||||
ID int64 `json:"id"`
|
||||
Bids [][2]float64 `json:"bids"`
|
||||
Asks [][2]float64 `json:"asks"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Version int64 `json:"version"`
|
||||
Channel string `json:"ch"`
|
||||
Event string `json:"event"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsMarketDetail stores market detail data for futures and swap websocket
|
||||
type WsMarketDetail struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
ID int64 `json:"id"`
|
||||
MRID int64 `json:"mrid"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
Amount float64 `json:"amount"`
|
||||
Volume float64 `json:"vol"`
|
||||
Count float64 `json:"count"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsMarketBBOData stores BBO data for futures and swap websocket
|
||||
type WsMarketBBOData struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
Channel string `json:"ch"`
|
||||
MRID int64 `json:"mrid"`
|
||||
ID int64 `json:"id"`
|
||||
Bid [2]float64 `json:"bid"`
|
||||
Ask [2]float64 `json:"ask"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Version int64 `json:":version"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// WsSubTradeDetail stores trade detail data for futures websocket
|
||||
type WsSubTradeDetail struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
ID int64 `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
Amount float64 `json:"amount"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Direction string `json:"direction"`
|
||||
} `json:"data"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// Futures
|
||||
|
||||
// FWsRequestKline stores requested kline data for futures websocket
|
||||
type FWsRequestKline struct {
|
||||
Rep string `json:"rep"`
|
||||
ID string `json:"id"`
|
||||
WsID int64 `json:"wsid"`
|
||||
Tick []struct {
|
||||
Volume float64 `json:"vol"`
|
||||
Count float64 `json:"count"`
|
||||
ID int64 `json:"id"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
Low float64 `json:"low"`
|
||||
High float64 `json:"high"`
|
||||
Amount float64 `json:"amount"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// FWsReqTradeDetail stores requested trade detail data for futures websocket
|
||||
type FWsReqTradeDetail struct {
|
||||
Rep string `json:"rep"`
|
||||
ID string `json:"id"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
ID int64 `json:"id"`
|
||||
Price float64 `json:"price"`
|
||||
Amount float64 `json:"amount"`
|
||||
Direction string `json:"direction"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubKlineIndex stores subscribed kline index data for futures websocket
|
||||
type FWsSubKlineIndex struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
ID string `json:"id"`
|
||||
Open float64 `json:"open,string"`
|
||||
Close float64 `json:"close,string"`
|
||||
High float64 `json:"high,string"`
|
||||
Low float64 `json:"low,string"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
Volume float64 `json:"vol,string"`
|
||||
Count float64 `json:"count,string"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// FWsReqKlineIndex stores requested kline index data for futures websocket
|
||||
type FWsReqKlineIndex struct {
|
||||
ID string `json:"id"`
|
||||
Rep string `json:"rep"`
|
||||
WsID int64 `json:"wsid"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Data []struct {
|
||||
ID int64 `json:"id"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
Low float64 `json:"low"`
|
||||
High float64 `json:"high"`
|
||||
Amount float64 `json:"amount"`
|
||||
Volume float64 `json:"vol"`
|
||||
Count float64 `json:"count"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubBasisData stores subscribed basis data for futures websocket
|
||||
type FWsSubBasisData struct {
|
||||
Channel string `json:"ch"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Tick struct {
|
||||
ID int64 `json:"id"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
ContractPrice float64 `json:"contract_price,string"`
|
||||
Basis float64 `json:"basis,string"`
|
||||
BasisRate float64 `json:"basis_rate,string"`
|
||||
}
|
||||
}
|
||||
|
||||
// FWsReqBasisData stores requested basis data for futures websocket
|
||||
type FWsReqBasisData struct {
|
||||
ID string `json:"id"`
|
||||
Rep string `json:"rep"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
WsID int64 `json:"wsid"`
|
||||
Tick struct {
|
||||
ID int64 `json:"id"`
|
||||
IndexPrice float64 `json:"index_price,string"`
|
||||
ContractPrice float64 `json:"contract_price,string"`
|
||||
Basis float64 `json:"basis,string"`
|
||||
BasisRate float64 `json:"basis_rate,string"`
|
||||
} `json:"tick"`
|
||||
}
|
||||
|
||||
// FWsSubOrderData stores subscribed order data for futures websocket
|
||||
type FWsSubOrderData struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
UID string `json:"uid"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
Status int64 `json:"status"`
|
||||
LeverageRate int64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_string"`
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
OrderSource string `json:"order_source"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
Fee float64 `json:"fee"`
|
||||
TradeAvgPrice float64 `json:"trade_avg_price"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
Profit float64 `json:"profit"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
CancelledAt int64 `json:"canceled_at"`
|
||||
Trade []struct {
|
||||
ID string `json:"id"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
TradeFee float64 `json:"trade_fee"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Role string `json:"role"`
|
||||
FeeAsset string `json:"fee_asset"`
|
||||
} `json:"trade"`
|
||||
}
|
||||
|
||||
// FWsSubMatchOrderData stores subscribed match order data for futures websocket
|
||||
type FWsSubMatchOrderData struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
UID string `json:"uid"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Symbol string `json:"symbol"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Status int64 `json:"status"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_string"`
|
||||
OrderType string `json:"order_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
ClientOrderID int64 `json:"client_order_id"`
|
||||
Trade []struct {
|
||||
ID string `json:"id"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
TradeVolume float64 `json:"trade_volume"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
TradeTurnover float64 `json:"trade_turnover"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
Role string `json:"role"`
|
||||
}
|
||||
}
|
||||
|
||||
// FWsSubEquityUpdates stores account equity updates data for futures websocket
|
||||
type FWsSubEquityUpdates struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
UID string `json:"uid"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Event string `json:"event"`
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
MarginBalance float64 `json:"margin_balance"`
|
||||
MarginStatic int64 `json:"margin_static"`
|
||||
MarginPosition float64 `json:"margin_position"`
|
||||
MarginFrozen float64 `json:"margin_frozen"`
|
||||
MarginAvailable float64 `json:"margin_available"`
|
||||
ProfitReal float64 `json:"profit_real"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
WithdrawAvailable float64 `json:"withdraw_available"`
|
||||
RiskRate float64 `json:"risk_rate"`
|
||||
LiquidationPrice float64 `json:"liquidation_price"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
AdjustFactor float64 `json:"adjust_factor"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubPositionUpdates stores subscribed position updates data for futures websocket
|
||||
type FWsSubPositionUpdates struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
UID string `json:"uid"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Event string `json:"event"`
|
||||
PositionsData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
Available float64 `json:"available"`
|
||||
Frozen float64 `json:"frozen"`
|
||||
CostOpen float64 `json:"cost_open"`
|
||||
CostHold float64 `json:"cost_hold"`
|
||||
ProfitUnreal float64 `json:"profit_unreal"`
|
||||
ProfitRate float64 `json:"profit_rate"`
|
||||
Profit float64 `json:"profit"`
|
||||
PositionMargin float64 `json:"position_margin"`
|
||||
LeverageRate float64 `json:"lever_rate"`
|
||||
Direction string `json:"direction"`
|
||||
LastPrice float64 `json:"last_price"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubLiquidationOrders stores subscribed liquidation orders data for futures websocket
|
||||
type FWsSubLiquidationOrders struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
OrdersData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
Volume float64 `json:"volume"`
|
||||
Price float64 `json:"price"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubContractInfo stores contract info data for futures websocket
|
||||
type FWsSubContractInfo struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
Timestamp int64 `json:"ts"`
|
||||
Event string `json:"event"`
|
||||
ContractData []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractSize float64 `json:"contract_size"`
|
||||
PriceTick float64 `json:"price_tick"`
|
||||
DeliveryDate string `json:"delivery_date"`
|
||||
CreateDate string `json:"create_date"`
|
||||
ContractStatus int64 `json:"contract_status"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// FWsSubTriggerOrderUpdates stores subscribed trigger order updates data for futures websocket
|
||||
type FWsSubTriggerOrderUpdates struct {
|
||||
Operation string `json:"op"`
|
||||
Topic string `json:"topic"`
|
||||
UID string `json:"uid"`
|
||||
Event string `json:"event"`
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractType string `json:"contract_type"`
|
||||
TriggerType string `json:"trigger_type"`
|
||||
Volume float64 `json:"volume"`
|
||||
OrderType int64 `json:"order_type"`
|
||||
Direction string `json:"direction"`
|
||||
Offset string `json:"offset"`
|
||||
LeverageRate int64 `json:"lever_rate"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
OrderIDString string `json:"order_id_str"`
|
||||
RelationOrderID string `json:"relation_order_id"`
|
||||
OrderPriceType string `json:"order_price_type"`
|
||||
Status int64 `json:"status"`
|
||||
OrderSource string `json:"order_source"`
|
||||
TriggerPrice float64 `json:"trigger_price"`
|
||||
TriggeredPrice float64 `json:"triggered_price"`
|
||||
OrderPrice float64 `json:"order_price"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
TriggeredAt int64 `json:"triggered_at"`
|
||||
OrderInsertAt int64 `json:"order_insert_at"`
|
||||
CancelledAt int64 `json:"canceled_at"`
|
||||
FailCode int64 `json:"fail_code"`
|
||||
FailReason string `json:"fail_reason"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// --------------------------------Spot-----------------------------------------
|
||||
|
||||
// Response stores the Huobi response information
|
||||
type Response struct {
|
||||
Status string `json:"status"`
|
||||
@@ -9,12 +420,38 @@ type Response struct {
|
||||
ErrorMessage string `json:"err-msg"`
|
||||
}
|
||||
|
||||
// MarginRatesData stores margin rates data
|
||||
type MarginRatesData struct {
|
||||
Data []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Currencies []struct {
|
||||
Currency string `json:"currency"`
|
||||
InterestRate float64 `json:"interest-rate,string"`
|
||||
MinLoanAmount float64 `json:"min-loan-amt,string"`
|
||||
MaxLoanAmount float64 `json:"max-loan-amt,string"`
|
||||
LoanableAmount float64 `json:"loanable-amt,string"`
|
||||
ActualRate float64 `json:"actual-rate,string"`
|
||||
} `json:"currencies"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
// ResponseV2 stores the Huobi generic response info
|
||||
type ResponseV2 struct {
|
||||
Code int32 `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// SwapMarketsData stores market data for swaps
|
||||
type SwapMarketsData struct {
|
||||
Symbol string `json:"symbol"`
|
||||
ContractCode string `json:"contract_code"`
|
||||
ContractSize float64 `json:"contract_size"`
|
||||
PriceTick float64 `json:"price_tick"`
|
||||
SettlementDate string `json:"settlement_date"`
|
||||
CreateDate string `json:"create_date"`
|
||||
ContractStatus int64 `json:"contract_status"`
|
||||
}
|
||||
|
||||
// KlineItem stores a kline item
|
||||
type KlineItem struct {
|
||||
ID int64 `json:"id"`
|
||||
@@ -79,8 +516,8 @@ var (
|
||||
|
||||
// OrderBookDataRequestParams represents Klines request data.
|
||||
type OrderBookDataRequestParams struct {
|
||||
Symbol string `json:"symbol"` // Required; example LTCBTC,BTCUSDT
|
||||
Type OrderBookDataRequestParamsType `json:"type"` // step0, step1, step2, step3, step4, step5 (combined depth 0-5); when step0, no depth is merged
|
||||
Symbol currency.Pair // Required; example LTCBTC,BTCUSDT
|
||||
Type OrderBookDataRequestParamsType `json:"type"` // step0, step1, step2, step3, step4, step5 (combined depth 0-5); when step0, no depth is merged
|
||||
}
|
||||
|
||||
// Orderbook stores the orderbook data
|
||||
@@ -122,17 +559,25 @@ type Detail struct {
|
||||
|
||||
// Symbol stores the symbol data
|
||||
type Symbol struct {
|
||||
BaseCurrency string `json:"base-currency"`
|
||||
QuoteCurrency string `json:"quote-currency"`
|
||||
PricePrecision int `json:"price-precision"`
|
||||
AmountPrecision int `json:"amount-precision"`
|
||||
SymbolPartition string `json:"symbol-partition"`
|
||||
Innovation string `json:"innovation"`
|
||||
State string `json:"state"`
|
||||
ValuePrecision int `json:"value-precision"`
|
||||
MinimumOrderAmount float64 `json:"min-order-amt"`
|
||||
MaximumOrderAmount float64 `json:"max-order-amt"`
|
||||
MinimumOrderValue float64 `json:"min-order-value"`
|
||||
BaseCurrency string `json:"base-currency"`
|
||||
QuoteCurrency string `json:"quote-currency"`
|
||||
PricePrecision float64 `json:"price-precision"`
|
||||
AmountPrecision float64 `json:"amount-precision"`
|
||||
SymbolPartition string `json:"symbol-partition"`
|
||||
Symbol string `json:"symbol"`
|
||||
State string `json:"state"`
|
||||
ValuePrecision float64 `json:"value-precision"`
|
||||
MinOrderAmt float64 `json:"min-order-amt"`
|
||||
MaxOrderAmt float64 `json:"max-order-amt"`
|
||||
MinOrderValue float64 `json:"min-order-value"`
|
||||
LimitOrderMinOrderAmt float64 `json:"limit-order-min-order-amt"`
|
||||
LimitOrderMaxOrderAmt float64 `json:"limit-order-max-order-amt"`
|
||||
SellMarketMinOrderAmt float64 `json:"sell-market-min-order-amt"`
|
||||
SellMarketMaxOrderAmt float64 `json:"sell-market-max-order-amt"`
|
||||
BuyMarketMaxOrderAmt float64 `json:"buy-market-max-order-amt"`
|
||||
LeverageRatio float64 `json:"leverage-ratio"`
|
||||
SuperMarginLeverageRatio float64 `json:"super-margin-leverage-ratio"`
|
||||
FundingLeverageRatio float64 `json:"funding-leverage-ratio"`
|
||||
}
|
||||
|
||||
// Account stores the account data
|
||||
@@ -248,7 +693,7 @@ type SpotNewOrderRequestParams struct {
|
||||
Amount float64 `json:"amount"` // The limit price indicates the quantity of the order, the market price indicates how much to buy when the order is paid, and the market price indicates how much the coin is sold when the order is sold.
|
||||
Price float64 `json:"price"` // Order price, market price does not use this parameter
|
||||
Source string `json:"source"` // Order source, api: API call, margin-api: loan asset transaction
|
||||
Symbol string `json:"symbol"` // The symbol to use; example btcusdt, bccbtc......
|
||||
Symbol currency.Pair `json:"symbol"` // The symbol to use; example btcusdt, bccbtc......
|
||||
Type SpotNewOrderRequestParamsType `json:"type"` // 订单类型, buy-market: 市价买, sell-market: 市价卖, buy-limit: 限价买, sell-limit: 限价卖
|
||||
}
|
||||
|
||||
@@ -299,9 +744,9 @@ var (
|
||||
|
||||
// KlinesRequestParams represents Klines request data.
|
||||
type KlinesRequestParams struct {
|
||||
Symbol string // Symbol to be used; example btcusdt, bccbtc......
|
||||
Period string // Kline time interval; 1min, 5min, 15min......
|
||||
Size int // Size; [1-2000]
|
||||
Symbol currency.Pair // Symbol to be used; example btcusdt, bccbtc......
|
||||
Period string // Kline time interval; 1min, 5min, 15min......
|
||||
Size int // Size; [1-2000]
|
||||
}
|
||||
|
||||
// WsRequest defines a request data structure
|
||||
@@ -597,3 +1042,167 @@ type authenticationPing struct {
|
||||
OP string `json:"op"`
|
||||
TS int64 `json:"ts"`
|
||||
}
|
||||
|
||||
// OrderVars stores side, status and type for any order/trade
|
||||
type OrderVars struct {
|
||||
Side order.Side
|
||||
Status order.Status
|
||||
OrderType order.Type
|
||||
Fee float64
|
||||
}
|
||||
|
||||
// Variables below are used to check api requests being sent out
|
||||
|
||||
var (
|
||||
validPeriods = []string{"5min", "15min", "30min", "60min", "4hour", "1day"}
|
||||
|
||||
validBasisPriceTypes = []string{"open", "close", "high", "low", "average"}
|
||||
|
||||
validAmountType = map[string]int64{
|
||||
"cont": 1,
|
||||
"cryptocurrency": 2,
|
||||
}
|
||||
|
||||
validTransferType = []string{
|
||||
"master_to_sub", "sub_to_master",
|
||||
}
|
||||
|
||||
validTradeTypes = map[string]int64{
|
||||
"filled": 0,
|
||||
"closed": 5,
|
||||
"open": 6,
|
||||
}
|
||||
|
||||
validOrderType = map[string]int64{
|
||||
"quotation": 1,
|
||||
"cancelledOrder": 2,
|
||||
"forcedLiquidation": 3,
|
||||
"deliveryOrder": 4,
|
||||
}
|
||||
|
||||
validOrderTypes = []string{
|
||||
"limit", "opponent", "lightning", "optimal_5", "optimal_10", "optimal_20",
|
||||
"fok", "ioc", "opponent_ioc", "lightning_ioc", "optimal_5_ioc",
|
||||
"optimal_10_ioc", "optimal_20_ioc", "opponent_fok", "optimal_20_fok",
|
||||
}
|
||||
|
||||
validTriggerType = map[string]string{
|
||||
"greaterOrEqual": "ge",
|
||||
"smallerOrEqual": "le",
|
||||
}
|
||||
|
||||
validOrderPriceType = []string{
|
||||
"limit", "optimal_5", "optimal_10", "optimal_20",
|
||||
}
|
||||
|
||||
validLightningOrderPriceType = []string{
|
||||
"lightning", "lightning_fok", "lightning_ioc",
|
||||
}
|
||||
|
||||
validTradeType = map[string]int64{
|
||||
"all": 0,
|
||||
"openLong": 1,
|
||||
"openShort": 2,
|
||||
"closeShort": 3,
|
||||
"closeLong": 4,
|
||||
"liquidateLong": 5,
|
||||
"liquidateShort": 6,
|
||||
}
|
||||
|
||||
validFuturesTradeType = map[string]int64{
|
||||
"all": 0,
|
||||
"openLong": 1,
|
||||
"openShort": 2,
|
||||
"closeShort": 3,
|
||||
"closeLong": 4,
|
||||
"liquidateLong": 5,
|
||||
"liquidateShort": 6,
|
||||
"deliveryLong": 7,
|
||||
"deliveryShort": 8,
|
||||
"reduceLong": 11,
|
||||
"reduceShort": 12,
|
||||
}
|
||||
|
||||
validContractTypes = []string{
|
||||
"this_week", "next_week", "quarter", "next_quarter",
|
||||
}
|
||||
|
||||
validFuturesPeriods = []string{
|
||||
"1min", "5min", "15min", "30min", "60min", "1hour", "4hour", "1day",
|
||||
}
|
||||
|
||||
validFuturesOrderPriceTypes = []string{
|
||||
"limit", "opponent", "lightning", "optimal_5", "optimal_10",
|
||||
"optimal_20", "fok", "ioc", "opponent_ioc", "lightning_ioc",
|
||||
"optimal_5_ioc", "optimal_10_ioc", "optimal_20_ioc", "opponent_fok",
|
||||
"lightning_fok", "optimal_5_fok", "optimal_10_fok", "optimal_20_fok",
|
||||
}
|
||||
|
||||
validFuturesRecordTypes = map[string]string{
|
||||
"closeLong": "3",
|
||||
"closeShort": "4",
|
||||
"openOpenPositionsTakerFees": "5",
|
||||
"openPositionsMakerFees": "6",
|
||||
"closePositionsTakerFees": "7",
|
||||
"closePositionsMakerFees": "8",
|
||||
"closeLongDelivery": "9",
|
||||
"closeShortDelivery": "10",
|
||||
"deliveryFee": "11",
|
||||
"longLiquidationClose": "12",
|
||||
"shortLiquidationClose": "13",
|
||||
"transferFromSpotToContracts": "14",
|
||||
"transferFromContractsToSpot": "15",
|
||||
"settleUnrealizedLongPNL": "16",
|
||||
"settleUnrealizedShortPNL": "17",
|
||||
"clawback": "19",
|
||||
"system": "26",
|
||||
"activityPrizeRewards": "28",
|
||||
"rebate": "29",
|
||||
"transferToSub": "34",
|
||||
"transferFromSub": "35",
|
||||
"transferToMaster": "36",
|
||||
"transferFromMaster": "37",
|
||||
}
|
||||
|
||||
validOffsetTypes = []string{
|
||||
"open", "close",
|
||||
}
|
||||
|
||||
validOPTypes = []string{
|
||||
"lightning", "lightning_fok", "lightning_ioc",
|
||||
}
|
||||
|
||||
validFuturesReqType = map[string]int64{
|
||||
"all": 1,
|
||||
"finishedStatus": 2,
|
||||
}
|
||||
|
||||
validFuturesOrderTypes = map[string]int64{
|
||||
"limit": 1,
|
||||
"opponent": 3,
|
||||
"lightning": 4,
|
||||
"triggerOrder": 5,
|
||||
"postOnly": 6,
|
||||
"optimal_5": 7,
|
||||
"optimal_10": 8,
|
||||
"optimal_20": 9,
|
||||
"fok": 10,
|
||||
"ioc": 11,
|
||||
}
|
||||
|
||||
validOrderStatus = map[order.Status]int64{
|
||||
order.AnyStatus: 0,
|
||||
order.Active: 3,
|
||||
order.PartiallyFilled: 4,
|
||||
order.PartiallyCancelled: 5,
|
||||
order.Filled: 6,
|
||||
order.Cancelled: 7,
|
||||
}
|
||||
|
||||
validStatusTypes = map[string]int64{
|
||||
"all": 0,
|
||||
"success": 4,
|
||||
"failed": 5,
|
||||
"cancelled": 6,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -25,7 +25,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
baseWSURL = "wss://api.huobi.pro"
|
||||
baseWSURL = "wss://api.huobi.pro"
|
||||
futuresWSURL = "wss://api.hbdm.com/"
|
||||
|
||||
wsMarketURL = baseWSURL + "/ws"
|
||||
wsMarketKline = "market.%s.kline.1min"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,7 @@ type IBotExchange interface {
|
||||
GetName() string
|
||||
IsEnabled() bool
|
||||
SetEnabled(bool)
|
||||
ValidateCredentials() error
|
||||
ValidateCredentials(a asset.Item) error
|
||||
FetchTicker(p currency.Pair, a asset.Item) (*ticker.Price, error)
|
||||
UpdateTicker(p currency.Pair, a asset.Item) (*ticker.Price, error)
|
||||
FetchOrderbook(p currency.Pair, a asset.Item) (*orderbook.Base, error)
|
||||
@@ -35,8 +35,8 @@ type IBotExchange interface {
|
||||
UpdateTradablePairs(forceUpdate bool) error
|
||||
GetEnabledPairs(a asset.Item) (currency.Pairs, error)
|
||||
GetAvailablePairs(a asset.Item) (currency.Pairs, error)
|
||||
FetchAccountInfo() (account.Holdings, error)
|
||||
UpdateAccountInfo() (account.Holdings, error)
|
||||
FetchAccountInfo(a asset.Item) (account.Holdings, error)
|
||||
UpdateAccountInfo(a asset.Item) (account.Holdings, error)
|
||||
GetAuthenticatedAPISupport(endpoint uint8) bool
|
||||
SetPairs(pairs currency.Pairs, a asset.Item, enabled bool) error
|
||||
GetAssetTypes() asset.Items
|
||||
|
||||
@@ -43,18 +43,18 @@ type ItBit struct {
|
||||
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
|
||||
func (i *ItBit) GetTicker(currencyPair string) (Ticker, error) {
|
||||
var response Ticker
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", i.API.Endpoints.URL, itbitMarkets, currencyPair, itbitTicker)
|
||||
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, itbitTicker)
|
||||
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
}
|
||||
|
||||
// GetOrderbook returns full order book for the specified market.
|
||||
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
|
||||
func (i *ItBit) GetOrderbook(currencyPair string) (OrderbookResponse, error) {
|
||||
response := OrderbookResponse{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", i.API.Endpoints.URL, itbitMarkets, currencyPair, itbitOrderbook)
|
||||
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, itbitOrderbook)
|
||||
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns recent trades for a specified market.
|
||||
@@ -68,9 +68,9 @@ func (i *ItBit) GetTradeHistory(currencyPair, tradeID string) (Trades, error) {
|
||||
if tradeID != "" {
|
||||
req += "?since=" + tradeID
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", i.API.Endpoints.URL, itbitMarkets, currencyPair, req)
|
||||
path := fmt.Sprintf("/%s/%s/%s", itbitMarkets, currencyPair, req)
|
||||
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
return response, i.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
}
|
||||
|
||||
// GetWallets returns information about all wallets associated with the account.
|
||||
@@ -82,7 +82,7 @@ func (i *ItBit) GetWallets(params url.Values) ([]Wallet, error) {
|
||||
var resp []Wallet
|
||||
params.Set("userId", i.API.Credentials.ClientID)
|
||||
path := fmt.Sprintf("/%s?%s", itbitWallets, params.Encode())
|
||||
return resp, i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
return resp, i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
}
|
||||
|
||||
// CreateWallet creates a new wallet with a specified name.
|
||||
@@ -92,7 +92,7 @@ func (i *ItBit) CreateWallet(walletName string) (Wallet, error) {
|
||||
params["userId"] = i.API.Credentials.ClientID
|
||||
params["name"] = walletName
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodPost, "/"+itbitWallets, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, "/"+itbitWallets, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func (i *ItBit) GetWallet(walletID string) (Wallet, error) {
|
||||
resp := Wallet{}
|
||||
path := fmt.Sprintf("/%s/%s", itbitWallets, walletID)
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -123,7 +123,7 @@ func (i *ItBit) GetWalletBalance(walletID, currency string) (Balance, error) {
|
||||
resp := Balance{}
|
||||
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitBalances, currency)
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func (i *ItBit) GetOrders(walletID, symbol, status string, page, perPage int64)
|
||||
params["perPage"] = strconv.FormatInt(perPage, 10)
|
||||
}
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest(http.MethodGet, itbitOrders, params, &resp)
|
||||
return resp, i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, itbitOrders, params, &resp)
|
||||
}
|
||||
|
||||
// GetWalletTrades returns all trades for a specified wallet.
|
||||
@@ -162,7 +162,7 @@ func (i *ItBit) GetWalletTrades(walletID string, params url.Values) (Records, er
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitTrades)
|
||||
path := common.EncodeURLValues(urlPath, params)
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -178,7 +178,7 @@ func (i *ItBit) GetFundingHistoryForWallet(walletID string, params url.Values) (
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitFundingHistory)
|
||||
path := common.EncodeURLValues(urlPath, params)
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -205,7 +205,7 @@ func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, p
|
||||
params["clientOrderIdentifier"] = clientRef
|
||||
}
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodPost, path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -221,7 +221,7 @@ func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
|
||||
urlPath := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
|
||||
path := common.EncodeURLValues(urlPath, params)
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodGet, path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodGet, path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
|
||||
func (i *ItBit) CancelExistingOrder(walletID, orderID string) error {
|
||||
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitOrders, orderID)
|
||||
|
||||
return i.SendAuthenticatedHTTPRequest(http.MethodDelete, path, nil, nil)
|
||||
return i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodDelete, path, nil, nil)
|
||||
}
|
||||
|
||||
// GetCryptoDepositAddress returns a deposit address to send cryptocurrency to.
|
||||
@@ -246,7 +246,7 @@ func (i *ItBit) GetCryptoDepositAddress(walletID, currency string) (CryptoCurren
|
||||
params := make(map[string]interface{})
|
||||
params["currency"] = currency
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodPost, path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -267,7 +267,7 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount
|
||||
params["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
params["currencyCode"] = currency
|
||||
|
||||
err := i.SendAuthenticatedHTTPRequest(http.MethodPost, path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -278,10 +278,14 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (i *ItBit) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (i *ItBit) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := i.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return i.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: i.Verbose,
|
||||
HTTPDebugging: i.HTTPDebugging,
|
||||
@@ -290,20 +294,22 @@ func (i *ItBit) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request to itBit
|
||||
func (i *ItBit) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) error {
|
||||
func (i *ItBit) SendAuthenticatedHTTPRequest(ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) error {
|
||||
if !i.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, i.Name)
|
||||
}
|
||||
|
||||
endpoint, err := i.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
req := make(map[string]interface{})
|
||||
urlPath := i.API.Endpoints.URL + path
|
||||
urlPath := endpoint + path
|
||||
|
||||
for key, value := range params {
|
||||
req[key] = value
|
||||
}
|
||||
|
||||
PayloadJSON := []byte("")
|
||||
var err error
|
||||
|
||||
if params != nil {
|
||||
PayloadJSON, err = json.Marshal(req)
|
||||
|
||||
@@ -269,7 +269,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := i.GetActiveOrders(&getOrdersRequest)
|
||||
@@ -282,7 +283,8 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := i.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -378,7 +380,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := i.UpdateAccountInfo()
|
||||
_, err := i.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
|
||||
@@ -94,9 +94,13 @@ func (i *ItBit) SetDefaults() {
|
||||
|
||||
i.Requester = request.New(i.Name,
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
|
||||
i.API.Endpoints.URLDefault = itbitAPIURL
|
||||
i.API.Endpoints.URL = i.API.Endpoints.URLDefault
|
||||
i.API.Endpoints = i.NewEndpoints()
|
||||
err = i.API.Endpoints.SetDefaultEndpoints(map[exchange.URL]string{
|
||||
exchange.RestSpot: itbitAPIURL,
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorln(log.ExchangeSys, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Setup sets the exchange parameters from exchange config
|
||||
@@ -244,7 +248,7 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies
|
||||
func (i *ItBit) UpdateAccountInfo() (account.Holdings, error) {
|
||||
func (i *ItBit) UpdateAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
var info account.Holdings
|
||||
info.Exchange = i.Name
|
||||
|
||||
@@ -293,10 +297,10 @@ func (i *ItBit) UpdateAccountInfo() (account.Holdings, error) {
|
||||
}
|
||||
|
||||
// FetchAccountInfo retrieves balances for all enabled currencies
|
||||
func (i *ItBit) FetchAccountInfo() (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(i.Name)
|
||||
func (i *ItBit) FetchAccountInfo(assetType asset.Item) (account.Holdings, error) {
|
||||
acc, err := account.GetHoldings(i.Name, assetType)
|
||||
if err != nil {
|
||||
return i.UpdateAccountInfo()
|
||||
return i.UpdateAccountInfo(assetType)
|
||||
}
|
||||
|
||||
return acc, nil
|
||||
@@ -625,8 +629,8 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
|
||||
|
||||
// ValidateCredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
func (i *ItBit) ValidateCredentials() error {
|
||||
_, err := i.UpdateAccountInfo()
|
||||
func (i *ItBit) ValidateCredentials(assetType asset.Item) error {
|
||||
_, err := i.UpdateAccountInfo(assetType)
|
||||
return i.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
576
exchanges/kraken/futures_types.go
Normal file
576
exchanges/kraken/futures_types.go
Normal file
@@ -0,0 +1,576 @@
|
||||
package kraken
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
)
|
||||
|
||||
var (
|
||||
validOrderTypes = map[order.Type]string{
|
||||
order.ImmediateOrCancel: "ioc",
|
||||
order.Limit: "lmt",
|
||||
order.Stop: "stp",
|
||||
order.PostOnly: "post",
|
||||
order.TakeProfit: "take_profit",
|
||||
}
|
||||
|
||||
validSide = []string{"buy", "sell"}
|
||||
|
||||
validTriggerSignal = []string{"mark", "index", "last"}
|
||||
|
||||
validReduceOnly = []string{"true", "false"}
|
||||
|
||||
validBatchOrderType = []string{
|
||||
"edit", "cancel", "send",
|
||||
}
|
||||
)
|
||||
|
||||
// WSFuturesTickerData stores ws ticker data for futures websocket
|
||||
type WSFuturesTickerData struct {
|
||||
Time int64 `json:"time"`
|
||||
Feed string `json:"feed"`
|
||||
ProductID string `json:"product_id"`
|
||||
Bid float64 `json:"bid"`
|
||||
Ask float64 `json:"ask"`
|
||||
BidSize float64 `json:"bid_size"`
|
||||
AskSize float64 `json:"ask_size"`
|
||||
Volume float64 `json:"volume"`
|
||||
DTM float64 `json:"dtm"`
|
||||
Leverage string `json:"leverage"`
|
||||
Index float64 `json:"index"`
|
||||
Premium float64 `json:"premium"`
|
||||
Last float64 `json:"last"`
|
||||
Change float64 `json:"change"`
|
||||
Suspended bool `json:"suspended"`
|
||||
Tag string `json:"tag"`
|
||||
Pair string `json:"pair"`
|
||||
OpenInterest float64 `json:"openinterest"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
MaturityTime int64 `json:"maturityTime"`
|
||||
FundingRate float64 `json:"funding_rate"`
|
||||
FundingRatePrediction float64 `json:"funding_rate_prediction"`
|
||||
RelativeFundingRate float64 `json:"relative_funding_rate"`
|
||||
RelativeFundingRatePrediction float64 `json:"relative_funding_rate_prediction"`
|
||||
NextFundingRateTime int64 `json:"next_funding_rate_time"`
|
||||
}
|
||||
|
||||
// WsFuturesTradeData stores public trade data for futures websocket
|
||||
type WsFuturesTradeData struct {
|
||||
Feed string `json:"feed"`
|
||||
ProductID string `json:"product_id"`
|
||||
Trades []struct {
|
||||
Feed string `json:"feed"`
|
||||
ProductID string `json:"product_id"`
|
||||
Side string `json:"side"`
|
||||
ProductType string `json:"type"`
|
||||
Seq int64 `json:"seq"`
|
||||
Time int64 `json:"time"`
|
||||
Quantity float64 `json:"qty"`
|
||||
Price float64 `json:"price"`
|
||||
} `json:"trades"`
|
||||
}
|
||||
|
||||
// WsFuturesTickerLite stores ticker lite data for futures websocket
|
||||
type WsFuturesTickerLite struct {
|
||||
Feed string `json:"feed"`
|
||||
ProductID string `json:"product_id"`
|
||||
Bid float64 `json:"bid"`
|
||||
Ask float64 `json:"ask"`
|
||||
Change float64 `json:"change"`
|
||||
Premium float64 `json:"premium"`
|
||||
Volume float64 `json:"volume"`
|
||||
Tag string `json:"tag"`
|
||||
Pair string `json:"pair"`
|
||||
DTM float64 `json:"dtm"`
|
||||
}
|
||||
|
||||
// WsFuturesOB stores orderbook data for futures websocket
|
||||
type WsFuturesOB struct {
|
||||
Feed string `json:"feed"`
|
||||
ProductID string `json:"product_id"`
|
||||
Seq int64 `json:"seq"`
|
||||
Bids []wsOBItem `json:"bids"`
|
||||
Asks []wsOBItem `json:"asks"`
|
||||
}
|
||||
|
||||
type wsOBItem struct {
|
||||
Price float64 `json:"price"`
|
||||
Quantity float64 `json:"qty"`
|
||||
}
|
||||
|
||||
// WsVerboseOpenOrders stores verbose open orders data for futures websocket
|
||||
type WsVerboseOpenOrders struct {
|
||||
Feed string `json:"feed"`
|
||||
Account string `json:"account"`
|
||||
Orders []struct {
|
||||
Instrument string `json:"instrument"`
|
||||
Time int64 `json:"time"`
|
||||
LastUpdateTime int64 `json:"last_update_time"`
|
||||
Qty float64 `json:"qty"`
|
||||
Filled float64 `json:"filled"`
|
||||
LimitPrice float64 `json:"limit_price"`
|
||||
StopPrice float64 `json:"stop_price"`
|
||||
OrderType string `json:"type"`
|
||||
OrderID string `json:"order_id"`
|
||||
Direction int64 `json:"direction"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
} `json:"orders"`
|
||||
}
|
||||
|
||||
// WsOpenPositions stores open positions data for futures websocket
|
||||
type WsOpenPositions struct {
|
||||
Feed string `json:"feed"`
|
||||
Account string `json:"account"`
|
||||
Positions []struct {
|
||||
Instrument string `json:"instrument"`
|
||||
Balance float64 `json:"balance"`
|
||||
EntryPrice float64 `json:"entry_price"`
|
||||
MarkPrice float64 `json:"mark_price"`
|
||||
IndexPrice float64 `json:"index_price"`
|
||||
ProfitAndLoss float64 `json:"pnl"`
|
||||
} `json:"positions"`
|
||||
}
|
||||
|
||||
// WsFuturesAccountLog stores account log data for futures websocket
|
||||
type WsFuturesAccountLog struct {
|
||||
Feed string `json:"feed"`
|
||||
Logs []struct {
|
||||
ID int64 `json:"id"`
|
||||
Date string `json:"date"`
|
||||
Asset string `json:"asset"`
|
||||
Info string `json:"info"`
|
||||
BookingUID string `json:"booking_uid"`
|
||||
MarginAccount string `json:"margin_account"`
|
||||
OldBalance float64 `json:"old_balance"`
|
||||
NewBalance float64 `json:"new_balance"`
|
||||
OldAverageEntry float64 `json:"old_average_entry"`
|
||||
NewAverageEntry float64 `json:"new_average_entry"`
|
||||
TradePrice float64 `json:"trade_price"`
|
||||
MarkPrice float64 `json:"mark_price"`
|
||||
RealizedPNL float64 `json:"realized_pnl"`
|
||||
Fee float64 `json:"fee"`
|
||||
Execution string `json:"execution"`
|
||||
Collateral string `json:"collateral"`
|
||||
FundingRate float64 `json:"funding_rate"`
|
||||
RealizedFunding float64 `json:"realized_funding"`
|
||||
} `json:"logs"`
|
||||
}
|
||||
|
||||
// WsFuturesFillsData stores fills data for futures websocket
|
||||
type WsFuturesFillsData struct {
|
||||
Feed string `json:"feed"`
|
||||
Account string `json:"account"`
|
||||
Fills []struct {
|
||||
Instrument string `json:"instrument"`
|
||||
Time int64 `json:"time"`
|
||||
Price float64 `json:"price"`
|
||||
Seq int64 `json:"seq"`
|
||||
Buy bool `json:"buy"`
|
||||
Quantity float64 `json:"qty"`
|
||||
OrderID string `json:"order_id"`
|
||||
ClientOrderID string `json:"cli_order_id"`
|
||||
FillID string `json:"fill_id"`
|
||||
FillType string `json:"fill_type"`
|
||||
} `json:"fills"`
|
||||
}
|
||||
|
||||
// WsFuturesOpenOrders stores open orders data for futures websocket
|
||||
type WsFuturesOpenOrders struct {
|
||||
Feed string `json:"feed"`
|
||||
Account string `json:"account"`
|
||||
Orders []struct {
|
||||
Instrument string `json:"instrument"`
|
||||
Time int64 `json:"time"`
|
||||
LastUpdateTime int64 `json:"last_update_time"`
|
||||
Qty float64 `json:"qty"`
|
||||
Filled float64 `json:"filled"`
|
||||
LimitPrice float64 `json:"limit_price"`
|
||||
StopPrice float64 `json:"stop_price"`
|
||||
OrderType string `json:"order_type"`
|
||||
OrderID string `json:"order_id"`
|
||||
Direction string `json:"direction"`
|
||||
ReduceOnly bool `json:"reduce_only"`
|
||||
} `json:"orders"`
|
||||
}
|
||||
|
||||
// WsAccountBalancesAndMargin stores account balances and margin data for futures websocket
|
||||
type WsAccountBalancesAndMargin struct {
|
||||
Seq int64 `json:"seq"`
|
||||
Feed string `json:"feed"`
|
||||
Account string `json:"account"`
|
||||
MarginAccounts []struct {
|
||||
Name string `json:"name"`
|
||||
PortfolioValue float64 `json:"pv"`
|
||||
Balance float64 `json:"balance"`
|
||||
Funding float64 `json:"funding"`
|
||||
MaintenanceMargin float64 `json:"mm"`
|
||||
ProfitAndLoss float64 `json:"pnl"`
|
||||
InitialMargin float64 `json:"im"`
|
||||
AM float64 `json:"am"`
|
||||
} `json:"margin_accounts"`
|
||||
}
|
||||
|
||||
// WsFuturesNotifications stores notifications data for futures websocket
|
||||
type WsFuturesNotifications struct {
|
||||
Feed string `json:"feed"`
|
||||
Notifications []struct {
|
||||
ID int64 `json:"id"`
|
||||
NotificationType string `json:"notificationType"`
|
||||
Priority string `json:"priority"`
|
||||
Note string `json:"note"`
|
||||
EffectiveTime int64 `json:"effective_time"`
|
||||
}
|
||||
}
|
||||
|
||||
type assetTranslatorStore struct {
|
||||
l sync.RWMutex
|
||||
Assets map[string]string
|
||||
}
|
||||
|
||||
// FuturesOrderbookData stores orderbook data for futures
|
||||
type FuturesOrderbookData struct {
|
||||
ServerTime string `json:"serverTime"`
|
||||
Orderbook struct {
|
||||
Bids [][2]float64 `json:"bids"`
|
||||
Asks [][2]float64 `json:"asks"`
|
||||
} `json:"orderBook"`
|
||||
}
|
||||
|
||||
// TimeResponse type
|
||||
type TimeResponse struct {
|
||||
Unixtime int64 `json:"unixtime"`
|
||||
Rfc1123 string `json:"rfc1123"`
|
||||
}
|
||||
|
||||
// FuturesInstrumentData stores info for futures market
|
||||
type FuturesInstrumentData struct {
|
||||
Instruments []struct {
|
||||
Symbol string `json:"symbol"`
|
||||
FutureType string `json:"type"`
|
||||
Underlying string `json:"underlying"`
|
||||
LastTradingTime string `json:"lastTradingTime"`
|
||||
TickSize float64 `json:"tickSize"`
|
||||
ContractSize float64 `json:"contractSize"`
|
||||
Tradable bool `json:"tradeable"`
|
||||
MarginLevels []struct {
|
||||
Contracts float64 `json:"contracts"`
|
||||
InitialMargin float64 `json:"initialMargin"`
|
||||
MaintenanceMargin float64 `json:"maintenanceMargin"`
|
||||
} `json:"marginLevels"`
|
||||
} `json:"instruments"`
|
||||
}
|
||||
|
||||
// FuturesTradeHistoryData stores trade history data for futures
|
||||
type FuturesTradeHistoryData struct {
|
||||
History []struct {
|
||||
Time string `json:"time"`
|
||||
TradeID int64 `json:"trade_id"`
|
||||
Price float64 `json:"price"`
|
||||
Size float64 `json:"size"`
|
||||
Side string `json:"side"`
|
||||
TradeType string `json:"type"`
|
||||
} `json:"history"`
|
||||
}
|
||||
|
||||
// FuturesTickerData stores info for futures ticker
|
||||
type FuturesTickerData struct {
|
||||
Tickers []struct {
|
||||
Tag string `json:"tag"`
|
||||
Pair string `json:"pair"`
|
||||
Symbol string `json:"symbol"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
Bid float64 `json:"bid"`
|
||||
BidSize float64 `json:"bidSize"`
|
||||
Ask float64 `json:"ask"`
|
||||
AskSize float64 `json:"askSize"`
|
||||
Vol24h float64 `json:"vol24h"`
|
||||
OpenInterest float64 `json:"openInterest"`
|
||||
Open24H float64 `json:"open24h"`
|
||||
Last float64 `json:"last"`
|
||||
LastTime string `json:"lastTime"`
|
||||
LastSize float64 `json:"lastSize"`
|
||||
Suspended bool `json:"suspended"`
|
||||
FundingRate float64 `json:"fundingRate"`
|
||||
FundingRatePrediction float64 `json:"fundingRatePrediction"`
|
||||
} `json:"tickers"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesEditedOrderData stores an edited order's data
|
||||
type FuturesEditedOrderData struct {
|
||||
ServerTime string `json:"serverTime"`
|
||||
EditStatus struct {
|
||||
Status string `json:"status"`
|
||||
OrderID string `json:"orderId"`
|
||||
ReceivedTime string `json:"receivedTime"`
|
||||
OrderEvents []struct {
|
||||
Old FuturesOrderData `json:"old"`
|
||||
New FuturesOrderData `json:"new"`
|
||||
} `json:"orderEvents"`
|
||||
ReduceQuantity string `json:"reduceQuantity"`
|
||||
DataType string `json:"type"`
|
||||
} `json:"editStatus"`
|
||||
}
|
||||
|
||||
// FuturesSendOrderData stores send order data
|
||||
type FuturesSendOrderData struct {
|
||||
SendStatus struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Status string `json:"status"`
|
||||
ReceivedTime string `json:"receivedTime"`
|
||||
OrderEvents []struct {
|
||||
UID string `json:"uid"`
|
||||
Order FuturesOrderData `json:"order"`
|
||||
Reason string `json:"reason"`
|
||||
DataType string `json:"type"`
|
||||
} `json:"orderEvents"`
|
||||
} `json:"sendStatus"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesOrderData stores order data
|
||||
type FuturesOrderData struct {
|
||||
OrderID string `json:"orderId"`
|
||||
ClientOrderID string `json:"cliOrderId"`
|
||||
OrderType string `json:"type"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Filled float64 `json:"filled"`
|
||||
LimitPrice float64 `json:"limitPrice"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
LastUpdateTimestamp string `json:"lastUpdateTimestamp"`
|
||||
}
|
||||
|
||||
// FuturesCancelOrderData stores cancel order data for futures
|
||||
type FuturesCancelOrderData struct {
|
||||
CancelStatus struct {
|
||||
Status string `json:"status"`
|
||||
OrderID string `json:"order_id"`
|
||||
ReceivedTime string `json:"receivedTime"`
|
||||
OrderEvents []struct {
|
||||
UID string `json:"uid"`
|
||||
Order FuturesOrderData `json:"order"`
|
||||
DataType string `json:"type"`
|
||||
} `json:"orderEvents"`
|
||||
} `json:"cancelStatus"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesFillsData stores fills data
|
||||
type FuturesFillsData struct {
|
||||
Fills []struct {
|
||||
FillID string `json:"fill_id"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"buy"`
|
||||
OrderID string `json:"order_id"`
|
||||
Size float64 `json:"size"`
|
||||
Price float64 `json:"price"`
|
||||
FillTime string `json:"fillTime"`
|
||||
FillType string `json:"fillType"`
|
||||
} `json:"fills"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesTransferData stores transfer data
|
||||
type FuturesTransferData struct {
|
||||
Result string `json:"result"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesOpenPositions stores open positions data for futures
|
||||
type FuturesOpenPositions struct {
|
||||
OpenPositions []struct {
|
||||
Side string `json:"side"`
|
||||
Symbol string `json:"symbol"`
|
||||
Price float64 `json:"price"`
|
||||
FillTime string `json:"fillTime"`
|
||||
Size float64 `json:"size"`
|
||||
UnrealizedFunding float64 `json:"unrealizedFunding"`
|
||||
} `json:"openPositions"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesNotificationData stores notification data
|
||||
type FuturesNotificationData struct {
|
||||
Notifications []struct {
|
||||
NotificationType string `json:"type"`
|
||||
Priority string `json:"priority"`
|
||||
Note string `json:"note"`
|
||||
EffectiveTime string `json:"effectiveTime"`
|
||||
} `json:"notifcations"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// FuturesAccountsData stores account data
|
||||
type FuturesAccountsData struct {
|
||||
ServerTime string `json:"serverTime"`
|
||||
Accounts map[string]AccountsData `json:"accounts"`
|
||||
}
|
||||
|
||||
// AccountsData stores data of an account
|
||||
type AccountsData struct {
|
||||
AccType string `json:"type"`
|
||||
Currency string `json:"currency"`
|
||||
Balances map[string]float64 `json:"balances"`
|
||||
Auxiliary struct {
|
||||
AvailableFunds float64 `json:"af"`
|
||||
ProfitAndLoss float64 `json:"pnl"`
|
||||
PortfolioValue float64 `json:"pv"`
|
||||
} `json:"auxiliary"`
|
||||
MarginRequirements struct {
|
||||
InitialMargin float64 `json:"im"`
|
||||
MaintenanceMargin float64 `json:"mm"`
|
||||
LiquidationThreshold float64 `json:"lt"`
|
||||
TerminationThreshold float64 `json:"tt"`
|
||||
} `json:"marginRequirements"`
|
||||
TriggerEstimates struct {
|
||||
InitialMargin float64 `json:"im"`
|
||||
MaintenanceMargin float64 `json:"mm"`
|
||||
LiquidationThreshold float64 `json:"lt"`
|
||||
TerminationThreshold float64 `json:"tt"`
|
||||
} `json:"triggerEstimates"`
|
||||
}
|
||||
|
||||
// CancelAllOrdersData stores order data for all cancelled orders
|
||||
type CancelAllOrdersData struct {
|
||||
CancelStatus struct {
|
||||
ReceivedTime string `json:"receivedTime"`
|
||||
CancelOnly string `json:"cancelOnly"`
|
||||
Status string `json:"status"`
|
||||
CancelledOrders []struct {
|
||||
OrderID string `json:"order_id"`
|
||||
} `json:"cancelledOrders"`
|
||||
OrderEvents []struct {
|
||||
UID string `json:"uid"`
|
||||
} `json:"uid"`
|
||||
Order FuturesOrderData `json:"order"`
|
||||
DataType string `json:"type"`
|
||||
} `json:"cancelStatus"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// CancelOrdersAfterData stores data of all orders after a certain time that are cancelled
|
||||
type CancelOrdersAfterData struct {
|
||||
Result string `json:"result"`
|
||||
Status struct {
|
||||
CurrentTime string `json:"currentTime"`
|
||||
TriggerTime string `json:"triggerTime"`
|
||||
} `json:"status"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
|
||||
// RecentOrderData stores order data of a recent order
|
||||
type RecentOrderData struct {
|
||||
UID string `json:"uid"`
|
||||
AccountID string `json:"accountId"`
|
||||
Tradeable string `json:"tradeable"`
|
||||
Direction string `json:"direction"`
|
||||
Quantity float64 `json:"quantity,string"`
|
||||
Filled float64 `json:"filled,string"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
LimitPrice float64 `json:"limitPrice,string"`
|
||||
OrderType string `json:"orderType"`
|
||||
ClientID string `json:"clientId"`
|
||||
StopPrice float64 `json:"stopPrice,string"`
|
||||
}
|
||||
|
||||
// FOpenOrdersData stores open orders data for futures
|
||||
type FOpenOrdersData struct {
|
||||
OrderID string `json:"order_id"`
|
||||
ClientOrderID string `json:"cliOrdId"`
|
||||
Symbol string `json:"symbol"`
|
||||
Side string `json:"side"`
|
||||
OrderType string `json:"orderType"`
|
||||
LimitPrice float64 `json:"limitPrice"`
|
||||
StopPrice float64 `json:"stopPrice"`
|
||||
UnfilledSize float64 `json:"unfilledSize"`
|
||||
ReceivedTime string `json:"receivedTime"`
|
||||
Status string `json:"status"`
|
||||
FilledSize float64 `json:"filledSize"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
TriggerSignal string `json:"triggerSignal"`
|
||||
LastUpdateTime string `json:"lastUpdateTime"`
|
||||
}
|
||||
|
||||
// FuturesRecentOrdersData stores recent orders data
|
||||
type FuturesRecentOrdersData struct {
|
||||
OrderEvents []struct {
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Event struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
UID string `json:"uid"`
|
||||
OrderPlaced struct {
|
||||
RecentOrder RecentOrderData `json:"order"`
|
||||
Reason string `json:"reason"`
|
||||
} `json:"orderPlaced"`
|
||||
OrderCancelled struct {
|
||||
RecentOrder RecentOrderData `json:"order"`
|
||||
Reason string `json:"reason"`
|
||||
} `json:"orderCancelled"`
|
||||
OrderRejected struct {
|
||||
RecentOrder RecentOrderData `json:"order"`
|
||||
Reason string `json:"reason"`
|
||||
} `json:"orderRejected"`
|
||||
ExecutionEvent struct {
|
||||
Execution ExecutionData `json:"execution"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
Price float64 `json:"price"`
|
||||
MarkPrice float64 `json:"markPrice"`
|
||||
LimitFilled bool `json:"limitFilled"`
|
||||
} `json:"executionEvent"`
|
||||
} `json:"event"`
|
||||
} `json:"orderEvents"`
|
||||
}
|
||||
|
||||
// BatchOrderData stores batch order data
|
||||
type BatchOrderData struct {
|
||||
Result bool `json:"result"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
BatchStatus []struct {
|
||||
Status string `json:"status"`
|
||||
OrderTag string `json:"order_tag"`
|
||||
OrderID string `json:"order_id"`
|
||||
DateTimeReceived string `json:"dateTimeReceieved"`
|
||||
OrderEvents []struct {
|
||||
OrderPlaced FuturesOrderData `json:"orderPlaced"`
|
||||
ReduceOnly bool `json:"reduceOnly"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
OldEditedOrder FuturesOrderData `json:"old"`
|
||||
NewEditedOrder FuturesOrderData `json:"new"`
|
||||
UID string `json:"uid"`
|
||||
RequestType string `json:"requestType"`
|
||||
} `json:"orderEvents"`
|
||||
} `json:"batchStatus"`
|
||||
}
|
||||
|
||||
// PlaceBatchOrderData stores data required to place a batch order
|
||||
type PlaceBatchOrderData struct {
|
||||
PlaceOrderType string `json:"order,omitempty"`
|
||||
OrderType string `json:"orderType,omitempty"`
|
||||
OrderTag string `json:"order_tag,omitempty"`
|
||||
Symbol string `json:"symbol,omitempty"`
|
||||
Side string `json:"side,omitempty"`
|
||||
Size float64 `json:"size,omitempty"`
|
||||
LimitPrice float64 `json:"limitPrice,omitempty"`
|
||||
StopPrice float64 `json:"stopPrice,omitempty"`
|
||||
ClientOrderID int64 `json:"cliOrdId,omitempty"`
|
||||
ReduceOnly string `json:"reduceOnly,omitempty"`
|
||||
OrderID string `json:"order_id,omitempty"`
|
||||
}
|
||||
|
||||
// ExecutionData stores execution data
|
||||
type ExecutionData struct {
|
||||
UID string `json:"uid"`
|
||||
TakerOrder RecentOrderData `json:"takerOrder"`
|
||||
}
|
||||
|
||||
// FuturesOpenOrdersData stores open orders data for futures
|
||||
type FuturesOpenOrdersData struct {
|
||||
Result string `json:"result"`
|
||||
OpenOrders []FOpenOrdersData `json:"openOrders"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package kraken
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@@ -15,53 +16,18 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
const (
|
||||
krakenAPIURL = "https://api.kraken.com"
|
||||
krakenAPIVersion = "0"
|
||||
krakenServerTime = "Time"
|
||||
krakenAssets = "Assets"
|
||||
krakenAssetPairs = "AssetPairs"
|
||||
krakenTicker = "Ticker"
|
||||
krakenOHLC = "OHLC"
|
||||
krakenDepth = "Depth"
|
||||
krakenTrades = "Trades"
|
||||
krakenSpread = "Spread"
|
||||
krakenBalance = "Balance"
|
||||
krakenTradeBalance = "TradeBalance"
|
||||
krakenOpenOrders = "OpenOrders"
|
||||
krakenClosedOrders = "ClosedOrders"
|
||||
krakenQueryOrders = "QueryOrders"
|
||||
krakenTradeHistory = "TradesHistory"
|
||||
krakenQueryTrades = "QueryTrades"
|
||||
krakenOpenPositions = "OpenPositions"
|
||||
krakenLedgers = "Ledgers"
|
||||
krakenQueryLedgers = "QueryLedgers"
|
||||
krakenTradeVolume = "TradeVolume"
|
||||
krakenOrderCancel = "CancelOrder"
|
||||
krakenOrderPlace = "AddOrder"
|
||||
krakenWithdrawInfo = "WithdrawInfo"
|
||||
krakenWithdraw = "Withdraw"
|
||||
krakenDepositMethods = "DepositMethods"
|
||||
krakenDepositAddresses = "DepositAddresses"
|
||||
krakenWithdrawStatus = "WithdrawStatus"
|
||||
krakenWithdrawCancel = "WithdrawCancel"
|
||||
krakenWebsocketToken = "GetWebSocketsToken"
|
||||
|
||||
// Rate limit consts
|
||||
krakenRateInterval = time.Second
|
||||
krakenRequestRate = 1
|
||||
|
||||
// Status consts
|
||||
statusOpen = "open"
|
||||
)
|
||||
|
||||
var (
|
||||
assetTranslator assetTranslatorStore
|
||||
krakenAPIURL = "https://api.kraken.com"
|
||||
krakenFuturesURL = "https://futures.kraken.com"
|
||||
futuresURL = "https://futures.kraken.com/derivatives"
|
||||
krakenSpotVersion = "0"
|
||||
krakenFuturesVersion = "3"
|
||||
)
|
||||
|
||||
// Kraken is the overarching type across the alphapoint package
|
||||
@@ -72,14 +38,14 @@ type Kraken struct {
|
||||
|
||||
// GetServerTime returns current server time
|
||||
func (k *Kraken) GetServerTime() (TimeResponse, error) {
|
||||
path := fmt.Sprintf("%s/%s/public/%s", k.API.Endpoints.URL, krakenAPIVersion, krakenServerTime)
|
||||
path := fmt.Sprintf("/%s/public/%s", krakenAPIVersion, krakenServerTime)
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TimeResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
if err := k.SendHTTPRequest(exchange.RestSpot, path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -93,55 +59,70 @@ func (k *Kraken) SeedAssets() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range assets {
|
||||
assetTranslator.Seed(k, v.Altname)
|
||||
for orig, val := range assets {
|
||||
assetTranslator.Seed(orig, val.Altname)
|
||||
}
|
||||
|
||||
assetPairs, err := k.GetAssetPairs()
|
||||
assetPairs, err := k.GetAssetPairs([]string{}, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for k, v := range assetPairs {
|
||||
assetTranslator.Seed(k, v.Altname)
|
||||
for k := range assetPairs {
|
||||
assetTranslator.Seed(k, assetPairs[k].Altname)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAssets returns a full asset list
|
||||
func (k *Kraken) GetAssets() (map[string]*Asset, error) {
|
||||
path := fmt.Sprintf("%s/%s/public/%s", k.API.Endpoints.URL, krakenAPIVersion, krakenAssets)
|
||||
path := fmt.Sprintf("/%s/public/%s", krakenAPIVersion, krakenAssets)
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]*Asset `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
if err := k.SendHTTPRequest(exchange.RestSpot, path, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetAssetPairs returns a full asset pair list
|
||||
func (k *Kraken) GetAssetPairs() (map[string]*AssetPairs, error) {
|
||||
path := fmt.Sprintf("%s/%s/public/%s", k.API.Endpoints.URL, krakenAPIVersion, krakenAssetPairs)
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]*AssetPairs `json:"result"`
|
||||
// Parameter 'info' only supports 4 strings: "fees", "leverage", "margin", "info" <- (default)
|
||||
func (k *Kraken) GetAssetPairs(assetPairs []string, info string) (map[string]AssetPairs, error) {
|
||||
path := fmt.Sprintf("/%s/public/%s", krakenAPIVersion, krakenAssetPairs)
|
||||
params := url.Values{}
|
||||
var assets string
|
||||
if len(assetPairs) != 0 {
|
||||
assets = strings.Join(assetPairs, ",")
|
||||
params.Set("pair", assets)
|
||||
}
|
||||
|
||||
if err := k.SendHTTPRequest(path, &response); err != nil {
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result map[string]AssetPairs `json:"result"`
|
||||
}
|
||||
if info != "" {
|
||||
if info != "margin" && info != "leverage" && info != "fees" && info != "info" {
|
||||
return response.Result, errors.New("parameter info can only be 'asset', 'margin', 'fees' or 'leverage'")
|
||||
}
|
||||
params.Set("info", info)
|
||||
}
|
||||
if err := k.SendHTTPRequest(exchange.RestSpot, path+params.Encode(), &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
return response.Result, GetError(response.Error)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information from kraken
|
||||
func (k *Kraken) GetTicker(symbol string) (Ticker, error) {
|
||||
func (k *Kraken) GetTicker(symbol currency.Pair) (Ticker, error) {
|
||||
tick := Ticker{}
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return tick, err
|
||||
}
|
||||
values.Set("pair", symbolValue)
|
||||
|
||||
type Response struct {
|
||||
Error []interface{} `json:"error"`
|
||||
@@ -149,9 +130,9 @@ func (k *Kraken) GetTicker(symbol string) (Ticker, error) {
|
||||
}
|
||||
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenTicker, values.Encode())
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenTicker, values.Encode())
|
||||
|
||||
err := k.SendHTTPRequest(path, &resp)
|
||||
err = k.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return tick, err
|
||||
}
|
||||
@@ -187,9 +168,9 @@ func (k *Kraken) GetTickers(pairList string) (map[string]Ticker, error) {
|
||||
}
|
||||
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenTicker, values.Encode())
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenTicker, values.Encode())
|
||||
|
||||
err := k.SendHTTPRequest(path, &resp)
|
||||
err := k.SendHTTPRequest(exchange.RestSpot, path, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -217,9 +198,17 @@ func (k *Kraken) GetTickers(pairList string) (map[string]Ticker, error) {
|
||||
}
|
||||
|
||||
// GetOHLC returns an array of open high low close values of a currency pair
|
||||
func (k *Kraken) GetOHLC(symbol, interval string) ([]OpenHighLowClose, error) {
|
||||
func (k *Kraken) GetOHLC(symbol currency.Pair, interval string) ([]OpenHighLowClose, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
translatedAsset := assetTranslator.LookupCurrency(symbolValue)
|
||||
if translatedAsset == "" {
|
||||
translatedAsset = symbolValue
|
||||
}
|
||||
values.Set("pair", translatedAsset)
|
||||
values.Set("interval", interval)
|
||||
type Response struct {
|
||||
Error []interface{} `json:"error"`
|
||||
@@ -229,9 +218,9 @@ func (k *Kraken) GetOHLC(symbol, interval string) ([]OpenHighLowClose, error) {
|
||||
var OHLC []OpenHighLowClose
|
||||
var result Response
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenOHLC, values.Encode())
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenOHLC, values.Encode())
|
||||
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
err = k.SendHTTPRequest(exchange.RestSpot, path, &result)
|
||||
if err != nil {
|
||||
return OHLC, err
|
||||
}
|
||||
@@ -240,12 +229,12 @@ func (k *Kraken) GetOHLC(symbol, interval string) ([]OpenHighLowClose, error) {
|
||||
return OHLC, fmt.Errorf("getOHLC error: %s", result.Error)
|
||||
}
|
||||
|
||||
_, ok := result.Data[symbol].([]interface{})
|
||||
_, ok := result.Data[translatedAsset].([]interface{})
|
||||
if !ok {
|
||||
return nil, errors.New("invalid data returned")
|
||||
}
|
||||
|
||||
for _, y := range result.Data[symbol].([]interface{}) {
|
||||
for _, y := range result.Data[translatedAsset].([]interface{}) {
|
||||
o := OpenHighLowClose{}
|
||||
for i, x := range y.([]interface{}) {
|
||||
switch i {
|
||||
@@ -273,15 +262,17 @@ func (k *Kraken) GetOHLC(symbol, interval string) ([]OpenHighLowClose, error) {
|
||||
}
|
||||
|
||||
// GetDepth returns the orderbook for a particular currency
|
||||
func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
|
||||
func (k *Kraken) GetDepth(symbol currency.Pair) (Orderbook, error) {
|
||||
var result interface{}
|
||||
var orderBook Orderbook
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenDepth, values.Encode())
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
values := url.Values{}
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
values.Set("pair", symbolValue)
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenDepth, values.Encode())
|
||||
err = k.SendHTTPRequest(exchange.RestSpot, path, &result)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -334,16 +325,21 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
|
||||
}
|
||||
|
||||
// GetTrades returns current trades on Kraken
|
||||
func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) {
|
||||
func (k *Kraken) GetTrades(symbol currency.Pair) ([]RecentTrades, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
translatedAsset := assetTranslator.LookupCurrency(symbolValue)
|
||||
values.Set("pair", translatedAsset)
|
||||
|
||||
var recentTrades []RecentTrades
|
||||
var result interface{}
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenTrades, values.Encode())
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenTrades, values.Encode())
|
||||
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
err = k.SendHTTPRequest(exchange.RestSpot, path, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -390,7 +386,7 @@ func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) {
|
||||
|
||||
var trades []interface{}
|
||||
var tradesForSymbol interface{}
|
||||
tradesForSymbol, ok = tradeInfo[symbol]
|
||||
tradesForSymbol, ok = tradeInfo[translatedAsset]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no data returned for symbol %v", symbol)
|
||||
}
|
||||
@@ -440,16 +436,20 @@ func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) {
|
||||
}
|
||||
|
||||
// GetSpread returns the full spread on Kraken
|
||||
func (k *Kraken) GetSpread(symbol string) ([]Spread, error) {
|
||||
func (k *Kraken) GetSpread(symbol currency.Pair) ([]Spread, error) {
|
||||
values := url.Values{}
|
||||
values.Set("pair", symbol)
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values.Set("pair", symbolValue)
|
||||
|
||||
var peanutButter []Spread
|
||||
var response interface{}
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", k.API.Endpoints.URL, krakenAPIVersion, krakenSpread, values.Encode())
|
||||
path := fmt.Sprintf("/%s/public/%s?%s", krakenAPIVersion, krakenSpread, values.Encode())
|
||||
|
||||
err := k.SendHTTPRequest(path, &response)
|
||||
err = k.SendHTTPRequest(exchange.RestSpot, path, &response)
|
||||
if err != nil {
|
||||
return peanutButter, err
|
||||
}
|
||||
@@ -457,7 +457,7 @@ func (k *Kraken) GetSpread(symbol string) ([]Spread, error) {
|
||||
data := response.(map[string]interface{})
|
||||
result := data["result"].(map[string]interface{})
|
||||
|
||||
for _, x := range result[symbol].([]interface{}) {
|
||||
for _, x := range result[symbolValue].([]interface{}) {
|
||||
s := Spread{}
|
||||
for i, y := range x.([]interface{}) {
|
||||
switch i {
|
||||
@@ -481,7 +481,7 @@ func (k *Kraken) GetBalance() (map[string]float64, error) {
|
||||
Result map[string]string `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenBalance, url.Values{}, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenBalance, url.Values{}, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -507,7 +507,7 @@ func (k *Kraken) GetWithdrawInfo(currency string, amount float64) (WithdrawInfor
|
||||
params.Set("key", "")
|
||||
params.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWithdrawInfo, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenWithdrawInfo, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ func (k *Kraken) Withdraw(asset, key string, amount float64) (string, error) {
|
||||
params.Set("key", key)
|
||||
params.Set("amount", fmt.Sprintf("%f", amount))
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWithdraw, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenWithdraw, params, &response); err != nil {
|
||||
return response.ReferenceID, err
|
||||
}
|
||||
|
||||
@@ -541,7 +541,7 @@ func (k *Kraken) GetDepositMethods(currency string) ([]DepositMethods, error) {
|
||||
params := url.Values{}
|
||||
params.Set("asset", currency)
|
||||
|
||||
err := k.SendAuthenticatedHTTPRequest(krakenDepositMethods, params, &response)
|
||||
err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenDepositMethods, params, &response)
|
||||
if err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
@@ -568,7 +568,7 @@ func (k *Kraken) GetTradeBalance(args ...TradeBalanceOptions) (TradeBalanceInfo,
|
||||
Result TradeBalanceInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeBalance, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenTradeBalance, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -592,7 +592,7 @@ func (k *Kraken) GetOpenOrders(args OrderInfoOptions) (OpenOrders, error) {
|
||||
Result OpenOrders `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOpenOrders, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenOpenOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -632,7 +632,7 @@ func (k *Kraken) GetClosedOrders(args GetClosedOrdersOptions) (ClosedOrders, err
|
||||
Result ClosedOrders `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenClosedOrders, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenClosedOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -662,7 +662,7 @@ func (k *Kraken) QueryOrdersInfo(args OrderInfoOptions, txid string, txids ...st
|
||||
Result map[string]OrderInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryOrders, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenQueryOrders, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -700,7 +700,7 @@ func (k *Kraken) GetTradesHistory(args ...GetTradesHistoryOptions) (TradesHistor
|
||||
Result TradesHistory `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeHistory, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenTradeHistory, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -726,7 +726,7 @@ func (k *Kraken) QueryTrades(trades bool, txid string, txids ...string) (map[str
|
||||
Result map[string]TradeInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryTrades, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenQueryTrades, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -750,7 +750,7 @@ func (k *Kraken) OpenPositions(docalcs bool, txids ...string) (map[string]Positi
|
||||
Result map[string]Position `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOpenPositions, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenOpenPositions, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -792,7 +792,7 @@ func (k *Kraken) GetLedgers(args ...GetLedgersOptions) (Ledgers, error) {
|
||||
Result Ledgers `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenLedgers, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenLedgers, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -814,7 +814,7 @@ func (k *Kraken) QueryLedgers(id string, ids ...string) (map[string]LedgerInfo,
|
||||
Result map[string]LedgerInfo `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenQueryLedgers, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenQueryLedgers, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -822,23 +822,29 @@ func (k *Kraken) QueryLedgers(id string, ids ...string) (map[string]LedgerInfo,
|
||||
}
|
||||
|
||||
// GetTradeVolume returns your trade volume by currency
|
||||
func (k *Kraken) GetTradeVolume(feeinfo bool, symbol ...string) (TradeVolumeResponse, error) {
|
||||
func (k *Kraken) GetTradeVolume(feeinfo bool, symbol ...currency.Pair) (TradeVolumeResponse, error) {
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TradeVolumeResponse `json:"result"`
|
||||
}
|
||||
params := url.Values{}
|
||||
|
||||
var formattedPairs []string
|
||||
for x := range symbol {
|
||||
symbolValue, err := k.FormatSymbol(symbol[x], asset.Spot)
|
||||
if err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
formattedPairs = append(formattedPairs, symbolValue)
|
||||
}
|
||||
if symbol != nil {
|
||||
params.Set("pair", strings.Join(symbol, ","))
|
||||
params.Set("pair", strings.Join(formattedPairs, ","))
|
||||
}
|
||||
|
||||
if feeinfo {
|
||||
params.Set("fee-info", "true")
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result TradeVolumeResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenTradeVolume, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenTradeVolume, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -846,9 +852,17 @@ func (k *Kraken) GetTradeVolume(feeinfo bool, symbol ...string) (TradeVolumeResp
|
||||
}
|
||||
|
||||
// AddOrder adds a new order for Kraken exchange
|
||||
func (k *Kraken) AddOrder(symbol, side, orderType string, volume, price, price2, leverage float64, args *AddOrderOptions) (AddOrderResponse, error) {
|
||||
func (k *Kraken) AddOrder(symbol currency.Pair, side, orderType string, volume, price, price2, leverage float64, args *AddOrderOptions) (AddOrderResponse, error) {
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result AddOrderResponse `json:"result"`
|
||||
}
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
params := url.Values{
|
||||
"pair": {symbol},
|
||||
"pair": {symbolValue},
|
||||
"type": {strings.ToLower(side)},
|
||||
"ordertype": {strings.ToLower(orderType)},
|
||||
"volume": {strconv.FormatFloat(volume, 'f', -1, 64)},
|
||||
@@ -894,12 +908,7 @@ func (k *Kraken) AddOrder(symbol, side, orderType string, volume, price, price2,
|
||||
params.Set("validate", "true")
|
||||
}
|
||||
|
||||
var response struct {
|
||||
Error []string `json:"error"`
|
||||
Result AddOrderResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOrderPlace, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenOrderPlace, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -917,7 +926,7 @@ func (k *Kraken) CancelExistingOrder(txid string) (CancelOrderResponse, error) {
|
||||
Result CancelOrderResponse `json:"result"`
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenOrderCancel, values, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenOrderCancel, values, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -944,10 +953,14 @@ func GetError(apiErrors []string) error {
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP requests
|
||||
func (k *Kraken) SendHTTPRequest(path string, result interface{}) error {
|
||||
func (k *Kraken) SendHTTPRequest(ep exchange.URL, path string, result interface{}) error {
|
||||
endpoint, err := k.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return k.SendPayload(context.Background(), &request.Item{
|
||||
Method: http.MethodGet,
|
||||
Path: path,
|
||||
Path: endpoint + path,
|
||||
Result: result,
|
||||
Verbose: k.Verbose,
|
||||
HTTPDebugging: k.HTTPDebugging,
|
||||
@@ -956,12 +969,15 @@ func (k *Kraken) SendHTTPRequest(path string, result interface{}) error {
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (k *Kraken) SendAuthenticatedHTTPRequest(method string, params url.Values, result interface{}) (err error) {
|
||||
func (k *Kraken) SendAuthenticatedHTTPRequest(ep exchange.URL, method string, params url.Values, result interface{}) error {
|
||||
if !k.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
k.Name)
|
||||
}
|
||||
|
||||
endpoint, err := k.API.Endpoints.GetURL(ep)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := fmt.Sprintf("/%s/private/%s", krakenAPIVersion, method)
|
||||
|
||||
params.Set("nonce", k.Requester.GetNonce(true).String())
|
||||
@@ -972,7 +988,7 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, params url.Values,
|
||||
|
||||
if k.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "Sending POST request to %s, path: %s, params: %s",
|
||||
k.API.Endpoints.URL,
|
||||
endpoint,
|
||||
path,
|
||||
encoded)
|
||||
}
|
||||
@@ -981,40 +997,49 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, params url.Values,
|
||||
headers["API-Key"] = k.API.Credentials.Key
|
||||
headers["API-Sign"] = signature
|
||||
|
||||
return k.SendPayload(context.Background(), &request.Item{
|
||||
interim := json.RawMessage{}
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
|
||||
defer cancel()
|
||||
err = k.SendPayload(ctx, &request.Item{
|
||||
Method: http.MethodPost,
|
||||
Path: k.API.Endpoints.URL + path,
|
||||
Path: endpoint + path,
|
||||
Headers: headers,
|
||||
Body: strings.NewReader(encoded),
|
||||
Result: result,
|
||||
Result: &interim,
|
||||
AuthRequest: true,
|
||||
NonceEnabled: true,
|
||||
Verbose: k.Verbose,
|
||||
HTTPDebugging: k.HTTPDebugging,
|
||||
HTTPRecording: k.HTTPRecording,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var errCap SpotAuthError
|
||||
if err := json.Unmarshal(interim, &errCap); err == nil {
|
||||
if len(errCap.Error) != 0 {
|
||||
return errors.New(errCap.Error[0])
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(interim, result)
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
func (k *Kraken) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
|
||||
var fee float64
|
||||
c := feeBuilder.Pair.Base.String() +
|
||||
feeBuilder.Pair.Delimiter +
|
||||
feeBuilder.Pair.Quote.String()
|
||||
|
||||
switch feeBuilder.FeeType {
|
||||
case exchange.CryptocurrencyTradeFee:
|
||||
feePair, err := k.GetTradeVolume(true, c)
|
||||
feePair, err := k.GetTradeVolume(true, feeBuilder.Pair)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if feeBuilder.IsMaker {
|
||||
fee = calculateTradingFee(c,
|
||||
fee = calculateTradingFee(feePair.Currency,
|
||||
feePair.FeesMaker,
|
||||
feeBuilder.PurchasePrice,
|
||||
feeBuilder.Amount)
|
||||
} else {
|
||||
fee = calculateTradingFee(c,
|
||||
fee = calculateTradingFee(feePair.Currency,
|
||||
feePair.Fees,
|
||||
feeBuilder.PurchasePrice,
|
||||
feeBuilder.Amount)
|
||||
@@ -1078,7 +1103,7 @@ func (k *Kraken) GetCryptoDepositAddress(method, code string) (string, error) {
|
||||
values.Set("asset", code)
|
||||
values.Set("method", method)
|
||||
|
||||
err := k.SendAuthenticatedHTTPRequest(krakenDepositAddresses, values, &resp)
|
||||
err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenDepositAddresses, values, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1103,7 +1128,7 @@ func (k *Kraken) WithdrawStatus(c currency.Code, method string) ([]WithdrawStatu
|
||||
params.Set("method", method)
|
||||
}
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWithdrawStatus, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenWithdrawStatus, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -1121,7 +1146,7 @@ func (k *Kraken) WithdrawCancel(c currency.Code, refID string) (bool, error) {
|
||||
params.Set("asset", c.String())
|
||||
params.Set("refid", refID)
|
||||
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWithdrawCancel, params, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenWithdrawCancel, params, &response); err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
|
||||
@@ -1131,7 +1156,7 @@ func (k *Kraken) WithdrawCancel(c currency.Code, refID string) (bool, error) {
|
||||
// GetWebsocketToken returns a websocket token
|
||||
func (k *Kraken) GetWebsocketToken() (string, error) {
|
||||
var response WsTokenResponse
|
||||
if err := k.SendAuthenticatedHTTPRequest(krakenWebsocketToken, url.Values{}, &response); err != nil {
|
||||
if err := k.SendAuthenticatedHTTPRequest(exchange.RestSpot, krakenWebsocketToken, url.Values{}, &response); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(response.Error) > 0 {
|
||||
|
||||
307
exchanges/kraken/kraken_futures.go
Normal file
307
exchanges/kraken/kraken_futures.go
Normal file
@@ -0,0 +1,307 @@
|
||||
package kraken
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
// GetFuturesOrderbook gets orderbook data for futures
|
||||
func (k *Kraken) GetFuturesOrderbook(symbol currency.Pair) (FuturesOrderbookData, error) {
|
||||
var resp FuturesOrderbookData
|
||||
params := url.Values{}
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
return resp, k.SendHTTPRequest(exchange.RestFutures, futuresOrderbook+"?"+params.Encode(), &resp)
|
||||
}
|
||||
|
||||
// GetFuturesMarkets gets a list of futures markets and their data
|
||||
func (k *Kraken) GetFuturesMarkets() (FuturesInstrumentData, error) {
|
||||
var resp FuturesInstrumentData
|
||||
return resp, k.SendHTTPRequest(exchange.RestFutures, futuresInstruments, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesTickers gets a list of futures tickers and their data
|
||||
func (k *Kraken) GetFuturesTickers() (FuturesTickerData, error) {
|
||||
var resp FuturesTickerData
|
||||
return resp, k.SendHTTPRequest(exchange.RestFutures, futuresTickers, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesTradeHistory gets public trade history data for futures
|
||||
func (k *Kraken) GetFuturesTradeHistory(symbol currency.Pair, lastTime time.Time) (FuturesTradeHistoryData, error) {
|
||||
var resp FuturesTradeHistoryData
|
||||
params := url.Values{}
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
if !lastTime.IsZero() {
|
||||
params.Set("lastTime", lastTime.Format("2006-01-02T15:04:05.070Z"))
|
||||
}
|
||||
return resp, k.SendHTTPRequest(exchange.RestFutures, futuresTradeHistory+"?"+params.Encode(), &resp)
|
||||
}
|
||||
|
||||
// FuturesBatchOrder places a batch order for futures
|
||||
func (k *Kraken) FuturesBatchOrder(data []PlaceBatchOrderData) (FuturesAccountsData, error) {
|
||||
var resp FuturesAccountsData
|
||||
for x := range data {
|
||||
unformattedPair, err := currency.NewPairFromString(data[x].Symbol)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
formattedPair, err := k.FormatExchangeCurrency(unformattedPair, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
data[x].Symbol = formattedPair.String()
|
||||
}
|
||||
req := make(map[string]interface{})
|
||||
req["batchOrder"] = data
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresBatchOrder, nil, req, &resp)
|
||||
}
|
||||
|
||||
// FuturesEditOrder edits a futures order
|
||||
func (k *Kraken) FuturesEditOrder(orderID, clientOrderID string, size, limitPrice, stopPrice float64) (FuturesAccountsData, error) {
|
||||
var resp FuturesAccountsData
|
||||
params := url.Values{}
|
||||
if orderID != "" {
|
||||
params.Set("orderId", orderID)
|
||||
}
|
||||
if clientOrderID != "" {
|
||||
params.Set("cliOrderId", clientOrderID)
|
||||
}
|
||||
params.Set("size", strconv.FormatFloat(size, 'f', -1, 64))
|
||||
params.Set("limitPrice", strconv.FormatFloat(limitPrice, 'f', -1, 64))
|
||||
params.Set("stopPrice", strconv.FormatFloat(stopPrice, 'f', -1, 64))
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresEditOrder, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesSendOrder sends a futures order
|
||||
func (k *Kraken) FuturesSendOrder(orderType order.Type, symbol currency.Pair, side, triggerSignal, clientOrderID, reduceOnly string,
|
||||
size, limitPrice, stopPrice float64) (FuturesSendOrderData, error) {
|
||||
var resp FuturesSendOrderData
|
||||
oType, ok := validOrderTypes[orderType]
|
||||
if !ok {
|
||||
return resp, errors.New("invalid orderType")
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Set("orderType", oType)
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
if !common.StringDataCompare(validSide, side) {
|
||||
return resp, errors.New("invalid side")
|
||||
}
|
||||
params.Set("side", side)
|
||||
if triggerSignal != "" {
|
||||
if !common.StringDataCompare(validTriggerSignal, triggerSignal) {
|
||||
return resp, errors.New("invalid triggerSignal")
|
||||
}
|
||||
params.Set("triggerSignal", triggerSignal)
|
||||
}
|
||||
if clientOrderID != "" {
|
||||
params.Set("cliOrdId", clientOrderID)
|
||||
}
|
||||
if reduceOnly != "" {
|
||||
if !common.StringDataCompare(validReduceOnly, reduceOnly) {
|
||||
return resp, errors.New("invalid reduceOnly")
|
||||
}
|
||||
params.Set("reduceOnly", reduceOnly)
|
||||
}
|
||||
params.Set("size", strconv.FormatFloat(size, 'f', -1, 64))
|
||||
params.Set("limitPrice", strconv.FormatFloat(limitPrice, 'f', -1, 64))
|
||||
if stopPrice != 0 {
|
||||
params.Set("stopPrice", strconv.FormatFloat(stopPrice, 'f', -1, 64))
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresSendOrder, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesCancelOrder cancels an order
|
||||
func (k *Kraken) FuturesCancelOrder(orderID, clientOrderID string) (FuturesCancelOrderData, error) {
|
||||
var resp FuturesCancelOrderData
|
||||
params := url.Values{}
|
||||
if orderID != "" {
|
||||
params.Set("order_id", orderID)
|
||||
}
|
||||
if clientOrderID != "" {
|
||||
params.Set("cliOrdId", clientOrderID)
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresCancelOrder, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesGetFills gets order fills for futures
|
||||
func (k *Kraken) FuturesGetFills(lastFillTime time.Time) (FuturesFillsData, error) {
|
||||
var resp FuturesFillsData
|
||||
params := url.Values{}
|
||||
if !lastFillTime.IsZero() {
|
||||
params.Set("lastFillTime", lastFillTime.UTC().Format("2006-01-02T15:04:05.999Z"))
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresOrderFills, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesTransfer transfers funds between accounts
|
||||
func (k *Kraken) FuturesTransfer(fromAccount, toAccount, unit string, amount float64) (FuturesTransferData, error) {
|
||||
var resp FuturesTransferData
|
||||
req := make(map[string]interface{})
|
||||
req["fromAccount"] = fromAccount
|
||||
req["toAccount"] = toAccount
|
||||
req["unit"] = unit
|
||||
req["amount"] = amount
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresTransfer, nil, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesGetOpenPositions gets futures platform's notifications
|
||||
func (k *Kraken) FuturesGetOpenPositions() (FuturesOpenPositions, error) {
|
||||
var resp FuturesOpenPositions
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresOpenPositions, nil, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesNotifications gets futures notifications
|
||||
func (k *Kraken) FuturesNotifications() (FuturesNotificationData, error) {
|
||||
var resp FuturesNotificationData
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresNotifications, nil, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesCancelAllOrders cancels all futures orders for a given symbol or all symbols
|
||||
func (k *Kraken) FuturesCancelAllOrders(symbol currency.Pair) (CancelAllOrdersData, error) {
|
||||
var resp CancelAllOrdersData
|
||||
params := url.Values{}
|
||||
if symbol != (currency.Pair{}) {
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresCancelAllOrders, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesCancelAllOrdersAfter cancels all futures orders for all symbols after a period of time (timeout measured in seconds)
|
||||
func (k *Kraken) FuturesCancelAllOrdersAfter(timeout int64) (CancelOrdersAfterData, error) {
|
||||
var resp CancelOrdersAfterData
|
||||
params := url.Values{}
|
||||
params.Set("timeout", strconv.FormatInt(timeout, 10))
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresCancelOrdersAfter, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesOpenOrders gets all futures open orders
|
||||
func (k *Kraken) FuturesOpenOrders() (FuturesOpenOrdersData, error) {
|
||||
var resp FuturesOpenOrdersData
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresOpenOrders, nil, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesRecentOrders gets recent futures orders for a symbol or all symbols
|
||||
func (k *Kraken) FuturesRecentOrders(symbol currency.Pair) (FuturesRecentOrdersData, error) {
|
||||
var resp FuturesRecentOrdersData
|
||||
params := url.Values{}
|
||||
if symbol != (currency.Pair{}) {
|
||||
symbolValue, err := k.FormatSymbol(symbol, asset.Futures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresRecentOrders, nil, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesWithdrawToSpotWallet withdraws currencies from futures wallet to spot wallet
|
||||
func (k *Kraken) FuturesWithdrawToSpotWallet(currency string, amount float64) (GenericResponse, error) {
|
||||
var resp GenericResponse
|
||||
params := url.Values{}
|
||||
params.Set("currency", currency)
|
||||
params.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodPost, futuresWithdraw, params, nil, &resp)
|
||||
}
|
||||
|
||||
// FuturesGetTransfers withdraws currencies from futures wallet to spot wallet
|
||||
func (k *Kraken) FuturesGetTransfers(lastTransferTime time.Time) (GenericResponse, error) {
|
||||
var resp GenericResponse
|
||||
params := url.Values{}
|
||||
if !lastTransferTime.IsZero() {
|
||||
params.Set("lastTransferTime", lastTransferTime.UTC().Format(time.RFC3339))
|
||||
}
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresTransfers, params, nil, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesAccountData gets account data for futures
|
||||
func (k *Kraken) GetFuturesAccountData() (FuturesAccountsData, error) {
|
||||
var resp FuturesAccountsData
|
||||
return resp, k.SendFuturesAuthRequest(http.MethodGet, futuresAccountData, nil, nil, &resp)
|
||||
}
|
||||
|
||||
func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) string {
|
||||
message := data + nonce + endpoint
|
||||
hash := crypto.GetSHA256([]byte(message))
|
||||
hc := crypto.GetHMAC(crypto.HashSHA512, hash, []byte(k.API.Credentials.Secret))
|
||||
return base64.StdEncoding.EncodeToString(hc)
|
||||
}
|
||||
|
||||
// SendFuturesAuthRequest will send an auth req
|
||||
func (k *Kraken) SendFuturesAuthRequest(method, path string, postData url.Values, data map[string]interface{}, result interface{}) error {
|
||||
if !k.AllowAuthenticatedRequest() {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
k.Name)
|
||||
}
|
||||
if postData == nil {
|
||||
postData = url.Values{}
|
||||
}
|
||||
nonce := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
|
||||
reqData := ""
|
||||
if len(data) > 0 {
|
||||
temp, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
postData.Add("json", string(temp))
|
||||
reqData = "json=" + string(temp)
|
||||
}
|
||||
sig := k.signFuturesRequest(path, nonce, reqData)
|
||||
headers := map[string]string{
|
||||
"APIKey": k.API.Credentials.Key,
|
||||
"Authent": sig,
|
||||
"Nonce": nonce,
|
||||
}
|
||||
interim := json.RawMessage{}
|
||||
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
|
||||
defer cancel()
|
||||
err := k.SendPayload(ctx, &request.Item{
|
||||
Method: method,
|
||||
Path: futuresURL + common.EncodeURLValues(path, postData),
|
||||
Headers: headers,
|
||||
Result: &interim,
|
||||
AuthRequest: true,
|
||||
Verbose: k.Verbose,
|
||||
HTTPDebugging: k.HTTPDebugging,
|
||||
HTTPRecording: k.HTTPRecording,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var errCap AuthErrorData
|
||||
if err := json.Unmarshal(interim, &errCap); err == nil {
|
||||
if errCap.Result != "success" && errCap.Error != "" {
|
||||
return errors.New(errCap.Error)
|
||||
}
|
||||
}
|
||||
return json.Unmarshal(interim, result)
|
||||
}
|
||||
@@ -49,7 +49,6 @@ func TestMain(m *testing.M) {
|
||||
krakenConfig.API.AuthenticatedSupport = true
|
||||
krakenConfig.API.Credentials.Key = apiKey
|
||||
krakenConfig.API.Credentials.Secret = apiSecret
|
||||
krakenConfig.API.Endpoints.WebsocketURL = k.API.Endpoints.WebsocketURL
|
||||
k.Websocket = sharedtestvalues.NewTestWebsocket()
|
||||
err = k.Setup(krakenConfig)
|
||||
if err != nil {
|
||||
@@ -67,6 +66,301 @@ func TestGetServerTime(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchTradablePairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.FetchTradablePairs(asset.Futures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
sp, err := currency.NewPairFromString("XBTUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.UpdateTicker(sp, asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
fp, err := currency.NewPairFromString("pi_xbtusd")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.UpdateTicker(fp, asset.Futures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
sp, err := currency.NewPairFromString("BTCEUR")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.UpdateOrderbook(sp, asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
fp, err := currency.NewPairFromString("pi_xbtusd")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.UpdateOrderbook(fp, asset.Futures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
_, err := k.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapperGetOrderInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.GetOrderInfo("123", currency.Pair{}, asset.Futures)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesBatchOrder(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
var data []PlaceBatchOrderData
|
||||
var tempData PlaceBatchOrderData
|
||||
tempData.PlaceOrderType = "cancel"
|
||||
tempData.OrderID = "test123"
|
||||
tempData.Symbol = "pi_xbtusd"
|
||||
data = append(data, tempData)
|
||||
_, err := k.FuturesBatchOrder(data)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesEditOrder(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesEditOrder("test123", "", 5.2, 1, 0)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesSendOrder(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
cp, err := currency.NewPairFromString("PI_XBTUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.FuturesSendOrder(order.Limit, cp, "buy", "", "", "", 1, 1, 0.9)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesCancelOrder(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesCancelOrder("test123", "")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesGetFills(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesGetFills(time.Now().Add(-time.Hour * 24))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesTransfer(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesTransfer("cash", "futures", "btc", 2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesGetOpenPositions(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesGetOpenPositions()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesNotifications(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesNotifications()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesCancelAllOrders(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
cp, err := currency.NewPairFromString("PI_XBTUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.FuturesCancelAllOrders(cp)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesAccountData(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.GetFuturesAccountData()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesCancelAllOrdersAfter(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesCancelAllOrdersAfter(50)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesOpenOrders(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesOpenOrders()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesRecentOrders(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
cp, err := currency.NewPairFromString("PI_XBTUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.FuturesRecentOrders(cp)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesWithdrawToSpotWallet(t *testing.T) {
|
||||
if !areTestAPIKeysSet() || !canManipulateRealOrders {
|
||||
t.Skip("skipping test: api keys not set or canManipulateRealOrders")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesWithdrawToSpotWallet("xbt", 5)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFuturesGetTransfers(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := k.FuturesGetTransfers(time.Now().Add(-time.Hour * 24))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
cp, err := currency.NewPairFromString("FI_xbtusd_200925")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetFuturesOrderbook(cp)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesMarkets(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetFuturesMarkets()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesTickers(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetFuturesTickers()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFuturesTradeHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
cp, err := currency.NewPairFromString("pi_xbtusd")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetFuturesTradeHistory(cp, time.Now().Add(-time.Hour*24))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetAssets API endpoint test
|
||||
func TestGetAssets(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -137,7 +431,19 @@ func TestLookupCurrency(t *testing.T) {
|
||||
// TestGetAssetPairs API endpoint test
|
||||
func TestGetAssetPairs(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetAssetPairs()
|
||||
_, err := k.GetAssetPairs([]string{}, "fees")
|
||||
if err != nil {
|
||||
t.Error("GetAssetPairs() error", err)
|
||||
}
|
||||
_, err = k.GetAssetPairs([]string{}, "leverage")
|
||||
if err != nil {
|
||||
t.Error("GetAssetPairs() error", err)
|
||||
}
|
||||
_, err = k.GetAssetPairs([]string{}, "margin")
|
||||
if err != nil {
|
||||
t.Error("GetAssetPairs() error", err)
|
||||
}
|
||||
_, err = k.GetAssetPairs([]string{}, "")
|
||||
if err != nil {
|
||||
t.Error("GetAssetPairs() error", err)
|
||||
}
|
||||
@@ -146,7 +452,11 @@ func TestGetAssetPairs(t *testing.T) {
|
||||
// TestGetTicker API endpoint test
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTicker("BCHEUR")
|
||||
cp, err := currency.NewPairFromString("BCHEUR")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetTicker(cp)
|
||||
if err != nil {
|
||||
t.Error("GetTicker() error", err)
|
||||
}
|
||||
@@ -164,7 +474,11 @@ func TestGetTickers(t *testing.T) {
|
||||
// TestGetOHLC API endpoint test
|
||||
func TestGetOHLC(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetOHLC("XXBTZUSD", "1440")
|
||||
cp, err := currency.NewPairFromString("XXBTZUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetOHLC(cp, "1440")
|
||||
if err != nil {
|
||||
t.Error("GetOHLC() error", err)
|
||||
}
|
||||
@@ -173,7 +487,11 @@ func TestGetOHLC(t *testing.T) {
|
||||
// TestGetDepth API endpoint test
|
||||
func TestGetDepth(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetDepth("BCHEUR")
|
||||
cp, err := currency.NewPairFromString("BCHEUR")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetDepth(cp)
|
||||
if err != nil {
|
||||
t.Error("GetDepth() error", err)
|
||||
}
|
||||
@@ -182,12 +500,19 @@ func TestGetDepth(t *testing.T) {
|
||||
// TestGetTrades API endpoint test
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTrades("BCHEUR")
|
||||
cp, err := currency.NewPairFromString("BCHEUR")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetTrades(cp)
|
||||
if err != nil {
|
||||
t.Error("GetTrades() error", err)
|
||||
}
|
||||
|
||||
_, err = k.GetTrades("MADEUP")
|
||||
cp2, err := currency.NewPairFromString("MADEUP")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetTrades(cp2)
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
@@ -196,7 +521,11 @@ func TestGetTrades(t *testing.T) {
|
||||
// TestGetSpread API endpoint test
|
||||
func TestGetSpread(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetSpread("BCHEUR")
|
||||
cp, err := currency.NewPairFromString("BCHEUR")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetSpread(cp)
|
||||
if err != nil {
|
||||
t.Error("GetSpread() error", err)
|
||||
}
|
||||
@@ -301,7 +630,11 @@ func TestQueryLedgers(t *testing.T) {
|
||||
// TestGetTradeVolume API endpoint test
|
||||
func TestGetTradeVolume(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := k.GetTradeVolume(true, "OAVY7T-MV5VK-KHDF5X")
|
||||
cp, err := currency.NewPairFromString("OAVY7T-MV5VK-KHDF5X")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.GetTradeVolume(true, cp)
|
||||
if err == nil {
|
||||
t.Error("GetTradeVolume() Expected error")
|
||||
}
|
||||
@@ -311,7 +644,11 @@ func TestGetTradeVolume(t *testing.T) {
|
||||
func TestAddOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
args := AddOrderOptions{OrderFlags: "fcib"}
|
||||
_, err := k.AddOrder("XXBTZUSD",
|
||||
cp, err := currency.NewPairFromString("XXBTZUSD")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = k.AddOrder(cp,
|
||||
order.Sell.Lower(), order.Limit.Lower(),
|
||||
0.00000001, 0, 0, 0, &args)
|
||||
if err == nil {
|
||||
@@ -447,22 +784,31 @@ func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
|
||||
// TestGetActiveOrders wrapper test
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("skipping test: api keys not set")
|
||||
}
|
||||
pair, err := currency.NewPairFromString("LTC_USDT")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
Pairs: currency.Pairs{pair},
|
||||
}
|
||||
|
||||
_, err := k.GetActiveOrders(&getOrdersRequest)
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get open orders: %s", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
_, err = k.GetActiveOrders(&getOrdersRequest)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetOrderHistory wrapper test
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
var getOrdersRequest = order.GetOrdersRequest{
|
||||
Type: order.AnyType,
|
||||
Type: order.AnyType,
|
||||
AssetType: asset.Spot,
|
||||
}
|
||||
|
||||
_, err := k.GetOrderHistory(&getOrdersRequest)
|
||||
@@ -594,18 +940,30 @@ func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
// TestGetAccountInfo wrapper test
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if areTestAPIKeysSet() {
|
||||
_, err := k.UpdateAccountInfo()
|
||||
_, err := k.UpdateAccountInfo(asset.Spot)
|
||||
if err != nil {
|
||||
// Spot and Futures have separate api keys. Please ensure that the correct one is provided
|
||||
t.Error("GetAccountInfo() error", err)
|
||||
}
|
||||
} else {
|
||||
_, err := k.UpdateAccountInfo()
|
||||
_, err := k.UpdateAccountInfo(asset.Spot)
|
||||
if err == nil {
|
||||
t.Error("GetAccountInfo() Expected error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateFuturesAccountInfo(t *testing.T) {
|
||||
if !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set. Skipping the test")
|
||||
}
|
||||
_, err := k.UpdateAccountInfo(asset.Futures)
|
||||
if err != nil {
|
||||
// Spot and Futures have separate api keys. Please ensure that the correct one is provided
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// TestModifyOrder wrapper test
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
@@ -620,6 +978,7 @@ func TestModifyOrder(t *testing.T) {
|
||||
// TestWithdraw wrapper test
|
||||
func TestWithdraw(t *testing.T) {
|
||||
withdrawCryptoRequest := withdraw.Request{
|
||||
Exchange: k.Name,
|
||||
Crypto: withdraw.CryptoRequest{
|
||||
Address: core.BitcoinDonationAddress,
|
||||
},
|
||||
@@ -1335,7 +1694,7 @@ func TestWsOpenOrders(t *testing.T) {
|
||||
"cost": "0.00000",
|
||||
"descr": {
|
||||
"close": "",
|
||||
"leverage": "0:1",
|
||||
"leverage": "0.1",
|
||||
"order": "sell 10.00345345 XBT/USD @ limit 34.50000 with 0:1 leverage",
|
||||
"ordertype": "limit",
|
||||
"pair": "XBT/USD",
|
||||
@@ -1364,7 +1723,7 @@ func TestWsOpenOrders(t *testing.T) {
|
||||
"cost": "0.00000",
|
||||
"descr": {
|
||||
"close": "",
|
||||
"leverage": "0:1",
|
||||
"leverage": "0.1",
|
||||
"order": "sell 0.00000010 XBT/USD @ limit 5334.60000 with 0:1 leverage",
|
||||
"ordertype": "limit",
|
||||
"pair": "XBT/USD",
|
||||
@@ -1393,7 +1752,7 @@ func TestWsOpenOrders(t *testing.T) {
|
||||
"cost": "0.00000",
|
||||
"descr": {
|
||||
"close": "",
|
||||
"leverage": "0:1",
|
||||
"leverage": "0.1",
|
||||
"order": "sell 0.00001000 XBT/USD @ limit 90.40000 with 0:1 leverage",
|
||||
"ordertype": "limit",
|
||||
"pair": "XBT/USD",
|
||||
@@ -1422,7 +1781,7 @@ func TestWsOpenOrders(t *testing.T) {
|
||||
"cost": "0.00000",
|
||||
"descr": {
|
||||
"close": "",
|
||||
"leverage": "0:1",
|
||||
"leverage": "0.1",
|
||||
"order": "sell 0.00001000 XBT/USD @ limit 9.00000 with 0:1 leverage",
|
||||
"ordertype": "limit",
|
||||
"pair": "XBT/USD",
|
||||
|
||||
@@ -1,22 +1,96 @@
|
||||
package kraken
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
|
||||
)
|
||||
|
||||
type assetTranslatorStore struct {
|
||||
l sync.RWMutex
|
||||
Assets map[string]string
|
||||
const (
|
||||
krakenAPIVersion = "0"
|
||||
krakenServerTime = "Time"
|
||||
krakenAssets = "Assets"
|
||||
krakenAssetPairs = "AssetPairs?"
|
||||
krakenTicker = "Ticker"
|
||||
krakenOHLC = "OHLC"
|
||||
krakenDepth = "Depth"
|
||||
krakenTrades = "Trades"
|
||||
krakenSpread = "Spread"
|
||||
krakenBalance = "Balance"
|
||||
krakenTradeBalance = "TradeBalance"
|
||||
krakenOpenOrders = "OpenOrders"
|
||||
krakenClosedOrders = "ClosedOrders"
|
||||
krakenQueryOrders = "QueryOrders"
|
||||
krakenTradeHistory = "TradesHistory"
|
||||
krakenQueryTrades = "QueryTrades"
|
||||
krakenOpenPositions = "OpenPositions"
|
||||
krakenLedgers = "Ledgers"
|
||||
krakenQueryLedgers = "QueryLedgers"
|
||||
krakenTradeVolume = "TradeVolume"
|
||||
krakenOrderCancel = "CancelOrder"
|
||||
krakenOrderPlace = "AddOrder"
|
||||
krakenWithdrawInfo = "WithdrawInfo"
|
||||
krakenWithdraw = "Withdraw"
|
||||
krakenDepositMethods = "DepositMethods"
|
||||
krakenDepositAddresses = "DepositAddresses"
|
||||
krakenWithdrawStatus = "WithdrawStatus"
|
||||
krakenWithdrawCancel = "WithdrawCancel"
|
||||
krakenWebsocketToken = "GetWebSocketsToken"
|
||||
|
||||
// Futures
|
||||
futuresTickers = "/api/v3/tickers"
|
||||
futuresOrderbook = "/api/v3/orderbook"
|
||||
futuresInstruments = "/api/v3/instruments"
|
||||
futuresTradeHistory = "/api/v3/history"
|
||||
|
||||
futuresSendOrder = "/api/v3/sendorder"
|
||||
futuresCancelOrder = "/api/v3/cancelorder"
|
||||
futuresOrderFills = "/api/v3/fills"
|
||||
futuresTransfer = "/api/v3/transfer"
|
||||
futuresOpenPositions = "/api/v3/openpositions"
|
||||
futuresBatchOrder = "/api/v3/batchorder"
|
||||
futuresNotifications = "/api/v3/notifications"
|
||||
futuresAccountData = "/api/v3/accounts"
|
||||
futuresCancelAllOrders = "/api/v3/cancelallorders"
|
||||
futuresCancelOrdersAfter = "/api/v3/cancelallordersafter"
|
||||
futuresOpenOrders = "/api/v3/openorders"
|
||||
futuresRecentOrders = "/api/v3/recentorders"
|
||||
futuresWithdraw = "/api/v3/withdrawal"
|
||||
futuresTransfers = "/api/v3/transfers"
|
||||
futuresEditOrder = "/api/v3/editorder"
|
||||
|
||||
// Rate limit consts
|
||||
krakenRateInterval = time.Second
|
||||
krakenRequestRate = 1
|
||||
|
||||
// Status consts
|
||||
statusOpen = "open"
|
||||
|
||||
krakenFormat = "2006-01-02T15:04:05.000Z"
|
||||
)
|
||||
|
||||
var (
|
||||
assetTranslator assetTranslatorStore
|
||||
)
|
||||
|
||||
// GenericResponse stores general response data for functions that only return success
|
||||
type GenericResponse struct {
|
||||
Timestamp string `json:"timestamp"`
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
// TimeResponse type
|
||||
type TimeResponse struct {
|
||||
Unixtime int64 `json:"unixtime"`
|
||||
Rfc1123 string `json:"rfc1123"`
|
||||
// AuthErrorData stores authenticated error messages
|
||||
type AuthErrorData struct {
|
||||
Result string `json:"result"`
|
||||
ServerTime string `json:"serverTime"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// SpotAuthError stores authenticated error messages
|
||||
type SpotAuthError struct {
|
||||
Error []string `json:"error"`
|
||||
}
|
||||
|
||||
// Asset holds asset information
|
||||
@@ -30,6 +104,7 @@ type Asset struct {
|
||||
// AssetPairs holds asset pair information
|
||||
type AssetPairs struct {
|
||||
Altname string `json:"altname"`
|
||||
Wsname string `json:"wsname"`
|
||||
AclassBase string `json:"aclass_base"`
|
||||
Base string `json:"base"`
|
||||
AclassQuote string `json:"aclass_quote"`
|
||||
@@ -45,6 +120,7 @@ type AssetPairs struct {
|
||||
FeeVolumeCurrency string `json:"fee_volume_currency"`
|
||||
MarginCall int `json:"margin_call"`
|
||||
MarginStop int `json:"margin_stop"`
|
||||
Ordermin string `json:"ordermin"`
|
||||
}
|
||||
|
||||
// Ticker is a standard ticker type
|
||||
@@ -520,7 +596,7 @@ type WsOpenOrder struct {
|
||||
Close string `json:"close"`
|
||||
Price float64 `json:"price,string"`
|
||||
Price2 float64 `json:"price2,string"`
|
||||
Leverage string `json:"leverage"`
|
||||
Leverage float64 `json:"leverage,string"`
|
||||
Order string `json:"order"`
|
||||
OrderType string `json:"ordertype"`
|
||||
Pair string `json:"pair"`
|
||||
@@ -623,3 +699,11 @@ type WsCancelOrderResponse struct {
|
||||
RequestID int64 `json:"reqid"`
|
||||
Count int64 `json:"count"`
|
||||
}
|
||||
|
||||
// OrderVars stores side, status and type for any order/trade
|
||||
type OrderVars struct {
|
||||
Side order.Side
|
||||
Status order.Status
|
||||
OrderType order.Type
|
||||
Fee float64
|
||||
}
|
||||
|
||||
@@ -599,7 +599,7 @@ func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) error {
|
||||
// allowing correlation between subscriptions and returned data
|
||||
func (k *Kraken) addNewSubscriptionChannelData(response *wsSubscription) {
|
||||
// We change the / to - to maintain compatibility with REST/config
|
||||
var pair currency.Pair
|
||||
var pair, fPair currency.Pair
|
||||
if response.Pair != "" {
|
||||
var err error
|
||||
pair, err = currency.NewPairFromString(response.Pair)
|
||||
@@ -607,11 +607,15 @@ func (k *Kraken) addNewSubscriptionChannelData(response *wsSubscription) {
|
||||
log.Errorf(log.ExchangeSys, "%s exchange error: %s", k.Name, err)
|
||||
return
|
||||
}
|
||||
pair.Delimiter = k.CurrencyPairs.RequestFormat.Delimiter
|
||||
fPair, err = k.FormatExchangeCurrency(pair, asset.Spot)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s exchange error: %s", k.Name, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
subscriptionChannelPair = append(subscriptionChannelPair, WebsocketChannelData{
|
||||
Subscription: response.Subscription.Name,
|
||||
Pair: pair,
|
||||
Pair: fPair,
|
||||
ChannelID: response.ChannelID,
|
||||
})
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user