account: segregate holdings by credentials for future multi-key management (#956)

* exchanges/account: shift credentials to account package and segregate funds to keys

* merge: fixes

* linter: fix

* Update exchanges/account/account.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits + protection for string panic

* glorious_suggestion: add method for matching keys

* linter: fix tests

* account: add protected method for credentials minimizing access, display full account details to rpc.

* linter: spelling kweeeeeeen

* accounts/portfolio: clean/check portfolio code and quickly check balances from change. Add protected method for future matching.

* accounts: theres no point in pointerising everything

* linter: ok pointerise this then...

* exchanges: fix regression add in little notes.

* glorious: nits

* Update exchanges/account/credentials.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/account/credentials_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/account/credentials_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* gloriously: fix glorious glorious test gloriously

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
Ryan O'Hara-Reid
2022-07-21 15:05:31 +10:00
committed by GitHub
parent 455738f25f
commit 663e753f52
48 changed files with 1010 additions and 549 deletions

View File

@@ -57,10 +57,7 @@ func setupPortfolioManager(e *ExchangeManager, portfolioManagerDelay time.Durati
// IsRunning safely checks whether the subsystem is running
func (m *portfolioManager) IsRunning() bool {
if m == nil {
return false
}
return atomic.LoadInt32(&m.started) == 1
return m != nil && atomic.LoadInt32(&m.started) == 1
}
// Start runs the subsystem
@@ -160,11 +157,10 @@ func (m *portfolioManager) seedExchangeAccountInfo(accounts []account.Holdings)
return
}
for x := range accounts {
exchangeName := accounts[x].Exchange
var currencies []account.Balance
for y := range accounts[x].Accounts {
next:
for z := range accounts[x].Accounts[y].Currencies {
var update bool
for i := range currencies {
if !accounts[x].Accounts[y].Currencies[z].CurrencyName.Equal(currencies[i].CurrencyName) {
continue
@@ -174,10 +170,7 @@ func (m *portfolioManager) seedExchangeAccountInfo(accounts []account.Holdings)
currencies[i].AvailableWithoutBorrow += accounts[x].Accounts[y].Currencies[z].AvailableWithoutBorrow
currencies[i].Free += accounts[x].Accounts[y].Currencies[z].Free
currencies[i].Borrowed += accounts[x].Accounts[y].Currencies[z].Borrowed
update = true
}
if update {
continue
continue next
}
currencies = append(currencies, account.Balance{
CurrencyName: accounts[x].Accounts[y].Currencies[z].CurrencyName,
@@ -190,51 +183,50 @@ func (m *portfolioManager) seedExchangeAccountInfo(accounts []account.Holdings)
}
}
for x := range currencies {
currencyName := currencies[x].CurrencyName
total := currencies[x].Total
if !m.base.ExchangeAddressExists(exchangeName, currencyName) {
if total <= 0 {
for j := range currencies {
if !m.base.ExchangeAddressExists(accounts[x].Exchange, currencies[j].CurrencyName) {
if currencies[j].Total <= 0 {
continue
}
log.Debugf(log.PortfolioMgr, "Portfolio: Adding new exchange address: %s, %s, %f, %s\n",
exchangeName,
currencyName,
total,
accounts[x].Exchange,
currencies[j].CurrencyName,
currencies[j].Total,
portfolio.ExchangeAddress)
m.base.Addresses = append(
m.base.Addresses,
portfolio.Address{Address: exchangeName,
CoinType: currencyName,
Balance: total,
Description: portfolio.ExchangeAddress})
} else {
if total <= 0 {
log.Debugf(log.PortfolioMgr, "Portfolio: Removing %s %s entry.\n",
exchangeName,
currencyName)
m.base.RemoveExchangeAddress(exchangeName, currencyName)
} else {
balance, ok := m.base.GetAddressBalance(exchangeName,
portfolio.ExchangeAddress,
currencyName)
if !ok {
continue
}
m.base.Addresses = append(m.base.Addresses, portfolio.Address{
Address: accounts[x].Exchange,
CoinType: currencies[j].CurrencyName,
Balance: currencies[j].Total,
Description: portfolio.ExchangeAddress,
})
continue
}
if balance != total {
log.Debugf(log.PortfolioMgr, "Portfolio: Updating %s %s entry with balance %f.\n",
exchangeName,
currencyName,
total)
m.base.UpdateExchangeAddressBalance(exchangeName,
currencyName,
total)
}
}
if currencies[j].Total <= 0 {
log.Debugf(log.PortfolioMgr, "Portfolio: Removing %s %s entry.\n",
accounts[x].Exchange,
currencies[j].CurrencyName)
m.base.RemoveExchangeAddress(accounts[x].Exchange, currencies[j].CurrencyName)
continue
}
balance, ok := m.base.GetAddressBalance(accounts[x].Exchange,
portfolio.ExchangeAddress,
currencies[j].CurrencyName)
if !ok {
continue
}
if balance != currencies[j].Total {
log.Debugf(log.PortfolioMgr, "Portfolio: Updating %s %s entry with balance %f.\n",
accounts[x].Exchange,
currencies[j].CurrencyName,
currencies[j].Total)
m.base.UpdateExchangeAddressBalance(accounts[x].Exchange,
currencies[j].CurrencyName,
currencies[j].Total)
}
}
}

View File

@@ -112,7 +112,7 @@ func (s *RPCServer) authenticateClient(ctx context.Context) (context.Context, er
password != s.Config.RemoteControl.Password {
return ctx, fmt.Errorf("username/password mismatch")
}
ctx, err = exchange.ParseCredentialsMetadata(ctx, md)
ctx, err = account.ParseCredentialsMetadata(ctx, md)
if err != nil {
return ctx, err
}
@@ -618,7 +618,7 @@ func createAccountInfoRequest(h account.Holdings) (*gctrpc.GetAccountInfoRespons
accounts := make([]*gctrpc.Account, len(h.Accounts))
for x := range h.Accounts {
var a gctrpc.Account
a.Id = h.Accounts[x].ID
a.Id = h.Accounts[x].Credentials.String()
for _, y := range h.Accounts[x].Currencies {
if y.Total == 0 &&
y.Hold == 0 &&

View File

@@ -2198,10 +2198,12 @@ func TestGetFuturesPositions(t *testing.T) {
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
}
ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{
Key: "wow",
Secret: "super wow",
})
ctx := account.DeployCredentialsToContext(context.Background(),
&account.Credentials{
Key: "wow",
Secret: "super wow",
},
)
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
Exchange: fakeExchangeName,
@@ -2312,7 +2314,8 @@ func TestGetCollateral(t *testing.T) {
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
}
ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Key: "fakerino", Secret: "supafake"})
ctx := account.DeployCredentialsToContext(context.Background(),
&account.Credentials{Key: "fakerino", Secret: "supafake"})
_, err = s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
Exchange: fakeExchangeName,
@@ -2322,7 +2325,8 @@ func TestGetCollateral(t *testing.T) {
t.Fatalf("received '%v', expected '%v'", err, errNoAccountInformation)
}
ctx = exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Key: "fakerino", Secret: "supafake", SubAccount: "1337"})
ctx = account.DeployCredentialsToContext(context.Background(),
&account.Credentials{Key: "fakerino", Secret: "supafake", SubAccount: "1337"})
r, err := s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
Exchange: fakeExchangeName,