Exchange withdraw capabilities (#199)

* Initial broken commit for updating exchanges to store data on whether withdrawals can be handled completely by the API

* Changes to use base exchange method to determine withdrawal permissions using bitshifting

* Adds withdrawal capabilities for alphapoint, anx, binance, bitfinex, bitflyer, bithumb, bitmex, bitstamp, bittrex exchanges

* Adds withdraw capabilities for btcmarkets, coinbasepro, coinut, exmo, gateio, gemini, hitbtc, huobi, hadax

* Adds withdraw capabilities for itbit, kraken, lakebtc, liqui, localbitcoins, okcoin, okex, poloniex, wex, yobit, zb

* Titillating tests & Wonderful wrappers

* Fixes typo, double checks all apis and corrects permissions

* Fixes gemini test

* Fixes incorrect log placement. Removes breaks

* Addresses PR comments. Changes readable function to: FormatWithdrawPermissions, adds new function 'GetWithdrawPermissions' and 'SupportsWithdrawPermissions'. Adds three functions to interface

* Removes unnecessary config_example.json additions

* Fixes bitwise comparisons. Adds more tests to highlight expected outcomes
This commit is contained in:
Scott
2018-11-05 10:35:03 +11:00
committed by Adrian Gallagher
parent e104d29028
commit baffb46300
93 changed files with 808 additions and 39 deletions

View File

@@ -55,6 +55,7 @@ func (a *Alphapoint) SetDefaults() {
a.AssetTypes = []string{ticker.Spot}
a.SupportsAutoPairUpdating = false
a.SupportsRESTTickerBatching = false
a.APIWithdrawPermissions = exchange.WithdrawCryptoWith2FA | exchange.AutoWithdrawCryptoWithAPIPermission
a.Requester = request.New(a.Name,
request.NewRateLimit(time.Minute*10, alphapointAuthRate),
request.NewRateLimit(time.Minute*10, alphapointUnauthRate),

View File

@@ -4,6 +4,7 @@ import (
"testing"
"github.com/thrasher-/gocryptotrader/common"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
)
const (
@@ -490,3 +491,16 @@ func TestGetOrderFee(t *testing.T) {
t.Error("Test Failed - GetUserInfo() error")
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
a := &Alphapoint{}
a.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawCryptoWith2FAText
// Act
withdrawPermissions := a.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -181,3 +181,8 @@ func (a *Alphapoint) GetWebsocket() (*exchange.Websocket, error) {
func (a *Alphapoint) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return 0, errors.New("not yet implemented")
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (a *Alphapoint) GetWithdrawCapabilities() uint32 {
return a.GetWithdrawPermissions()
}

View File

@@ -31,6 +31,7 @@ const (
anxCreateAddress = "receive/create"
anxTicker = "money/ticker"
anxDepth = "money/depth/full"
anxAccount = "account"
// ANX rate limites for authenticated and unauthenticated requests
anxAuthRate = 0
@@ -56,6 +57,8 @@ func (a *ANX) SetDefaults() {
a.ConfigCurrencyPairFormat.Delimiter = "_"
a.ConfigCurrencyPairFormat.Uppercase = true
a.ConfigCurrencyPairFormat.Index = ""
a.APIWithdrawPermissions = exchange.WithdrawCryptoWithEmail | exchange.AutoWithdrawCryptoWithSetup |
exchange.WithdrawCryptoWith2FA | exchange.WithdrawFiatViaWebsiteOnly
a.AssetTypes = []string{ticker.Spot}
a.SupportsAutoPairUpdating = true
a.SupportsRESTTickerBatching = false
@@ -443,3 +446,45 @@ func getInternationalBankWithdrawalFee(currency string, amount float64) float64
//TODO, other fiat currencies require consultation with ANXPRO
return fee
}
// GetAccountInformation retrieves details including API permissions
func (a *ANX) GetAccountInformation() (AccountInformation, error) {
request := make(map[string]interface{})
var response AccountInformation
err := a.SendAuthenticatedHTTPRequest(anxOrderInfo, request, &response)
if err != nil {
return response, err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return response, errors.New(response.ResultCode)
}
return response, nil
}
// CheckAPIWithdrawPermission checks if the API key is allowed to withdraw
func (a *ANX) CheckAPIWithdrawPermission() (bool, error) {
accountInfo, err := a.GetAccountInformation()
if err != nil {
return false, err
}
var apiAllowsWithdraw bool
for _, a := range accountInfo.Rights {
if a == "withdraw" {
apiAllowsWithdraw = true
}
}
if !apiAllowsWithdraw {
log.Printf("API key is missing withdrawal permissions")
}
return apiAllowsWithdraw, nil
}

View File

@@ -207,3 +207,16 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
a.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawCryptoWith2FAText + " & " +
exchange.WithdrawCryptoWithEmailText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := a.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -57,6 +57,29 @@ type CurrencyPair struct {
SimpleTradeEnabled bool `json:"simpleTradeEnabled"`
}
// AccountInformation Used by Get account information
// Retrieves details of the account and api's
type AccountInformation struct {
UserUUID string `json:"userUuid"`
Rights []string `json:"Rights"`
ResultCode string `json:"resultCode"`
Wallets struct {
Balance Amount `json:"Balance"`
AvailableBalance Amount `json:"Available_Balance"`
DailyWithdrawalLimit Amount `json:"Daily_Withdrawal_Limit"`
MaxWithdraw Amount `json:"Max_Withdraw"`
}
}
// Amount basic storage of wallet details
type Amount struct {
DisplayShort string `json:"displayShort"`
ValueInt int64 `json:"valueInt"`
Currency string `json:"currency"`
Display string `json:"display"`
Value float64 `json:"value"`
}
// CurrencyPairs stores currency pair info
type CurrencyPairs map[string]CurrencyPair

View File

@@ -254,3 +254,8 @@ func (a *ANX) GetWebsocket() (*exchange.Websocket, error) {
func (a *ANX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return a.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (a *ANX) GetWithdrawCapabilities() uint32 {
return a.GetWithdrawPermissions()
}

View File

@@ -69,6 +69,7 @@ func (b *Binance) SetDefaults() {
b.AssetTypes = []string{ticker.Spot}
b.SupportsAutoPairUpdating = true
b.SupportsRESTTickerBatching = true
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
b.SetValues()
b.Requester = request.New(b.Name,
request.NewRateLimit(time.Second, binanceAuthRate),

View File

@@ -316,3 +316,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -199,3 +199,8 @@ func (b *Binance) GetWebsocket() (*exchange.Websocket, error) {
func (b *Binance) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Binance) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -93,6 +93,7 @@ func (b *Bitfinex) SetDefaults() {
b.Verbose = false
b.RESTPollingDelay = 10
b.WebsocketSubdChannels = make(map[int]WebsocketChanInfo)
b.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission | exchange.AutoWithdrawFiatWithAPIPermission
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -706,3 +706,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.AutoWithdrawFiatWithAPIPermissionText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -231,3 +231,8 @@ func (b *Bitfinex) GetWebsocket() (*exchange.Websocket, error) {
func (b *Bitfinex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bitfinex) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -81,6 +81,7 @@ func (b *Bitflyer) SetDefaults() {
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.WithdrawCryptoViaWebsiteOnly | exchange.AutoWithdrawFiat
b.RequestCurrencyPairFormat.Delimiter = "_"
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = "_"

View File

@@ -183,7 +183,6 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
@@ -235,3 +234,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawFiatText + " & " + exchange.WithdrawCryptoViaWebsiteOnlyText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -206,3 +206,8 @@ func (b *Bitflyer) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cu
func (b *Bitflyer) GetWebsocket() (*exchange.Websocket, error) {
return nil, errors.New("not yet implemented")
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bitflyer) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -62,6 +62,7 @@ func (b *Bithumb) SetDefaults() {
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.AutoWithdrawFiat
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -219,7 +219,6 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
@@ -270,3 +269,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.AutoWithdrawFiatText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -198,3 +198,8 @@ func (b *Bithumb) GetWebsocket() (*exchange.Websocket, error) {
func (b *Bithumb) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bithumb) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -114,6 +114,7 @@ func (b *Bitmex) SetDefaults() {
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission | exchange.WithdrawCryptoWithEmail | exchange.WithdrawCryptoWith2FA
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -449,3 +449,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawCryptoWith2FAText + " & " + exchange.WithdrawCryptoWithEmailText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -202,3 +202,8 @@ func (b *Bitmex) GetWebsocket() (*exchange.Websocket, error) {
func (b *Bitmex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bitmex) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -67,6 +67,7 @@ func (b *Bitstamp) SetDefaults() {
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.AutoWithdrawFiat
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -334,3 +334,15 @@ func TestTransferAccountBalance(t *testing.T) {
t.Error("Test Failed - TransferAccountBalance() error", err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.AutoWithdrawFiatText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -218,3 +218,8 @@ func (b *Bitstamp) WithdrawFiatExchangeFundsToInternationalBank(currency pair.Cu
func (b *Bitstamp) GetWebsocket() (*exchange.Websocket, error) {
return b.Websocket, nil
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bitstamp) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -68,6 +68,7 @@ func (b *Bittrex) SetDefaults() {
b.Enabled = false
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission
b.RequestCurrencyPairFormat.Delimiter = "-"
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = "-"

View File

@@ -315,3 +315,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -228,3 +228,8 @@ func (b *Bittrex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error)
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *Bittrex) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -32,6 +32,7 @@ func (b *BTCC) SetDefaults() {
b.Fee = 0
b.Verbose = false
b.RESTPollingDelay = 10
b.APIWithdrawPermissions = exchange.NoAPIWithdrawalMethods
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""
@@ -93,8 +94,6 @@ func (b *BTCC) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns an estimate of fee based on type of transaction
func (b *BTCC) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
var fee float64

View File

@@ -156,3 +156,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.NoAPIWithdrawalMethodsText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -209,3 +209,8 @@ func (b *BTCC) GetWebsocket() (*exchange.Websocket, error) {
func (b *BTCC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *BTCC) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -58,6 +58,7 @@ func (b *BTCMarkets) SetDefaults() {
b.Verbose = false
b.RESTPollingDelay = 10
b.Ticker = make(map[string]Ticker)
b.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.AutoWithdrawFiat
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = "-"

View File

@@ -296,3 +296,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
b.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.AutoWithdrawFiatText
// Act
withdrawPermissions := b.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -260,3 +260,8 @@ func (b *BTCMarkets) GetWebsocket() (*exchange.Websocket, error) {
func (b *BTCMarkets) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (b *BTCMarkets) GetWithdrawCapabilities() uint32 {
return b.GetWithdrawPermissions()
}

View File

@@ -70,6 +70,7 @@ func (c *CoinbasePro) SetDefaults() {
c.TakerFee = 0.25
c.MakerFee = 0
c.RESTPollingDelay = 10
c.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission | exchange.AutoWithdrawFiatWithAPIPermission
c.RequestCurrencyPairFormat.Delimiter = "-"
c.RequestCurrencyPairFormat.Uppercase = true
c.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -390,3 +390,15 @@ func TestCalculateTradingFee(t *testing.T) {
t.Errorf("Test Failed - GetFee() error. Expected: %f, Recieved: %f", float64(0), resp)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
c.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.AutoWithdrawFiatWithAPIPermissionText
// Act
withdrawPermissions := c.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -196,3 +196,8 @@ func (c *CoinbasePro) GetWebsocket() (*exchange.Websocket, error) {
func (c *CoinbasePro) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return c.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (c *CoinbasePro) GetWithdrawCapabilities() uint32 {
return c.GetWithdrawPermissions()
}

View File

@@ -56,6 +56,7 @@ func (c *COINUT) SetDefaults() {
c.MakerFee = 0
c.Verbose = false
c.RESTPollingDelay = 10
c.APIWithdrawPermissions = exchange.WithdrawCryptoViaWebsiteOnly | exchange.WithdrawFiatViaWebsiteOnly
c.RequestCurrencyPairFormat.Delimiter = ""
c.RequestCurrencyPairFormat.Uppercase = true
c.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -174,3 +174,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
c.SetDefaults()
expectedResult := exchange.WithdrawCryptoViaWebsiteOnlyText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := c.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -199,3 +199,8 @@ func (c *COINUT) GetWebsocket() (*exchange.Websocket, error) {
func (c *COINUT) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return c.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (c *COINUT) GetWithdrawCapabilities() uint32 {
return c.GetWithdrawPermissions()
}

View File

@@ -6,6 +6,7 @@ import (
"log"
"net/http"
"net/url"
"strings"
"sync"
"time"
@@ -20,7 +21,6 @@ import (
const (
warningBase64DecryptSecretKeyFailed = "WARNING -- Exchange %s unable to base64 decode secret key.. Disabling Authenticated API support."
// WarningAuthenticatedRequestWithoutCredentialsSet error message for authenticated request without credentials set
WarningAuthenticatedRequestWithoutCredentialsSet = "WARNING -- Exchange %s authenticated HTTP request called but not supported due to unset/default API keys."
// ErrExchangeNotFound is a constant for an error message
@@ -83,6 +83,51 @@ type FeeBuilder struct {
Amount float64
}
// Definitions for each type of withdrawal method for a given exchange
const (
// No withdraw
NoAPIWithdrawalMethods uint32 = 0
NoAPIWithdrawalMethodsText string = "NONE, WEBSITE ONLY"
AutoWithdrawCrypto uint32 = (1 << 0)
AutoWithdrawCryptoWithAPIPermission uint32 = (1 << 1)
AutoWithdrawCryptoWithSetup uint32 = (1 << 2)
AutoWithdrawCryptoText string = "AUTO WITHDRAW CRYPTO"
AutoWithdrawCryptoWithAPIPermissionText string = "AUTO WITHDRAW CRYPTO WITH API PERMISSION"
AutoWithdrawCryptoWithSetupText string = "AUTO WITHDRAW CRYPTO WITH SETUP"
WithdrawCryptoWith2FA uint32 = (1 << 3)
WithdrawCryptoWithSMS uint32 = (1 << 4)
WithdrawCryptoWithEmail uint32 = (1 << 5)
WithdrawCryptoWithWebsiteApproval uint32 = (1 << 6)
WithdrawCryptoWithAPIPermission uint32 = (1 << 7)
WithdrawCryptoWith2FAText string = "WITHDRAW CRYPTO WITH 2FA"
WithdrawCryptoWithSMSText string = "WITHDRAW CRYPTO WITH SMS"
WithdrawCryptoWithEmailText string = "WITHDRAW CRYPTO WITH EMAIL"
WithdrawCryptoWithWebsiteApprovalText string = "WITHDRAW CRYPTO WITH WEBSITE APPROVAL"
WithdrawCryptoWithAPIPermissionText string = "WITHDRAW CRYPTO WITH API PERMISSION"
AutoWithdrawFiat uint32 = (1 << 8)
AutoWithdrawFiatWithAPIPermission uint32 = (1 << 9)
AutoWithdrawFiatWithSetup uint32 = (1 << 10)
AutoWithdrawFiatText string = "AUTO WITHDRAW FIAT"
AutoWithdrawFiatWithAPIPermissionText string = "AUTO WITHDRAW FIAT WITH API PERMISSION"
AutoWithdrawFiatWithSetupText string = "AUTO WITHDRAW FIAT WITH SETUP"
WithdrawFiatWith2FA uint32 = (1 << 11)
WithdrawFiatWithSMS uint32 = (1 << 12)
WithdrawFiatWithEmail uint32 = (1 << 13)
WithdrawFiatWithWebsiteApproval uint32 = (1 << 14)
WithdrawFiatWithAPIPermission uint32 = (1 << 15)
WithdrawFiatWith2FAText string = "WITHDRAW FIAT WITH 2FA"
WithdrawFiatWithSMSText string = "WITHDRAW FIAT WITH SMS"
WithdrawFiatWithEmailText string = "WITHDRAW FIAT WITH EMAIL"
WithdrawFiatWithWebsiteApprovalText string = "WITHDRAW FIAT WITH WEBSITE APPROVAL"
WithdrawFiatWithAPIPermissionText string = "WITHDRAW FIAT WITH API PERMISSION"
WithdrawCryptoViaWebsiteOnly uint32 = (1 << 16)
WithdrawFiatViaWebsiteOnly uint32 = (1 << 17)
WithdrawCryptoViaWebsiteOnlyText string = "WITHDRAW CRYPTO VIA WEBSITE ONLY"
WithdrawFiatViaWebsiteOnlyText string = "WITHDRAW FIAT VIA WEBSITE ONLY"
UnknownWithdrawalTypeText string = "UNKNOWN"
)
// AccountInfo is a Generic type to hold each exchange's holdings in
// all enabled currencies
type AccountInfo struct {
@@ -147,6 +192,7 @@ type Base struct {
Verbose bool
RESTPollingDelay time.Duration
AuthenticatedAPISupport bool
APIWithdrawPermissions uint32
APIAuthPEMKeySupport bool
APISecret, APIKey, APIAuthPEMKey, ClientID string
Nonce nonce.Nonce
@@ -195,6 +241,10 @@ type IBotExchange interface {
GetLastPairsUpdateTime() int64
SupportsRESTTickerBatchUpdates() bool
GetWithdrawPermissions() uint32
FormatWithdrawPermissions() string
SupportsWithdrawPermissions(permissions uint32) bool
GetExchangeFundTransferHistory() ([]FundHistory, error)
SubmitExchangeOrder(p pair.CurrencyPair, side OrderSide, orderType OrderType, amount, price float64, clientID string) (int64, error)
ModifyExchangeOrder(orderID int64, modify ModifyOrder) (int64, error)
@@ -773,3 +823,72 @@ func (e *Base) GetAPIURLDefault() string {
func (e *Base) GetAPIURLSecondaryDefault() string {
return e.APIUrlSecondaryDefault
}
// GetWithdrawPermissions passes through the exchange's withdraw permissions
func (e *Base) GetWithdrawPermissions() uint32 {
return e.APIWithdrawPermissions
}
// SupportsWithdrawPermissions compares the supplied permissions with the exchange's to verify they're supported
func (e *Base) SupportsWithdrawPermissions(permissions uint32) bool {
exchangePermissions := e.GetWithdrawPermissions()
if permissions&exchangePermissions == permissions {
return true
}
return false
}
// FormatWithdrawPermissions will return each of the exchange's compatible withdrawal methods in readable form
func (e *Base) FormatWithdrawPermissions() string {
services := []string{}
for i := 0; i < 32; i++ {
var check uint32 = 1 << uint32(i)
if e.GetWithdrawPermissions()&check != 0 {
switch check {
case AutoWithdrawCrypto:
services = append(services, AutoWithdrawCryptoText)
case AutoWithdrawCryptoWithAPIPermission:
services = append(services, AutoWithdrawCryptoWithAPIPermissionText)
case AutoWithdrawCryptoWithSetup:
services = append(services, AutoWithdrawCryptoWithSetupText)
case WithdrawCryptoWith2FA:
services = append(services, WithdrawCryptoWith2FAText)
case WithdrawCryptoWithSMS:
services = append(services, WithdrawCryptoWithSMSText)
case WithdrawCryptoWithEmail:
services = append(services, WithdrawCryptoWithEmailText)
case WithdrawCryptoWithWebsiteApproval:
services = append(services, WithdrawCryptoWithWebsiteApprovalText)
case WithdrawCryptoWithAPIPermission:
services = append(services, WithdrawCryptoWithAPIPermissionText)
case AutoWithdrawFiat:
services = append(services, AutoWithdrawFiatText)
case AutoWithdrawFiatWithAPIPermission:
services = append(services, AutoWithdrawFiatWithAPIPermissionText)
case AutoWithdrawFiatWithSetup:
services = append(services, AutoWithdrawFiatWithSetupText)
case WithdrawFiatWith2FA:
services = append(services, WithdrawFiatWith2FAText)
case WithdrawFiatWithSMS:
services = append(services, WithdrawFiatWithSMSText)
case WithdrawFiatWithEmail:
services = append(services, WithdrawFiatWithEmailText)
case WithdrawFiatWithWebsiteApproval:
services = append(services, WithdrawFiatWithWebsiteApprovalText)
case WithdrawFiatWithAPIPermission:
services = append(services, WithdrawFiatWithAPIPermissionText)
case WithdrawCryptoViaWebsiteOnly:
services = append(services, WithdrawCryptoViaWebsiteOnlyText)
case WithdrawFiatViaWebsiteOnly:
services = append(services, WithdrawFiatViaWebsiteOnlyText)
default:
services = append(services, fmt.Sprintf("%s[%v]", UnknownWithdrawalTypeText, check))
}
}
}
if len(services) > 0 {
return strings.Join(services, " & ")
}
return NoAPIWithdrawalMethodsText
}

View File

@@ -844,3 +844,49 @@ func TestAPIURL(t *testing.T) {
t.Error("test failed - incorrect return URL")
}
}
func TestSupportsWithdrawPermissions(t *testing.T) {
UAC := Base{Name: "ANX"}
UAC.APIWithdrawPermissions = AutoWithdrawCrypto | AutoWithdrawCryptoWithAPIPermission
withdrawPermissions := UAC.SupportsWithdrawPermissions(AutoWithdrawCrypto)
if !withdrawPermissions {
t.Errorf("Expected: %v, Recieved: %v", true, withdrawPermissions)
}
withdrawPermissions = UAC.SupportsWithdrawPermissions(AutoWithdrawCrypto | AutoWithdrawCryptoWithAPIPermission)
if !withdrawPermissions {
t.Errorf("Expected: %v, Recieved: %v", true, withdrawPermissions)
}
withdrawPermissions = UAC.SupportsWithdrawPermissions(AutoWithdrawCrypto | WithdrawCryptoWith2FA)
if withdrawPermissions {
t.Errorf("Expected: %v, Recieved: %v", false, withdrawPermissions)
}
withdrawPermissions = UAC.SupportsWithdrawPermissions(AutoWithdrawCrypto | AutoWithdrawCryptoWithAPIPermission | WithdrawCryptoWith2FA)
if withdrawPermissions {
t.Errorf("Expected: %v, Recieved: %v", false, withdrawPermissions)
}
withdrawPermissions = UAC.SupportsWithdrawPermissions(WithdrawCryptoWith2FA)
if withdrawPermissions {
t.Errorf("Expected: %v, Recieved: %v", false, withdrawPermissions)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
cfg := config.GetConfig()
err := cfg.LoadConfig(config.ConfigTestFile)
if err != nil {
t.Fatal("Test failed. TestUpdateEnabledCurrencies failed to load config")
}
UAC := Base{Name: "ANX"}
UAC.APIWithdrawPermissions = AutoWithdrawCrypto | AutoWithdrawCryptoWithAPIPermission
withdrawPermissions := UAC.FormatWithdrawPermissions()
if withdrawPermissions != AutoWithdrawCryptoText+" & "+AutoWithdrawCryptoWithAPIPermissionText {
t.Errorf("Expected: %s, Recieved: %s", AutoWithdrawCryptoText+" & "+AutoWithdrawCryptoWithAPIPermissionText, withdrawPermissions)
}
}

View File

@@ -57,6 +57,7 @@ func (e *EXMO) SetDefaults() {
e.Enabled = false
e.Verbose = false
e.RESTPollingDelay = 10
e.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithSetup
e.RequestCurrencyPairFormat.Delimiter = "_"
e.RequestCurrencyPairFormat.Uppercase = true
e.RequestCurrencyPairFormat.Separator = ","

View File

@@ -233,3 +233,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
e.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithSetupText
// Act
withdrawPermissions := e.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -234,3 +234,8 @@ func (e *EXMO) GetWebsocket() (*exchange.Websocket, error) {
func (e *EXMO) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return e.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (e *EXMO) GetWithdrawCapabilities() uint32 {
return e.GetWithdrawPermissions()
}

View File

@@ -46,6 +46,7 @@ func (g *Gateio) SetDefaults() {
g.Enabled = false
g.Verbose = false
g.RESTPollingDelay = 10
g.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
g.RequestCurrencyPairFormat.Delimiter = "_"
g.RequestCurrencyPairFormat.Uppercase = false
g.ConfigCurrencyPairFormat.Delimiter = "_"

View File

@@ -235,3 +235,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
g.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText
// Act
withdrawPermissions := g.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -185,3 +185,8 @@ func (g *Gateio) GetWebsocket() (*exchange.Websocket, error) {
func (g *Gateio) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return g.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (g *Gateio) GetWithdrawCapabilities() uint32 {
return g.GetWithdrawPermissions()
}

View File

@@ -102,6 +102,7 @@ func (g *Gemini) SetDefaults() {
g.Enabled = false
g.Verbose = false
g.RESTPollingDelay = 10
g.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission | exchange.AutoWithdrawCryptoWithSetup | exchange.WithdrawFiatViaWebsiteOnly
g.RequestCurrencyPairFormat.Delimiter = ""
g.RequestCurrencyPairFormat.Uppercase = true
g.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -309,3 +309,14 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := Session[1].FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -185,3 +185,8 @@ func (g *Gemini) GetWebsocket() (*exchange.Websocket, error) {
func (g *Gemini) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return g.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (g *Gemini) GetWithdrawCapabilities() uint32 {
return g.GetWithdrawPermissions()
}

View File

@@ -61,6 +61,7 @@ func (h *HitBTC) SetDefaults() {
h.Fee = 0
h.Verbose = false
h.RESTPollingDelay = 10
h.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
h.RequestCurrencyPairFormat.Delimiter = ""
h.RequestCurrencyPairFormat.Uppercase = true
h.ConfigCurrencyPairFormat.Delimiter = "-"

View File

@@ -160,3 +160,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
h.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText
// Act
withdrawPermissions := h.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -213,3 +213,8 @@ func (h *HitBTC) GetWebsocket() (*exchange.Websocket, error) {
func (h *HitBTC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (h *HitBTC) GetWithdrawCapabilities() uint32 {
return h.GetWithdrawPermissions()
}

View File

@@ -73,6 +73,7 @@ func (h *HUOBI) SetDefaults() {
h.Fee = 0
h.Verbose = false
h.RESTPollingDelay = 10
h.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithSetup
h.RequestCurrencyPairFormat.Delimiter = ""
h.RequestCurrencyPairFormat.Uppercase = false
h.ConfigCurrencyPairFormat.Delimiter = "-"

View File

@@ -381,3 +381,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
h.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithSetupText
// Act
withdrawPermissions := h.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -228,3 +228,8 @@ func (h *HUOBI) GetWebsocket() (*exchange.Websocket, error) {
func (h *HUOBI) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (h *HUOBI) GetWithdrawCapabilities() uint32 {
return h.GetWithdrawPermissions()
}

View File

@@ -65,6 +65,7 @@ func (h *HUOBIHADAX) SetDefaults() {
h.Fee = 0
h.Verbose = false
h.RESTPollingDelay = 10
h.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithSetup
h.RequestCurrencyPairFormat.Delimiter = ""
h.RequestCurrencyPairFormat.Uppercase = false
h.ConfigCurrencyPairFormat.Delimiter = "-"

View File

@@ -360,3 +360,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
h.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithSetupText
// Act
withdrawPermissions := h.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -193,3 +193,8 @@ func (h *HUOBIHADAX) GetWebsocket() (*exchange.Websocket, error) {
func (h *HUOBIHADAX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return h.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (h *HUOBIHADAX) GetWithdrawCapabilities() uint32 {
return h.GetWithdrawPermissions()
}

View File

@@ -48,6 +48,7 @@ func (i *ItBit) SetDefaults() {
i.TakerFee = 0.50
i.Verbose = false
i.RESTPollingDelay = 10
i.APIWithdrawPermissions = exchange.WithdrawCryptoViaWebsiteOnly | exchange.WithdrawFiatViaWebsiteOnly
i.RequestCurrencyPairFormat.Delimiter = ""
i.RequestCurrencyPairFormat.Uppercase = true
i.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -229,3 +229,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
i.SetDefaults()
expectedResult := exchange.WithdrawCryptoViaWebsiteOnlyText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := i.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -187,3 +187,8 @@ func (i *ItBit) GetWebsocket() (*exchange.Websocket, error) {
func (i *ItBit) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return i.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (i *ItBit) GetWithdrawCapabilities() uint32 {
return i.GetWithdrawPermissions()
}

View File

@@ -60,6 +60,7 @@ func (k *Kraken) SetDefaults() {
k.CryptoFee = 0.10
k.Verbose = false
k.RESTPollingDelay = 10
k.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithSetup | exchange.WithdrawCryptoWith2FA | exchange.AutoWithdrawFiatWithSetup | exchange.WithdrawFiatWith2FA
k.RequestCurrencyPairFormat.Delimiter = ""
k.RequestCurrencyPairFormat.Uppercase = true
k.RequestCurrencyPairFormat.Separator = ","
@@ -960,9 +961,9 @@ func (k *Kraken) GetFee(feeBuilder exchange.FeeBuilder) (float64, error) {
case exchange.InternationalBankWithdrawalFee:
fee = getWithdrawalFee(feeBuilder.CurrencyItem)
}
if fee < 0 {
fee = 0
}
if fee < 0 {
fee = 0
}
return fee, nil
}

View File

@@ -315,3 +315,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
k.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithSetupText + " & " + exchange.WithdrawCryptoWith2FAText + " & " + exchange.AutoWithdrawFiatWithSetupText + " & " + exchange.WithdrawFiatWith2FAText
// Act
withdrawPermissions := k.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -219,3 +219,8 @@ func (k *Kraken) GetWebsocket() (*exchange.Websocket, error) {
func (k *Kraken) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return k.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (k *Kraken) GetWithdrawCapabilities() uint32 {
return k.GetWithdrawPermissions()
}

View File

@@ -49,6 +49,7 @@ func (l *LakeBTC) SetDefaults() {
l.MakerFee = 0.15
l.Verbose = false
l.RESTPollingDelay = 10
l.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.WithdrawFiatViaWebsiteOnly
l.RequestCurrencyPairFormat.Delimiter = ""
l.RequestCurrencyPairFormat.Uppercase = true
l.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -146,12 +146,12 @@ func TestCreateWithdraw(t *testing.T) {
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.BTC,
SecondCurrency: symbol.LTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
@@ -233,3 +233,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
l.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := l.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -197,3 +197,8 @@ func (l *LakeBTC) GetWebsocket() (*exchange.Websocket, error) {
func (l *LakeBTC) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (l *LakeBTC) GetWithdrawCapabilities() uint32 {
return l.GetWithdrawPermissions()
}

View File

@@ -51,6 +51,7 @@ func (l *Liqui) SetDefaults() {
l.Verbose = false
l.RESTPollingDelay = 10
l.Ticker = make(map[string]Ticker)
l.APIWithdrawPermissions = exchange.NoAPIWithdrawalMethods
l.RequestCurrencyPairFormat.Delimiter = "_"
l.RequestCurrencyPairFormat.Uppercase = false
l.RequestCurrencyPairFormat.Separator = "-"

View File

@@ -219,3 +219,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
l.SetDefaults()
expectedResult := exchange.NoAPIWithdrawalMethodsText
// Act
withdrawPermissions := l.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -206,3 +206,8 @@ func (l *Liqui) GetWebsocket() (*exchange.Websocket, error) {
func (l *Liqui) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (l *Liqui) GetWithdrawCapabilities() uint32 {
return l.GetWithdrawPermissions()
}

View File

@@ -117,6 +117,7 @@ func (l *LocalBitcoins) SetDefaults() {
l.Verbose = false
l.Verbose = false
l.RESTPollingDelay = 10
l.APIWithdrawPermissions = exchange.WithdrawCryptoViaWebsiteOnly
l.RequestCurrencyPairFormat.Delimiter = ""
l.RequestCurrencyPairFormat.Uppercase = true
l.ConfigCurrencyPairFormat.Delimiter = ""

View File

@@ -80,12 +80,12 @@ func TestEditAd(t *testing.T) {
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
@@ -167,3 +167,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
l.SetDefaults()
expectedResult := exchange.WithdrawCryptoViaWebsiteOnlyText
// Act
withdrawPermissions := l.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -178,3 +178,8 @@ func (l *LocalBitcoins) GetWebsocket() (*exchange.Websocket, error) {
func (l *LocalBitcoins) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return l.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (l *LocalBitcoins) GetWithdrawCapabilities() uint32 {
return l.GetWithdrawPermissions()
}

View File

@@ -99,6 +99,7 @@ func (o *OKCoin) SetDefaults() {
o.Verbose = false
o.RESTPollingDelay = 10
o.AssetTypes = []string{ticker.Spot}
o.APIWithdrawPermissions = exchange.AutoWithdrawCrypto | exchange.WithdrawFiatViaWebsiteOnly
o.SupportsAutoPairUpdating = false
o.SupportsRESTTickerBatching = false
o.WebsocketInit()

View File

@@ -38,12 +38,12 @@ func TestSetup(t *testing.T) {
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
@@ -125,3 +125,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
o.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := o.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -244,3 +244,8 @@ func (o *OKCoin) GetWebsocket() (*exchange.Websocket, error) {
func (o *OKCoin) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return o.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (o *OKCoin) GetWithdrawCapabilities() uint32 {
return o.GetWithdrawPermissions()
}

View File

@@ -102,6 +102,7 @@ func (o *OKEX) SetDefaults() {
o.Enabled = false
o.Verbose = false
o.RESTPollingDelay = 10
o.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
o.RequestCurrencyPairFormat.Delimiter = "_"
o.RequestCurrencyPairFormat.Uppercase = false
o.ConfigCurrencyPairFormat.Delimiter = "_"

View File

@@ -374,3 +374,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
o.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText
// Act
withdrawPermissions := o.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -210,3 +210,8 @@ func (o *OKEX) GetWebsocket() (*exchange.Websocket, error) {
func (o *OKEX) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return o.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (o *OKEX) GetWithdrawCapabilities() uint32 {
return o.GetWithdrawPermissions()
}

View File

@@ -66,6 +66,7 @@ func (p *Poloniex) SetDefaults() {
p.Fee = 0
p.Verbose = false
p.RESTPollingDelay = 10
p.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission
p.RequestCurrencyPairFormat.Delimiter = "_"
p.RequestCurrencyPairFormat.Uppercase = true
p.ConfigCurrencyPairFormat.Delimiter = "_"

View File

@@ -178,3 +178,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
p.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText
// Act
withdrawPermissions := p.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -213,3 +213,8 @@ func (p *Poloniex) GetWebsocket() (*exchange.Websocket, error) {
func (p *Poloniex) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return p.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (p *Poloniex) GetWithdrawCapabilities() uint32 {
return p.GetWithdrawPermissions()
}

View File

@@ -56,6 +56,7 @@ func (w *WEX) SetDefaults() {
w.Verbose = false
w.RESTPollingDelay = 10
w.Ticker = make(map[string]Ticker)
w.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission
w.RequestCurrencyPairFormat.Delimiter = "_"
w.RequestCurrencyPairFormat.Uppercase = false
w.RequestCurrencyPairFormat.Separator = "-"

View File

@@ -164,12 +164,12 @@ func TestRedeemCoupon(t *testing.T) {
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
Amount: 1,
Delimiter: "_",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
@@ -196,7 +196,6 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
// CryptocurrencyTradeFee IsMaker
feeBuilder = setFeeBuilder()
feeBuilder.IsMaker = true
@@ -254,3 +253,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
w.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText
// Act
withdrawPermissions := w.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -216,3 +216,8 @@ func (w *WEX) GetWebsocket() (*exchange.Websocket, error) {
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()
}

View File

@@ -55,6 +55,7 @@ func (y *Yobit) SetDefaults() {
y.RESTPollingDelay = 10
y.AuthenticatedAPISupport = true
y.Ticker = make(map[string]Ticker)
y.APIWithdrawPermissions = exchange.AutoWithdrawCryptoWithAPIPermission | exchange.WithdrawFiatViaWebsiteOnly
y.RequestCurrencyPairFormat.Delimiter = "_"
y.RequestCurrencyPairFormat.Uppercase = false
y.RequestCurrencyPairFormat.Separator = "-"

View File

@@ -148,12 +148,12 @@ func TestRedeemYobicode(t *testing.T) {
func setFeeBuilder() exchange.FeeBuilder {
return exchange.FeeBuilder{
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
Amount: 1,
Delimiter: "-",
FeeType: exchange.CryptocurrencyTradeFee,
FirstCurrency: symbol.LTC,
SecondCurrency: symbol.BTC,
IsMaker: false,
PurchasePrice: 1,
CurrencyItem: symbol.USD,
BankTransactionType: exchange.WireTransfer,
@@ -297,3 +297,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
y.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoWithAPIPermissionText + " & " + exchange.WithdrawFiatViaWebsiteOnlyText
// Act
withdrawPermissions := y.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -198,3 +198,8 @@ func (y *Yobit) GetWebsocket() (*exchange.Websocket, error) {
func (y *Yobit) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return y.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (y *Yobit) GetWithdrawCapabilities() uint32 {
return y.GetWithdrawPermissions()
}

View File

@@ -49,6 +49,7 @@ func (z *ZB) SetDefaults() {
z.Fee = 0
z.Verbose = false
z.RESTPollingDelay = 10
z.APIWithdrawPermissions = exchange.AutoWithdrawCrypto
z.RequestCurrencyPairFormat.Delimiter = "_"
z.RequestCurrencyPairFormat.Uppercase = false
z.ConfigCurrencyPairFormat.Delimiter = "_"

View File

@@ -228,3 +228,15 @@ func TestGetFee(t *testing.T) {
t.Error(err)
}
}
func TestFormatWithdrawPermissions(t *testing.T) {
// Arrange
z.SetDefaults()
expectedResult := exchange.AutoWithdrawCryptoText
// Act
withdrawPermissions := z.FormatWithdrawPermissions()
// Assert
if withdrawPermissions != expectedResult {
t.Errorf("Expected: %s, Recieved: %s", expectedResult, withdrawPermissions)
}
}

View File

@@ -194,3 +194,8 @@ func (z *ZB) GetWebsocket() (*exchange.Websocket, error) {
func (z *ZB) GetFeeByType(feeBuilder exchange.FeeBuilder) (float64, error) {
return z.GetFee(feeBuilder)
}
// GetWithdrawCapabilities returns the types of withdrawal methods permitted by the exchange
func (z *ZB) GetWithdrawCapabilities() uint32 {
return z.GetWithdrawPermissions()
}