mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 15:09:57 +00:00
poloniex: websocket update (#659)
* poloniex: websocket update with debug output and currency tracking system * linter: fix issues * nits: Addr * poloniex: govet fix * nits: addr * Bittrex: Fix fee test
This commit is contained in:
@@ -47,3 +47,12 @@ type Balance struct {
|
||||
TotalValue float64
|
||||
Hold float64
|
||||
}
|
||||
|
||||
// Change defines incoming balance change on currency holdings
|
||||
type Change struct {
|
||||
Exchange string
|
||||
Currency currency.Code
|
||||
Asset asset.Item
|
||||
Amount float64
|
||||
Account string
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
b.Websocket.DataHandler <- &order.Cancel{
|
||||
b.Websocket.DataHandler <- &order.Modify{
|
||||
Price: response.Data[x].Price,
|
||||
Amount: response.Data[x].OrderQuantity,
|
||||
Exchange: b.Name,
|
||||
|
||||
@@ -304,8 +304,8 @@ func TestGetFee(t *testing.T) {
|
||||
// CryptocurrencyWithdrawalFee Basic
|
||||
feeBuilder = setFeeBuilder()
|
||||
feeBuilder.FeeType = exchange.CryptocurrencyWithdrawalFee
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.00015) || err != nil {
|
||||
t.Errorf("Expected: %f, Received: %f", float64(0.00015), resp)
|
||||
if resp, err := b.GetFee(feeBuilder); resp != float64(0.0003) || err != nil {
|
||||
t.Errorf("Expected: %f, Received: %f", float64(0.0003), resp)
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
|
||||
@@ -238,6 +238,7 @@ const (
|
||||
Open Status = "OPEN"
|
||||
AutoDeleverage Status = "ADL"
|
||||
Closed Status = "CLOSED"
|
||||
Pending Status = "PENDING"
|
||||
)
|
||||
|
||||
// Type enforces a standard for order types across the code base
|
||||
|
||||
235
exchanges/poloniex/currency_details.go
Normal file
235
exchanges/poloniex/currency_details.go
Normal file
@@ -0,0 +1,235 @@
|
||||
package poloniex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
// CurrencyDetails stores a map of currencies associated with their ID
|
||||
type CurrencyDetails struct {
|
||||
pairs map[float64]PairSummaryInfo
|
||||
codes map[float64]CodeSummaryInfo
|
||||
// Mutex used for future when we will periodically update this table every
|
||||
// week or so in production
|
||||
m sync.RWMutex
|
||||
}
|
||||
|
||||
// PairSummaryInfo defines currency pair information
|
||||
type PairSummaryInfo struct {
|
||||
Pair currency.Pair
|
||||
IsFrozen bool
|
||||
PostOnly bool
|
||||
}
|
||||
|
||||
// CodeSummaryInfo defines currency information
|
||||
type CodeSummaryInfo struct {
|
||||
Currency currency.Code
|
||||
WithdrawalTXFee float64
|
||||
MinimumConfirmations int64
|
||||
DepositAddress string
|
||||
WithdrawalDepositDisabled bool
|
||||
Frozen bool
|
||||
}
|
||||
|
||||
var (
|
||||
errCannotLoadNoData = errors.New("cannot load websocket currency data as data is nil")
|
||||
errNoDepositAddress = errors.New("no public deposit address for currency")
|
||||
errPairMapIsNil = errors.New("cannot get currency pair, map is nil")
|
||||
errCodeMapIsNil = errors.New("cannot get currency code, map is nil")
|
||||
errCurrencyNotFoundInMap = errors.New("currency not found")
|
||||
)
|
||||
|
||||
// loadPairs loads currency pair associations with unique identifiers from
|
||||
// ticker data map
|
||||
func (w *CurrencyDetails) loadPairs(data map[string]Ticker) error {
|
||||
if data == nil {
|
||||
return errCannotLoadNoData
|
||||
}
|
||||
w.m.Lock()
|
||||
defer w.m.Unlock()
|
||||
for k, v := range data {
|
||||
pair, err := currency.NewPairFromString(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if w.pairs == nil {
|
||||
w.pairs = make(map[float64]PairSummaryInfo)
|
||||
}
|
||||
w.pairs[v.ID] = PairSummaryInfo{
|
||||
Pair: pair,
|
||||
IsFrozen: v.IsFrozen == 1,
|
||||
PostOnly: v.PostOnly == 1,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadCodes loads currency codes from currency map
|
||||
func (w *CurrencyDetails) loadCodes(data map[string]Currencies) error {
|
||||
if data == nil {
|
||||
return errCannotLoadNoData
|
||||
}
|
||||
w.m.Lock()
|
||||
defer w.m.Unlock()
|
||||
for k, v := range data {
|
||||
if v.Delisted == 1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if w.codes == nil {
|
||||
w.codes = make(map[float64]CodeSummaryInfo)
|
||||
}
|
||||
|
||||
w.codes[v.ID] = CodeSummaryInfo{
|
||||
Currency: currency.NewCode(k),
|
||||
WithdrawalTXFee: v.TxFee,
|
||||
MinimumConfirmations: v.MinConfirmations,
|
||||
DepositAddress: v.DepositAddress,
|
||||
WithdrawalDepositDisabled: v.WithdrawalDepositDisabled == 1,
|
||||
Frozen: v.Frozen == 1,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPair returns a currency pair by its ID
|
||||
func (w *CurrencyDetails) GetPair(id float64) (currency.Pair, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.pairs == nil {
|
||||
return currency.Pair{}, errPairMapIsNil
|
||||
}
|
||||
|
||||
p, ok := w.pairs[id]
|
||||
if ok {
|
||||
return p.Pair, nil
|
||||
}
|
||||
|
||||
// This is here so we can still log an order with the ID as the currency
|
||||
// pair which you can then cross reference later with the exchange ID list,
|
||||
// rather than error out.
|
||||
op, err := currency.NewPairFromString(strconv.FormatFloat(id, 'f', -1, 64))
|
||||
if err != nil {
|
||||
return op, err
|
||||
}
|
||||
return op, errIDNotFoundInPairMap
|
||||
}
|
||||
|
||||
// GetCode returns a currency code by its ID
|
||||
func (w *CurrencyDetails) GetCode(id float64) (currency.Code, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return currency.Code{}, errCodeMapIsNil
|
||||
}
|
||||
c, ok := w.codes[id]
|
||||
if ok {
|
||||
return c.Currency, nil
|
||||
}
|
||||
return currency.Code{}, errIDNotFoundInCodeMap
|
||||
}
|
||||
|
||||
// GetWithdrawalTXFee returns withdrawal transaction fee for the currency
|
||||
func (w *CurrencyDetails) GetWithdrawalTXFee(c currency.Code) (float64, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return 0, errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.codes {
|
||||
if v.Currency == c {
|
||||
return v.WithdrawalTXFee, nil
|
||||
}
|
||||
}
|
||||
return 0, errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// GetDepositAddress returns the public deposit address details for the currency
|
||||
func (w *CurrencyDetails) GetDepositAddress(c currency.Code) (string, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return "", errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.codes {
|
||||
if v.Currency == c {
|
||||
if v.DepositAddress == "" {
|
||||
return "", errNoDepositAddress
|
||||
}
|
||||
return v.DepositAddress, nil
|
||||
}
|
||||
}
|
||||
return "", errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// IsWithdrawAndDepositsEnabled returns if withdrawals or deposits are enabled
|
||||
func (w *CurrencyDetails) IsWithdrawAndDepositsEnabled(c currency.Code) (bool, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return false, errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.codes {
|
||||
if v.Currency == c {
|
||||
return !v.WithdrawalDepositDisabled, nil
|
||||
}
|
||||
}
|
||||
return false, errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// IsTradingEnabledForCurrency returns if the currency is allowed to be traded
|
||||
func (w *CurrencyDetails) IsTradingEnabledForCurrency(c currency.Code) (bool, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return false, errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.codes {
|
||||
if v.Currency == c {
|
||||
return !v.Frozen, nil
|
||||
}
|
||||
}
|
||||
return false, errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// IsTradingEnabledForPair returns if the currency pair is allowed to be traded
|
||||
func (w *CurrencyDetails) IsTradingEnabledForPair(pair currency.Pair) (bool, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return false, errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.pairs {
|
||||
if v.Pair.Equal(pair) {
|
||||
return !v.IsFrozen, nil
|
||||
}
|
||||
}
|
||||
return false, errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// IsPostOnlyForPair returns if an order is allowed to take liquidity from the
|
||||
// books or reduce positions
|
||||
func (w *CurrencyDetails) IsPostOnlyForPair(pair currency.Pair) (bool, error) {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
if w.codes == nil {
|
||||
return false, errCodeMapIsNil
|
||||
}
|
||||
for _, v := range w.pairs {
|
||||
if v.Pair.Equal(pair) {
|
||||
return v.PostOnly, nil
|
||||
}
|
||||
}
|
||||
return false, errCurrencyNotFoundInMap
|
||||
}
|
||||
|
||||
// isInitial checks state of maps to determine if they have been loaded or not
|
||||
func (w *CurrencyDetails) isInitial() bool {
|
||||
w.m.RLock()
|
||||
defer w.m.RUnlock()
|
||||
return w.codes == nil || w.pairs == nil
|
||||
}
|
||||
209
exchanges/poloniex/currency_details_test.go
Normal file
209
exchanges/poloniex/currency_details_test.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package poloniex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
func TestWsCurrencyMap(t *testing.T) {
|
||||
var m CurrencyDetails
|
||||
|
||||
if !m.isInitial() {
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
|
||||
err := m.loadPairs(nil)
|
||||
if !errors.Is(err, errCannotLoadNoData) {
|
||||
t.Fatalf("expected: %v but received: %v", errCannotLoadNoData, err)
|
||||
}
|
||||
|
||||
err = m.loadCodes(nil)
|
||||
if !errors.Is(err, errCannotLoadNoData) {
|
||||
t.Fatalf("expected: %v but received: %v", errCannotLoadNoData, err)
|
||||
}
|
||||
|
||||
_, err = m.GetPair(1337)
|
||||
if !errors.Is(err, errPairMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errPairMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.GetCode(1337)
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.GetWithdrawalTXFee(currency.Code{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.GetDepositAddress(currency.Code{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.IsWithdrawAndDepositsEnabled(currency.Code{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.IsTradingEnabledForCurrency(currency.Code{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.IsTradingEnabledForPair(currency.Pair{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
_, err = m.IsPostOnlyForPair(currency.Pair{})
|
||||
if !errors.Is(err, errCodeMapIsNil) {
|
||||
t.Fatalf("expected: %v but received: %v", errCodeMapIsNil, err)
|
||||
}
|
||||
|
||||
c, err := p.GetCurrencies()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = m.loadCodes(c)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
tick, err := p.GetTicker()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = m.loadPairs(tick)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
pTest, err := m.GetPair(1337)
|
||||
if !errors.Is(err, errIDNotFoundInPairMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errIDNotFoundInPairMap, err)
|
||||
}
|
||||
|
||||
if pTest.String() != "1337" {
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
|
||||
_, err = m.GetCode(1337)
|
||||
if !errors.Is(err, errIDNotFoundInCodeMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errIDNotFoundInCodeMap, err)
|
||||
}
|
||||
|
||||
btcusdt, err := m.GetPair(121)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if btcusdt.String() != "USDT_BTC" {
|
||||
t.Fatal("expecting USDT_BTC pair")
|
||||
}
|
||||
|
||||
maid, err := m.GetCode(127)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if maid.String() != "MAID" {
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
|
||||
txFee, err := m.GetWithdrawalTXFee(maid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if txFee != 80 {
|
||||
t.Fatal("unexpected value")
|
||||
}
|
||||
|
||||
_, err = m.GetDepositAddress(maid)
|
||||
if !errors.Is(err, errNoDepositAddress) {
|
||||
t.Fatalf("expected: %v but received: %v", errNoDepositAddress, err)
|
||||
}
|
||||
|
||||
dAddr, err := m.GetDepositAddress(currency.NewCode("BCN"))
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if dAddr != "25cZNQYVAi3issDCoa6fWA2Aogd4FgPhYdpX3p8KLfhKC6sN8s6Q9WpcW4778TPwcUS5jEM25JrQvjD3XjsvXuNHSWhYUsu" {
|
||||
t.Fatal("unexpected deposit address")
|
||||
}
|
||||
|
||||
wdEnabled, err := m.IsWithdrawAndDepositsEnabled(maid)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if !wdEnabled {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
|
||||
tEnabled, err := m.IsTradingEnabledForCurrency(maid)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if !tEnabled {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
|
||||
cp := currency.NewPair(currency.USDT, currency.BTC)
|
||||
|
||||
tEnabled, err = m.IsTradingEnabledForPair(cp)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if !tEnabled {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
|
||||
postOnly, err := m.IsPostOnlyForPair(cp)
|
||||
if !errors.Is(err, nil) {
|
||||
t.Fatalf("expected: %v but received: %v", nil, err)
|
||||
}
|
||||
|
||||
if postOnly {
|
||||
t.Fatal("unexpected results")
|
||||
}
|
||||
|
||||
_, err = m.GetWithdrawalTXFee(currency.Code{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
|
||||
_, err = m.GetDepositAddress(currency.Code{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
|
||||
_, err = m.IsWithdrawAndDepositsEnabled(currency.Code{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
|
||||
_, err = m.IsTradingEnabledForCurrency(currency.Code{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
|
||||
_, err = m.IsTradingEnabledForPair(currency.Pair{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
|
||||
_, err = m.IsPostOnlyForPair(currency.Pair{})
|
||||
if !errors.Is(err, errCurrencyNotFoundInMap) {
|
||||
t.Fatalf("expected: %v but received: %v", errCurrencyNotFoundInMap, err)
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ const (
|
||||
// Poloniex is the overarching type across the poloniex package
|
||||
type Poloniex struct {
|
||||
exchange.Base
|
||||
details CurrencyDetails
|
||||
}
|
||||
|
||||
// GetTicker returns current ticker information
|
||||
@@ -258,27 +259,15 @@ func (p *Poloniex) GetBalances() (Balance, error) {
|
||||
|
||||
// GetCompleteBalances returns complete balances from your account.
|
||||
func (p *Poloniex) GetCompleteBalances() (CompleteBalances, error) {
|
||||
var result interface{}
|
||||
|
||||
err := p.SendAuthenticatedHTTPRequest(exchange.RestSpot, http.MethodPost, poloniexBalancesComplete, url.Values{}, &result)
|
||||
if err != nil {
|
||||
return CompleteBalances{}, err
|
||||
}
|
||||
|
||||
data := result.(map[string]interface{})
|
||||
balance := CompleteBalances{}
|
||||
balance.Currency = make(map[string]CompleteBalance)
|
||||
|
||||
for x, y := range data {
|
||||
dataVals := y.(map[string]interface{})
|
||||
balancesData := CompleteBalance{}
|
||||
balancesData.Available, _ = strconv.ParseFloat(dataVals["available"].(string), 64)
|
||||
balancesData.OnOrders, _ = strconv.ParseFloat(dataVals["onOrders"].(string), 64)
|
||||
balancesData.BTCValue, _ = strconv.ParseFloat(dataVals["btcValue"].(string), 64)
|
||||
balance.Currency[x] = balancesData
|
||||
}
|
||||
|
||||
return balance, nil
|
||||
var result CompleteBalances
|
||||
vals := url.Values{}
|
||||
vals.Set("account", "all")
|
||||
err := p.SendAuthenticatedHTTPRequest(exchange.RestSpot,
|
||||
http.MethodPost,
|
||||
poloniexBalancesComplete,
|
||||
vals,
|
||||
&result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// GetDepositAddresses returns deposit addresses for all enabled cryptos.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package poloniex
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -565,7 +566,7 @@ func TestWsSubAck(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsTicker(t *testing.T) {
|
||||
err := p.getCurrencyIDMap()
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -577,7 +578,7 @@ func TestWsTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsExchangeVolume(t *testing.T) {
|
||||
err := p.getCurrencyIDMap()
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -589,7 +590,8 @@ func TestWsExchangeVolume(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsTrades(t *testing.T) {
|
||||
err := p.getCurrencyIDMap()
|
||||
p.SetSaveTradeDataStatus(true)
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -601,7 +603,7 @@ func TestWsTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsPriceAggregateOrderbook(t *testing.T) {
|
||||
err := p.getCurrencyIDMap()
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -617,25 +619,6 @@ func TestWsPriceAggregateOrderbook(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
func TestWsHandleAccountData(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := p.getCurrencyIDMap()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
jsons := []string{
|
||||
`[1000,"",[["o",807230187,"0.00000000", "f"],["b",267,"e","0.10000000"]]]`,
|
||||
`[1000,"",[["n",50,807230187,0,"1000.00000000","0.10000000","2018-11-07 16:42:42"],["b",267,"e","-0.10000000"]]]`,
|
||||
`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345"]]]`,
|
||||
`[1000,"",[["k", 1337, ""]]]`,
|
||||
}
|
||||
for i := range jsons {
|
||||
err := p.wsHandleData([]byte(jsons[i]))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHistoricCandles(t *testing.T) {
|
||||
currencyPair, err := currency.NewPairFromString("BTC_LTC")
|
||||
@@ -712,3 +695,330 @@ func TestGetHistoricTrades(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountMarginPosition(t *testing.T) {
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
margin := []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000"]]]`)
|
||||
err = p.wsHandleData(margin)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
margin = []byte(`[1000,"",[["m", "23432933", 28, "-0.06000000", null]]]`)
|
||||
err = p.wsHandleData(margin)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, "28", "-0.06000000", null]]]`)
|
||||
err = p.wsHandleData(margin)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, 28, -0.06000000, null]]]`)
|
||||
err = p.wsHandleData(margin)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000", null]]]`)
|
||||
err = p.wsHandleData(margin)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountPendingOrder(t *testing.T) {
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pending := []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0"]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p","431682155857",127,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,"127","1000.00000000","1.00000000","0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,1000.00000000,"1.00000000","0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000",1.00000000,"0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000",0,null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Unmatched pair in system
|
||||
pending = []byte(`[1000,"",[["p",431682155857,666,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = p.wsHandleData(pending)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountOrderUpdate(t *testing.T) {
|
||||
orderUpdate := []byte(`[1000,"",[["o",431682155857,"0.00000000","f"]]]`)
|
||||
err := p.wsHandleData(orderUpdate)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o","431682155857","0.00000000","f",null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,0.00000000,"f",null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000",123,null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","c",null,"0.50000000"]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null,"1.00000000"]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","f",null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","s",null]]]`)
|
||||
err = p.wsHandleData(orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountOrderLimit(t *testing.T) {
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
accountTrade := []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000"]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n","127",431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,"431682155857","0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,0,"1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0",1000.00000000,"1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000",1.00000000,"2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000",1234,"1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56",1.00000000,null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = p.wsHandleData(accountTrade)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountBalanceUpdate(t *testing.T) {
|
||||
err := p.loadCurrencyDetails()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
balance := []byte(`[1000,"",[["b",243,"e"]]]`)
|
||||
err = p.wsHandleData(balance)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
balance = []byte(`[1000,"",[["b","243","e","-1.00000000"]]]`)
|
||||
err = p.wsHandleData(balance)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
balance = []byte(`[1000,"",[["b",243,1234,"-1.00000000"]]]`)
|
||||
err = p.wsHandleData(balance)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
balance = []byte(`[1000,"",[["b",243,"e",-1.00000000]]]`)
|
||||
err = p.wsHandleData(balance)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
balance = []byte(`[1000,"",[["b",243,"e","-1.00000000"]]]`)
|
||||
err = p.wsHandleData(balance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountTrades(t *testing.T) {
|
||||
accountTrades := []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345"]]]`)
|
||||
err := p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", "12345", "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, 0.03000000, "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", 0.50000000, "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, 0.00000375, "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, 0.0000037, "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", 12345, "12345", 0.015]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", "2018-09-08 05:54:09", "12345", "0.015"]]]`)
|
||||
err = p.wsHandleData(accountTrades)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessAccountKilledOrder(t *testing.T) {
|
||||
kill := []byte(`[1000,"",[["k", 1337]]]`)
|
||||
err := p.wsHandleData(kill)
|
||||
if !errors.Is(err, errNotEnoughData) {
|
||||
t.Fatalf("expected: %v but received: %v", errNotEnoughData, err)
|
||||
}
|
||||
|
||||
kill = []byte(`[1000,"",[["k", "1337", null]]]`)
|
||||
err = p.wsHandleData(kill)
|
||||
if !errors.Is(err, errTypeAssertionFailure) {
|
||||
t.Fatalf("expected: %v but received: %v", errTypeAssertionFailure, err)
|
||||
}
|
||||
|
||||
kill = []byte(`[1000,"",[["k", 1337, null]]]`)
|
||||
err = p.wsHandleData(kill)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCompleteBalances(t *testing.T) {
|
||||
if !mockTests && !areTestAPIKeysSet() {
|
||||
t.Skip("API keys not set, mockTests false, skipping test")
|
||||
}
|
||||
_, err := p.GetCompleteBalances()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,10 @@ type Ticker struct {
|
||||
PercentChange float64 `json:"percentChange,string"`
|
||||
BaseVolume float64 `json:"baseVolume,string"`
|
||||
QuoteVolume float64 `json:"quoteVolume,string"`
|
||||
IsFrozen int64 `json:"isFrozen,string"`
|
||||
High24Hr float64 `json:"high24hr,string"`
|
||||
Low24Hr float64 `json:"low24hr,string"`
|
||||
IsFrozen uint8 `json:"isFrozen,string"`
|
||||
PostOnly uint8 `json:"postOnly,string"`
|
||||
}
|
||||
|
||||
// OrderbookResponseAll holds the full response type orderbook
|
||||
@@ -27,9 +28,7 @@ type OrderbookResponseAll struct {
|
||||
}
|
||||
|
||||
// CompleteBalances holds the full balance data
|
||||
type CompleteBalances struct {
|
||||
Currency map[string]CompleteBalance
|
||||
}
|
||||
type CompleteBalances map[string]CompleteBalance
|
||||
|
||||
// OrderbookResponse is a sub-type for orderbooks
|
||||
type OrderbookResponse struct {
|
||||
@@ -116,15 +115,14 @@ type ChartData struct {
|
||||
|
||||
// Currencies contains currency information
|
||||
type Currencies struct {
|
||||
ID float64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
MaxDailyWithdrawal string `json:"maxDailyWithdrawal"`
|
||||
TxFee float64 `json:"txFee,string"`
|
||||
MinConfirmations int64 `json:"minConf"`
|
||||
DepositAddresses interface{} `json:"depositAddress"`
|
||||
Disabled int64 `json:"disabled"`
|
||||
Delisted int64 `json:"delisted"`
|
||||
Frozen int64 `json:"frozen"`
|
||||
ID float64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
TxFee float64 `json:"txFee,string"`
|
||||
MinConfirmations int64 `json:"minConf"`
|
||||
DepositAddress string `json:"depositAddress"`
|
||||
WithdrawalDepositDisabled uint8 `json:"disabled"`
|
||||
Delisted uint8 `json:"delisted"`
|
||||
Frozen uint8 `json:"frozen"`
|
||||
}
|
||||
|
||||
// LoanOrder holds loan order information
|
||||
@@ -148,9 +146,9 @@ type Balance struct {
|
||||
|
||||
// CompleteBalance contains the complete balance with a btcvalue
|
||||
type CompleteBalance struct {
|
||||
Available float64
|
||||
OnOrders float64
|
||||
BTCValue float64
|
||||
Available float64 `json:"available,string"`
|
||||
OnOrders float64 `json:"onOrders,string"`
|
||||
BTCValue float64 `json:"btcValue,string"`
|
||||
}
|
||||
|
||||
// DepositAddresses holds the full address per crypto-currency
|
||||
@@ -442,13 +440,6 @@ var WithdrawalFees = map[currency.Code]float64{
|
||||
currency.ZEC: 0.001,
|
||||
}
|
||||
|
||||
// WsAccountBalanceUpdateResponse Authenticated Ws Account data
|
||||
type WsAccountBalanceUpdateResponse struct {
|
||||
currencyID float64
|
||||
wallet string
|
||||
amount float64
|
||||
}
|
||||
|
||||
// WsOrderUpdateResponse Authenticated Ws Account data
|
||||
type WsOrderUpdateResponse struct {
|
||||
OrderNumber float64
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user