mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-09 07:26:48 +00:00
accounts: Move to instance methods, fix races and isolate tests (#1923)
* Bybit: Fix race in TestUpdateAccountInfo and TestWSHandleData * DriveBy rename TestWSHandleData * This doesn't address running with -race=2+ due to the singleton * Accounts: Add account.GetService() * exchange: Assertify TestSetupDefaults * Exchanges: Add account.Service override for testing * Exchanges: Remove duplicate IsWebsocketEnabled test from TestSetupDefaults * Dispatch: Replace nil checks with NilGuard * Engine: Remove deprecated printAccountHoldingsChangeSummary * Dispatcher: Add EnsureRunning method * Accounts: Move singleton accounts service to exchange Accounts * Move singleton accounts service to exchange Accounts This maintains the concept of a global store, whilst allowing exchanges to override it when needed, particularly for testing. APIServer: * Remove getAllActiveAccounts from apiserver Deprecated apiserver only thing using this, so remove it instead of updating it * Update comment for UpdateAccountBalances everywhere * Docs: Add punctuation to function comments * Bybit: Coverage for wsProcessWalletPushData Save
This commit is contained in:
@@ -223,35 +223,32 @@ func (e *Exchange) GetLoanOrders(ctx context.Context, ccy string) (LoanOrders, e
|
||||
}
|
||||
|
||||
// GetBalances returns balances for your account.
|
||||
func (e *Exchange) GetBalances(ctx context.Context) (Balance, error) {
|
||||
func (e *Exchange) GetBalances(ctx context.Context) (map[currency.Code]float64, error) {
|
||||
var result any
|
||||
if err := e.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, poloniexBalances, url.Values{}, &result); err != nil {
|
||||
return Balance{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, ok := result.(map[string]any)
|
||||
if !ok {
|
||||
return Balance{}, common.GetTypeAssertError("map[string]any", result, "balance result")
|
||||
return nil, common.GetTypeAssertError("map[string]any", result, "balance result")
|
||||
}
|
||||
|
||||
balance := Balance{
|
||||
Currency: make(map[string]float64),
|
||||
}
|
||||
bals := make(map[currency.Code]float64, len(data))
|
||||
|
||||
for x, y := range data {
|
||||
bal, ok := y.(string)
|
||||
if !ok {
|
||||
return Balance{}, common.GetTypeAssertError("string", y, "balance amount")
|
||||
return nil, common.GetTypeAssertError("string", y, "balance amount")
|
||||
}
|
||||
|
||||
var err error
|
||||
balance.Currency[x], err = strconv.ParseFloat(bal, 64)
|
||||
if err != nil {
|
||||
return Balance{}, err
|
||||
if bals[currency.NewCode(x)], err = strconv.ParseFloat(bal, 64); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return balance, nil
|
||||
return bals, nil
|
||||
}
|
||||
|
||||
// GetCompleteBalances returns complete balances from your account.
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/accounts"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
@@ -550,7 +551,7 @@ func TestWsAuth(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go e.wsReadData()
|
||||
go e.wsReadData(t.Context())
|
||||
creds, err := e.GetCredentials(t.Context())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -570,7 +571,7 @@ func TestWsAuth(t *testing.T) {
|
||||
|
||||
func TestWsSubAck(t *testing.T) {
|
||||
pressXToJSON := []byte(`[1002, 1]`)
|
||||
err := e.wsHandleData(pressXToJSON)
|
||||
err := e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -582,7 +583,7 @@ func TestWsTicker(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
pressXToJSON := []byte(`[1002, null, [ 50, "382.98901522", "381.99755898", "379.41296309", "-0.04312950", "14969820.94951828", "38859.58435407", 0, "412.25844455", "364.56122072" ] ]`)
|
||||
err = e.wsHandleData(pressXToJSON)
|
||||
err = e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -594,7 +595,7 @@ func TestWsExchangeVolume(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
pressXToJSON := []byte(`[1003,null,["2018-11-07 16:26",5804,{"BTC":"3418.409","ETH":"2645.921","USDT":"10832502.689","USDC":"1578020.908"}]]`)
|
||||
err = e.wsHandleData(pressXToJSON)
|
||||
err = e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -607,7 +608,7 @@ func TestWsTrades(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
pressXToJSON := []byte(`[14, 8768, [["t", "42706057", 1, "0.05567134", "0.00181421", 1522877119]]]`)
|
||||
err = e.wsHandleData(pressXToJSON)
|
||||
err = e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -619,13 +620,13 @@ func TestWsPriceAggregateOrderbook(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
pressXToJSON := []byte(`[50,141160924,[["i",{"currencyPair":"BTC_LTC","orderBook":[{"0.002784":"17.55","0.002786":"1.47","0.002792":"13.25","0.0028":"0.21","0.002804":"0.02","0.00281":"1.5","0.002811":"258.82","0.002812":"3.81","0.002817":"0.06","0.002824":"3","0.002825":"0.02","0.002836":"18.01","0.002837":"0.03","0.00284":"0.03","0.002842":"12.7","0.00285":"0.02","0.002852":"0.02","0.002855":"1.3","0.002857":"15.64","0.002864":"0.01"},{"0.002782":"45.93","0.002781":"1.46","0.002774":"13.34","0.002773":"0.04","0.002771":"0.05","0.002765":"6.21","0.002764":"3","0.00276":"10.77","0.002758":"3.11","0.002754":"0.02","0.002751":"288.94","0.00275":"24.06","0.002745":"187.27","0.002743":"0.04","0.002742":"0.96","0.002731":"0.06","0.00273":"12.13","0.002727":"0.02","0.002725":"0.03","0.002719":"1.09"}]}, "1692080077892"]]]`)
|
||||
err = e.wsHandleData(pressXToJSON)
|
||||
err = e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pressXToJSON = []byte(`[50,141160925,[["o",1,"0.002742","0", "1692080078806"],["o",1,"0.002718","0.02", "1692080078806"]]]`)
|
||||
err = e.wsHandleData(pressXToJSON)
|
||||
err = e.wsHandleData(t.Context(), pressXToJSON)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -675,23 +676,23 @@ func TestProcessAccountMarginPosition(t *testing.T) {
|
||||
}
|
||||
|
||||
margin := []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000"]]]`)
|
||||
err = e.wsHandleData(margin)
|
||||
err = e.wsHandleData(t.Context(), margin)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
margin = []byte(`[1000,"",[["m", "23432933", 28, "-0.06000000", null]]]`)
|
||||
err = e.wsHandleData(margin)
|
||||
err = e.wsHandleData(t.Context(), margin)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, "28", "-0.06000000", null]]]`)
|
||||
err = e.wsHandleData(margin)
|
||||
err = e.wsHandleData(t.Context(), margin)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, 28, -0.06000000, null]]]`)
|
||||
err = e.wsHandleData(margin)
|
||||
err = e.wsHandleData(t.Context(), margin)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
margin = []byte(`[1000,"",[["m", 23432933, 28, "-0.06000000", null]]]`)
|
||||
err = e.wsHandleData(margin)
|
||||
err = e.wsHandleData(t.Context(), margin)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -704,38 +705,38 @@ func TestProcessAccountPendingOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
pending := []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0"]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
pending = []byte(`[1000,"",[["p","431682155857",127,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,"127","1000.00000000","1.00000000","0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,1000.00000000,"1.00000000","0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000",1.00000000,"0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000",0,null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
pending = []byte(`[1000,"",[["p",431682155857,127,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Unmatched pair in system
|
||||
pending = []byte(`[1000,"",[["p",431682155857,666,"1000.00000000","1.00000000","0",null]]]`)
|
||||
err = e.wsHandleData(pending)
|
||||
err = e.wsHandleData(t.Context(), pending)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -743,45 +744,45 @@ func TestProcessAccountPendingOrder(t *testing.T) {
|
||||
|
||||
func TestProcessAccountOrderUpdate(t *testing.T) {
|
||||
orderUpdate := []byte(`[1000,"",[["o",431682155857,"0.00000000","f"]]]`)
|
||||
err := e.wsHandleData(orderUpdate)
|
||||
err := e.wsHandleData(t.Context(), orderUpdate)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o","431682155857","0.00000000","f",null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,0.00000000,"f",null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000",123,null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","c",null,"0.50000000"]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","c",null,"1.00000000"]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.50000000","f",null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
orderUpdate = []byte(`[1000,"",[["o",431682155857,"0.00000000","s",null]]]`)
|
||||
err = e.wsHandleData(orderUpdate)
|
||||
err = e.wsHandleData(t.Context(), orderUpdate)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -794,39 +795,39 @@ func TestProcessAccountOrderLimit(t *testing.T) {
|
||||
}
|
||||
|
||||
accountTrade := []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000"]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n","127",431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,"431682155857","0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,0,"1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0",1000.00000000,"1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000",1.00000000,"2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000",1234,"1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56",1.00000000,null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrade = []byte(`[1000,"",[["n",127,431682155857,"0","1000.00000000","1.00000000","2021-04-13 07:19:56","1.00000000",null]]]`)
|
||||
err = e.wsHandleData(accountTrade)
|
||||
err = e.wsHandleData(t.Context(), accountTrade)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -839,59 +840,58 @@ func TestProcessAccountBalanceUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
balance := []byte(`[1000,"",[["b",243,"e"]]]`)
|
||||
err = e.wsHandleData(balance)
|
||||
err = e.wsHandleData(t.Context(), balance)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
balance = []byte(`[1000,"",[["b","243","e","-1.00000000"]]]`)
|
||||
err = e.wsHandleData(balance)
|
||||
err = e.wsHandleData(t.Context(), balance)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
balance = []byte(`[1000,"",[["b",243,1234,"-1.00000000"]]]`)
|
||||
err = e.wsHandleData(balance)
|
||||
err = e.wsHandleData(t.Context(), balance)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
balance = []byte(`[1000,"",[["b",243,"e",-1.00000000]]]`)
|
||||
err = e.wsHandleData(balance)
|
||||
err = e.wsHandleData(t.Context(), balance)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
ctx := accounts.DeployCredentialsToContext(t.Context(), &accounts.Credentials{Key: "test", Secret: "test"})
|
||||
balance = []byte(`[1000,"",[["b",243,"e","-1.00000000"]]]`)
|
||||
err = e.wsHandleData(balance)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = e.wsHandleData(ctx, balance)
|
||||
require.NoError(t, err, "wsHandleData must not error")
|
||||
}
|
||||
|
||||
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 := e.wsHandleData(accountTrades)
|
||||
err := e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
accountTrades = []byte(`[1000,"",[["t", 12345, "0.03000000", "0.50000000", "0.00250000", 0, 6083059, "0.00000375", 12345, "12345", 0.015]]]`)
|
||||
err = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
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 = e.wsHandleData(accountTrades)
|
||||
err = e.wsHandleData(t.Context(), accountTrades)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -899,15 +899,15 @@ func TestProcessAccountTrades(t *testing.T) {
|
||||
|
||||
func TestProcessAccountKilledOrder(t *testing.T) {
|
||||
kill := []byte(`[1000,"",[["k", 1337]]]`)
|
||||
err := e.wsHandleData(kill)
|
||||
err := e.wsHandleData(t.Context(), kill)
|
||||
require.ErrorIs(t, err, errNotEnoughData)
|
||||
|
||||
kill = []byte(`[1000,"",[["k", "1337", null]]]`)
|
||||
err = e.wsHandleData(kill)
|
||||
err = e.wsHandleData(t.Context(), kill)
|
||||
require.ErrorIs(t, err, errTypeAssertionFailure)
|
||||
|
||||
kill = []byte(`[1000,"",[["k", 1337, null]]]`)
|
||||
err = e.wsHandleData(kill)
|
||||
err = e.wsHandleData(t.Context(), kill)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -144,11 +144,6 @@ type LoanOrders struct {
|
||||
Demands []LoanOrder `json:"demands"`
|
||||
}
|
||||
|
||||
// Balance holds data for a range of currencies
|
||||
type Balance struct {
|
||||
Currency map[string]float64
|
||||
}
|
||||
|
||||
// CompleteBalance contains the complete balance with a btcvalue
|
||||
type CompleteBalance struct {
|
||||
Available float64 `json:"available,string"`
|
||||
|
||||
@@ -15,8 +15,8 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/encoding/json"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/accounts"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
|
||||
@@ -72,7 +72,7 @@ func (e *Exchange) WsConnect() error {
|
||||
}
|
||||
|
||||
e.Websocket.Wg.Add(1)
|
||||
go e.wsReadData()
|
||||
go e.wsReadData(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -103,21 +103,21 @@ func (e *Exchange) loadCurrencyDetails(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// wsReadData handles data from the websocket connection
|
||||
func (e *Exchange) wsReadData() {
|
||||
func (e *Exchange) wsReadData(ctx context.Context) {
|
||||
defer e.Websocket.Wg.Done()
|
||||
for {
|
||||
resp := e.Websocket.Conn.ReadMessage()
|
||||
if resp.Raw == nil {
|
||||
return
|
||||
}
|
||||
err := e.wsHandleData(resp.Raw)
|
||||
err := e.wsHandleData(ctx, resp.Raw)
|
||||
if err != nil {
|
||||
e.Websocket.DataHandler <- fmt.Errorf("%s: %w", e.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Exchange) wsHandleData(respRaw []byte) error {
|
||||
func (e *Exchange) wsHandleData(ctx context.Context, respRaw []byte) error {
|
||||
var result any
|
||||
err := json.Unmarshal(respRaw, &result)
|
||||
if err != nil {
|
||||
@@ -185,7 +185,7 @@ func (e *Exchange) wsHandleData(respRaw []byte) error {
|
||||
return fmt.Errorf("account notification limit order creation: %w", err)
|
||||
}
|
||||
case accountNotificationBalanceUpdate:
|
||||
err = e.processAccountBalanceUpdate(notification)
|
||||
err = e.processAccountBalanceUpdate(ctx, notification)
|
||||
if err != nil {
|
||||
return fmt.Errorf("account notification balance update: %w", err)
|
||||
}
|
||||
@@ -585,7 +585,7 @@ func (e *Exchange) Unsubscribe(subs subscription.List) error {
|
||||
}
|
||||
|
||||
func (e *Exchange) manageSubs(ctx context.Context, subs subscription.List, op wsOp) error {
|
||||
var creds *account.Credentials
|
||||
var creds *accounts.Credentials
|
||||
if e.IsWebsocketAuthenticationSupported() {
|
||||
var err error
|
||||
creds, err = e.GetCredentials(ctx)
|
||||
@@ -918,7 +918,7 @@ func (e *Exchange) processAccountOrderLimit(notification []any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Exchange) processAccountBalanceUpdate(notification []any) error {
|
||||
func (e *Exchange) processAccountBalanceUpdate(ctx context.Context, notification []any) error {
|
||||
if len(notification) < 4 {
|
||||
return errNotEnoughData
|
||||
}
|
||||
@@ -927,7 +927,7 @@ func (e *Exchange) processAccountBalanceUpdate(notification []any) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("%w currency ID not float64", errTypeAssertionFailure)
|
||||
}
|
||||
code, err := e.details.GetCode(currencyID)
|
||||
curr, err := e.details.GetCode(currencyID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -946,18 +946,20 @@ func (e *Exchange) processAccountBalanceUpdate(notification []any) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO: Integrate with exchange account system
|
||||
// NOTES: This will affect free amount, a rest call might be needed to get
|
||||
// locked and total amounts periodically.
|
||||
e.Websocket.DataHandler <- account.Change{
|
||||
Account: deriveWalletType(walletType),
|
||||
AssetType: asset.Spot,
|
||||
Balance: &account.Balance{
|
||||
Currency: code,
|
||||
Total: amount,
|
||||
Free: amount,
|
||||
},
|
||||
bal := accounts.Balance{
|
||||
Currency: curr,
|
||||
Total: amount,
|
||||
Free: amount,
|
||||
}
|
||||
|
||||
id := deriveWalletType(walletType)
|
||||
subAccts := accounts.SubAccounts{accounts.NewSubAccount(asset.Spot, id)}
|
||||
subAccts[0].Balances.Set(curr, bal)
|
||||
|
||||
if err := e.Accounts.Save(ctx, subAccts, true); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Websocket.DataHandler <- subAccts
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/accounts"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/websocket"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchange/websocket/buffer"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/deposit"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/fundingrate"
|
||||
@@ -339,43 +339,20 @@ func (e *Exchange) UpdateOrderbook(ctx context.Context, pair currency.Pair, asse
|
||||
return orderbook.Get(e.Name, pair, assetType)
|
||||
}
|
||||
|
||||
// UpdateAccountInfo retrieves balances for all enabled currencies for the
|
||||
// Poloniex exchange
|
||||
func (e *Exchange) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
|
||||
var response account.Holdings
|
||||
response.Exchange = e.Name
|
||||
accountBalance, err := e.GetBalances(ctx)
|
||||
// UpdateAccountBalances retrieves currency balances
|
||||
func (e *Exchange) UpdateAccountBalances(ctx context.Context, assetType asset.Item) (accounts.SubAccounts, error) {
|
||||
resp, err := e.GetBalances(ctx)
|
||||
if err != nil {
|
||||
return response, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
currencies := make([]account.Balance, 0, len(accountBalance.Currency))
|
||||
for x, y := range accountBalance.Currency {
|
||||
currencies = append(currencies, account.Balance{
|
||||
Currency: currency.NewCode(x),
|
||||
Total: y,
|
||||
})
|
||||
subAccts := accounts.SubAccounts{accounts.NewSubAccount(assetType, "")}
|
||||
for curr, bal := range resp {
|
||||
subAccts[0].Balances.Set(curr, accounts.Balance{Total: bal})
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
AssetType: assetType,
|
||||
Currencies: currencies,
|
||||
})
|
||||
|
||||
creds, err := e.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
err = account.Process(&response, creds)
|
||||
if err != nil {
|
||||
return account.Holdings{}, err
|
||||
}
|
||||
|
||||
return response, nil
|
||||
return subAccts, e.Accounts.Save(ctx, subAccts, true)
|
||||
}
|
||||
|
||||
// GetAccountFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
// GetAccountFundingHistory returns funding history, deposits and withdrawals
|
||||
func (e *Exchange) GetAccountFundingHistory(ctx context.Context) ([]exchange.FundingHistory, error) {
|
||||
end := time.Now()
|
||||
walletActivity, err := e.WalletActivity(ctx, end.Add(-time.Hour*24*365), end, "")
|
||||
@@ -932,10 +909,9 @@ func (e *Exchange) GetOrderHistory(ctx context.Context, req *order.MultiOrderReq
|
||||
return req.Filter(e.Name, orders), nil
|
||||
}
|
||||
|
||||
// ValidateAPICredentials validates current credentials used for wrapper
|
||||
// functionality
|
||||
// ValidateAPICredentials validates current credentials used for wrapper functionality
|
||||
func (e *Exchange) ValidateAPICredentials(ctx context.Context, assetType asset.Item) error {
|
||||
_, err := e.UpdateAccountInfo(ctx, assetType)
|
||||
_, err := e.UpdateAccountBalances(ctx, assetType)
|
||||
return e.CheckTransientError(err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user