diff --git a/exchanges/alphapoint/alphapoint.go b/exchanges/alphapoint/alphapoint.go index 5fac7db1..987d951d 100644 --- a/exchanges/alphapoint/alphapoint.go +++ b/exchanges/alphapoint/alphapoint.go @@ -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), diff --git a/exchanges/alphapoint/alphapoint_test.go b/exchanges/alphapoint/alphapoint_test.go index 912f421c..b19b42d7 100644 --- a/exchanges/alphapoint/alphapoint_test.go +++ b/exchanges/alphapoint/alphapoint_test.go @@ -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) + } +} diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go index 6c0cb78f..543b145e 100644 --- a/exchanges/alphapoint/alphapoint_wrapper.go +++ b/exchanges/alphapoint/alphapoint_wrapper.go @@ -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() +} diff --git a/exchanges/anx/anx.go b/exchanges/anx/anx.go index d98a522c..ac3c4800 100644 --- a/exchanges/anx/anx.go +++ b/exchanges/anx/anx.go @@ -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 +} diff --git a/exchanges/anx/anx_test.go b/exchanges/anx/anx_test.go index 955c8c4b..064c3e06 100644 --- a/exchanges/anx/anx_test.go +++ b/exchanges/anx/anx_test.go @@ -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) + } +} diff --git a/exchanges/anx/anx_types.go b/exchanges/anx/anx_types.go index 36dc3317..7794bf35 100644 --- a/exchanges/anx/anx_types.go +++ b/exchanges/anx/anx_types.go @@ -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 diff --git a/exchanges/anx/anx_wrapper.go b/exchanges/anx/anx_wrapper.go index d0d97e8c..5768c69d 100644 --- a/exchanges/anx/anx_wrapper.go +++ b/exchanges/anx/anx_wrapper.go @@ -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() +} diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index b0cf80b8..fb81633a 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -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), diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index ad25453b..9fc92141 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -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) + } +} diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 63542946..a7a9c13b 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -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() +} diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index 10822135..af96f0e1 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -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 = "" diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index c225bb07..2459c340 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -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) + } +} diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 6ed3426c..a7c0265c 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -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() +} diff --git a/exchanges/bitflyer/bitflyer.go b/exchanges/bitflyer/bitflyer.go index 645ddd7d..9313a795 100644 --- a/exchanges/bitflyer/bitflyer.go +++ b/exchanges/bitflyer/bitflyer.go @@ -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 = "_" diff --git a/exchanges/bitflyer/bitflyer_test.go b/exchanges/bitflyer/bitflyer_test.go index 6e42f5f5..6cf3835b 100644 --- a/exchanges/bitflyer/bitflyer_test.go +++ b/exchanges/bitflyer/bitflyer_test.go @@ -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) + } +} diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go index 45613deb..17604d2a 100644 --- a/exchanges/bitflyer/bitflyer_wrapper.go +++ b/exchanges/bitflyer/bitflyer_wrapper.go @@ -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() +} diff --git a/exchanges/bithumb/bithumb.go b/exchanges/bithumb/bithumb.go index 7d405353..84126c17 100644 --- a/exchanges/bithumb/bithumb.go +++ b/exchanges/bithumb/bithumb.go @@ -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 = "" diff --git a/exchanges/bithumb/bithumb_test.go b/exchanges/bithumb/bithumb_test.go index 0dfbfcd1..dfcee7b0 100644 --- a/exchanges/bithumb/bithumb_test.go +++ b/exchanges/bithumb/bithumb_test.go @@ -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) + } +} diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index 76b75d74..19f4107a 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -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() +} diff --git a/exchanges/bitmex/bitmex.go b/exchanges/bitmex/bitmex.go index d778630f..04ad86e7 100644 --- a/exchanges/bitmex/bitmex.go +++ b/exchanges/bitmex/bitmex.go @@ -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 = "" diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go index d1eecf1b..a2a86539 100644 --- a/exchanges/bitmex/bitmex_test.go +++ b/exchanges/bitmex/bitmex_test.go @@ -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) + } +} diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index f4cd8d5e..172ddb65 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -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() +} diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index 969aadf5..53298a2f 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -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 = "" diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go index b269ca0b..11633cc6 100644 --- a/exchanges/bitstamp/bitstamp_test.go +++ b/exchanges/bitstamp/bitstamp_test.go @@ -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) + } +} diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index aca4728e..d9649718 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -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() +} diff --git a/exchanges/bittrex/bittrex.go b/exchanges/bittrex/bittrex.go index fab87dd3..baf90d25 100644 --- a/exchanges/bittrex/bittrex.go +++ b/exchanges/bittrex/bittrex.go @@ -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 = "-" diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go index 59dec0a2..34b7f0a8 100644 --- a/exchanges/bittrex/bittrex_test.go +++ b/exchanges/bittrex/bittrex_test.go @@ -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) + } +} diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 45429031..4f65ff26 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -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() +} diff --git a/exchanges/btcc/btcc.go b/exchanges/btcc/btcc.go index 7ca9e355..4367162c 100644 --- a/exchanges/btcc/btcc.go +++ b/exchanges/btcc/btcc.go @@ -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 diff --git a/exchanges/btcc/btcc_test.go b/exchanges/btcc/btcc_test.go index 75451c52..32c4b947 100644 --- a/exchanges/btcc/btcc_test.go +++ b/exchanges/btcc/btcc_test.go @@ -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) + } +} diff --git a/exchanges/btcc/btcc_wrapper.go b/exchanges/btcc/btcc_wrapper.go index 272a900f..69b15c98 100644 --- a/exchanges/btcc/btcc_wrapper.go +++ b/exchanges/btcc/btcc_wrapper.go @@ -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() +} diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index 4d02a6ad..67a8d351 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -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 = "-" diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index 626f6143..f4601adb 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -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) + } +} diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 5d842df2..77bed933 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -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() +} diff --git a/exchanges/coinbasepro/coinbasepro.go b/exchanges/coinbasepro/coinbasepro.go index 69b5ce89..0d45ecbb 100644 --- a/exchanges/coinbasepro/coinbasepro.go +++ b/exchanges/coinbasepro/coinbasepro.go @@ -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 = "" diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go index 03b1817a..4cff5d05 100644 --- a/exchanges/coinbasepro/coinbasepro_test.go +++ b/exchanges/coinbasepro/coinbasepro_test.go @@ -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) + } +} diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index ddac22d2..ba8620aa 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -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() +} diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index e072d98e..2ad3397c 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -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 = "" diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index 2eac1dd4..f79662f9 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -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) + } +} diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 436ca2b3..2ae71d3f 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -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() +} diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 745d18b9..a3454683 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -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 +} diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 6249d0e2..72e7d183 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -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) + } + +} diff --git a/exchanges/exmo/exmo.go b/exchanges/exmo/exmo.go index 988cf24a..e1f830ac 100644 --- a/exchanges/exmo/exmo.go +++ b/exchanges/exmo/exmo.go @@ -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 = "," diff --git a/exchanges/exmo/exmo_test.go b/exchanges/exmo/exmo_test.go index 4f09e25b..4e14fcc9 100644 --- a/exchanges/exmo/exmo_test.go +++ b/exchanges/exmo/exmo_test.go @@ -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) + } +} diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index 75732255..8e64b583 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -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() +} diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go index 6d220b46..97acbb2d 100644 --- a/exchanges/gateio/gateio.go +++ b/exchanges/gateio/gateio.go @@ -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 = "_" diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index 6915d062..23a85a5d 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -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) + } +} diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go index af4c96c6..fb81e6ed 100644 --- a/exchanges/gateio/gateio_wrapper.go +++ b/exchanges/gateio/gateio_wrapper.go @@ -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() +} diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index b0556240..dd7b26ed 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -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 = "" diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go index b583dca4..a6c2e71e 100644 --- a/exchanges/gemini/gemini_test.go +++ b/exchanges/gemini/gemini_test.go @@ -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) + } +} diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 4edfcf27..4c02d7a6 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -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() +} diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go index efd5fc76..b47fbc72 100644 --- a/exchanges/hitbtc/hitbtc.go +++ b/exchanges/hitbtc/hitbtc.go @@ -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 = "-" diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go index 873baf8e..08249c9f 100644 --- a/exchanges/hitbtc/hitbtc_test.go +++ b/exchanges/hitbtc/hitbtc_test.go @@ -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) + } +} diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 094afe5f..479418d1 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -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() +} diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index db544a57..699ea6e7 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -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 = "-" diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index b31a9e39..c4bf97b7 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -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) + } +} diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index f4fbbd42..2187671f 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -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() +} diff --git a/exchanges/huobihadax/huobihadax.go b/exchanges/huobihadax/huobihadax.go index 7883920d..7ff535af 100644 --- a/exchanges/huobihadax/huobihadax.go +++ b/exchanges/huobihadax/huobihadax.go @@ -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 = "-" diff --git a/exchanges/huobihadax/huobihadax_test.go b/exchanges/huobihadax/huobihadax_test.go index e1f920ed..07aeee61 100644 --- a/exchanges/huobihadax/huobihadax_test.go +++ b/exchanges/huobihadax/huobihadax_test.go @@ -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) + } +} diff --git a/exchanges/huobihadax/huobihadax_wrapper.go b/exchanges/huobihadax/huobihadax_wrapper.go index 5d1e63d4..a5c06baf 100644 --- a/exchanges/huobihadax/huobihadax_wrapper.go +++ b/exchanges/huobihadax/huobihadax_wrapper.go @@ -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() +} diff --git a/exchanges/itbit/itbit.go b/exchanges/itbit/itbit.go index 61af064a..f71bbf6e 100644 --- a/exchanges/itbit/itbit.go +++ b/exchanges/itbit/itbit.go @@ -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 = "" diff --git a/exchanges/itbit/itbit_test.go b/exchanges/itbit/itbit_test.go index fc6683ae..013c75f8 100644 --- a/exchanges/itbit/itbit_test.go +++ b/exchanges/itbit/itbit_test.go @@ -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) + } +} diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index 5752ffac..f7703d30 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -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() +} diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index 96c3d015..501393ea 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -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 } diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index d9464fa5..89990610 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -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) + } +} diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index b720ab69..b2ff9e01 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -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() +} diff --git a/exchanges/lakebtc/lakebtc.go b/exchanges/lakebtc/lakebtc.go index ec34b6b2..ed402b88 100644 --- a/exchanges/lakebtc/lakebtc.go +++ b/exchanges/lakebtc/lakebtc.go @@ -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 = "" diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go index bcdbacd8..ef35b44a 100644 --- a/exchanges/lakebtc/lakebtc_test.go +++ b/exchanges/lakebtc/lakebtc_test.go @@ -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) + } +} diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index 90c86100..ace3b044 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -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() +} diff --git a/exchanges/liqui/liqui.go b/exchanges/liqui/liqui.go index 99f85a28..2400fb52 100644 --- a/exchanges/liqui/liqui.go +++ b/exchanges/liqui/liqui.go @@ -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 = "-" diff --git a/exchanges/liqui/liqui_test.go b/exchanges/liqui/liqui_test.go index a63f3fd6..bb3cb9c6 100644 --- a/exchanges/liqui/liqui_test.go +++ b/exchanges/liqui/liqui_test.go @@ -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) + } +} diff --git a/exchanges/liqui/liqui_wrapper.go b/exchanges/liqui/liqui_wrapper.go index 736e0f1e..77a5705e 100644 --- a/exchanges/liqui/liqui_wrapper.go +++ b/exchanges/liqui/liqui_wrapper.go @@ -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() +} diff --git a/exchanges/localbitcoins/localbitcoins.go b/exchanges/localbitcoins/localbitcoins.go index 39f7eb87..3b50026d 100644 --- a/exchanges/localbitcoins/localbitcoins.go +++ b/exchanges/localbitcoins/localbitcoins.go @@ -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 = "" diff --git a/exchanges/localbitcoins/localbitcoins_test.go b/exchanges/localbitcoins/localbitcoins_test.go index 7241ea8c..2f05f0d1 100644 --- a/exchanges/localbitcoins/localbitcoins_test.go +++ b/exchanges/localbitcoins/localbitcoins_test.go @@ -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) + } +} diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 5abe9165..5612b2ed 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -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() +} diff --git a/exchanges/okcoin/okcoin.go b/exchanges/okcoin/okcoin.go index 6b2dde56..2a3c8d34 100644 --- a/exchanges/okcoin/okcoin.go +++ b/exchanges/okcoin/okcoin.go @@ -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() diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go index 3dea0ae0..cabd8b25 100644 --- a/exchanges/okcoin/okcoin_test.go +++ b/exchanges/okcoin/okcoin_test.go @@ -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) + } +} diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go index 9fd49eb0..2ecbe16c 100644 --- a/exchanges/okcoin/okcoin_wrapper.go +++ b/exchanges/okcoin/okcoin_wrapper.go @@ -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() +} diff --git a/exchanges/okex/okex.go b/exchanges/okex/okex.go index 9791363f..180b030d 100644 --- a/exchanges/okex/okex.go +++ b/exchanges/okex/okex.go @@ -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 = "_" diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index 392855bd..4884bfe5 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -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) + } +} diff --git a/exchanges/okex/okex_wrapper.go b/exchanges/okex/okex_wrapper.go index a756b345..792e21ea 100644 --- a/exchanges/okex/okex_wrapper.go +++ b/exchanges/okex/okex_wrapper.go @@ -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() +} diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 2cc3f5d6..212c2afb 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -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 = "_" diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go index 57e97e63..abcdf121 100644 --- a/exchanges/poloniex/poloniex_test.go +++ b/exchanges/poloniex/poloniex_test.go @@ -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) + } +} diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index beb3700d..ea4a5d64 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -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() +} diff --git a/exchanges/wex/wex.go b/exchanges/wex/wex.go index 8af95f9b..f4dde152 100644 --- a/exchanges/wex/wex.go +++ b/exchanges/wex/wex.go @@ -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 = "-" diff --git a/exchanges/wex/wex_test.go b/exchanges/wex/wex_test.go index 80027e82..33c7052a 100644 --- a/exchanges/wex/wex_test.go +++ b/exchanges/wex/wex_test.go @@ -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) + } +} diff --git a/exchanges/wex/wex_wrapper.go b/exchanges/wex/wex_wrapper.go index 5501a576..79ead6ea 100644 --- a/exchanges/wex/wex_wrapper.go +++ b/exchanges/wex/wex_wrapper.go @@ -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() +} diff --git a/exchanges/yobit/yobit.go b/exchanges/yobit/yobit.go index d84b8073..0c38d3f4 100644 --- a/exchanges/yobit/yobit.go +++ b/exchanges/yobit/yobit.go @@ -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 = "-" diff --git a/exchanges/yobit/yobit_test.go b/exchanges/yobit/yobit_test.go index 31c74f47..0335d995 100644 --- a/exchanges/yobit/yobit_test.go +++ b/exchanges/yobit/yobit_test.go @@ -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) + } +} diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index 9a07d16e..7a74fab7 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -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() +} diff --git a/exchanges/zb/zb.go b/exchanges/zb/zb.go index 51e7220a..2470d648 100644 --- a/exchanges/zb/zb.go +++ b/exchanges/zb/zb.go @@ -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 = "_" diff --git a/exchanges/zb/zb_test.go b/exchanges/zb/zb_test.go index f11ce0bd..77da1e28 100644 --- a/exchanges/zb/zb_test.go +++ b/exchanges/zb/zb_test.go @@ -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) + } +} diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index cdde5810..f99d68fc 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -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() +}