mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
Remove WEX exchange support
This commit is contained in:
@@ -554,7 +554,7 @@ func TestGetExchangeFormatCurrencySeperator(t *testing.T) {
|
||||
}
|
||||
|
||||
expected := true
|
||||
actual := GetExchangeFormatCurrencySeperator("WEX")
|
||||
actual := GetExchangeFormatCurrencySeperator("Yobit")
|
||||
|
||||
if expected != actual {
|
||||
t.Errorf("Test failed - TestGetExchangeFormatCurrencySeperator expected %v != actual %v",
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
# GoCryptoTrader package Wex
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
|
||||
[](https://travis-ci.org/thrasher-/gocryptotrader)
|
||||
[](https://github.com/thrasher-/gocryptotrader/blob/master/LICENSE)
|
||||
[](https://godoc.org/github.com/thrasher-/gocryptotrader/exchanges/wex)
|
||||
[](http://codecov.io/github/thrasher-/gocryptotrader?branch=master)
|
||||
[](https://goreportcard.com/report/github.com/thrasher-/gocryptotrader)
|
||||
|
||||
|
||||
This wex package is part of the GoCryptoTrader codebase.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://gocryptotrader.herokuapp.com/)
|
||||
|
||||
## Wex Exchange
|
||||
|
||||
### Current Features
|
||||
|
||||
+ REST Support
|
||||
|
||||
### How to enable
|
||||
|
||||
+ [Enable via configuration](https://github.com/thrasher-/gocryptotrader/tree/master/config#enable-exchange-via-config-example)
|
||||
|
||||
+ Individual package example below:
|
||||
|
||||
```go
|
||||
// Exchanges will be abstracted out in further updates and examples will be
|
||||
// supplied then
|
||||
```
|
||||
|
||||
### How to do REST public/private calls
|
||||
|
||||
+ If enabled via "configuration".json file the exchange will be added to the
|
||||
IBotExchange array in the ```go var bot Bot``` and you will only be able to use
|
||||
the wrapper interface functions for accessing exchange data. View routines.go
|
||||
for an example of integration usage with GoCryptoTrader. Rudimentary example
|
||||
below:
|
||||
|
||||
main.go
|
||||
```go
|
||||
var w exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Wex" {
|
||||
y = bot.exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := w.GetTickerPrice()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := w.GetOrderbookEx()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - wrapper functions - make sure your APIKEY and APISECRET are
|
||||
// set and AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := w.GetAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
+ If enabled via individually importing package, rudimentary example below:
|
||||
|
||||
```go
|
||||
// Public calls
|
||||
|
||||
// Fetches current ticker information
|
||||
ticker, err := w.GetTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := w.GetDepth()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Private calls - make sure your APIKEY and APISECRET are set and
|
||||
// AuthenticatedAPISupport is set to true
|
||||
|
||||
// Fetches current account information
|
||||
accountInfo, err := w.GetAccountInfo()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Submits an order and the exchange and returns its tradeID
|
||||
tradeID, err := w.Trade("BTCUSD", "MARKET", 1, 2)
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
```
|
||||
|
||||
### Please click GoDocs chevron above to view current GoDoc information for this package
|
||||
|
||||
## Contribution
|
||||
|
||||
Please feel free to submit any pull requests or suggest any desired features to be added.
|
||||
|
||||
When submitting a PR, please abide by our coding guidelines:
|
||||
|
||||
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||
+ Code must adhere to our [coding style](https://github.com/thrasher-/gocryptotrader/blob/master/doc/coding_style.md).
|
||||
+ Pull requests need to be based on and opened against the `master` branch.
|
||||
|
||||
## Donations
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
|
||||
|
||||
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
|
||||
|
||||
***1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB***
|
||||
|
||||
@@ -1,457 +0,0 @@
|
||||
package wex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency/symbol"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
const (
|
||||
wexAPIPublicURL = "https://wex1.in/api"
|
||||
wexAPIPrivateURL = "https://wex1.in/tapi"
|
||||
wexAPIPublicVersion = "3"
|
||||
wexAPIPrivateVersion = "1"
|
||||
wexInfo = "info"
|
||||
wexTicker = "ticker"
|
||||
wexDepth = "depth"
|
||||
wexTrades = "trades"
|
||||
wexAccountInfo = "getInfo"
|
||||
wexTrade = "Trade"
|
||||
wexActiveOrders = "ActiveOrders"
|
||||
wexOrderInfo = "OrderInfo"
|
||||
wexCancelOrder = "CancelOrder"
|
||||
wexTradeHistory = "TradeHistory"
|
||||
wexTransactionHistory = "TransHistory"
|
||||
wexWithdrawCoin = "WithdrawCoin"
|
||||
wexCoinDepositAddress = "CoinDepositAddress"
|
||||
wexCreateCoupon = "CreateCoupon"
|
||||
wexRedeemCoupon = "RedeemCoupon"
|
||||
|
||||
wexAuthRate = 0
|
||||
wexUnauthRate = 0
|
||||
)
|
||||
|
||||
// WEX is the overarching type across the wex package
|
||||
type WEX struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
}
|
||||
|
||||
// SetDefaults sets current default value for WEX
|
||||
func (w *WEX) SetDefaults() {
|
||||
w.Name = "WEX"
|
||||
w.Enabled = false
|
||||
w.Fee = 0.2
|
||||
w.Verbose = false
|
||||
w.RESTPollingDelay = 10
|
||||
w.Ticker = make(map[string]Ticker)
|
||||
w.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission |
|
||||
exchange.NoFiatWithdrawals
|
||||
w.RequestCurrencyPairFormat.Delimiter = "_"
|
||||
w.RequestCurrencyPairFormat.Uppercase = false
|
||||
w.RequestCurrencyPairFormat.Separator = "-"
|
||||
w.ConfigCurrencyPairFormat.Delimiter = "_"
|
||||
w.ConfigCurrencyPairFormat.Uppercase = true
|
||||
w.AssetTypes = []string{ticker.Spot}
|
||||
w.SupportsAutoPairUpdating = true
|
||||
w.SupportsRESTTickerBatching = true
|
||||
w.Requester = request.New(w.Name,
|
||||
request.NewRateLimit(time.Second, wexAuthRate),
|
||||
request.NewRateLimit(time.Second, wexUnauthRate),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
w.APIUrlDefault = wexAPIPublicURL
|
||||
w.APIUrl = w.APIUrlDefault
|
||||
w.APIUrlSecondaryDefault = wexAPIPrivateURL
|
||||
w.APIUrlSecondary = w.APIUrlSecondaryDefault
|
||||
w.WebsocketInit()
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for WEX
|
||||
func (w *WEX) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
w.SetEnabled(false)
|
||||
} else {
|
||||
w.Enabled = true
|
||||
w.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
w.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
w.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
w.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
w.RESTPollingDelay = exch.RESTPollingDelay
|
||||
w.Verbose = exch.Verbose
|
||||
w.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
w.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
w.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := w.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = w.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = w.SetAutoPairDefaults()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = w.SetAPIURL(exch)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = w.SetClientProxyAddress(exch.ProxyAddress)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetTradablePairs returns a list of available pairs from the exchange
|
||||
func (w *WEX) GetTradablePairs() ([]string, error) {
|
||||
result, err := w.GetInfo()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var currencies []string
|
||||
for x := range result.Pairs {
|
||||
currencies = append(currencies, common.StringToUpper(x))
|
||||
}
|
||||
|
||||
return currencies, nil
|
||||
}
|
||||
|
||||
// GetInfo returns the WEX info
|
||||
func (w *WEX) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
req := fmt.Sprintf("%s/%s/%s/", w.APIUrl, wexAPIPublicVersion, wexInfo)
|
||||
|
||||
return resp, w.SendHTTPRequest(req, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns a ticker for a specific currency
|
||||
func (w *WEX) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
type Response struct {
|
||||
Data map[string]Ticker
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", w.APIUrl, wexAPIPublicVersion, wexTicker, symbol)
|
||||
|
||||
return response.Data, w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth returns the depth for a specific currency
|
||||
func (w *WEX) GetDepth(symbol string) (Orderbook, error) {
|
||||
type Response struct {
|
||||
Data map[string]Orderbook
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", w.APIUrl, wexAPIPublicVersion, wexDepth, symbol)
|
||||
|
||||
return response.Data[symbol], w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns the trades for a specific currency
|
||||
func (w *WEX) GetTrades(symbol string) ([]Trades, error) {
|
||||
type Response struct {
|
||||
Data map[string][]Trades
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", w.APIUrl, wexAPIPublicVersion, wexTrades, symbol)
|
||||
|
||||
return response.Data[symbol], w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInformation returns a users account info
|
||||
func (w *WEX) GetAccountInformation() (AccountInfo, error) {
|
||||
var result AccountInfo
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexAccountInfo, url.Values{}, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetOpenOrders returns the active orders for a specific currency
|
||||
func (w *WEX) GetOpenOrders(pair string) (map[string]ActiveOrders, error) {
|
||||
req := url.Values{}
|
||||
req.Add("pair", pair)
|
||||
|
||||
var result map[string]ActiveOrders
|
||||
|
||||
return result, w.SendAuthenticatedHTTPRequest(wexActiveOrders, req, &result)
|
||||
}
|
||||
|
||||
// GetOrderInformation returns the order info for a specific order ID
|
||||
func (w *WEX) GetOrderInformation(OrderID int64) (map[string]OrderInfo, error) {
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
var result map[string]OrderInfo
|
||||
|
||||
return result, w.SendAuthenticatedHTTPRequest(wexOrderInfo, req, &result)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels an order for a specific order ID
|
||||
func (w *WEX) CancelExistingOrder(OrderID int64) (bool, error) {
|
||||
req := url.Values{}
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
var result CancelOrder
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCancelOrder, req, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return false, errors.New(result.Error)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Trade places an order and returns the order ID if successful or an error
|
||||
func (w *WEX) 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))
|
||||
|
||||
var result Trade
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexTrade, req, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return 0, errors.New(result.Error)
|
||||
}
|
||||
return int64(result.OrderID), nil
|
||||
}
|
||||
|
||||
// GetTransactionHistory returns the transaction history
|
||||
func (w *WEX) GetTransactionHistory(TIDFrom, Count, TIDEnd int64, order, since, end string) (map[string]TransHistory, 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)
|
||||
|
||||
var result map[string]TransHistory
|
||||
|
||||
return result,
|
||||
w.SendAuthenticatedHTTPRequest(wexTransactionHistory, req, &result)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns the trade history
|
||||
func (w *WEX) GetTradeHistory(TIDFrom, Count, TIDEnd, since, end int64, order, 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", strconv.FormatInt(since, 10))
|
||||
req.Add("end", strconv.FormatInt(end, 10))
|
||||
req.Add("pair", pair)
|
||||
|
||||
result := TradeHistoryResponse{}
|
||||
|
||||
return result.Data, w.SendAuthenticatedHTTPRequest(wexTradeHistory, req, &result)
|
||||
}
|
||||
|
||||
// WithdrawCoins withdraws coins for a specific coin
|
||||
func (w *WEX) WithdrawCoins(coin string, amount float64, address string) (WithdrawCoins, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coinName", coin)
|
||||
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
|
||||
req.Add("address", address)
|
||||
|
||||
var result WithdrawCoins
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexWithdrawCoin, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CoinDepositAddress returns the deposit address for a specific currency
|
||||
func (w *WEX) CoinDepositAddress(coin string) (string, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coinName", coin)
|
||||
|
||||
var result CoinDepositAddress
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCoinDepositAddress, req, &result)
|
||||
if err != nil {
|
||||
return result.Address, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result.Address, errors.New(result.Error)
|
||||
}
|
||||
return result.Address, nil
|
||||
}
|
||||
|
||||
// CreateCoupon creates an exchange coupon for a sepcific currency
|
||||
func (w *WEX) 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
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCreateCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// RedeemCoupon redeems an exchange coupon
|
||||
func (w *WEX) RedeemCoupon(coupon string) (RedeemCoupon, error) {
|
||||
req := url.Values{}
|
||||
req.Add("coupon", coupon)
|
||||
|
||||
var result RedeemCoupon
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexRedeemCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (w *WEX) SendHTTPRequest(path string, result interface{}) error {
|
||||
return w.SendPayload(http.MethodGet, path, nil, nil, result, false, w.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to WEX
|
||||
func (w *WEX) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) {
|
||||
if !w.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
|
||||
w.Name)
|
||||
}
|
||||
|
||||
if w.Nonce.Get() == 0 {
|
||||
w.Nonce.Set(time.Now().Unix())
|
||||
} else {
|
||||
w.Nonce.Inc()
|
||||
}
|
||||
values.Set("nonce", w.Nonce.String())
|
||||
values.Set("method", method)
|
||||
|
||||
encoded := values.Encode()
|
||||
hmac := common.GetHMAC(common.HashSHA512, []byte(encoded), []byte(w.APISecret))
|
||||
|
||||
if w.Verbose {
|
||||
log.Debugf("Sending POST request to %s calling method %s with params %s\n",
|
||||
w.APIUrlSecondary,
|
||||
method,
|
||||
encoded)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Key"] = w.APIKey
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
return w.SendPayload(http.MethodPost,
|
||||
w.APIUrlSecondary,
|
||||
headers,
|
||||
strings.NewReader(encoded),
|
||||
result,
|
||||
true,
|
||||
w.Verbose)
|
||||
}
|
||||
|
||||
// GetFee returns an estimate of fee based on type of transaction
|
||||
func (w *WEX) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
|
||||
var fee float64
|
||||
switch feeBuilder.FeeType {
|
||||
case exchange.CryptocurrencyTradeFee:
|
||||
info, err := w.GetInfo()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
currency := feeBuilder.FirstCurrency + feeBuilder.Delimiter + feeBuilder.SecondCurrency
|
||||
fee = calculateTradingFee(info, currency, feeBuilder.PurchasePrice, feeBuilder.Amount)
|
||||
case exchange.CryptocurrencyWithdrawalFee:
|
||||
fee = getWithdrawalFee(feeBuilder.FirstCurrency)
|
||||
case exchange.InternationalBankDepositFee:
|
||||
fee = getInternationalBankDepositFee(feeBuilder.CurrencyItem, feeBuilder.Amount, feeBuilder.BankTransactionType)
|
||||
}
|
||||
if fee < 0 {
|
||||
fee = 0
|
||||
}
|
||||
|
||||
return fee, nil
|
||||
}
|
||||
|
||||
func calculateTradingFee(info Info, currency string, purchasePrice, amount float64) (fee float64) {
|
||||
fee = info.Pairs[common.StringToLower(currency)].Fee
|
||||
return (fee / 100) * amount * purchasePrice
|
||||
}
|
||||
|
||||
func getWithdrawalFee(currency string) float64 {
|
||||
return WithdrawalFees[currency]
|
||||
}
|
||||
|
||||
func getInternationalBankDepositFee(currency string, amount float64, bankTransactionType exchange.InternationalBankTransactionType) float64 {
|
||||
var fee float64
|
||||
|
||||
switch bankTransactionType {
|
||||
case exchange.WireTransfer:
|
||||
fallthrough
|
||||
case exchange.WesternUnion:
|
||||
switch currency {
|
||||
case symbol.USD:
|
||||
fee = 0.065 * amount
|
||||
}
|
||||
case exchange.MoneyGram:
|
||||
switch currency {
|
||||
case symbol.USD:
|
||||
fee = 0.065 * amount
|
||||
}
|
||||
case exchange.Contact:
|
||||
switch currency {
|
||||
case symbol.USD:
|
||||
fee = 0.065 * amount
|
||||
}
|
||||
}
|
||||
return fee
|
||||
}
|
||||
@@ -1,514 +0,0 @@
|
||||
package wex
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/currency/symbol"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
var w WEX
|
||||
|
||||
// Please supply your own keys for better unit testing
|
||||
const (
|
||||
apiKey = ""
|
||||
apiSecret = ""
|
||||
canManipulateRealOrders = false
|
||||
isWexEncounteringIssues = true
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
wexConfig := config.GetConfig()
|
||||
wexConfig.LoadConfig("../../testdata/configtest.json")
|
||||
conf, err := wexConfig.GetExchangeConfig("WEX")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - WEX init error")
|
||||
}
|
||||
conf.APIKey = apiKey
|
||||
conf.APISecret = apiSecret
|
||||
conf.AuthenticatedAPISupport = true
|
||||
|
||||
w.Setup(conf)
|
||||
}
|
||||
|
||||
func TestGetTradablePairs(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetTradablePairs()
|
||||
if err != nil {
|
||||
t.Errorf("Test failed. GetTradablePairs err: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetInfo()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetInfo() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetTicker("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetDepth("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetDepth() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetTrades("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTrades() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetAccountInfo() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func GetOpenOrders(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetOpenOrders("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOpenOrders() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetOrderInfo(6196974)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOrderInfo() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelExistingOrder(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.CancelExistingOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelExistingOrder() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrade(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.Trade("", "buy", 0, 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Trade() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTransactionHistory(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.GetTransactionHistory(0, 0, 0, "", "", "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTransactionHistory() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawCoins(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.WithdrawCoins("", 0, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoins() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCoinDepositAddress(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.CoinDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoins() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCoupon(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.CreateCoupon("bla", 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CreateCoupon() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRedeemCoupon(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
_, err := w.RedeemCoupon("bla")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - RedeemCoupon() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func setFeeBuilder() exchange.FeeBuilder {
|
||||
return exchange.FeeBuilder{
|
||||
Amount: 1,
|
||||
Delimiter: "_",
|
||||
FeeType: exchange.CryptocurrencyTradeFee,
|
||||
FirstCurrency: symbol.LTC,
|
||||
SecondCurrency: symbol.BTC,
|
||||
IsMaker: false,
|
||||
PurchasePrice: 1,
|
||||
CurrencyItem: symbol.USD,
|
||||
BankTransactionType: exchange.WireTransfer,
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
var feeBuilder = setFeeBuilder()
|
||||
|
||||
// CryptocurrencyTradeFee Basic
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
|
||||
t.Error(err)
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.002), resp)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee High quantity
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.Amount = 1000
|
||||
feeBuilder.PurchasePrice = 1000
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(2000) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(2000), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee IsMaker
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.IsMaker = true
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0.002) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.002), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyTradeFee Negative purchase price
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.PurchasePrice = -1000
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
// CryptocurrencyWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0.001) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.001), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CryptocurrencyWithdrawalFee Invalid currency
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FirstCurrency = "hello"
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// CyptocurrencyDepositFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CyptocurrencyDepositFee
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// InternationalBankDepositFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.InternationalBankDepositFee
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0.065) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0.065), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// InternationalBankWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.InternationalBankWithdrawalFee
|
||||
feeBuilder.CurrencyItem = symbol.USD
|
||||
if resp, err := w.GetFee(feeBuilder); resp != float64(0) || err != nil {
|
||||
t.Errorf("Test Failed - GetFee() error. Expected: %f, Received: %f", float64(0), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFormatWithdrawPermissions(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
w.SetDefaults()
|
||||
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.NoFiatWithdrawalsText
|
||||
|
||||
withdrawPermissions := w.FormatWithdrawPermissions()
|
||||
|
||||
if withdrawPermissions != expectedResult {
|
||||
t.Errorf("Expected: %s, Received: %s", expectedResult, withdrawPermissions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = exchange.GetOrdersRequest{
|
||||
OrderType: exchange.AnyOrderType,
|
||||
Currencies: []pair.CurrencyPair{pair.NewCurrencyPair(symbol.LTC, symbol.BTC)},
|
||||
}
|
||||
|
||||
_, err := w.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")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
var getOrdersRequest = exchange.GetOrdersRequest{
|
||||
OrderType: exchange.AnyOrderType,
|
||||
Currencies: []pair.CurrencyPair{pair.NewCurrencyPair(symbol.LTC, symbol.BTC)},
|
||||
StartTicks: time.Unix(0, 0),
|
||||
EndTicks: time.Unix(math.MaxInt64, 0),
|
||||
}
|
||||
|
||||
_, err := w.GetOrderHistory(getOrdersRequest)
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not get order history: %s", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
// Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them
|
||||
// ----------------------------------------------------------------------------------------------------------------------------
|
||||
func areTestAPIKeysSet() bool {
|
||||
if w.APIKey != "" && w.APIKey != "Key" &&
|
||||
w.APISecret != "" && w.APISecret != "Secret" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func TestSubmitOrder(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var pair = pair.CurrencyPair{
|
||||
Delimiter: "_",
|
||||
FirstCurrency: symbol.BTC,
|
||||
SecondCurrency: symbol.USD,
|
||||
}
|
||||
response, err := w.SubmitOrder(pair, exchange.BuyOrderSide, exchange.MarketOrderType, 1, 10, "hi")
|
||||
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
|
||||
t.Errorf("Order failed to be placed: %v", err)
|
||||
} else if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelExchangeOrder(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := pair.NewCurrencyPair(symbol.LTC, symbol.BTC)
|
||||
|
||||
var orderCancellation = exchange.OrderCancellation{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
AccountID: "1",
|
||||
CurrencyPair: currencyPair,
|
||||
}
|
||||
|
||||
err := w.CancelOrder(orderCancellation)
|
||||
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not cancel orders: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCancelAllExchangeOrders(t *testing.T) {
|
||||
if isWexEncounteringIssues {
|
||||
t.Skip()
|
||||
}
|
||||
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
currencyPair := pair.NewCurrencyPair(symbol.LTC, symbol.BTC)
|
||||
|
||||
var orderCancellation = exchange.OrderCancellation{
|
||||
OrderID: "1",
|
||||
WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
AccountID: "1",
|
||||
CurrencyPair: currencyPair,
|
||||
}
|
||||
|
||||
resp, err := w.CancelAllOrders(orderCancellation)
|
||||
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Could not cancel orders: %v", err)
|
||||
}
|
||||
|
||||
if len(resp.OrderStatus) > 0 {
|
||||
t.Errorf("%v orders failed to cancel", len(resp.OrderStatus))
|
||||
}
|
||||
}
|
||||
|
||||
func TestModifyOrder(t *testing.T) {
|
||||
_, err := w.ModifyOrder(exchange.ModifyOrder{})
|
||||
if err == nil {
|
||||
t.Error("Test failed - ModifyOrder() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
var withdrawCryptoRequest = exchange.WithdrawRequest{
|
||||
Amount: 100,
|
||||
Currency: symbol.LTC,
|
||||
Address: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB",
|
||||
Description: "WITHDRAW IT ALL",
|
||||
}
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
_, err := w.WithdrawCryptocurrencyFunds(withdrawCryptoRequest)
|
||||
if !areTestAPIKeysSet() && err == nil {
|
||||
t.Error("Expecting an error when no keys are set")
|
||||
}
|
||||
if areTestAPIKeysSet() && err != nil {
|
||||
t.Errorf("Withdraw failed to be placed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawFiat(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var withdrawFiatRequest = exchange.WithdrawRequest{}
|
||||
|
||||
_, err := w.WithdrawFiatFunds(withdrawFiatRequest)
|
||||
if err != common.ErrFunctionNotSupported {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWithdrawInternationalBank(t *testing.T) {
|
||||
w.SetDefaults()
|
||||
TestSetup(t)
|
||||
|
||||
if areTestAPIKeysSet() && !canManipulateRealOrders {
|
||||
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
|
||||
}
|
||||
|
||||
var withdrawFiatRequest = exchange.WithdrawRequest{}
|
||||
|
||||
_, err := w.WithdrawFiatFundsToInternationalBank(withdrawFiatRequest)
|
||||
if err != common.ErrFunctionNotSupported {
|
||||
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
|
||||
}
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
package wex
|
||||
|
||||
import "github.com/thrasher-/gocryptotrader/currency/symbol"
|
||||
|
||||
// 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
|
||||
Low float64
|
||||
Avg float64
|
||||
Vol float64
|
||||
VolumeCurrent float64 `json:"vol_cur"`
|
||||
Last float64
|
||||
Buy float64
|
||||
Sell float64
|
||||
Updated int64
|
||||
}
|
||||
|
||||
// Orderbook stores the asks and bids orderbook information
|
||||
type Orderbook struct {
|
||||
Asks [][]float64 `json:"asks"`
|
||||
Bids [][]float64 `json:"bids"`
|
||||
}
|
||||
|
||||
// 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:"sell"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"time_created"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// Pair holds pair information
|
||||
type Pair struct {
|
||||
DecimalPlaces int `json:"decimal_places"`
|
||||
MinPrice float64 `json:"min_price"`
|
||||
MaxPrice float64 `json:"max_price"`
|
||||
MinAmount float64 `json:"min_amount"`
|
||||
Hidden int `json:"hidden"`
|
||||
Fee float64 `json:"fee"`
|
||||
}
|
||||
|
||||
// AccountInfo stores the account information for a user
|
||||
type AccountInfo struct {
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
OpenOrders int `json:"open_orders"`
|
||||
Rights struct {
|
||||
Info int `json:"info"`
|
||||
Trade int `json:"trade"`
|
||||
Withdraw int `json:"withdraw"`
|
||||
} `json:"rights"`
|
||||
ServerTime float64 `json:"server_time"`
|
||||
TransactionCount int `json:"transaction_count"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// OrderInfo stores order information
|
||||
type OrderInfo struct {
|
||||
Pair string `json:"pair"`
|
||||
Type string `json:"sell"`
|
||||
StartAmount float64 `json:"start_amount"`
|
||||
Amount float64 `json:"amount"`
|
||||
Rate float64 `json:"rate"`
|
||||
TimestampCreated float64 `json:"time_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"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// 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"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// TransHistory stores transaction history
|
||||
type TransHistory struct {
|
||||
Type int `json:"type"`
|
||||
Amount float64 `json:"amount"`
|
||||
Currency string `json:"currency"`
|
||||
Description string `json:"desc"`
|
||||
Status int `json:"status"`
|
||||
Timestamp float64 `json:"timestamp"`
|
||||
}
|
||||
|
||||
//TradeHistoryResponse returns all your trade history
|
||||
type TradeHistoryResponse struct {
|
||||
Success int64 `json:"success"`
|
||||
Data map[string]TradeHistory `json:"return,omitempty"`
|
||||
}
|
||||
|
||||
// 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 CoinDepositAddress struct {
|
||||
Address string `json:"address"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawCoins stores information for a withdrawcoins request
|
||||
type WithdrawCoins struct {
|
||||
TID int64 `json:"tId"`
|
||||
AmountSent float64 `json:"amountSent"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// CreateCoupon stores information coupon information
|
||||
type CreateCoupon struct {
|
||||
Coupon string `json:"coupon"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// RedeemCoupon stores redeem coupon information
|
||||
type RedeemCoupon struct {
|
||||
CouponAmount float64 `json:"couponAmount,string"`
|
||||
CouponCurrency string `json:"couponCurrency"`
|
||||
TransID int64 `json:"transID"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawalFees the large list of predefined withdrawal fees
|
||||
// Prone to change, using highest value
|
||||
var WithdrawalFees = map[string]float64{
|
||||
symbol.BTC: 0.0004,
|
||||
symbol.LTC: 0.001,
|
||||
symbol.NMC: 0.1,
|
||||
symbol.NVC: 0.1,
|
||||
symbol.PPC: 0.1,
|
||||
symbol.DSH: 0.001,
|
||||
symbol.ETH: 0.003,
|
||||
symbol.BCH: 0.001,
|
||||
symbol.ZEC: 0.001,
|
||||
symbol.USDT: 10,
|
||||
symbol.XMR: 0.01,
|
||||
}
|
||||
@@ -1,351 +0,0 @@
|
||||
package wex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Start starts the WEX go routine
|
||||
func (w *WEX) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
w.Run()
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// Run implements the WEX wrapper
|
||||
func (w *WEX) Run() {
|
||||
if w.Verbose {
|
||||
log.Debugf("%s Websocket: %s.", w.GetName(), common.IsEnabled(w.Websocket.IsEnabled()))
|
||||
log.Debugf("%s polling delay: %ds.\n", w.GetName(), w.RESTPollingDelay)
|
||||
log.Debugf("%s %d currencies enabled: %s.\n", w.GetName(), len(w.EnabledPairs), w.EnabledPairs)
|
||||
}
|
||||
|
||||
exchangeProducts, err := w.GetTradablePairs()
|
||||
if err != nil {
|
||||
log.Errorf("%s Failed to get available symbols.\n", w.GetName())
|
||||
} else {
|
||||
forceUpgrade := false
|
||||
if !common.StringDataContains(w.EnabledPairs, "_") || !common.StringDataContains(w.AvailablePairs, "_") {
|
||||
forceUpgrade = true
|
||||
}
|
||||
|
||||
if forceUpgrade {
|
||||
enabledPairs := []string{"BTC_USD", "LTC_USD", "LTC_BTC", "ETH_USD"}
|
||||
log.Warn("Enabled pairs for WEX reset due to config upgrade, please enable the ones you would like again.")
|
||||
|
||||
err = w.UpdateCurrencies(enabledPairs, true, true)
|
||||
if err != nil {
|
||||
log.Errorf("%s Failed to get config.\n", w.GetName())
|
||||
}
|
||||
}
|
||||
err = w.UpdateCurrencies(exchangeProducts, false, forceUpgrade)
|
||||
if err != nil {
|
||||
log.Errorf("%s Failed to get config.\n", w.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (w *WEX) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
pairsCollated, err := exchange.GetAndFormatExchangeCurrencies(w.Name, w.GetEnabledCurrencies())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
result, err := w.GetTicker(pairsCollated.String())
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
|
||||
for _, x := range w.GetEnabledCurrencies() {
|
||||
currency := exchange.FormatExchangeCurrency(w.Name, x).Lower().String()
|
||||
var tp ticker.Price
|
||||
tp.Pair = x
|
||||
tp.Last = result[currency].Last
|
||||
tp.Ask = result[currency].Sell
|
||||
tp.Bid = result[currency].Buy
|
||||
tp.Last = result[currency].Last
|
||||
tp.Low = result[currency].Low
|
||||
tp.Volume = result[currency].VolumeCurrent
|
||||
ticker.ProcessTicker(w.Name, x, tp, assetType)
|
||||
}
|
||||
return ticker.GetTicker(w.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func (w *WEX) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tick, err := ticker.GetTicker(w.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return w.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tick, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns the orderbook for a currency pair
|
||||
func (w *WEX) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook(w.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return w.UpdateOrderbook(p, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (w *WEX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := w.GetDepth(exchange.FormatExchangeCurrency(w.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(w.GetName(), p, orderBook, assetType)
|
||||
return orderbook.GetOrderbook(w.Name, p, assetType)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
// WEX exchange
|
||||
func (w *WEX) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
response.Exchange = w.GetName()
|
||||
accountBalance, err := w.GetAccountInformation()
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
var currencies []exchange.AccountCurrencyInfo
|
||||
for x, y := range accountBalance.Funds {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = common.StringToUpper(x)
|
||||
exchangeCurrency.TotalValue = y
|
||||
exchangeCurrency.Hold = 0
|
||||
currencies = append(currencies, exchangeCurrency)
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, exchange.Account{
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (w *WEX) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func (w *WEX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
var resp []exchange.TradeHistory
|
||||
|
||||
return resp, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// SubmitOrder submits a new order
|
||||
func (w *WEX) SubmitOrder(p pair.CurrencyPair, side exchange.OrderSide, orderType exchange.OrderType, amount, price float64, _ string) (exchange.SubmitOrderResponse, error) {
|
||||
var submitOrderResponse exchange.SubmitOrderResponse
|
||||
|
||||
if orderType != exchange.LimitOrderType {
|
||||
return submitOrderResponse, errors.New("only limit orders are allowed")
|
||||
}
|
||||
|
||||
response, err := w.Trade(p.Pair().String(), side.ToString(), amount, price)
|
||||
if response > 0 {
|
||||
submitOrderResponse.OrderID = fmt.Sprintf("%v", response)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
submitOrderResponse.IsOrderPlaced = true
|
||||
}
|
||||
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
|
||||
// ModifyOrder will allow of changing orderbook placement and limit to
|
||||
// market conversion
|
||||
func (w *WEX) ModifyOrder(action exchange.ModifyOrder) (string, error) {
|
||||
return "", common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (w *WEX) CancelOrder(order exchange.OrderCancellation) error {
|
||||
orderIDInt, err := strconv.ParseInt(order.OrderID, 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = w.CancelExistingOrder(orderIDInt)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// CancelAllOrders cancels all orders associated with a currency pair
|
||||
func (w *WEX) CancelAllOrders(_ exchange.OrderCancellation) (exchange.CancelAllOrdersResponse, error) {
|
||||
cancelAllOrdersResponse := exchange.CancelAllOrdersResponse{
|
||||
OrderStatus: make(map[string]string),
|
||||
}
|
||||
var allActiveOrders map[string]ActiveOrders
|
||||
|
||||
for _, pair := range w.EnabledPairs {
|
||||
activeOrders, err := w.GetOpenOrders(pair)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
for k, v := range activeOrders {
|
||||
allActiveOrders[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
for k := range allActiveOrders {
|
||||
orderIDInt, err := strconv.ParseInt(k, 10, 64)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
_, err = w.CancelExistingOrder(orderIDInt)
|
||||
if err != nil {
|
||||
cancelAllOrdersResponse.OrderStatus[k] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
return cancelAllOrdersResponse, nil
|
||||
}
|
||||
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (w *WEX) GetOrderInfo(orderID int64) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
func (w *WEX) GetDepositAddress(cryptocurrency pair.CurrencyItem, accountID string) (string, error) {
|
||||
return "", common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
|
||||
// submitted
|
||||
func (w *WEX) WithdrawCryptocurrencyFunds(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
resp, err := w.WithdrawCoins(withdrawRequest.Currency.String(), withdrawRequest.Amount, withdrawRequest.Address)
|
||||
return fmt.Sprintf("%v", resp.TID), err
|
||||
}
|
||||
|
||||
// WithdrawFiatFunds returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (w *WEX) WithdrawFiatFunds(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
|
||||
// withdrawal is submitted
|
||||
func (w *WEX) WithdrawFiatFundsToInternationalBank(withdrawRequest exchange.WithdrawRequest) (string, error) {
|
||||
return "", common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetWebsocket returns a pointer to the exchange websocket
|
||||
func (w *WEX) GetWebsocket() (*exchange.Websocket, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// GetFeeByType returns an estimate of fee based on type of transaction
|
||||
func (w *WEX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
|
||||
return w.GetFee(feeBuilder)
|
||||
}
|
||||
|
||||
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
|
||||
func (w *WEX) GetWithdrawCapabilities() uint32 {
|
||||
return w.GetWithdrawPermissions()
|
||||
}
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (w *WEX) GetActiveOrders(getOrdersRequest exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
var orders []exchange.OrderDetail
|
||||
for _, currency := range getOrdersRequest.Currencies {
|
||||
resp, err := w.GetOpenOrders(exchange.FormatExchangeCurrency(w.Name, currency).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for ID, order := range resp {
|
||||
symbol := pair.NewCurrencyPairDelimiter(order.Pair, w.ConfigCurrencyPairFormat.Delimiter)
|
||||
orderDate := time.Unix(int64(order.TimestampCreated), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(order.Type))
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: ID,
|
||||
Amount: order.Amount,
|
||||
Price: order.Rate,
|
||||
OrderSide: side,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: symbol,
|
||||
Exchange: w.Name,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
exchange.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks, getOrdersRequest.EndTicks)
|
||||
exchange.FilterOrdersBySide(&orders, getOrdersRequest.OrderSide)
|
||||
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (w *WEX) GetOrderHistory(getOrdersRequest exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
var allOrders []TradeHistory
|
||||
for _, currency := range getOrdersRequest.Currencies {
|
||||
resp, err := w.GetTradeHistory(0, 10000, math.MaxInt64, getOrdersRequest.StartTicks.Unix(), getOrdersRequest.EndTicks.Unix(), "DESC", exchange.FormatExchangeCurrency(w.Name, currency).String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, order := range resp {
|
||||
allOrders = append(allOrders, order)
|
||||
}
|
||||
}
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for _, order := range allOrders {
|
||||
symbol := pair.NewCurrencyPairDelimiter(order.Pair, w.ConfigCurrencyPairFormat.Delimiter)
|
||||
orderDate := time.Unix(int64(order.Timestamp), 0)
|
||||
side := exchange.OrderSide(strings.ToUpper(order.Type))
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: fmt.Sprintf("%v", order.OrderID),
|
||||
Amount: order.Amount,
|
||||
Price: order.Rate,
|
||||
OrderSide: side,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: symbol,
|
||||
Exchange: w.Name,
|
||||
})
|
||||
}
|
||||
|
||||
exchange.FilterOrdersBySide(&orders, getOrdersRequest.OrderSide)
|
||||
|
||||
return orders, nil
|
||||
}
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
)
|
||||
|
||||
// Start starts the WEX go routine
|
||||
// Start starts the Yobit go routine
|
||||
func (y *Yobit) Start(wg *sync.WaitGroup) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
|
||||
Reference in New Issue
Block a user