mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
Port from idoall's codebase (#161)
* 修复火币Post REST API方法不正确的问题,同时增加火币海带丝交易所 * add vendor folder * 修改命名空间依赖 * 第一次提交分支 * 增加取消订单功能 * 修复binance.GetAccount方法 * 更新readme.md * 增加 Gateio 交易所的支持,支持获取K线、支持的交易对、交易市场参数 * 替换HuobiHadax的参数 * 买/卖订单、取消订单 * OKEX 币币交易:增加获取用户信息,下订单,取消订单 * 测试ok kline * 修复 Bitfinex 的 GetAccountInfo 方法 * 做一些不必要的删减 * 修复binfinex不返回错误的bug * 统一我修改交易所的Kline获取方式 * Bitfinex 增加获取最新价格 * update main.go * 更新GetSymbol方法 * 修改火币和海带丝的Kline编号ID类型 * 修改海带丝的默认配置大小写 * okex增加获取最新价格 * 调整okex的参数判断 * 调整比特儿的参数名称 * 修改火币、火币Hadax的参数全名 * 更新海带丝的配置名称 * 修改bintfinex的GetAccountInfo方法 * 去掉一行注释 * 支持zb交易所的部分功能 * 修复获取K线时没有设置参数的错误 * 增加 Binance 取消订单的方法,获取订单状态,获取所有打开的状态以及所有订单 * 修改获取深度和历史订单的数据 * 修改币安获取深度的参数 * 修改火币获取市场深度的参数 * 修改okex获取市场深度的参数 * 修改币安、OKex获取历史订单的参数 * 修复币安提交参数错误的问题 * merge upstrem * merge后,调整一部分命名空间 * 修改ZB时间参数的命名方式 * 继续替换命名空间 * 命名空间的替换 * 继续命名空间的替换 * 测试 * Port code from idoall's PR * Drop errors dep * Start amending PR * Fix commented code * Translate text from Chinese to English (except for ZB). The reasning behind this is that it's a Chinese exchange and the structs are self explanatory in English, but would for other developers in China * Translate Chinese text, basic formatting changes * Remove commented lines and address feedback on PR
This commit is contained in:
9
exchanges/gateio/README.md
Normal file
9
exchanges/gateio/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# GoCryptoTrader package gateio
|
||||
|
||||
This gateio package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## Gateio Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
Gateio 交易所的支持,支持获取K线、支持的交易对、交易市场参数、买/卖订单、取消订单
|
||||
375
exchanges/gateio/gateio.go
Normal file
375
exchanges/gateio/gateio.go
Normal file
@@ -0,0 +1,375 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
const (
|
||||
gateioTradeURL = "https://api.gateio.io"
|
||||
gateioMarketURL = "https://data.gateio.io"
|
||||
gateioAPIVersion = "api2/1"
|
||||
|
||||
gateioSymbol = "pairs"
|
||||
gateioMarketInfo = "marketinfo"
|
||||
gateioKline = "candlestick2"
|
||||
gateioOrder = "private"
|
||||
gateioBalances = "private/balances"
|
||||
gateioCancelOrder = "private/cancelOrder"
|
||||
gateioTicker = "ticker"
|
||||
gateioTickers = "tickers"
|
||||
gateioOrderbook = "orderBook"
|
||||
|
||||
gateioAuthRate = 100
|
||||
gateioUnauthRate = 100
|
||||
)
|
||||
|
||||
// Gateio is the overarching type across this package
|
||||
type Gateio struct {
|
||||
exchange.Base
|
||||
}
|
||||
|
||||
// SetDefaults sets default values for the exchange
|
||||
func (g *Gateio) SetDefaults() {
|
||||
g.Name = "GateIO"
|
||||
g.Enabled = false
|
||||
g.Verbose = false
|
||||
g.Websocket = false
|
||||
g.RESTPollingDelay = 10
|
||||
g.RequestCurrencyPairFormat.Delimiter = "_"
|
||||
g.RequestCurrencyPairFormat.Uppercase = false
|
||||
g.ConfigCurrencyPairFormat.Delimiter = "_"
|
||||
g.ConfigCurrencyPairFormat.Uppercase = true
|
||||
g.AssetTypes = []string{ticker.Spot}
|
||||
g.SupportsAutoPairUpdating = true
|
||||
g.SupportsRESTTickerBatching = true
|
||||
g.Requester = request.New(g.Name, request.NewRateLimit(time.Second*10, gateioAuthRate), request.NewRateLimit(time.Second*10, gateioUnauthRate), common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
}
|
||||
|
||||
// Setup sets user configuration
|
||||
func (g *Gateio) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
g.SetEnabled(false)
|
||||
} else {
|
||||
g.Enabled = true
|
||||
g.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
g.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
g.APIAuthPEMKey = exch.APIAuthPEMKey
|
||||
g.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
g.RESTPollingDelay = exch.RESTPollingDelay
|
||||
g.Verbose = exch.Verbose
|
||||
g.Websocket = exch.Websocket
|
||||
g.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
g.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
g.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := g.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = g.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = g.SetAutoPairDefaults()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetSymbols returns all supported symbols
|
||||
func (g *Gateio) GetSymbols() ([]string, error) {
|
||||
var result []string
|
||||
|
||||
url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioSymbol)
|
||||
|
||||
err := g.SendHTTPRequest(url, &result)
|
||||
if err != nil {
|
||||
return nil, nil
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetMarketInfo returns information about all trading pairs, including
|
||||
// transaction fee, minimum order quantity, price accuracy and so on
|
||||
func (g *Gateio) GetMarketInfo() (MarketInfoResponse, error) {
|
||||
type response struct {
|
||||
Result string `json:"result"`
|
||||
Pairs []interface{} `json:"pairs"`
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioMarketInfo)
|
||||
|
||||
var res response
|
||||
var result MarketInfoResponse
|
||||
err := g.SendHTTPRequest(url, &res)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
result.Result = res.Result
|
||||
for _, v := range res.Pairs {
|
||||
item := v.(map[string]interface{})
|
||||
for itemk, itemv := range item {
|
||||
pairv := itemv.(map[string]interface{})
|
||||
result.Pairs = append(result.Pairs, MarketInfoPairsResponse{
|
||||
Symbol: itemk,
|
||||
DecimalPlaces: pairv["decimal_places"].(float64),
|
||||
MinAmount: pairv["min_amount"].(float64),
|
||||
Fee: pairv["fee"].(float64),
|
||||
})
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetLatestSpotPrice returns latest spot price of symbol
|
||||
// updated every 10 seconds
|
||||
//
|
||||
// symbol: string of currency pair
|
||||
func (g *Gateio) GetLatestSpotPrice(symbol string) (float64, error) {
|
||||
res, err := g.GetTicker(symbol)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return res.Last, nil
|
||||
}
|
||||
|
||||
// GetTicker returns a ticker for the supplied symbol
|
||||
// updated every 10 seconds
|
||||
func (g *Gateio) GetTicker(symbol string) (TickerResponse, error) {
|
||||
url := fmt.Sprintf("%s/%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioTicker, symbol)
|
||||
|
||||
var res TickerResponse
|
||||
err := g.SendHTTPRequest(url, &res)
|
||||
if err != nil {
|
||||
return res, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// GetTickers returns tickers for all symbols
|
||||
func (g *Gateio) GetTickers() (map[string]TickerResponse, error) {
|
||||
url := fmt.Sprintf("%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioTickers)
|
||||
|
||||
resp := make(map[string]TickerResponse)
|
||||
err := g.SendHTTPRequest(url, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetOrderbook returns the orderbook data for a suppled symbol
|
||||
func (g *Gateio) GetOrderbook(symbol string) (Orderbook, error) {
|
||||
url := fmt.Sprintf("%s/%s/%s/%s", gateioMarketURL, gateioAPIVersion, gateioOrderbook, symbol)
|
||||
|
||||
var resp OrderbookResponse
|
||||
err := g.SendHTTPRequest(url, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
|
||||
if resp.Result != "true" {
|
||||
return Orderbook{}, errors.New("result was not true")
|
||||
}
|
||||
|
||||
var ob Orderbook
|
||||
|
||||
// Asks are in reverse order
|
||||
for x := len(resp.Asks) - 1; x != 0; x-- {
|
||||
data := resp.Asks[x]
|
||||
|
||||
price, err := strconv.ParseFloat(data[0], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(data[1], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount})
|
||||
}
|
||||
|
||||
for x := range resp.Bids {
|
||||
data := resp.Bids[x]
|
||||
|
||||
price, err := strconv.ParseFloat(data[0], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(data[1], 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount})
|
||||
}
|
||||
|
||||
ob.Result = resp.Result
|
||||
ob.Elapsed = resp.Elapsed
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// GetSpotKline returns kline data for the most recent time period
|
||||
func (g *Gateio) GetSpotKline(arg KlinesRequestParams) ([]*KLineResponse, error) {
|
||||
url := fmt.Sprintf("%s/%s/%s/%s?group_sec=%d&range_hour=%d", gateioMarketURL, gateioAPIVersion, gateioKline, arg.Symbol, arg.GroupSec, arg.HourSize)
|
||||
var rawKlines map[string]interface{}
|
||||
err := g.SendHTTPRequest(url, &rawKlines)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []*KLineResponse
|
||||
if rawKlines == nil || rawKlines["data"] == nil {
|
||||
return nil, fmt.Errorf("rawKlines is nil. Err: %s", err)
|
||||
}
|
||||
|
||||
rawKlineDatasString, _ := json.Marshal(rawKlines["data"].([]interface{}))
|
||||
rawKlineDatas := [][]interface{}{}
|
||||
if err := json.Unmarshal(rawKlineDatasString, &rawKlineDatas); err != nil {
|
||||
return nil, fmt.Errorf("rawKlines unmarshal failed. Err: %s", err)
|
||||
}
|
||||
|
||||
for _, k := range rawKlineDatas {
|
||||
otString, _ := strconv.ParseFloat(k[0].(string), 64)
|
||||
ot, err := common.TimeFromUnixTimestampFloat(otString)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.OpenTime. Err: %s", err)
|
||||
}
|
||||
_vol, err := common.FloatFromString(k[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.Volume. Err: %s", err)
|
||||
}
|
||||
_id, err := common.FloatFromString(k[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.Id. Err: %s", err)
|
||||
}
|
||||
_close, err := common.FloatFromString(k[2])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.Close. Err: %s", err)
|
||||
}
|
||||
_high, err := common.FloatFromString(k[3])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.High. Err: %s", err)
|
||||
}
|
||||
_low, err := common.FloatFromString(k[4])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.Low. Err: %s", err)
|
||||
}
|
||||
_open, err := common.FloatFromString(k[5])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot parse Kline.Open. Err: %s", err)
|
||||
}
|
||||
result = append(result, &KLineResponse{
|
||||
ID: _id,
|
||||
KlineTime: ot,
|
||||
Volume: _vol,
|
||||
Close: _close,
|
||||
High: _high,
|
||||
Low: _low,
|
||||
Open: _open,
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetBalances obtains the users account balance
|
||||
func (g *Gateio) GetBalances() (BalancesResponse, error) {
|
||||
|
||||
var result BalancesResponse
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", gateioBalances, "", &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SpotNewOrder places a new order
|
||||
func (g *Gateio) SpotNewOrder(arg SpotNewOrderRequestParams) (SpotNewOrderResponse, error) {
|
||||
var result SpotNewOrderResponse
|
||||
|
||||
// Be sure to use the correct price precision before calling this
|
||||
params := fmt.Sprintf("currencyPair=%s&rate=%s&amount=%s",
|
||||
arg.Symbol,
|
||||
strconv.FormatFloat(arg.Price, 'f', -1, 64),
|
||||
strconv.FormatFloat(arg.Amount, 'f', -1, 64),
|
||||
)
|
||||
|
||||
strRequestURL := fmt.Sprintf("%s/%s", gateioOrder, arg.Type)
|
||||
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", strRequestURL, params, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order given the supplied orderID and symbol
|
||||
// orderID order ID number
|
||||
// symbol trade pair (ltc_btc)
|
||||
func (g *Gateio) CancelOrder(orderID int64, symbol string) (bool, error) {
|
||||
type response struct {
|
||||
Result bool `json:"result"`
|
||||
Code int `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
var result response
|
||||
// Be sure to use the correct price precision before calling this
|
||||
params := fmt.Sprintf("orderNumber=%d¤cyPair=%s",
|
||||
orderID,
|
||||
symbol,
|
||||
)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", gateioCancelOrder, params, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if !result.Result {
|
||||
return false, fmt.Errorf("code:%d message:%s", result.Code, result.Message)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (g *Gateio) SendHTTPRequest(path string, result interface{}) error {
|
||||
return g.SendPayload("GET", path, nil, nil, result, false, g.Verbose)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
if !g.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
headers["key"] = g.APIKey
|
||||
|
||||
hmac := common.GetHMAC(common.HashSHA512, []byte(param), []byte(g.APISecret))
|
||||
headers["sign"] = common.ByteArrayToString(hmac)
|
||||
|
||||
url := fmt.Sprintf("%s/%s/%s", gateioTradeURL, gateioAPIVersion, endpoint)
|
||||
|
||||
return g.SendPayload(method, url, headers, strings.NewReader(param), result, true, g.Verbose)
|
||||
}
|
||||
141
exchanges/gateio/gateio_test.go
Normal file
141
exchanges/gateio/gateio_test.go
Normal file
@@ -0,0 +1,141 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
// Please supply your own APIKEYS here for due diligence testing
|
||||
|
||||
const (
|
||||
apiKey = ""
|
||||
apiSecret = ""
|
||||
)
|
||||
|
||||
var g Gateio
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
g.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
gateioConfig, err := cfg.GetExchangeConfig("GateIO")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GateIO Setup() init error")
|
||||
}
|
||||
|
||||
gateioConfig.AuthenticatedAPISupport = true
|
||||
gateioConfig.APIKey = apiKey
|
||||
gateioConfig.APISecret = apiSecret
|
||||
|
||||
g.Setup(gateioConfig)
|
||||
}
|
||||
|
||||
func TestGetSymbols(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetSymbols()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio TestGetSymbols: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarketInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetMarketInfo()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetMarketInfo: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpotNewOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
_, err := g.SpotNewOrder(SpotNewOrderRequestParams{
|
||||
Symbol: "btc_usdt",
|
||||
Amount: 1.1,
|
||||
Price: 10.1,
|
||||
Type: SpotNewOrderRequestParamsTypeSell,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio SpotNewOrder: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
_, err := g.CancelOrder(917591554, "btc_usdt")
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio CancelOrder: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
if apiKey == "" || apiSecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
_, err := g.GetBalances()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetBalances: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestSpotPrice(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetLatestSpotPrice("btc_usdt")
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetLatestSpotPrice: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetTicker("btc_usdt")
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetTicker: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTickers(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetTickers()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetTicker: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetOrderbook("btc_usdt")
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetTicker: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSpotKline(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := g.GetSpotKline(KlinesRequestParams{
|
||||
Symbol: "btc_usdt",
|
||||
GroupSec: TimeIntervalFiveMinutes, // 5 minutes or less
|
||||
HourSize: 1, // 1 hour data
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Test failed - Gateio GetSpotKline: %s", err)
|
||||
}
|
||||
}
|
||||
127
exchanges/gateio/gateio_types.go
Normal file
127
exchanges/gateio/gateio_types.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package gateio
|
||||
|
||||
import "time"
|
||||
|
||||
// SpotNewOrderRequestParamsType order type (buy or sell)
|
||||
type SpotNewOrderRequestParamsType string
|
||||
|
||||
var (
|
||||
// SpotNewOrderRequestParamsTypeBuy buy order
|
||||
SpotNewOrderRequestParamsTypeBuy = SpotNewOrderRequestParamsType("buy")
|
||||
|
||||
// SpotNewOrderRequestParamsTypeSell sell order
|
||||
SpotNewOrderRequestParamsTypeSell = SpotNewOrderRequestParamsType("sell")
|
||||
)
|
||||
|
||||
// TimeInterval Interval represents interval enum.
|
||||
type TimeInterval int
|
||||
|
||||
// TimeInterval vars
|
||||
var (
|
||||
TimeIntervalMinute = TimeInterval(60)
|
||||
TimeIntervalThreeMinutes = TimeInterval(60 * 3)
|
||||
TimeIntervalFiveMinutes = TimeInterval(60 * 5)
|
||||
TimeIntervalFifteenMinutes = TimeInterval(60 * 15)
|
||||
TimeIntervalThirtyMinutes = TimeInterval(60 * 30)
|
||||
TimeIntervalHour = TimeInterval(60 * 60)
|
||||
TimeIntervalTwoHours = TimeInterval(2 * 60 * 60)
|
||||
TimeIntervalFourHours = TimeInterval(4 * 60 * 60)
|
||||
TimeIntervalSixHours = TimeInterval(6 * 60 * 60)
|
||||
TimeIntervalDay = TimeInterval(60 * 60 * 24)
|
||||
)
|
||||
|
||||
// MarketInfoResponse holds the market info data
|
||||
type MarketInfoResponse struct {
|
||||
Result string `json:"result"`
|
||||
Pairs []MarketInfoPairsResponse `json:"pairs"`
|
||||
}
|
||||
|
||||
// MarketInfoPairsResponse holds the market info response data
|
||||
type MarketInfoPairsResponse struct {
|
||||
Symbol string
|
||||
// DecimalPlaces symbol price accuracy
|
||||
DecimalPlaces float64
|
||||
// MinAmount minimum order amount
|
||||
MinAmount float64
|
||||
// Fee transaction fee
|
||||
Fee float64
|
||||
}
|
||||
|
||||
// BalancesResponse holds the user balances
|
||||
type BalancesResponse struct {
|
||||
Result string `json:"result"`
|
||||
Available map[string]string `json:"available"`
|
||||
Locked map[string]string `json:"locked"`
|
||||
}
|
||||
|
||||
// KlinesRequestParams represents Klines request data.
|
||||
type KlinesRequestParams struct {
|
||||
Symbol string // Required field; example LTCBTC,BTCUSDT
|
||||
HourSize int // How many hours of data
|
||||
GroupSec TimeInterval
|
||||
}
|
||||
|
||||
// KLineResponse holds the kline response data
|
||||
type KLineResponse struct {
|
||||
ID float64
|
||||
KlineTime time.Time
|
||||
Open float64
|
||||
Time float64
|
||||
High float64
|
||||
Low float64
|
||||
Close float64
|
||||
Volume float64
|
||||
Amount float64 `db:"amount"`
|
||||
}
|
||||
|
||||
// TickerResponse holds the ticker response data
|
||||
type TickerResponse struct {
|
||||
Result string `json:"result"`
|
||||
Volume float64 `json:"baseVolume,string"` // Trading volume
|
||||
High float64 `json:"high24hr,string"` // 24 hour high price
|
||||
Open float64 `json:"highestBid,string"` // Openening price
|
||||
Last float64 `json:"last,string"` // Last price
|
||||
Low float64 `json:"low24hr,string"` // 24 hour low price
|
||||
Close float64 `json:"lowestAsk,string"` // Closing price
|
||||
PercentChange float64 `json:"percentChange,string"` // Percentage change
|
||||
QuoteVolume float64 `json:"quoteVolume,string"` // Quote currency volume
|
||||
}
|
||||
|
||||
// OrderbookResponse stores the orderbook data
|
||||
type OrderbookResponse struct {
|
||||
Result string `json:"result"`
|
||||
Elapsed string `json:"elapsed"`
|
||||
Asks [][]string
|
||||
Bids [][]string
|
||||
}
|
||||
|
||||
// OrderbookItem stores an orderbook item
|
||||
type OrderbookItem struct {
|
||||
Price float64
|
||||
Amount float64
|
||||
}
|
||||
|
||||
// Orderbook stores the orderbook data
|
||||
type Orderbook struct {
|
||||
Result string
|
||||
Elapsed string
|
||||
Bids []OrderbookItem
|
||||
Asks []OrderbookItem
|
||||
}
|
||||
|
||||
// SpotNewOrderRequestParams Order params
|
||||
type SpotNewOrderRequestParams struct {
|
||||
Amount float64 `json:"amount"` // Order quantity
|
||||
Price float64 `json:"price"` // Order price
|
||||
Symbol string `json:"symbol"` // Trading pair; btc_usdt, eth_btc......
|
||||
Type SpotNewOrderRequestParamsType `json:"type"` // Order type (buy or sell),
|
||||
}
|
||||
|
||||
// SpotNewOrderResponse Order response
|
||||
type SpotNewOrderResponse struct {
|
||||
OrderNumber int64 `json:"orderNumber"` // OrderID number
|
||||
Price float64 `json:"rate,string"` // Order price
|
||||
LeftAmount float64 `json:"leftAmount,string"` // The remaining amount to fill
|
||||
FilledAmount float64 `json:"filledAmount,string"` // The filled amount
|
||||
Filledrate float64 `json:"filledRate,string"` // FilledPrice
|
||||
}
|
||||
177
exchanges/gateio/gateio_wrapper.go
Normal file
177
exchanges/gateio/gateio_wrapper.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package gateio
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Start starts the GateIO go routine
|
||||
func (g *Gateio) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
g.Run()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Run implements the GateIO wrapper
|
||||
func (g *Gateio) Run() {
|
||||
if g.Verbose {
|
||||
log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), g.WebsocketURL)
|
||||
log.Printf("%s polling delay: %ds.\n", g.GetName(), g.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", g.GetName(), len(g.EnabledPairs), g.EnabledPairs)
|
||||
}
|
||||
|
||||
symbols, err := g.GetSymbols()
|
||||
if err != nil {
|
||||
log.Printf("%s Unable to fetch symbols.\n", g.GetName())
|
||||
} else {
|
||||
err = g.UpdateCurrencies(symbols, false, false)
|
||||
if err != nil {
|
||||
log.Printf("%s Failed to update available currencies.\n", g.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (g *Gateio) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
result, err := g.GetTickers()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range g.GetEnabledCurrencies() {
|
||||
currency := exchange.FormatExchangeCurrency(g.Name, x).String()
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.High = result[currency].High
|
||||
tp.Last = result[currency].Last
|
||||
tp.Last = result[currency].Last
|
||||
tp.Low = result[currency].Low
|
||||
tp.Volume = result[currency].Volume
|
||||
ticker.ProcessTicker(g.Name, x, tp, assetType)
|
||||
}
|
||||
|
||||
return ticker.GetTicker(g.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (g *Gateio) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker(g.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return g.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func (g *Gateio) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(g.GetName(), currency, assetType)
|
||||
if err != nil {
|
||||
return g.UpdateOrderbook(currency, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (g *Gateio) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
currency := exchange.FormatExchangeCurrency(g.Name, p).String()
|
||||
|
||||
orderbookNew, err := g.GetOrderbook(currency)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Bids {
|
||||
data := orderbookNew.Bids[x]
|
||||
orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount, Price: data.Price})
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Asks {
|
||||
data := orderbookNew.Asks[x]
|
||||
orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price})
|
||||
}
|
||||
|
||||
orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType)
|
||||
return orderbook.GetOrderbook(g.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
|
||||
// ZB exchange
|
||||
func (g *Gateio) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
return response, errors.New("not implemented")
|
||||
}
|
||||
|
||||
// GetExchangeFundTransferHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (g *Gateio) GetExchangeFundTransferHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, errors.New("not supported on exchange")
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (g *Gateio) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, errors.New("trade history not yet implemented")
|
||||
}
|
||||
|
||||
// SubmitExchangeOrder submits a new order
|
||||
func (g *Gateio) SubmitExchangeOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, clientID string) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// ModifyExchangeOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (g *Gateio) ModifyExchangeOrder(orderID int64, action exchange.ModifyOrder) (int64, error) {
|
||||
return 0, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelExchangeOrder cancels an order by its corresponding ID number
|
||||
func (g *Gateio) CancelExchangeOrder(orderID int64) error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// CancelAllExchangeOrders cancels all orders associated with a currency pair
|
||||
func (g *Gateio) CancelAllExchangeOrders() error {
|
||||
return errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeOrderInfo returns information on a current open order
|
||||
func (g *Gateio) GetExchangeOrderInfo(orderID int64) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// GetExchangeDepositAddress returns a deposit address for a specified currency
|
||||
func (g *Gateio) GetExchangeDepositAddress(cryptocurrency pair.CurrencyItem) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawCryptoExchangeFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (g *Gateio) WithdrawCryptoExchangeFunds(address string, cryptocurrency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawFiatExchangeFunds returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (g *Gateio) WithdrawFiatExchangeFunds(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
|
||||
// WithdrawFiatExchangeFundsToInternationalBank returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (g *Gateio) WithdrawFiatExchangeFundsToInternationalBank(currency pair.CurrencyItem, amount float64) (string, error) {
|
||||
return "", errors.New("not yet implemented")
|
||||
}
|
||||
Reference in New Issue
Block a user