mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
@@ -542,6 +542,30 @@
|
||||
"Delimiter": "_",
|
||||
"Separator": "-"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Yobit",
|
||||
"Enabled": true,
|
||||
"Verbose": false,
|
||||
"Websocket": false,
|
||||
"UseSandbox": false,
|
||||
"RESTPollingDelay": 10,
|
||||
"AuthenticatedAPISupport": false,
|
||||
"APIKey": "Key",
|
||||
"APISecret": "Secret",
|
||||
"AvailablePairs": "DASH_BTC,WAVES_BTC,LSK_BTC,LIZA_BTC,BCC_BTC,ETH_BTC,LTC_BTC,TRX_BTC,DOGE_BTC,VNTX_BTC,SW_BTC,ZEC_BTC,DASH_ETH,WAVES_ETH,LSK_ETH,LIZA_ETH,BCC_ETH,,LTC_ETH,TRX_ETH,DOGE_ETH,VNTX_ETH,SW_ETH,ZEC_ETH,DASH_DOGE,WAVES_DOGE,LSK_DOGE,LIZA_DOGE,BCC_DOGE,LTC_DOGE,TRX_DOGE,VNTX_DOGE,SW_DOGE,ZEC_DOGE,DASH_USD,WAVES_USD,LSK_USD,LIZA_USD,BCC_USD,LTC_USD,TRX_USD,VNTX_USD,SW_USD,ZEC_USD,ETH_USD,BTC_USD,DASH_RUR,WAVES_BTC,WAVES_RUR,LSK_RUR,LIZA_RUR,BCC_RUR,LTC_RUR,TRX_RUR,VNTX_RUR,SW_RUR,ETH_RUR,ZEC_RUR",
|
||||
"EnabledPairs": "LTC_BTC,ETH_BTC,BTC_USD,DASH_BTC",
|
||||
"BaseCurrencies": "USD,RUR",
|
||||
"AssetTypes": "SPOT",
|
||||
"ConfigCurrencyPairFormat": {
|
||||
"Uppercase": true,
|
||||
"Delimiter": "_"
|
||||
},
|
||||
"RequestCurrencyPairFormat": {
|
||||
"Uppercase": false,
|
||||
"Delimiter": "_",
|
||||
"Separator": "-"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/okex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/poloniex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/wex"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/yobit"
|
||||
)
|
||||
|
||||
// vars related to exchange functions
|
||||
@@ -171,6 +172,8 @@ func LoadExchange(name string) error {
|
||||
exch = new(poloniex.Poloniex)
|
||||
case "wex":
|
||||
exch = new(wex.WEX)
|
||||
case "yobit":
|
||||
exch = new(yobit.Yobit)
|
||||
default:
|
||||
return ErrExchangeNotFound
|
||||
}
|
||||
|
||||
309
exchanges/yobit/yobit.go
Normal file
309
exchanges/yobit/yobit.go
Normal file
@@ -0,0 +1,309 @@
|
||||
package yobit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
const (
|
||||
apiPublicURL = "https://yobit.net/api"
|
||||
apiPrivateURL = "https://yobit.net/tapi"
|
||||
apiPublicVersion = "3"
|
||||
publicInfo = "info"
|
||||
publicTicker = "ticker"
|
||||
publicDepth = "depth"
|
||||
publicTrades = "trades"
|
||||
privateAccountInfo = "getInfo"
|
||||
privateTrade = "Trade"
|
||||
privateActiveOrders = "ActiveOrders"
|
||||
privateOrderInfo = "OrderInfo"
|
||||
privateCancelOrder = "CancelOrder"
|
||||
privateTradeHistory = "TradeHistory"
|
||||
privateGetDepositAddress = "GetDepositAddress"
|
||||
privateWithdrawCoinsToAddress = "WithdrawCoinsToAddress"
|
||||
privateCreateCoupon = "CreateYobicode"
|
||||
privateRedeemCoupon = "RedeemYobicode"
|
||||
)
|
||||
|
||||
// Yobit is the overarching type across the Yobit package
|
||||
type Yobit struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
}
|
||||
|
||||
// SetDefaults sets current default value for Yobit
|
||||
func (y *Yobit) SetDefaults() {
|
||||
y.Name = "Yobit"
|
||||
y.Enabled = true
|
||||
y.Fee = 0.2
|
||||
y.Verbose = false
|
||||
y.Websocket = false
|
||||
y.RESTPollingDelay = 10
|
||||
y.APIUrl = apiPublicURL
|
||||
y.AuthenticatedAPISupport = true
|
||||
y.Ticker = make(map[string]Ticker)
|
||||
y.RequestCurrencyPairFormat.Delimiter = "_"
|
||||
y.RequestCurrencyPairFormat.Uppercase = false
|
||||
y.RequestCurrencyPairFormat.Separator = "-"
|
||||
y.ConfigCurrencyPairFormat.Delimiter = "_"
|
||||
y.ConfigCurrencyPairFormat.Uppercase = true
|
||||
y.AssetTypes = []string{ticker.Spot}
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for Yobit
|
||||
func (y *Yobit) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
y.SetEnabled(false)
|
||||
} else {
|
||||
y.Enabled = true
|
||||
y.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
y.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
y.RESTPollingDelay = exch.RESTPollingDelay
|
||||
y.Verbose = exch.Verbose
|
||||
y.Websocket = exch.Websocket
|
||||
y.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
y.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
y.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := y.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = y.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetFee returns the exchange fee
|
||||
func (y *Yobit) GetFee() float64 {
|
||||
return y.Fee
|
||||
}
|
||||
|
||||
// GetInfo returns the Yobit info
|
||||
func (y *Yobit) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
path := fmt.Sprintf("%s/%s/%s/", apiPublicURL, apiPublicVersion, publicInfo)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, y.Verbose, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns a ticker for a specific currency
|
||||
func (y *Yobit) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
type Response struct {
|
||||
Data map[string]Ticker
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicTicker, symbol)
|
||||
|
||||
return response.Data, common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth returns the depth for a specific currency
|
||||
func (y *Yobit) GetDepth(symbol string) (Orderbook, error) {
|
||||
type Response struct {
|
||||
Data map[string]Orderbook
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicDepth, symbol)
|
||||
|
||||
return response.Data[symbol],
|
||||
common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns the trades for a specific currency
|
||||
func (y *Yobit) GetTrades(symbol string) ([]Trades, error) {
|
||||
type Response struct {
|
||||
Data map[string][]Trades
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicTrades, symbol)
|
||||
|
||||
return response.Data[symbol], common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns a users account info
|
||||
func (y *Yobit) GetAccountInfo() (AccountInfo, error) {
|
||||
result := AccountInfo{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateAccountInfo, url.Values{}, &result)
|
||||
}
|
||||
|
||||
// Trade places an order and returns the order ID if successful or an error
|
||||
func (y *Yobit) Trade(pair, orderType string, amount, price float64) (int64, error) {
|
||||
req := url.Values{}
|
||||
req.Add("pair", pair)
|
||||
req.Add("type", orderType)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("rate", strconv.FormatFloat(price, 'f', -1, 64))
|
||||
|
||||
result := Trade{}
|
||||
|
||||
return int64(result.OrderID), y.SendAuthenticatedHTTPRequest(privateTrade, req, &result)
|
||||
}
|
||||
|
||||
// GetActiveOrders returns the active orders for a specific currency
|
||||
func (y *Yobit) GetActiveOrders(pair string) (map[string]ActiveOrders, error) {
|
||||
req := url.Values{}
|
||||
req.Add("pair", pair)
|
||||
|
||||
result := map[string]ActiveOrders{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateActiveOrders, req, &result)
|
||||
}
|
||||
|
||||
// GetOrderInfo returns the order info for a specific order ID
|
||||
func (y *Yobit) GetOrderInfo(OrderID int64) (map[string]OrderInfo, error) {
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
result := map[string]OrderInfo{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateOrderInfo, req, &result)
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order for a specific order ID
|
||||
func (y *Yobit) CancelOrder(OrderID int64) (bool, error) {
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
result := CancelOrder{}
|
||||
err := y.SendAuthenticatedHTTPRequest(privateCancelOrder, req, &result)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// GetTradeHistory returns the trade history
|
||||
func (y *Yobit) GetTradeHistory(TIDFrom, Count, TIDEnd int64, order, since, end, pair string) (map[string]TradeHistory, error) {
|
||||
req := url.Values{}
|
||||
req.Add("from", strconv.FormatInt(TIDFrom, 10))
|
||||
req.Add("count", strconv.FormatInt(Count, 10))
|
||||
req.Add("from_id", strconv.FormatInt(TIDFrom, 10))
|
||||
req.Add("end_id", strconv.FormatInt(TIDEnd, 10))
|
||||
req.Add("order", order)
|
||||
req.Add("since", since)
|
||||
req.Add("end", end)
|
||||
req.Add("pair", pair)
|
||||
|
||||
result := map[string]TradeHistory{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateTradeHistory, req, &result)
|
||||
}
|
||||
|
||||
// CoinDepositAddress returns the deposit address for a specific currency
|
||||
func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coinName", coin)
|
||||
|
||||
result := DepositAddress{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateGetDepositAddress, req, &result)
|
||||
}
|
||||
|
||||
// CoinDepositAddress returns the deposit address for a specific currency
|
||||
func (y *Yobit) WithdrawCoinsToAddress(coin string, amount float64, address string) (WithdrawCoinsToAddress, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coinName", coin)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("address", address)
|
||||
|
||||
result := WithdrawCoinsToAddress{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateWithdrawCoinsToAddress, req, &result)
|
||||
}
|
||||
|
||||
// CreateCoupon creates an exchange coupon for a sepcific currency
|
||||
func (y *Yobit) CreateCoupon(currency string, amount float64) (CreateCoupon, error) {
|
||||
req := url.Values{}
|
||||
req.Add("currency", currency)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
|
||||
var result CreateCoupon
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateCreateCoupon, req, &result)
|
||||
}
|
||||
|
||||
// RedeemCoupon redeems an exchange coupon
|
||||
func (y *Yobit) RedeemCoupon(coupon string) (RedeemCoupon, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coupon", coupon)
|
||||
|
||||
result := RedeemCoupon{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateRedeemCoupon, req, &result)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to Yobit
|
||||
func (y *Yobit) SendAuthenticatedHTTPRequest(path string, params url.Values, result interface{}) (err error) {
|
||||
if !y.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, y.Name)
|
||||
}
|
||||
|
||||
if params == nil {
|
||||
params = url.Values{}
|
||||
}
|
||||
|
||||
if y.Nonce.Get() == 0 {
|
||||
y.Nonce.Set(time.Now().Unix())
|
||||
} else {
|
||||
y.Nonce.Inc()
|
||||
}
|
||||
params.Set("nonce", y.Nonce.String())
|
||||
params.Set("method", path)
|
||||
|
||||
encoded := params.Encode()
|
||||
hmac := common.GetHMAC(common.HashSHA512, []byte(encoded), []byte(y.APISecret))
|
||||
|
||||
if y.Verbose {
|
||||
log.Printf("Sending POST request to %s calling path %s with params %s\n", apiPrivateURL, path, encoded)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Key"] = y.APIKey
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
"POST", apiPrivateURL, headers, strings.NewReader(encoded),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if y.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
if err = common.JSONDecode([]byte(resp), &response); err != nil {
|
||||
return errors.New("sendAuthenticatedHTTPRequest: Unable to JSON Unmarshal response." + err.Error())
|
||||
}
|
||||
|
||||
if response.Success != 1 {
|
||||
return errors.New(response.Error)
|
||||
}
|
||||
|
||||
JSONEncoded, err := common.JSONEncode(response.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.JSONDecode(JSONEncoded, &result)
|
||||
}
|
||||
137
exchanges/yobit/yobit_test.go
Normal file
137
exchanges/yobit/yobit_test.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package yobit
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
var y Yobit
|
||||
|
||||
// Please supply your own keys for better unit testing
|
||||
const (
|
||||
apiKey = ""
|
||||
apiSecret = ""
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
y.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
yobitConfig := config.GetConfig()
|
||||
yobitConfig.LoadConfig("../../testdata/configtest.json")
|
||||
conf, err := yobitConfig.GetExchangeConfig("Yobit")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Yobit init error")
|
||||
}
|
||||
conf.APIKey = apiKey
|
||||
conf.APISecret = apiSecret
|
||||
conf.AuthenticatedAPISupport = true
|
||||
|
||||
y.Setup(conf)
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
if y.GetFee() != 0.2 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
_, err := y.GetInfo()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetInfo() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
_, err := y.GetTicker("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
_, err := y.GetDepth("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetDepth() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
_, err := y.GetTrades("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTrades() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
_, err := y.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetAccountInfo() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
_, err := y.GetActiveOrders("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetActiveOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
_, err := y.GetOrderInfo(6196974)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOrderInfo() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
_, err := y.CancelOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrade(t *testing.T) {
|
||||
_, err := y.Trade("", "buy", 0, 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Trade() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTradeHistory(t *testing.T) {
|
||||
_, err := y.GetTradeHistory(0, 0, 0, "", "", "", "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradeHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawCoinsToAddress(t *testing.T) {
|
||||
_, err := y.WithdrawCoinsToAddress("", 0, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoinsToAddress() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
_, err := y.GetDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetDepositAddress() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateYobicode(t *testing.T) {
|
||||
_, err := y.CreateCoupon("bla", 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CreateYobicode() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedeemYobicode(t *testing.T) {
|
||||
_, err := y.RedeemCoupon("bla")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - RedeemYobicode() error", err)
|
||||
}
|
||||
}
|
||||
139
exchanges/yobit/yobit_types.go
Normal file
139
exchanges/yobit/yobit_types.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package yobit
|
||||
|
||||
// Response is a generic struct used for exchange API request result
|
||||
type Response struct {
|
||||
Return interface{} `json:"return"`
|
||||
Success int `json:"success"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Info holds server time and pair information
|
||||
type Info struct {
|
||||
ServerTime int64 `json:"server_time"`
|
||||
Pairs map[string]Pair `json:"pairs"`
|
||||
}
|
||||
|
||||
// Ticker stores the ticker information
|
||||
type Ticker struct {
|
||||
High float64 // maximal price
|
||||
Low float64 // minimal price
|
||||
Avg float64 // average price
|
||||
Vol float64 // traded volume
|
||||
VolumeCurrent float64 `json:"vol_cur"` // traded volume in currency
|
||||
Last float64 // last transaction price
|
||||
Buy float64 // buying price
|
||||
Sell float64 // selling price
|
||||
Updated int64 // last cache upgrade
|
||||
}
|
||||
|
||||
// Orderbook stores the asks and bids orderbook information
|
||||
type Orderbook struct {
|
||||
Asks [][]float64 `json:"asks"` // selling orders
|
||||
Bids [][]float64 `json:"bids"` // buying orders
|
||||
}
|
||||
|
||||
// Trades stores trade information
|
||||
type Trades struct {
|
||||
Type string `json:"type"`
|
||||
Price float64 `json:"bid"`
|
||||
Amount float64 `json:"amount"`
|
||||
TID int64 `json:"tid"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// ActiveOrders stores active order information
|
||||
type ActiveOrders struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"timestamp_created"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// Pair holds pair information
|
||||
type Pair struct {
|
||||
DecimalPlaces int `json:"decimal_places"` // Quantity of permitted numbers after decimal point
|
||||
MinPrice float64 `json:"min_price"` // Minimal permitted price
|
||||
MaxPrice float64 `json:"max_price"` // Maximal permitted price
|
||||
MinAmount float64 `json:"min_amount"` // Minimal permitted buy or sell amount
|
||||
Hidden int `json:"hidden"` // Pair is hidden (0 or 1)
|
||||
Fee float64 `json:"fee"` // Pair commission
|
||||
}
|
||||
|
||||
// AccountInfo stores the account information for a user
|
||||
type AccountInfo struct {
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
FundsInclOrders map[string]float64 `json:"funds_incl_orders"`
|
||||
Rights struct {
|
||||
Info int `json:"info"`
|
||||
Trade int `json:"trade"`
|
||||
Withdraw int `json:"withdraw"`
|
||||
} `json:"rights"`
|
||||
TransactionCount int `json:"transaction_count"`
|
||||
OpenOrders int `json:"open_orders"`
|
||||
ServerTime float64 `json:"server_time"`
|
||||
}
|
||||
|
||||
// OrderInfo stores order information
|
||||
type OrderInfo struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
StartAmount float64 `json:"start_amount"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"timestamp_created"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// CancelOrder is used for the CancelOrder API request response
|
||||
type CancelOrder struct {
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
}
|
||||
|
||||
// Trade stores the trade information
|
||||
type Trade struct {
|
||||
Received float64 `json:"received"`
|
||||
Remains float64 `json:"remains"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
}
|
||||
|
||||
// TradeHistory stores trade history
|
||||
type TradeHistory struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"type"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
MyOrder int `json:"is_your_order"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// CoinDepositAddress stores a curency deposit address
|
||||
type DepositAddress struct {
|
||||
Address string `json:"address"`
|
||||
ProcessedAmount float64 `json:"processed_amount"`
|
||||
ServerTime int64 `json:"server_time"`
|
||||
}
|
||||
|
||||
// WithdrawCoins stores information for a withdrawcoins request
|
||||
type WithdrawCoinsToAddress struct {
|
||||
ServerTime int64 `json:"server_time"`
|
||||
}
|
||||
|
||||
// CreateCoupon stores information coupon information
|
||||
type CreateCoupon struct {
|
||||
Coupon string `json:"coupon"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
}
|
||||
|
||||
// RedeemCoupon stores redeem coupon information
|
||||
type RedeemCoupon struct {
|
||||
CouponAmount float64 `json:"couponAmount,string"`
|
||||
CouponCurrency string `json:"couponCurrency"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
}
|
||||
120
exchanges/yobit/yobit_wrapper.go
Normal file
120
exchanges/yobit/yobit_wrapper.go
Normal file
@@ -0,0 +1,120 @@
|
||||
package yobit
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Start starts the WEX go routine
|
||||
func (y *Yobit) Start() {
|
||||
go y.Run()
|
||||
}
|
||||
|
||||
// Run implements the Yobit wrapper
|
||||
func (y *Yobit) Run() {
|
||||
if y.Verbose {
|
||||
log.Printf("%s Websocket: %s.", y.GetName(), common.IsEnabled(y.Websocket))
|
||||
log.Printf("%s polling delay: %ds.\n", y.GetName(), y.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", y.GetName(), len(y.EnabledPairs), y.EnabledPairs)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (y *Yobit) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
pairsCollated, err := exchange.GetAndFormatExchangeCurrencies(y.Name, y.GetEnabledCurrencies())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
result, err := y.GetTicker(pairsCollated.String())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range y.GetEnabledCurrencies() {
|
||||
currency := exchange.FormatExchangeCurrency(y.Name, x).Lower().String()
|
||||
var tickerPrice ticker.Price
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Ask = result[currency].Sell
|
||||
tickerPrice.Bid = result[currency].Buy
|
||||
tickerPrice.Last = result[currency].Last
|
||||
tickerPrice.Low = result[currency].Low
|
||||
tickerPrice.Volume = result[currency].VolumeCurrent
|
||||
ticker.ProcessTicker(y.Name, x, tickerPrice, assetType)
|
||||
}
|
||||
return ticker.GetTicker(y.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (y *Yobit) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tick, err := ticker.GetTicker(y.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return y.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tick, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns the orderbook for a currency pair
|
||||
func (y *Yobit) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(y.GetName(), p, assetType)
|
||||
if err == nil {
|
||||
return y.UpdateOrderbook(p, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (y *Yobit) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := y.GetDepth(exchange.FormatExchangeCurrency(y.Name, p).String())
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Bids {
|
||||
data := orderbookNew.Bids[x]
|
||||
orderBook.Bids = append(orderBook.Bids, orderbook.Item{Price: data[0], Amount: data[1]})
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Asks {
|
||||
data := orderbookNew.Asks[x]
|
||||
orderBook.Asks = append(orderBook.Asks, orderbook.Item{Price: data[0], Amount: data[1]})
|
||||
}
|
||||
|
||||
orderbook.ProcessOrderbook(y.GetName(), p, orderBook, assetType)
|
||||
return orderbook.GetOrderbook(y.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Yobit exchange
|
||||
func (y *Yobit) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
response.ExchangeName = y.GetName()
|
||||
accountBalance, err := y.GetAccountInfo()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
for x, y := range accountBalance.FundsInclOrders {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = common.StringToUpper(x)
|
||||
exchangeCurrency.TotalValue = y
|
||||
exchangeCurrency.Hold = 0
|
||||
for z, w := range accountBalance.Funds {
|
||||
if z == x {
|
||||
exchangeCurrency.Hold = y - w
|
||||
}
|
||||
}
|
||||
|
||||
response.Currencies = append(response.Currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
25
testdata/configtest.json
vendored
25
testdata/configtest.json
vendored
@@ -542,6 +542,31 @@
|
||||
"Uppercase": true,
|
||||
"Delimiter": "_"
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Yobit",
|
||||
"Enabled": true,
|
||||
"Verbose": false,
|
||||
"Websocket": false,
|
||||
"UseSandbox": false,
|
||||
"RESTPollingDelay": 10,
|
||||
"AuthenticatedAPISupport": false,
|
||||
"APIKey": "Key",
|
||||
"APISecret": "Secret",
|
||||
"AvailablePairs": "DASH_BTC,WAVES_BTC,LSK_BTC,LIZA_BTC,BCC_BTC,ETH_BTC,LTC_BTC,TRX_BTC,DOGE_BTC,VNTX_BTC,SW_BTC,ZEC_BTC,DASH_ETH,WAVES_ETH,LSK_ETH,LIZA_ETH,BCC_ETH,,LTC_ETH,TRX_ETH,DOGE_ETH,VNTX_ETH,SW_ETH,ZEC_ETH,DASH_DOGE,WAVES_DOGE,LSK_DOGE,LIZA_DOGE,BCC_DOGE,LTC_DOGE,TRX_DOGE,VNTX_DOGE,SW_DOGE,ZEC_DOGE,DASH_USD,WAVES_USD,LSK_USD,LIZA_USD,BCC_USD,LTC_USD,TRX_USD,VNTX_USD,SW_USD,ZEC_USD,ETH_USD,BTC_USD,DASH_RUR,WAVES_BTC,WAVES_RUR,LSK_RUR,LIZA_RUR,BCC_RUR,LTC_RUR,TRX_RUR,VNTX_RUR,SW_RUR,ETH_RUR,ZEC_RUR",
|
||||
"EnabledPairs": "LTC_BTC,ETH_BTC,BTC_USD,DASH_BTC",
|
||||
"BaseCurrencies": "USD",
|
||||
"AssetTypes": "SPOT",
|
||||
"ConfigCurrencyPairFormat": {
|
||||
"Uppercase": true,
|
||||
"Delimiter": "_"
|
||||
},
|
||||
"RequestCurrencyPairFormat": {
|
||||
"Uppercase": false,
|
||||
"Delimiter": "_",
|
||||
"Separator": "-"
|
||||
}
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user