mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-31 15:10:42 +00:00
* 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
66 lines
1.4 KiB
Go
66 lines
1.4 KiB
Go
package accounts
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
"sync/atomic"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/dispatch"
|
|
)
|
|
|
|
// Store contains accounts for exchanges.
|
|
type Store struct {
|
|
exchangeAccounts exchangeMap
|
|
mu sync.Mutex
|
|
mux *dispatch.Mux
|
|
}
|
|
|
|
type exchangeMap map[exchange]*Accounts
|
|
|
|
type exchange interface {
|
|
GetName() string
|
|
GetCredentials(context.Context) (*Credentials, error)
|
|
}
|
|
|
|
type exchangeWrapper interface {
|
|
GetBase() exchange
|
|
}
|
|
|
|
var global atomic.Pointer[Store]
|
|
|
|
// NewStore returns a new store with the default global dispatcher mux.
|
|
func NewStore() *Store {
|
|
return &Store{
|
|
exchangeAccounts: make(exchangeMap),
|
|
mux: dispatch.GetNewMux(nil),
|
|
}
|
|
}
|
|
|
|
// GetStore returns the singleton accounts store for global use; Initialising if necessary.
|
|
func GetStore() *Store {
|
|
if s := global.Load(); s != nil {
|
|
return s
|
|
}
|
|
_ = global.CompareAndSwap(nil, NewStore())
|
|
return global.Load()
|
|
}
|
|
|
|
// GetExchangeAccounts returns accounts for a specific exchange.
|
|
func (s *Store) GetExchangeAccounts(e exchange) (a *Accounts, err error) {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
if w, ok := e.(exchangeWrapper); ok {
|
|
// Because SetupDefaults is called on Base, it's easiest to just use the Base pointer as the key
|
|
e = w.GetBase()
|
|
}
|
|
a, ok := s.exchangeAccounts[e]
|
|
if !ok {
|
|
a, err = NewAccounts(e, s.mux)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
s.exchangeAccounts[e] = a
|
|
}
|
|
return a, nil
|
|
}
|