(Exchanges) Introduce validation method and small updates (#565)

* Remove pointer reference

* Fix portfolio withdraw tests

* Add nil protection in validator method to reduce prospective panics and for future outbound checking

* Updated tests

* ch order var to not ref package

* rm comparison

* Add order ID validation check

* Add exchange name validation check

* Add in test details

* fix tests

* fix linter issues

* linter issues strikes again

* linter rabbit hole

* Addr nitterinos

* Add validation variadic interface to define sets of functionality check POC

* didn't want to add an amount other than 0, didn't want to add address to exchange withdraw, didn't want to whitlist, can change if need be

* add coverage

* Add validation method options for exchange wrappers and abstracted validation into its own package

* Add validation code for structs in exchange template generation

* remove extra validation call as this is done in wrapper

* fix niterinos for examplerinos

* Add template to documentation tool and regenerated documentation

* Addr niticles

* Fix tests due to validation update

* Add more validation checks for modify/submit orders

* update tests

* fix more tests

* Add asset type to submit variable in tests and rpc call. Regen funcs.

* Add field to modify struct in tests

* applied field asset to cancel struct across project

* fix woopsy
This commit is contained in:
Ryan O'Hara-Reid
2020-10-02 13:36:01 +10:00
committed by GitHub
parent ecbc68561f
commit 4e828a8124
93 changed files with 3070 additions and 1676 deletions

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -479,11 +480,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := a.SubmitOrder(orderSubmission)
@@ -511,6 +513,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := a.CancelOrder(orderCancellation)
@@ -534,6 +537,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := a.CancelAllOrders(orderCancellation)
@@ -554,7 +558,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := a.ModifyOrder(&order.Modify{})
_, err := a.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}

View File

@@ -214,6 +214,9 @@ func (a *Alphapoint) GetExchangeHistory(p currency.Pair, assetType asset.Item, t
// SubmitOrder submits a new order and returns a true value when
// successfully submitted
func (a *Alphapoint) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
if err := s.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
if err := s.Validate(); err != nil {
return submitOrderResponse, err
@@ -245,17 +248,23 @@ func (a *Alphapoint) ModifyOrder(_ *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (a *Alphapoint) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (a *Alphapoint) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
_, err = a.CancelExistingOrder(orderIDInt, order.AccountID)
_, err = a.CancelExistingOrder(orderIDInt, o.AccountID)
return err
}
// CancelAllOrders cancels all orders for a given account
func (a *Alphapoint) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
return order.CancelAllResponse{},
a.CancelAllExistingOrders(orderCancellation.AccountID)
}
@@ -317,6 +326,9 @@ func (a *Alphapoint) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, err
// GetActiveOrders retrieves any orders that are active/open
// This function is not concurrency safe due to orderSide/orderType maps
func (a *Alphapoint) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := a.GetOrders()
if err != nil {
return nil, err
@@ -359,6 +371,10 @@ func (a *Alphapoint) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detai
// Can Limit response to specific order status
// This function is not concurrency safe due to orderSide/orderType maps
func (a *Alphapoint) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := a.GetOrders()
if err != nil {
return nil, err

View File

@@ -410,11 +410,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.LTC,
Quote: currency.BTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1000000000,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1000000000,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
_, err := b.SubmitOrder(orderSubmission)
@@ -464,6 +465,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
}
_, err := b.CancelAllOrders(orderCancellation)
@@ -494,7 +496,7 @@ func TestGetAccountInfo(t *testing.T) {
func TestModifyOrder(t *testing.T) {
t.Parallel()
_, err := b.ModifyOrder(&order.Modify{})
_, err := b.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() error cannot be nil")
}
@@ -507,10 +509,11 @@ func TestWithdraw(t *testing.T) {
}
withdrawCryptoRequest := withdraw.Request{
Exchange: b.Name,
Amount: 0,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -521,8 +524,8 @@ func TestWithdraw(t *testing.T) {
t.Error("Withdraw() error", err)
case !areTestAPIKeysSet() && err == nil && !mockTests:
t.Error("Withdraw() expecting an error when no keys are set")
case mockTests && err != nil:
t.Error("Mock Withdraw() error", err)
case mockTests && err == nil:
t.Error("Mock Withdraw() error cannot be nil")
}
}

View File

@@ -497,6 +497,10 @@ func (b *Binance) GetExchangeHistory(p currency.Pair, assetType asset.Item, time
// SubmitOrder submits a new order
func (b *Binance) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
if err := s.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
if err := s.Validate(); err != nil {
return submitOrderResponse, err
@@ -551,20 +555,24 @@ func (b *Binance) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Binance) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (b *Binance) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
fpair, err := b.FormatExchangeCurrency(order.Pair, order.AssetType)
fpair, err := b.FormatExchangeCurrency(o.Pair, o.AssetType)
if err != nil {
return err
}
_, err = b.CancelExistingOrder(fpair.String(),
orderIDInt,
order.AccountID)
o.AccountID)
return err
}
@@ -604,6 +612,10 @@ func (b *Binance) GetDepositAddress(cryptocurrency currency.Code, _ string) (str
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Binance) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
amountStr := strconv.FormatFloat(withdrawRequest.Amount, 'f', -1, 64)
v, err := b.WithdrawCrypto(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
@@ -640,6 +652,10 @@ func (b *Binance) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("at least one currency is required to fetch order history")
}
@@ -690,6 +706,10 @@ func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("at least one currency is required to fetch order history")
}

View File

@@ -16,7 +16,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -808,6 +807,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
@@ -831,6 +831,7 @@ func TestCancelAllExchangeOrdera(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := b.CancelAllOrders(orderCancellation)
@@ -852,7 +853,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := b.ModifyOrder(&order.Modify{})
_, err := b.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -868,7 +869,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -892,8 +893,7 @@ func TestWithdrawFiat(t *testing.T) {
Amount: -1,
Currency: currency.USD,
Description: "WITHDRAW IT ALL",
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{},
Fiat: withdraw.FiatRequest{
WireCurrency: currency.USD.String(),
},
}
@@ -917,8 +917,7 @@ func TestWithdrawInternationalBank(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{},
Fiat: withdraw.FiatRequest{
WireCurrency: currency.USD.String(),
RequiresIntermediaryBank: true,
IsExpressWire: false,

View File

@@ -474,6 +474,10 @@ func (b *Bitfinex) GetExchangeHistory(p currency.Pair, assetType asset.Item, tim
// SubmitOrder submits a new order
func (b *Bitfinex) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
if err := o.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
err := o.Validate()
if err != nil {
@@ -528,6 +532,10 @@ func (b *Bitfinex) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (b *Bitfinex) ModifyOrder(action *order.Modify) (string, error) {
if err := action.Validate(); err != nil {
return "", err
}
orderIDInt, err := strconv.ParseInt(action.ID, 10, 64)
if err != nil {
return action.ID, err
@@ -547,8 +555,12 @@ func (b *Bitfinex) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitfinex) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (b *Bitfinex) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -594,6 +606,10 @@ func (b *Bitfinex) GetDepositAddress(c currency.Code, accountID string) (string,
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is submitted
func (b *Bitfinex) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
// Bitfinex has support for three types, exchange, margin and deposit
// As this is for trading, I've made the wrapper default 'exchange'
// TODO: Discover an automated way to make the decision for wallet type to withdraw from
@@ -616,6 +632,10 @@ func (b *Bitfinex) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request
// WithdrawFiatFunds returns a withdrawal ID when a withdrawal is submitted
// Returns comma delimited withdrawal IDs
func (b *Bitfinex) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
withdrawalType := "wire"
// Bitfinex has support for three types, exchange, margin and deposit
// As this is for trading, I've made the wrapper default 'exchange'
@@ -635,6 +655,10 @@ func (b *Bitfinex) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdr
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is submitted
// Returns comma delimited withdrawal IDs
func (b *Bitfinex) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := b.WithdrawFiatFunds(withdrawRequest)
if err != nil {
return nil, err
@@ -656,6 +680,10 @@ func (b *Bitfinex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
// GetActiveOrders retrieves any orders that are active/open
func (b *Bitfinex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
resp, err := b.GetOpenOrders()
if err != nil {
@@ -721,6 +749,10 @@ func (b *Bitfinex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *Bitfinex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
resp, err := b.GetInactiveOrders()
if err != nil {

View File

@@ -315,11 +315,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.LTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
_, err := b.SubmitOrder(orderSubmission)
if err != common.ErrNotYetImplemented {
@@ -339,6 +340,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
@@ -360,6 +362,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
_, err := b.CancelAllOrders(orderCancellation)
@@ -379,7 +382,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -395,7 +398,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := b.ModifyOrder(&order.Modify{})
_, err := b.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}

View File

@@ -298,7 +298,7 @@ func (b *Bitflyer) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitflyer) CancelOrder(order *order.Cancel) error {
func (b *Bitflyer) CancelOrder(_ *order.Cancel) error {
return common.ErrNotYetImplemented
}

View File

@@ -14,7 +14,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -387,11 +386,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.LTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := b.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -413,6 +413,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
@@ -436,6 +437,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := b.CancelAllOrders(orderCancellation)
@@ -474,11 +476,13 @@ func TestModifyOrder(t *testing.T) {
t.Fatal(err)
}
_, err = b.ModifyOrder(&order.Modify{
ID: "1337",
Price: 100,
Amount: 1000,
Side: order.Sell,
Pair: curr})
ID: "1337",
Price: 100,
Amount: 1000,
Side: order.Sell,
Pair: curr,
AssetType: asset.Spot,
})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -494,7 +498,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -515,8 +519,7 @@ func TestWithdrawFiat(t *testing.T) {
}
var withdrawFiatRequest = withdraw.Request{
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{},
Fiat: withdraw.FiatRequest{
WireCurrency: currency.KRW.String(),
RequiresIntermediaryBank: false,
IsExpressWire: false,

View File

@@ -337,6 +337,10 @@ func (b *Bithumb) GetExchangeHistory(p currency.Pair, assetType asset.Item, time
// SubmitOrder submits a new order
// TODO: Fill this out to support limit orders
func (b *Bithumb) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
if err := s.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
if err := s.Validate(); err != nil {
return submitOrderResponse, err
@@ -371,6 +375,10 @@ func (b *Bithumb) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (b *Bithumb) ModifyOrder(action *order.Modify) (string, error) {
if err := action.Validate(); err != nil {
return "", err
}
order, err := b.ModifyTrade(action.ID,
action.Pair.Base.String(),
action.Side.Lower(),
@@ -385,15 +393,23 @@ func (b *Bithumb) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bithumb) CancelOrder(order *order.Cancel) error {
_, err := b.CancelTrade(order.Side.String(),
order.ID,
order.Pair.Base.String())
func (b *Bithumb) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := b.CancelTrade(o.Side.String(),
o.ID,
o.Pair.Base.String())
return err
}
// CancelAllOrders cancels all orders associated with a currency pair
func (b *Bithumb) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
cancelAllOrdersResponse := order.CancelAllResponse{
Status: make(map[string]string),
}
@@ -447,6 +463,10 @@ func (b *Bithumb) GetDepositAddress(cryptocurrency currency.Code, _ string) (str
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bithumb) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := b.WithdrawCrypto(withdrawRequest.Crypto.Address,
withdrawRequest.Crypto.AddressTag,
withdrawRequest.Currency.String(),
@@ -463,6 +483,10 @@ func (b *Bithumb) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request)
// WithdrawFiatFunds returns a withdrawal ID when a
// withdrawal is submitted
func (b *Bithumb) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
if math.Mod(withdrawRequest.Amount, 1) != 0 {
return nil, errors.New("currency KRW does not support decimal places")
}
@@ -500,6 +524,9 @@ func (b *Bithumb) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (b *Bithumb) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
resp, err := b.GetOrders("", "", "1000", "", "")
if err != nil {
@@ -548,6 +575,10 @@ func (b *Bithumb) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
resp, err := b.GetOrders("", "", "1000", "", "")
if err != nil {

View File

@@ -14,6 +14,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
@@ -524,11 +525,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.XBT,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Futures,
}
response, err := b.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -549,6 +551,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Futures,
}
err := b.CancelOrder(orderCancellation)
@@ -571,6 +574,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Futures,
}
resp, err := b.CancelAllOrders(orderCancellation)
@@ -605,7 +609,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := b.ModifyOrder(&order.Modify{ID: "1337"})
_, err := b.ModifyOrder(&order.Modify{ID: "1337", AssetType: asset.Futures})
if err == nil {
t.Error("ModifyOrder() error")
}
@@ -613,7 +617,7 @@ func TestModifyOrder(t *testing.T) {
func TestWithdraw(t *testing.T) {
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
Amount: -1,

View File

@@ -451,6 +451,10 @@ func (b *Bitmex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (b *Bitmex) ModifyOrder(action *order.Modify) (string, error) {
if err := action.Validate(); err != nil {
return "", err
}
var params OrderAmendParams
if math.Mod(action.Amount, 1) != 0 {
@@ -470,9 +474,12 @@ func (b *Bitmex) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitmex) CancelOrder(order *order.Cancel) error {
func (b *Bitmex) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
var params = OrderCancelParams{
OrderID: order.ID,
OrderID: o.ID,
}
_, err := b.CancelOrders(&params)
return err
@@ -512,6 +519,10 @@ func (b *Bitmex) GetDepositAddress(cryptocurrency currency.Code, _ string) (stri
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitmex) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
var request = UserRequestWithdrawalParams{
Address: withdrawRequest.Crypto.Address,
Amount: withdrawRequest.Amount,
@@ -557,6 +568,10 @@ func (b *Bitmex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
// This function is not concurrency safe due to orderSide/orderType maps
func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
params := OrdersRequest{}
params.Filter = "{\"open\":true}"
@@ -605,6 +620,10 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// Can Limit response to specific order status
// This function is not concurrency safe due to orderSide/orderType maps
func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
params := OrdersRequest{}
resp, err := b.GetOrders(&params)

View File

@@ -384,11 +384,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := b.SubmitOrder(orderSubmission)
switch {
@@ -409,7 +410,8 @@ func TestCancelExchangeOrder(t *testing.T) {
}
orderCancellation := &order.Cancel{
ID: "1234",
ID: "1234",
AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
switch {
@@ -429,7 +431,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
resp, err := b.CancelAllOrders(&order.Cancel{})
resp, err := b.CancelAllOrders(&order.Cancel{AssetType: asset.Spot})
switch {
case !areTestAPIKeysSet() && err == nil && !mockTests:
t.Error("Expecting an error when no keys are set")
@@ -447,7 +449,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestModifyOrder(t *testing.T) {
t.Parallel()
_, err := b.ModifyOrder(&order.Modify{})
_, err := b.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -464,7 +466,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -488,8 +490,8 @@ func TestWithdrawFiat(t *testing.T) {
}
var withdrawFiatRequest = withdraw.Request{
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{
Fiat: withdraw.FiatRequest{
Bank: banking.Account{
AccountName: "Satoshi Nakamoto",
AccountNumber: "12345",
BankAddress: "123 Fake St",
@@ -528,8 +530,8 @@ func TestWithdrawInternationalBank(t *testing.T) {
}
var withdrawFiatRequest = withdraw.Request{
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{
Fiat: withdraw.FiatRequest{
Bank: banking.Account{
AccountName: "Satoshi Nakamoto",
AccountNumber: "12345",
BankAddress: "123 Fake St",

View File

@@ -416,8 +416,12 @@ func (b *Bitstamp) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bitstamp) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (b *Bitstamp) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -452,6 +456,10 @@ func (b *Bitstamp) GetDepositAddress(cryptocurrency currency.Code, _ string) (st
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bitstamp) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := b.CryptoWithdrawal(withdrawRequest.Amount,
withdrawRequest.Crypto.Address,
withdrawRequest.Currency.String(),
@@ -476,6 +484,10 @@ func (b *Bitstamp) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request
// WithdrawFiatFunds returns a withdrawal ID when a
// withdrawal is submitted
func (b *Bitstamp) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := b.OpenBankWithdrawal(withdrawRequest.Amount,
withdrawRequest.Currency.String(),
withdrawRequest.Fiat.Bank.AccountName,
@@ -507,6 +519,10 @@ func (b *Bitstamp) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdr
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
// withdrawal is submitted
func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := b.OpenInternationalBankWithdrawal(withdrawRequest.Amount,
withdrawRequest.Currency.String(),
withdrawRequest.Fiat.Bank.AccountName,
@@ -543,6 +559,10 @@ func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
// GetActiveOrders retrieves any orders that are active/open
func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var currPair string
if len(req.Pairs) != 1 {
currPair = "all"
@@ -593,6 +613,10 @@ func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var currPair string
if len(req.Pairs) == 1 {
currPair = req.Pairs[0].String()

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -393,11 +394,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.LTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := b.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -418,6 +420,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
@@ -440,6 +443,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := b.CancelAllOrders(orderCancellation)
@@ -460,7 +464,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := b.ModifyOrder(&order.Modify{})
_, err := b.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("Expected error")
}
@@ -471,7 +475,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -420,9 +420,11 @@ func (b *Bittrex) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *Bittrex) CancelOrder(order *order.Cancel) error {
_, err := b.CancelExistingOrder(order.ID)
func (b *Bittrex) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := b.CancelExistingOrder(o.ID)
return err
}
@@ -465,7 +467,14 @@ func (b *Bittrex) GetDepositAddress(cryptocurrency currency.Code, _ string) (str
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *Bittrex) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
uuid, err := b.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.Crypto.AddressTag, withdrawRequest.Crypto.Address, withdrawRequest.Amount)
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
uuid, err := b.Withdraw(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.AddressTag,
withdrawRequest.Crypto.Address,
withdrawRequest.Amount)
if err != nil {
return nil, err
}
@@ -497,6 +506,10 @@ func (b *Bittrex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var currPair string
if len(req.Pairs) == 1 {
currPair = req.Pairs[0].String()
@@ -557,6 +570,10 @@ func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var currPair string
if len(req.Pairs) == 1 {
currPair = req.Pairs[0].String()

View File

@@ -465,7 +465,11 @@ func (b *BTCMarkets) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (b *BTCMarkets) CancelOrder(o *order.Cancel) error {
_, err := b.RemoveOrder(o.ID)
err := o.Validate(o.StandardCancel())
if err != nil {
return err
}
_, err = b.RemoveOrder(o.ID)
return err
}
@@ -568,6 +572,9 @@ func (b *BTCMarkets) GetDepositAddress(cryptocurrency currency.Code, accountID s
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is submitted
func (b *BTCMarkets) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
a, err := b.RequestWithdraw(withdrawRequest.Currency.String(),
withdrawRequest.Amount,
withdrawRequest.Crypto.Address,
@@ -587,6 +594,10 @@ func (b *BTCMarkets) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Reque
// WithdrawFiatFunds returns a withdrawal ID when a
// withdrawal is submitted
func (b *BTCMarkets) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
if withdrawRequest.Currency != currency.AUD {
return nil, errors.New("only aud is supported for withdrawals")
}
@@ -623,6 +634,9 @@ func (b *BTCMarkets) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, err
// GetActiveOrders retrieves any orders that are active/open
func (b *BTCMarkets) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
allPairs, err := b.GetEnabledPairs(asset.Spot)
if err != nil {
@@ -698,6 +712,9 @@ func (b *BTCMarkets) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detai
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *BTCMarkets) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var resp []order.Detail
var tempResp order.Detail
var tempArray []string

View File

@@ -483,14 +483,18 @@ func (b *BTSE) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (b *BTSE) CancelOrder(order *order.Cancel) error {
fPair, err := b.FormatExchangeCurrency(order.Pair,
order.AssetType)
func (b *BTSE) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
fPair, err := b.FormatExchangeCurrency(o.Pair,
o.AssetType)
if err != nil {
return err
}
_, err = b.CancelExistingOrder(order.ID, fPair.String(), order.ClientOrderID)
_, err = b.CancelExistingOrder(o.ID, fPair.String(), o.ClientOrderID)
if err != nil {
return err
}
@@ -502,6 +506,10 @@ func (b *BTSE) CancelOrder(order *order.Cancel) error {
// If product ID is sent, all orders of that specified market will be cancelled
// If not specified, all orders of all markets will be cancelled
func (b *BTSE) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var resp order.CancelAllResponse
fPair, err := b.FormatExchangeCurrency(orderCancellation.Pair,
@@ -632,6 +640,10 @@ func (b *BTSE) GetDepositAddress(cryptocurrency currency.Code, accountID string)
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (b *BTSE) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
amountToString := strconv.FormatFloat(withdrawRequest.Amount, 'f', 8, 64)
resp, err := b.WalletWithdrawal(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
@@ -660,6 +672,10 @@ func (b *BTSE) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Re
// GetActiveOrders retrieves any orders that are active/open
func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("no pair provided")
}
@@ -764,6 +780,10 @@ func matchType(input int, required order.Type) bool {
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (b *BTSE) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var resp []order.Detail
if len(getOrdersRequest.Pairs) == 0 {
var err error

View File

@@ -438,11 +438,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := c.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -463,6 +464,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := c.CancelOrder(orderCancellation)
@@ -485,6 +487,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := c.CancelAllOrders(orderCancellation)
@@ -505,7 +508,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := c.ModifyOrder(&order.Modify{})
_, err := c.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -516,7 +519,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}
@@ -542,8 +545,8 @@ func TestWithdrawFiat(t *testing.T) {
var withdrawFiatRequest = withdraw.Request{
Amount: 100,
Currency: currency.USD,
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{
Fiat: withdraw.FiatRequest{
Bank: banking.Account{
BankName: "Federal Reserve Bank",
},
},
@@ -566,8 +569,8 @@ func TestWithdrawInternationalBank(t *testing.T) {
var withdrawFiatRequest = withdraw.Request{
Amount: 100,
Currency: currency.USD,
Fiat: &withdraw.FiatRequest{
Bank: &banking.Account{
Fiat: withdraw.FiatRequest{
Bank: banking.Account{
BankName: "Federal Reserve Bank",
},
},

View File

@@ -443,6 +443,10 @@ func (c *CoinbasePro) GetExchangeHistory(p currency.Pair, assetType asset.Item,
// SubmitOrder submits a new order
func (c *CoinbasePro) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
if err := s.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
if err := s.Validate(); err != nil {
return submitOrderResponse, err
@@ -497,8 +501,11 @@ func (c *CoinbasePro) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (c *CoinbasePro) CancelOrder(order *order.Cancel) error {
return c.CancelExistingOrder(order.ID)
func (c *CoinbasePro) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
return c.CancelExistingOrder(o.ID)
}
// CancelAllOrders cancels all orders associated with a currency pair
@@ -580,6 +587,9 @@ func (c *CoinbasePro) GetDepositAddress(cryptocurrency currency.Code, accountID
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (c *CoinbasePro) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := c.WithdrawCrypto(withdrawRequest.Amount, withdrawRequest.Currency.String(), withdrawRequest.Crypto.Address)
if err != nil {
return nil, err
@@ -592,6 +602,9 @@ func (c *CoinbasePro) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Requ
// WithdrawFiatFunds returns a withdrawal ID when a withdrawal is
// submitted
func (c *CoinbasePro) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
paymentMethods, err := c.GetPayMethods()
if err != nil {
return nil, err
@@ -621,6 +634,9 @@ func (c *CoinbasePro) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*wit
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
// withdrawal is submitted
func (c *CoinbasePro) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := c.WithdrawFiatFunds(withdrawRequest)
if err != nil {
return nil, err
@@ -642,6 +658,9 @@ func (c *CoinbasePro) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, er
// GetActiveOrders retrieves any orders that are active/open
func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var respOrders []GeneralizedOrderResponse
for i := range req.Pairs {
fpair, err := c.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
@@ -693,6 +712,9 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var respOrders []GeneralizedOrderResponse
for i := range req.Pairs {
fpair, err := c.FormatExchangeCurrency(req.Pairs[i], asset.Spot)

View File

@@ -550,13 +550,20 @@ func (c *Coinbene) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (c *Coinbene) CancelOrder(order *order.Cancel) error {
_, err := c.CancelSpotOrder(order.ID)
func (c *Coinbene) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := c.CancelSpotOrder(o.ID)
return err
}
// CancelAllOrders cancels all orders associated with a currency pair
func (c *Coinbene) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var resp order.CancelAllResponse
fpair, err := c.FormatExchangeCurrency(orderCancellation.Pair,
orderCancellation.AssetType)
@@ -626,6 +633,10 @@ func (c *Coinbene) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
// GetActiveOrders retrieves any orders that are active/open
func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
if len(getOrdersRequest.Pairs) == 0 {
allPairs, err := c.GetAllPairs()
if err != nil {
@@ -678,6 +689,10 @@ func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
if len(getOrdersRequest.Pairs) == 0 {
allPairs, err := c.GetAllPairs()
if err != nil {

View File

@@ -12,6 +12,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
@@ -289,11 +290,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "123",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "123",
AssetType: asset.Spot,
}
response, err := c.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -313,6 +315,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := c.CancelOrder(orderCancellation)
@@ -335,6 +338,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := c.CancelAllOrders(orderCancellation)
@@ -369,7 +373,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := c.ModifyOrder(&order.Modify{})
_, err := c.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -380,7 +384,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -202,6 +202,7 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
ID: strconv.FormatInt(cancel.OrderID, 10),
Status: order.Cancelled,
LastUpdated: time.Now(),
AssetType: asset.Spot,
}
case "cancel_orders":
var cancels WsCancelOrdersResponse
@@ -215,6 +216,7 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
ID: strconv.FormatInt(cancels.Results[i].OrderID, 10),
Status: order.Cancelled,
LastUpdated: time.Now(),
AssetType: asset.Spot,
}
}
case "trade_history":

View File

@@ -505,6 +505,10 @@ func (c *COINUT) GetExchangeHistory(p currency.Pair, assetType asset.Item, times
// SubmitOrder submits a new order
func (c *COINUT) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
if err := o.Validate(); err != nil {
return order.SubmitResponse{}, err
}
var submitOrderResponse order.SubmitResponse
var err error
if _, err = strconv.Atoi(o.ClientID); err != nil {
@@ -586,6 +590,10 @@ func (c *COINUT) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (c *COINUT) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
err := c.loadInstrumentsIfNotLoaded()
if err != nil {
return err
@@ -629,6 +637,10 @@ func (c *COINUT) CancelOrder(o *order.Cancel) error {
// CancelAllOrders cancels all orders associated with a currency pair
func (c *COINUT) CancelAllOrders(details *order.Cancel) (order.CancelAllResponse, error) {
if err := details.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var cancelAllOrdersResponse order.CancelAllResponse
err := c.loadInstrumentsIfNotLoaded()
if err != nil {
@@ -745,6 +757,10 @@ func (c *COINUT) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
err := c.loadInstrumentsIfNotLoaded()
if err != nil {
return nil, err
@@ -857,6 +873,10 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
err := c.loadInstrumentsIfNotLoaded()
if err != nil {
return nil, err

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -306,11 +307,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := e.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -331,6 +333,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := e.CancelOrder(orderCancellation)
@@ -353,6 +356,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := e.CancelAllOrders(orderCancellation)
@@ -373,7 +377,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := e.ModifyOrder(&order.Modify{})
_, err := e.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -388,7 +392,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -410,8 +410,12 @@ func (e *EXMO) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (e *EXMO) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (e *EXMO) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -464,6 +468,10 @@ func (e *EXMO) GetDepositAddress(cryptocurrency currency.Code, _ string) (string
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (e *EXMO) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := e.WithdrawCryptocurrency(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
withdrawRequest.Crypto.AddressTag,
@@ -497,6 +505,10 @@ func (e *EXMO) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
func (e *EXMO) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := e.GetOpenOrders()
if err != nil {
return nil, err
@@ -530,6 +542,10 @@ func (e *EXMO) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}

View File

@@ -822,7 +822,7 @@ func TestWithdrawCryptocurrencyFunds(t *testing.T) {
var cryptoData withdraw.CryptoRequest
cryptoData.Address = "testaddress123"
cryptoData.AddressTag = "testtag123"
request.Crypto = &cryptoData
request.Crypto = cryptoData
request.OneTimePassword = 123456
request.TradePassword = "incorrectTradePassword"
_, err := f.WithdrawCryptocurrencyFunds(request)
@@ -1111,6 +1111,10 @@ func TestGetExchangeHistory(t *testing.T) {
if err != nil {
t.Error(err)
}
_, err = f.GetExchangeHistory(p, a, time.Time{}, time.Now())
if err == nil {
t.Error("error cannot be nil ")
}
}
func TestTimestampFromFloat64(t *testing.T) {

View File

@@ -438,6 +438,15 @@ func (f *FTX) GetFundingHistory() ([]exchange.FundHistory, error) {
// GetExchangeHistory returns historic trade data within the timeframe provided.
func (f *FTX) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) {
if timestampStart.Equal(timestampEnd) ||
timestampEnd.After(time.Now()) ||
timestampEnd.Before(timestampStart) ||
(timestampStart.IsZero() && !timestampEnd.IsZero()) {
return nil, fmt.Errorf("invalid time range supplied. Start: %v End %v",
timestampStart,
timestampEnd)
}
marketName, err := f.FormatExchangeCurrency(p, assetType)
if err != nil {
return nil, err
@@ -523,6 +532,10 @@ func (f *FTX) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (f *FTX) ModifyOrder(action *order.Modify) (string, error) {
if err := action.Validate(); err != nil {
return "", err
}
if action.TriggerPrice != 0 {
a, err := f.ModifyTriggerOrder(action.ID,
action.Type.String(),
@@ -553,13 +566,20 @@ func (f *FTX) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (f *FTX) CancelOrder(order *order.Cancel) error {
_, err := f.DeleteOrder(order.ID)
func (f *FTX) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := f.DeleteOrder(o.ID)
return err
}
// CancelAllOrders cancels all orders associated with a currency pair
func (f *FTX) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var resp order.CancelAllResponse
formattedPair, err := f.FormatExchangeCurrency(orderCancellation.Pair, orderCancellation.AssetType)
if err != nil {
@@ -672,24 +692,24 @@ func (f *FTX) GetDepositAddress(cryptocurrency currency.Code, _ string) (string,
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (f *FTX) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
var address, addressTag string
if withdrawRequest.Crypto != nil {
address = withdrawRequest.Crypto.Address
addressTag = withdrawRequest.Crypto.AddressTag
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp := withdraw.ExchangeResponse{}
a, err := f.Withdraw(withdrawRequest.Currency.String(),
address,
addressTag,
resp, err := f.Withdraw(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
withdrawRequest.Crypto.AddressTag,
withdrawRequest.TradePassword,
strconv.FormatInt(withdrawRequest.OneTimePassword, 10),
withdrawRequest.Amount)
if err != nil {
return &resp, err
return nil, err
}
resp.ID = strconv.FormatInt(a.ID, 10)
resp.Status = a.Status
return &resp, nil
return &withdraw.ExchangeResponse{
ID: strconv.FormatInt(resp.ID, 10),
Status: resp.Status,
}, nil
}
// WithdrawFiatFunds returns a withdrawal ID when a withdrawal is
@@ -711,6 +731,10 @@ func (f *FTX) GetWebsocket() (*stream.Websocket, error) {
// GetActiveOrders retrieves any orders that are active/open
func (f *FTX) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var resp []order.Detail
for x := range getOrdersRequest.Pairs {
assetType, err := f.GetPairAssetType(getOrdersRequest.Pairs[x])
@@ -805,6 +829,9 @@ func (f *FTX) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var resp []order.Detail
for x := range getOrdersRequest.Pairs {
var tempResp order.Detail

View File

@@ -322,11 +322,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.LTC,
Quote: currency.BTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := g.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -347,6 +348,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := g.CancelOrder(orderCancellation)
@@ -369,6 +371,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := g.CancelAllOrders(orderCancellation)
@@ -403,7 +406,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := g.ModifyOrder(&order.Modify{})
_, err := g.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -414,7 +417,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -464,13 +464,17 @@ func (g *Gateio) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (g *Gateio) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (g *Gateio) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
fpair, err := g.FormatExchangeCurrency(order.Pair, order.AssetType)
fpair, err := g.FormatExchangeCurrency(o.Pair, o.AssetType)
if err != nil {
return err
}
@@ -561,7 +565,12 @@ func (g *Gateio) GetDepositAddress(cryptocurrency currency.Code, _ string) (stri
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (g *Gateio) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
return g.WithdrawCrypto(withdrawRequest.Currency.String(), withdrawRequest.Crypto.Address, withdrawRequest.Amount)
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
return g.WithdrawCrypto(withdrawRequest.Currency.String(),
withdrawRequest.Crypto.Address,
withdrawRequest.Amount)
}
// WithdrawFiatFunds returns a withdrawal ID when a
@@ -587,6 +596,10 @@ func (g *Gateio) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
var currPair string
if len(req.Pairs) == 1 {
@@ -675,6 +688,10 @@ func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (g *Gateio) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var trades []TradesResponse
for i := range req.Pairs {
resp, err := g.GetTradeHistory(req.Pairs[i].String())

View File

@@ -10,6 +10,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
"github.com/thrasher-corp/gocryptotrader/exchanges/stream"
@@ -402,11 +403,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.LTC,
Quote: currency.BTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 10,
Amount: 1,
ClientID: "1234234",
Side: order.Buy,
Type: order.Limit,
Price: 10,
Amount: 1,
ClientID: "1234234",
AssetType: asset.Spot,
}
response, err := g.SubmitOrder(orderSubmission)
@@ -426,7 +428,9 @@ func TestCancelExchangeOrder(t *testing.T) {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
var orderCancellation = &order.Cancel{
ID: "266029865",
ID: "266029865",
AssetType: asset.Spot,
Pair: currency.NewPair(currency.BTC, currency.USDT),
}
err := g.CancelOrder(orderCancellation)
@@ -452,6 +456,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := g.CancelAllOrders(orderCancellation)
@@ -471,7 +476,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestModifyOrder(t *testing.T) {
t.Parallel()
_, err := g.ModifyOrder(&order.Modify{})
_, err := g.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -483,7 +488,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -354,8 +354,12 @@ func (g *Gemini) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (g *Gemini) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (g *Gemini) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -399,6 +403,10 @@ func (g *Gemini) GetDepositAddress(cryptocurrency currency.Code, _ string) (stri
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (g *Gemini) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := g.WithdrawCrypto(withdrawRequest.Crypto.Address, withdrawRequest.Currency.String(), withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -435,6 +443,10 @@ func (g *Gemini) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := g.GetOrders()
if err != nil {
return nil, err
@@ -486,6 +498,10 @@ func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}

View File

@@ -307,11 +307,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.DGD,
Quote: currency.BTC,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := h.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -332,6 +333,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := h.CancelOrder(orderCancellation)
@@ -354,6 +356,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := h.CancelAllOrders(orderCancellation)
@@ -374,7 +377,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := h.ModifyOrder(&order.Modify{})
_, err := h.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -385,7 +388,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -499,8 +499,12 @@ func (h *HitBTC) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (h *HitBTC) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (h *HitBTC) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -551,6 +555,10 @@ func (h *HitBTC) GetDepositAddress(currency currency.Code, _ string) (string, er
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (h *HitBTC) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := h.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.Crypto.Address, withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -583,6 +591,10 @@ func (h *HitBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (h *HitBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}
@@ -629,6 +641,10 @@ func (h *HitBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (h *HitBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}

View File

@@ -495,11 +495,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USDT,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: strconv.FormatInt(accounts[0].ID, 10),
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: strconv.FormatInt(accounts[0].ID, 10),
AssetType: asset.Spot,
}
response, err := h.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -518,6 +519,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := h.CancelOrder(orderCancellation)
@@ -575,7 +577,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := h.ModifyOrder(&order.Modify{})
_, err := h.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -586,7 +588,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -609,8 +609,12 @@ func (h *HUOBI) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (h *HUOBI) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (h *HUOBI) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -621,6 +625,9 @@ func (h *HUOBI) CancelOrder(order *order.Cancel) error {
// CancelAllOrders cancels all orders associated with a currency pair
func (h *HUOBI) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var cancelAllOrdersResponse order.CancelAllResponse
enabledPairs, err := h.GetEnabledPairs(asset.Spot)
if err != nil {
@@ -750,7 +757,15 @@ func (h *HUOBI) GetDepositAddress(cryptocurrency currency.Code, accountID string
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (h *HUOBI) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
resp, err := h.Withdraw(withdrawRequest.Currency, withdrawRequest.Crypto.Address, withdrawRequest.Crypto.AddressTag, withdrawRequest.Amount, withdrawRequest.Crypto.FeeAmount)
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := h.Withdraw(withdrawRequest.Currency,
withdrawRequest.Crypto.Address,
withdrawRequest.Crypto.AddressTag,
withdrawRequest.Amount,
withdrawRequest.Crypto.FeeAmount)
if err != nil {
return nil, err
}
@@ -782,6 +797,10 @@ func (h *HUOBI) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}
@@ -889,6 +908,10 @@ func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if len(req.Pairs) == 0 {
return nil, errors.New("currency must be supplied")
}

View File

@@ -50,7 +50,7 @@ type IBotExchange interface {
GetFundingHistory() ([]FundHistory, error)
SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
ModifyOrder(action *order.Modify) (string, error)
CancelOrder(order *order.Cancel) error
CancelOrder(o *order.Cancel) error
CancelAllOrders(orders *order.Cancel) (order.CancelAllResponse, error)
GetOrderInfo(orderID string) (order.Detail, error)
GetDepositAddress(cryptocurrency currency.Code, accountID string) (string, error)

View File

@@ -11,6 +11,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -307,11 +308,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := i.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -332,6 +334,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := i.CancelOrder(orderCancellation)
@@ -355,6 +358,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := i.CancelAllOrders(orderCancellation)
@@ -384,7 +388,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := i.ModifyOrder(&order.Modify{})
_, err := i.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -395,7 +399,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -370,12 +370,18 @@ func (i *ItBit) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (i *ItBit) CancelOrder(order *order.Cancel) error {
return i.CancelExistingOrder(order.WalletAddress, order.ID)
func (i *ItBit) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
return i.CancelExistingOrder(o.WalletAddress, o.ID)
}
// CancelAllOrders cancels all orders associated with a currency pair
func (i *ItBit) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
cancelAllOrdersResponse := order.CancelAllResponse{
Status: make(map[string]string),
}
@@ -437,6 +443,9 @@ func (i *ItBit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
wallets, err := i.GetWallets(url.Values{})
if err != nil {
return nil, err
@@ -497,6 +506,10 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
wallets, err := i.GetWallets(url.Values{})
if err != nil {
return nil, err

View File

@@ -502,11 +502,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.XBT,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := k.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -523,7 +524,8 @@ func TestCancelExchangeOrder(t *testing.T) {
}
var orderCancellation = &order.Cancel{
ID: "OGEX6P-B5Q74-IGZ72R",
ID: "OGEX6P-B5Q74-IGZ72R",
AssetType: asset.Spot,
}
err := k.CancelOrder(orderCancellation)
@@ -541,7 +543,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
resp, err := k.CancelAllOrders(&order.Cancel{})
resp, err := k.CancelAllOrders(&order.Cancel{AssetType: asset.Spot})
if !areTestAPIKeysSet() && err == nil {
t.Error("Expecting an error when no keys are set")
}
@@ -574,7 +576,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := k.ModifyOrder(&order.Modify{})
_, err := k.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -583,7 +585,7 @@ func TestModifyOrder(t *testing.T) {
// TestWithdraw wrapper test
func TestWithdraw(t *testing.T) {
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
Amount: -1,

View File

@@ -571,11 +571,14 @@ func (k *Kraken) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (k *Kraken) CancelOrder(order *order.Cancel) error {
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
return k.wsCancelOrders([]string{order.ID})
func (k *Kraken) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
_, err := k.CancelExistingOrder(order.ID)
if k.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
return k.wsCancelOrders([]string{o.ID})
}
_, err := k.CancelExistingOrder(o.ID)
return err
}
@@ -693,6 +696,9 @@ func (k *Kraken) GetDepositAddress(cryptocurrency currency.Code, _ string) (stri
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal
// Populate exchange.WithdrawRequest.TradePassword with withdrawal key name, as set up on your account
func (k *Kraken) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := k.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.TradePassword, withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -705,6 +711,9 @@ func (k *Kraken) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request)
// WithdrawFiatFunds returns a withdrawal ID when a
// withdrawal is submitted
func (k *Kraken) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := k.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.TradePassword, withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -717,6 +726,9 @@ func (k *Kraken) WithdrawFiatFunds(withdrawRequest *withdraw.Request) (*withdraw
// WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a
// withdrawal is submitted
func (k *Kraken) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := k.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.TradePassword, withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -737,6 +749,9 @@ func (k *Kraken) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (k *Kraken) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := k.GetOpenOrders(OrderInfoOptions{})
if err != nil {
return nil, err
@@ -786,6 +801,9 @@ func (k *Kraken) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
req := GetClosedOrdersOptions{}
if getOrdersRequest.StartTicks.Unix() > 0 {
req.Start = strconv.FormatInt(getOrdersRequest.StartTicks.Unix(), 10)

View File

@@ -303,11 +303,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.EUR,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := l.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -328,6 +329,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := l.CancelOrder(orderCancellation)
@@ -350,6 +352,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := l.CancelAllOrders(orderCancellation)
@@ -370,7 +373,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := l.ModifyOrder(&order.Modify{})
_, err := l.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -381,7 +384,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -370,9 +370,12 @@ func (l *LakeBTC) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (l *LakeBTC) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (l *LakeBTC) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -420,6 +423,10 @@ func (l *LakeBTC) GetDepositAddress(cryptocurrency currency.Code, _ string) (str
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (l *LakeBTC) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
if withdrawRequest.Currency != currency.BTC {
return nil, errors.New("only BTC supported for withdrawals")
}
@@ -457,6 +464,10 @@ func (l *LakeBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
// GetActiveOrders retrieves any orders that are active/open
func (l *LakeBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := l.GetOpenOrders()
if err != nil {
return nil, err
@@ -499,6 +510,10 @@ func (l *LakeBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (l *LakeBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := l.GetOrders([]int64{})
if err != nil {
return nil, err

View File

@@ -317,11 +317,12 @@ func TestSubmitOrder(t *testing.T) {
Quote: currency.USDT,
Delimiter: "_",
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := l.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -339,6 +340,7 @@ func TestCancelOrder(t *testing.T) {
cp := currency.NewPairWithDelimiter(currency.ETH.String(), currency.BTC.String(), "_")
var a order.Cancel
a.Pair = cp
a.AssetType = asset.Spot
a.ID = "24f7ce27-af1d-4dca-a8c1-ef1cbeec1b23"
err := l.CancelOrder(&a)
if err != nil {

View File

@@ -372,17 +372,24 @@ func (l *Lbank) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (l *Lbank) CancelOrder(order *order.Cancel) error {
fpair, err := l.FormatExchangeCurrency(order.Pair, order.AssetType)
func (l *Lbank) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
fpair, err := l.FormatExchangeCurrency(o.Pair, o.AssetType)
if err != nil {
return err
}
_, err = l.RemoveOrder(fpair.String(), order.ID)
_, err = l.RemoveOrder(fpair.String(), o.ID)
return err
}
// CancelAllOrders cancels all orders associated with a currency pair
func (l *Lbank) CancelAllOrders(orders *order.Cancel) (order.CancelAllResponse, error) {
func (l *Lbank) CancelAllOrders(o *order.Cancel) (order.CancelAllResponse, error) {
if err := o.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
var resp order.CancelAllResponse
orderIDs, err := l.getAllOpenOrderID()
if err != nil {
@@ -390,7 +397,7 @@ func (l *Lbank) CancelAllOrders(orders *order.Cancel) (order.CancelAllResponse,
}
for key := range orderIDs {
if key != orders.Pair.String() {
if key != o.Pair.String() {
continue
}
var x, y = 0, 0
@@ -505,6 +512,10 @@ func (l *Lbank) GetDepositAddress(cryptocurrency currency.Code, accountID string
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (l *Lbank) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := l.Withdraw(withdrawRequest.Crypto.Address, withdrawRequest.Currency.String(),
strconv.FormatFloat(withdrawRequest.Amount, 'f', -1, 64), "",
withdrawRequest.Description, "")
@@ -530,6 +541,10 @@ func (l *Lbank) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.R
// GetActiveOrders retrieves any orders that are active/open
func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var finalResp []order.Detail
var resp order.Detail
tempData, err := l.getAllOpenOrderID()
@@ -602,6 +617,10 @@ func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]ord
// GetOrderHistory retrieves account order information *
// Can Limit response to specific order status
func (l *Lbank) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var finalResp []order.Detail
var resp order.Detail
var tempCurr currency.Pairs

View File

@@ -7,6 +7,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -253,11 +254,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.EUR,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := l.SubmitOrder(orderSubmission)
switch {
@@ -281,6 +283,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
}
err := l.CancelOrder(orderCancellation)
@@ -305,6 +308,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
}
resp, err := l.CancelAllOrders(orderCancellation)
@@ -325,7 +329,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
func TestModifyOrder(t *testing.T) {
t.Parallel()
_, err := l.ModifyOrder(&order.Modify{})
_, err := l.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err != common.ErrFunctionNotSupported {
t.Error("ModifyOrder() error", err)
}
@@ -338,7 +342,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -366,8 +366,11 @@ func (l *LocalBitcoins) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (l *LocalBitcoins) CancelOrder(order *order.Cancel) error {
return l.DeleteAd(order.ID)
func (l *LocalBitcoins) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
return l.DeleteAd(o.ID)
}
// CancelAllOrders cancels all orders associated with a currency pair
@@ -410,6 +413,10 @@ func (l *LocalBitcoins) GetDepositAddress(cryptocurrency currency.Code, _ string
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (l *LocalBitcoins) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
err := l.WalletSend(withdrawRequest.Crypto.Address,
withdrawRequest.Amount,
withdrawRequest.PIN)
@@ -442,6 +449,10 @@ func (l *LocalBitcoins) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64,
// GetActiveOrders retrieves any orders that are active/open
func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
resp, err := l.GetDashboardInfo()
if err != nil {
return nil, err
@@ -494,6 +505,10 @@ func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if err := getOrdersRequest.Validate(); err != nil {
return nil, err
}
var allTrades []DashBoardInfo
resp, err := l.GetDashboardCancelledTrades()
if err != nil {

View File

@@ -966,11 +966,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: -1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: -1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := o.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -1022,7 +1023,7 @@ func TestGetAccountInfo(t *testing.T) {
// TestModifyOrder Wrapper test
func TestModifyOrder(t *testing.T) {
TestSetRealOrderDefaults(t)
_, err := o.ModifyOrder(&order.Modify{})
_, err := o.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err != common.ErrFunctionNotSupported {
t.Errorf("Expected '%v', received: '%v'", common.ErrFunctionNotSupported, err)
}
@@ -1033,7 +1034,7 @@ func TestWithdraw(t *testing.T) {
TestSetRealOrderDefaults(t)
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
FeeAmount: 1,
},

View File

@@ -1687,11 +1687,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USDT,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := o.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -1747,7 +1748,7 @@ func TestGetAccountInfo(t *testing.T) {
func TestModifyOrder(t *testing.T) {
TestSetRealOrderDefaults(t)
t.Parallel()
_, err := o.ModifyOrder(&order.Modify{})
_, err := o.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err != common.ErrFunctionNotSupported {
t.Errorf("Expected '%v', received: '%v'",
common.ErrFunctionNotSupported,
@@ -1760,7 +1761,7 @@ func TestWithdraw(t *testing.T) {
TestSetRealOrderDefaults(t)
t.Parallel()
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
FeeAmount: 1,
},

View File

@@ -306,14 +306,19 @@ func (o *OKGroup) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (o *OKGroup) CancelOrder(orderCancellation *order.Cancel) (err error) {
orderID, err := strconv.ParseInt(orderCancellation.ID, 10, 64)
func (o *OKGroup) CancelOrder(cancel *order.Cancel) (err error) {
err = cancel.Validate(cancel.StandardCancel())
if err != nil {
return
}
fpair, err := o.FormatExchangeCurrency(orderCancellation.Pair,
orderCancellation.AssetType)
orderID, err := strconv.ParseInt(cancel.ID, 10, 64)
if err != nil {
return
}
fpair, err := o.FormatExchangeCurrency(cancel.Pair,
cancel.AssetType)
if err != nil {
return
}
@@ -333,6 +338,10 @@ func (o *OKGroup) CancelOrder(orderCancellation *order.Cancel) (err error) {
// CancelAllOrders cancels all orders associated with a currency pair
func (o *OKGroup) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
if err := orderCancellation.Validate(); err != nil {
return order.CancelAllResponse{}, err
}
orderIDs := strings.Split(orderCancellation.ID, ",")
resp := order.CancelAllResponse{}
resp.Status = make(map[string]string)
@@ -410,6 +419,10 @@ func (o *OKGroup) GetDepositAddress(p currency.Code, accountID string) (string,
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (o *OKGroup) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
withdrawal, err := o.AccountWithdraw(AccountWithdrawRequest{
Amount: withdrawRequest.Amount,
Currency: withdrawRequest.Currency.Lower().String(),
@@ -447,13 +460,20 @@ func (o *OKGroup) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
// GetActiveOrders retrieves any orders that are active/open
func (o *OKGroup) GetActiveOrders(req *order.GetOrdersRequest) (resp []order.Detail, err error) {
err = req.Validate()
if err != nil {
return nil, err
}
for x := range req.Pairs {
fpair, err := o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
var fPair currency.Pair
fPair, err = o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
if err != nil {
return nil, err
}
spotOpenOrders, err := o.GetSpotOpenOrders(GetSpotOpenOrdersRequest{
InstrumentID: fpair.String(),
var spotOpenOrders []GetSpotOrderResponse
spotOpenOrders, err = o.GetSpotOpenOrders(GetSpotOpenOrdersRequest{
InstrumentID: fPair.String(),
})
if err != nil {
return resp, err
@@ -473,21 +493,27 @@ func (o *OKGroup) GetActiveOrders(req *order.GetOrdersRequest) (resp []order.Det
})
}
}
return
return resp, err
}
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (o *OKGroup) GetOrderHistory(req *order.GetOrdersRequest) (resp []order.Detail, err error) {
err = req.Validate()
if err != nil {
return nil, err
}
for x := range req.Pairs {
fpair, err := o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
var fPair currency.Pair
fPair, err = o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
if err != nil {
return nil, err
}
spotOpenOrders, err := o.GetSpotOrders(GetSpotOrdersRequest{
var spotOpenOrders []GetSpotOrderResponse
spotOpenOrders, err = o.GetSpotOrders(GetSpotOrdersRequest{
Status: strings.Join([]string{"filled", "cancelled", "failure"}, "|"),
InstrumentID: fpair.String(),
InstrumentID: fPair.String(),
})
if err != nil {
return resp, err
@@ -507,8 +533,7 @@ func (o *OKGroup) GetOrderHistory(req *order.GetOrdersRequest) (resp []order.Det
})
}
}
return
return resp, err
}
// GetFeeByType returns an estimate of fee based on type of transaction

View File

@@ -7,13 +7,18 @@ import (
"time"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
)
var errValidationCheckFailed = errors.New("validation check failed")
func TestValidate(t *testing.T) {
testPair := currency.NewPair(currency.BTC, currency.LTC)
tester := []struct {
ExpectedErr error
Submit *Submit
ValidOpts validate.Checker
}{
{
ExpectedErr: ErrSubmissionIsNil,
@@ -25,55 +30,83 @@ func TestValidate(t *testing.T) {
}, // empty pair
{
ExpectedErr: ErrSideIsInvalid,
ExpectedErr: ErrAssetNotSet,
Submit: &Submit{Pair: testPair},
}, // valid pair but invalid asset
{
ExpectedErr: ErrSideIsInvalid,
Submit: &Submit{Pair: testPair, AssetType: asset.Spot},
}, // valid pair but invalid order side
{
ExpectedErr: ErrTypeIsInvalid,
Submit: &Submit{Pair: testPair,
Side: Buy},
Side: Buy,
AssetType: asset.Spot},
}, // valid pair and order side but invalid order type
{
ExpectedErr: ErrTypeIsInvalid,
Submit: &Submit{Pair: testPair,
Side: Sell},
Side: Sell,
AssetType: asset.Spot},
}, // valid pair and order side but invalid order type
{
ExpectedErr: ErrTypeIsInvalid,
Submit: &Submit{Pair: testPair,
Side: Bid},
Side: Bid,
AssetType: asset.Spot},
}, // valid pair and order side but invalid order type
{
ExpectedErr: ErrTypeIsInvalid,
Submit: &Submit{Pair: testPair,
Side: Ask},
Side: Ask,
AssetType: asset.Spot},
}, // valid pair and order side but invalid order type
{
ExpectedErr: ErrAmountIsInvalid,
Submit: &Submit{Pair: testPair,
Side: Ask,
Type: Market},
Side: Ask,
Type: Market,
AssetType: asset.Spot},
}, // valid pair, order side, type but invalid amount
{
ExpectedErr: ErrPriceMustBeSetIfLimitOrder,
Submit: &Submit{Pair: testPair,
Side: Ask,
Type: Limit,
Amount: 1},
Side: Ask,
Type: Limit,
Amount: 1,
AssetType: asset.Spot},
}, // valid pair, order side, type, amount but invalid price
{
ExpectedErr: errValidationCheckFailed,
Submit: &Submit{Pair: testPair,
Side: Ask,
Type: Limit,
Amount: 1,
Price: 1000,
AssetType: asset.Spot},
ValidOpts: validate.Check(func() error { return errValidationCheckFailed }),
}, // custom validation error check
{
ExpectedErr: nil,
Submit: &Submit{Pair: testPair,
Side: Ask,
Type: Limit,
Amount: 1,
Price: 1000},
Side: Ask,
Type: Limit,
Amount: 1,
Price: 1000,
AssetType: asset.Spot},
ValidOpts: validate.Check(func() error { return nil }),
}, // valid order!
}
for x := range tester {
if err := tester[x].Submit.Validate(); err != tester[x].ExpectedErr {
t.Errorf("Unexpected result. Got: %s, want: %s", err, tester[x].ExpectedErr)
if err := tester[x].Submit.Validate(tester[x].ValidOpts); err != tester[x].ExpectedErr {
if err != nil && tester[x].ExpectedErr != nil {
if err.Error() == tester[x].ExpectedErr.Error() {
continue
}
}
t.Errorf("Unexpected result. Got: %v, want: %v", err, tester[x].ExpectedErr)
}
}
}
@@ -949,3 +982,103 @@ func TestClassificationError_Error(t *testing.T) {
t.Fatal("unexpected output")
}
}
func TestValidationOnOrderTypes(t *testing.T) {
var cancelMe *Cancel
if cancelMe.Validate() != ErrCancelOrderIsNil {
t.Fatal("unexpected error")
}
cancelMe = new(Cancel)
if cancelMe.Validate() != ErrPairIsEmpty {
t.Fatal("unexpected error")
}
cancelMe.Pair = currency.NewPair(currency.BTC, currency.USDT)
if cancelMe.Validate() != ErrAssetNotSet {
t.Fatal("unexpected error")
}
cancelMe.AssetType = asset.Spot
if cancelMe.Validate() != nil {
t.Fatal("should not error")
}
if cancelMe.Validate(cancelMe.StandardCancel()) == nil {
t.Fatal("expected error")
}
if cancelMe.Validate(validate.Check(func() error {
return nil
})) != nil {
t.Fatal("should return nil")
}
cancelMe.ID = "1337"
if cancelMe.Validate(cancelMe.StandardCancel()) != nil {
t.Fatal("should return nil")
}
var getOrders *GetOrdersRequest
if getOrders.Validate() != ErrGetOrdersRequestIsNil {
t.Fatal("unexpected error")
}
getOrders = new(GetOrdersRequest)
if getOrders.Validate() != nil {
t.Fatal("should not error")
}
if getOrders.Validate(validate.Check(func() error {
return errors.New("this should error")
})) == nil {
t.Fatal("expected error")
}
if getOrders.Validate(validate.Check(func() error {
return nil
})) != nil {
t.Fatal("unexpected error")
}
var modifyOrder *Modify
if modifyOrder.Validate() != ErrModifyOrderIsNil {
t.Fatal("unexpected error")
}
modifyOrder = new(Modify)
if modifyOrder.Validate() != ErrPairIsEmpty {
t.Fatal("unexpected error")
}
p, err := currency.NewPairFromString("BTC-USD")
if err != nil {
t.Fatal(err)
}
modifyOrder.Pair = p
if modifyOrder.Validate() != ErrAssetNotSet {
t.Fatal("unexpected error")
}
modifyOrder.AssetType = asset.Spot
if modifyOrder.Validate() != ErrOrderIDNotSet {
t.Fatal("unexpected error")
}
modifyOrder.ClientOrderID = "1337"
if modifyOrder.Validate() != nil {
t.Fatal("should not error")
}
if modifyOrder.Validate(validate.Check(func() error {
return errors.New("this should error")
})) == nil {
t.Fatal("expected error")
}
if modifyOrder.Validate(validate.Check(func() error {
return nil
})) != nil {
t.Fatal("unexpected error")
}
}

View File

@@ -11,11 +11,16 @@ import (
// var error definitions
var (
ErrSubmissionIsNil = errors.New("order submission is nil")
ErrCancelOrderIsNil = errors.New("cancel order is nil")
ErrGetOrdersRequestIsNil = errors.New("get order request is nil")
ErrModifyOrderIsNil = errors.New("modify order request is nil")
ErrPairIsEmpty = errors.New("order pair is empty")
ErrAssetNotSet = errors.New("order asset type is not set")
ErrSideIsInvalid = errors.New("order side is invalid")
ErrTypeIsInvalid = errors.New("order type is invalid")
ErrAmountIsInvalid = errors.New("order amount is invalid")
ErrPriceMustBeSetIfLimitOrder = errors.New("order price must be set if limit order type is desired")
ErrOrderIDNotSet = errors.New("order id or client order id is not set")
)
// Submit contains all properties of an order that may be required

View File

@@ -7,11 +7,13 @@ import (
"strings"
"time"
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/validate"
)
// Validate checks the supplied data and returns whether or not it's valid
func (s *Submit) Validate() error {
func (s *Submit) Validate(opt ...validate.Checker) error {
if s == nil {
return ErrSubmissionIsNil
}
@@ -20,6 +22,10 @@ func (s *Submit) Validate() error {
return ErrPairIsEmpty
}
if s.AssetType == "" {
return ErrAssetNotSet
}
if s.Side != Buy &&
s.Side != Sell &&
s.Side != Bid &&
@@ -39,6 +45,18 @@ func (s *Submit) Validate() error {
return ErrPriceMustBeSetIfLimitOrder
}
var errs common.Errors
for _, o := range opt {
err := o.Check()
if err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return errs
}
return nil
}
@@ -676,3 +694,92 @@ func (o *ClassificationError) Error() string {
o.Exchange,
o.Err)
}
// StandardCancel defines an option in the validator to make sure an ID is set
// for a standard cancel
func (c *Cancel) StandardCancel() validate.Checker {
return validate.Check(func() error {
if c.ID == "" {
return errors.New("ID not set")
}
return nil
})
}
// Validate checks internal struct requirements
func (c *Cancel) Validate(opt ...validate.Checker) error {
if c == nil {
return ErrCancelOrderIsNil
}
if c.Pair.IsEmpty() {
return ErrPairIsEmpty
}
if c.AssetType == "" {
return ErrAssetNotSet
}
var errs common.Errors
for _, o := range opt {
err := o.Check()
if err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return errs
}
return nil
}
// Validate checks internal struct requirements
func (g *GetOrdersRequest) Validate(opt ...validate.Checker) error {
if g == nil {
return ErrGetOrdersRequestIsNil
}
var errs common.Errors
for _, o := range opt {
err := o.Check()
if err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return errs
}
return nil
}
// Validate checks internal struct requirements
func (m *Modify) Validate(opt ...validate.Checker) error {
if m == nil {
return ErrModifyOrderIsNil
}
if m.Pair.IsEmpty() {
return ErrPairIsEmpty
}
if m.AssetType.String() == "" {
return ErrAssetNotSet
}
var errs common.Errors
for _, o := range opt {
err := o.Check()
if err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return errs
}
if m.ClientOrderID == "" && m.ID == "" {
return ErrOrderIDNotSet
}
return nil
}

View File

@@ -263,11 +263,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.LTC,
},
Side: order.Buy,
Type: order.Market,
Price: 10,
Amount: 10000000,
ClientID: "hi",
Side: order.Buy,
Type: order.Market,
Price: 10,
Amount: 10000000,
ClientID: "hi",
AssetType: asset.Spot,
}
response, err := p.SubmitOrder(orderSubmission)
@@ -291,6 +292,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
AssetType: asset.Spot,
}
err := p.CancelOrder(orderCancellation)
@@ -316,6 +318,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := p.CancelAllOrders(orderCancellation)
@@ -338,7 +341,10 @@ func TestModifyOrder(t *testing.T) {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := p.ModifyOrder(&order.Modify{ID: "1337", Price: 1337})
_, err := p.ModifyOrder(&order.Modify{ID: "1337",
Price: 1337,
AssetType: asset.Spot,
Pair: currency.NewPair(currency.BTC, currency.USDT)})
switch {
case areTestAPIKeysSet() && err != nil && mockTests:
t.Error("ModifyOrder() error", err)
@@ -352,7 +358,8 @@ func TestModifyOrder(t *testing.T) {
func TestWithdraw(t *testing.T) {
t.Parallel()
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Exchange: p.Name,
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
FeeAmount: 1,
},
@@ -371,8 +378,8 @@ func TestWithdraw(t *testing.T) {
t.Errorf("Withdraw failed to be placed: %v", err)
case !areTestAPIKeysSet() && !mockTests && err == nil:
t.Error("Expecting an error when no keys are set")
case mockTests && err != nil:
t.Error("Mock Withdraw() err", err)
case mockTests && err == nil:
t.Error("Mock Withdraw() err cannot be nil")
}
}

View File

@@ -445,6 +445,10 @@ func (p *Poloniex) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
// ModifyOrder will allow of changing orderbook placement and limit to
// market conversion
func (p *Poloniex) ModifyOrder(action *order.Modify) (string, error) {
if err := action.Validate(); err != nil {
return "", err
}
oID, err := strconv.ParseInt(action.ID, 10, 64)
if err != nil {
return "", err
@@ -463,8 +467,12 @@ func (p *Poloniex) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (p *Poloniex) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (p *Poloniex) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -520,6 +528,10 @@ func (p *Poloniex) GetDepositAddress(cryptocurrency currency.Code, _ string) (st
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (p *Poloniex) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := p.Withdraw(withdrawRequest.Currency.String(), withdrawRequest.Crypto.Address, withdrawRequest.Amount)
if err != nil {
return nil, err
@@ -552,6 +564,10 @@ func (p *Poloniex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
// GetActiveOrders retrieves any orders that are active/open
func (p *Poloniex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := p.GetOpenOrdersForAllCurrencies()
if err != nil {
return nil, err
@@ -603,6 +619,10 @@ func (p *Poloniex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (p *Poloniex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
resp, err := p.GetAuthenticatedTradeHistory(req.StartTicks.Unix(),
req.EndTicks.Unix(),
10000)

View File

@@ -0,0 +1,112 @@
# GoCryptoTrader package Validate
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
[![Build Status](https://travis-ci.org/thrasher-corp/gocryptotrader.svg?branch=master)](https://travis-ci.org/thrasher-corp/gocryptotrader)
[![Software License](https://img.shields.io/badge/License-MIT-orange.svg?style=flat-square)](https://github.com/thrasher-corp/gocryptotrader/blob/master/LICENSE)
[![GoDoc](https://godoc.org/github.com/thrasher-corp/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-corp/gocryptotrader/exchanges/validate)
[![Coverage Status](http://codecov.io/github/thrasher-corp/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-corp/gocryptotrader?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/thrasher-corp/gocryptotrader)](https://goreportcard.com/report/github.com/thrasher-corp/gocryptotrader)
This validate package is part of the GoCryptoTrader codebase.
## This is still in active development
You can track ideas, planned features and what's in progress on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
Join our slack to discuss all things related to GoCryptoTrader! [GoCryptoTrader Slack](https://join.slack.com/t/gocryptotrader/shared_invite/enQtNTQ5NDAxMjA2Mjc5LTc5ZDE1ZTNiOGM3ZGMyMmY1NTAxYWZhODE0MWM5N2JlZDk1NDU0YTViYzk4NTk3OTRiMDQzNGQ1YTc4YmRlMTk)
## Current Features for validate
+ This package allows for validation options to occur exchange side e.g.
- Checking for ID in an order cancellation struct.
- Determining the correct withdrawal bank details for a specific exchange.
+ Example Usage below:
```go
// import package
"github.com/thrasher-corp/exchanges/validate"
// define your data structure across potential exchanges
type Critical struct {
ID string
Person string
Banks string
MoneysUSD float64
}
// define validation and add a variadic param
func (supercritcalinfo *Critical) Validate(opt ...validate.Checker) error {
// define base level validation
if supercritcalinfo != nil {
// oh no this is nil, could panic program!
}
// range over potential checks coming from individual packages
var errs common.Errors
for _, o := range opt {
err := o.Check()
if err != nil {
errs = append(errs, err)
}
}
if errs != nil {
return errs
}
return nil
}
// define an exchange or package level check that returns a validate.Checker
// interface
func (supercritcalinfo *Critical) PleaseDontSendMoneyToParents() validate.Checker {
return validate.Check(func() error {
if supercritcalinfo.Person == "Mother Dearest" ||
supercritcalinfo.Person == "Father Dearest" {
return errors.New("nope")
}
return nil
})
}
// Now in the package all you have to do is add in your options or not...
d := Critical{Person: "Mother Dearest", MoneysUSD: 1337.30}
// This should not error
err := d.Validate()
if err != nil {
return err
}
// This should error
err := d.Validate(d.PleaseDontSendMoneyToParents())
if err != nil {
return err
}
```
### Please click GoDocs chevron above to view current GoDoc information for this package
## Contribution
Please feel free to submit any pull requests or suggest any desired features to be added.
When submitting a PR, please abide by our coding guidelines:
+ Code must adhere to the official Go [formatting](https://golang.org/doc/effective_go.html#formatting) guidelines (i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
+ Code must be documented adhering to the official Go [commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
+ Code must adhere to our [coding style](https://github.com/thrasher-corp/gocryptotrader/blob/master/doc/coding_style.md).
+ Pull requests need to be based on and opened against the `master` branch.
## Donations
<img src="https://github.com/thrasher-corp/gocryptotrader/blob/master/web/src/assets/donate.png?raw=true" hspace="70">
If this framework helped you in any way, or you would like to support the developers working on it, please donate Bitcoin to:
***bc1qk0jareu4jytc0cfrhr5wgshsq8282awpavfahc***

View File

@@ -0,0 +1,15 @@
package validate
// Checker defines validation check functionality
type Checker interface {
Check() error
}
// Check defines a validation check function to close over individual validation
// check methods
type Check func() error
// Check initiates the Check functionality
func (v Check) Check() error {
return v()
}

View File

@@ -373,11 +373,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.BTC,
Quote: currency.USD,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := y.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && (err != nil || !response.IsOrderPlaced) {
@@ -398,6 +399,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := y.CancelOrder(orderCancellation)
@@ -420,6 +422,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := y.CancelAllOrders(orderCancellation)
@@ -440,7 +443,7 @@ func TestModifyOrder(t *testing.T) {
if areTestAPIKeysSet() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := y.ModifyOrder(&order.Modify{})
_, err := y.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -451,7 +454,7 @@ func TestWithdraw(t *testing.T) {
Amount: -1,
Currency: currency.BTC,
Description: "WITHDRAW IT ALL",
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
},
}

View File

@@ -364,8 +364,12 @@ func (y *Yobit) ModifyOrder(action *order.Modify) (string, error) {
}
// CancelOrder cancels an order by its corresponding ID number
func (y *Yobit) CancelOrder(order *order.Cancel) error {
orderIDInt, err := strconv.ParseInt(order.ID, 10, 64)
func (y *Yobit) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
}
@@ -434,7 +438,13 @@ func (y *Yobit) GetDepositAddress(cryptocurrency currency.Code, _ string) (strin
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (y *Yobit) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
resp, err := y.WithdrawCoinsToAddress(withdrawRequest.Currency.String(), withdrawRequest.Amount, withdrawRequest.Crypto.Address)
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
resp, err := y.WithdrawCoinsToAddress(withdrawRequest.Currency.String(),
withdrawRequest.Amount,
withdrawRequest.Crypto.Address)
if err != nil {
return nil, err
}
@@ -467,6 +477,10 @@ func (y *Yobit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
func (y *Yobit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var orders []order.Detail
format, err := y.GetPairFormat(asset.Spot, false)
@@ -512,6 +526,10 @@ func (y *Yobit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (y *Yobit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var allOrders []TradeHistory
for x := range req.Pairs {
fpair, err := y.FormatExchangeCurrency(req.Pairs[x], asset.Spot)

View File

@@ -316,11 +316,12 @@ func TestSubmitOrder(t *testing.T) {
Base: currency.XRP,
Quote: currency.USDT,
},
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
Side: order.Buy,
Type: order.Limit,
Price: 1,
Amount: 1,
ClientID: "meowOrder",
AssetType: asset.Spot,
}
response, err := z.SubmitOrder(orderSubmission)
if z.ValidateAPICredentials() && (err != nil || !response.IsOrderPlaced) {
@@ -341,6 +342,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
err := z.CancelOrder(orderCancellation)
@@ -363,6 +365,7 @@ func TestCancelAllExchangeOrders(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currencyPair,
AssetType: asset.Spot,
}
resp, err := z.CancelAllOrders(orderCancellation)
@@ -397,7 +400,7 @@ func TestModifyOrder(t *testing.T) {
if z.ValidateAPICredentials() && !canManipulateRealOrders {
t.Skip("API keys set, canManipulateRealOrders false, skipping test")
}
_, err := z.ModifyOrder(&order.Modify{})
_, err := z.ModifyOrder(&order.Modify{AssetType: asset.Spot})
if err == nil {
t.Error("ModifyOrder() Expected error")
}
@@ -405,7 +408,7 @@ func TestModifyOrder(t *testing.T) {
func TestWithdraw(t *testing.T) {
withdrawCryptoRequest := withdraw.Request{
Crypto: &withdraw.CryptoRequest{
Crypto: withdraw.CryptoRequest{
Address: core.BitcoinDonationAddress,
FeeAmount: 1,
},

View File

@@ -455,6 +455,10 @@ func (z *ZB) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (z *ZB) CancelOrder(o *order.Cancel) error {
if err := o.Validate(o.StandardCancel()); err != nil {
return err
}
orderIDInt, err := strconv.ParseInt(o.ID, 10, 64)
if err != nil {
return err
@@ -523,8 +527,9 @@ func (z *ZB) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
}
err = z.CancelOrder(&order.Cancel{
ID: strconv.FormatInt(allOpenOrders[i].ID, 10),
Pair: p,
ID: strconv.FormatInt(allOpenOrders[i].ID, 10),
Pair: p,
AssetType: asset.Spot,
})
if err != nil {
cancelAllOrdersResponse.Status[strconv.FormatInt(allOpenOrders[i].ID, 10)] = err.Error()
@@ -553,7 +558,16 @@ func (z *ZB) GetDepositAddress(cryptocurrency currency.Code, _ string) (string,
// WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is
// submitted
func (z *ZB) WithdrawCryptocurrencyFunds(withdrawRequest *withdraw.Request) (*withdraw.ExchangeResponse, error) {
v, err := z.Withdraw(withdrawRequest.Currency.Lower().String(), withdrawRequest.Crypto.Address, withdrawRequest.TradePassword, withdrawRequest.Amount, withdrawRequest.Crypto.FeeAmount, false)
if err := withdrawRequest.Validate(); err != nil {
return nil, err
}
v, err := z.Withdraw(withdrawRequest.Currency.Lower().String(),
withdrawRequest.Crypto.Address,
withdrawRequest.TradePassword,
withdrawRequest.Amount,
withdrawRequest.Crypto.FeeAmount,
false)
if err != nil {
return nil, err
}
@@ -586,6 +600,10 @@ func (z *ZB) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
// This function is not concurrency safe due to orderSide/orderType maps
func (z *ZB) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
var allOrders []Order
for x := range req.Pairs {
for i := int64(1); ; i++ {
@@ -648,6 +666,10 @@ func (z *ZB) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error
// Can Limit response to specific order status
// This function is not concurrency safe due to orderSide/orderType maps
func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
if err := req.Validate(); err != nil {
return nil, err
}
if req.Side == order.AnySide || req.Side == "" {
return nil, errors.New("specific order side is required")
}