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

@@ -6,97 +6,9 @@ import (
"testing"
"github.com/thrasher-corp/gocryptotrader/config"
"google.golang.org/grpc/metadata"
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
)
func TestParseCredentialsMetadata(t *testing.T) {
t.Parallel()
_, err := ParseCredentialsMetadata(context.Background(), nil)
if !errors.Is(err, errMetaDataIsNil) {
t.Fatalf("received: '%v' but expected: '%v'", err, errMetaDataIsNil)
}
_, err = ParseCredentialsMetadata(context.Background(), metadata.MD{})
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
ctx := metadata.AppendToOutgoingContext(context.Background(),
string(contextCredentialsFlag), "wow", string(contextCredentialsFlag), "wow2")
nortyMD, _ := metadata.FromOutgoingContext(ctx)
_, err = ParseCredentialsMetadata(context.Background(), nortyMD)
if !errors.Is(err, errInvalidCredentialMetaDataLength) {
t.Fatalf("received: '%v' but expected: '%v'", err, errInvalidCredentialMetaDataLength)
}
ctx = metadata.AppendToOutgoingContext(context.Background(),
string(contextCredentialsFlag), "brokenstring")
nortyMD, _ = metadata.FromOutgoingContext(ctx)
_, err = ParseCredentialsMetadata(context.Background(), nortyMD)
if !errors.Is(err, errMissingInfo) {
t.Fatalf("received: '%v' but expected: '%v'", err, errMissingInfo)
}
beforeCreds := Credentials{
Key: "superkey",
Secret: "supersecret",
SubAccount: "supersub",
ClientID: "superclient",
PEMKey: "superpem",
OneTimePassword: "superOneTimePasssssss",
}
flag, outGoing := beforeCreds.GetMetaData()
ctx = metadata.AppendToOutgoingContext(context.Background(), flag, outGoing)
lovelyMD, _ := metadata.FromOutgoingContext(ctx)
ctx, err = ParseCredentialsMetadata(context.Background(), lovelyMD)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
store, ok := ctx.Value(contextCredentialsFlag).(*contextCredentialsStore)
if !ok {
t.Fatal("should have processed")
}
afterCreds := store.Get()
if afterCreds.Key != "superkey" &&
afterCreds.Secret != "supersecret" &&
afterCreds.SubAccount != "supersub" &&
afterCreds.ClientID != "superclient" &&
afterCreds.PEMKey != "superpem" &&
afterCreds.OneTimePassword != "superOneTimePasssssss" {
t.Fatal("unexpected values")
}
// subaccount override
subaccount := Credentials{
SubAccount: "supersub",
}
flag, outGoing = subaccount.GetMetaData()
ctx = metadata.AppendToOutgoingContext(context.Background(), flag, outGoing)
lovelyMD, _ = metadata.FromOutgoingContext(ctx)
ctx, err = ParseCredentialsMetadata(context.Background(), lovelyMD)
if !errors.Is(err, nil) {
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
}
sa, ok := ctx.Value(contextSubAccountFlag).(string)
if !ok {
t.Fatal("should have processed")
}
if sa != "supersub" {
t.Fatal("unexpected value")
}
}
func TestGetCredentials(t *testing.T) {
t.Parallel()
var b Base
@@ -106,26 +18,26 @@ func TestGetCredentials(t *testing.T) {
}
b.API.CredentialsValidator.RequiresKey = true
ctx := DeployCredentialsToContext(context.Background(), &Credentials{Secret: "wow"})
ctx := account.DeployCredentialsToContext(context.Background(), &account.Credentials{Secret: "wow"})
_, err = b.GetCredentials(ctx)
if !errors.Is(err, errRequiresAPIKey) {
t.Fatalf("received: %v but expected: %v", err, errRequiresAPIKey)
}
b.API.CredentialsValidator.RequiresSecret = true
ctx = DeployCredentialsToContext(context.Background(), &Credentials{Key: "wow"})
ctx = account.DeployCredentialsToContext(context.Background(), &account.Credentials{Key: "wow"})
_, err = b.GetCredentials(ctx)
if !errors.Is(err, errRequiresAPISecret) {
t.Fatalf("received: %v but expected: %v", err, errRequiresAPISecret)
}
ctx = context.WithValue(context.Background(), contextCredentialsFlag, "pewpew")
ctx = context.WithValue(context.Background(), account.ContextCredentialsFlag, "pewpew")
_, err = b.GetCredentials(ctx)
if !errors.Is(err, errContextCredentialsFailure) {
t.Fatalf("received: %v but expected: %v", err, errContextCredentialsFailure)
}
fullCred := Credentials{
fullCred := &account.Credentials{
Key: "superkey",
Secret: "supersecret",
SubAccount: "supersub",
@@ -134,9 +46,7 @@ func TestGetCredentials(t *testing.T) {
OneTimePassword: "superOneTimePasssssss",
}
flag, store := fullCred.getInternal()
ctx = context.WithValue(context.Background(), flag, store)
ctx = account.DeployCredentialsToContext(context.Background(), fullCred)
creds, err := b.GetCredentials(ctx)
if !errors.Is(err, nil) {
t.Fatalf("received: %v but expected: %v", err, nil)
@@ -151,7 +61,7 @@ func TestGetCredentials(t *testing.T) {
t.Fatal("unexpected values")
}
lonelyCred := Credentials{
lonelyCred := &account.Credentials{
Key: "superkey",
Secret: "supersecret",
SubAccount: "supersub",
@@ -159,9 +69,7 @@ func TestGetCredentials(t *testing.T) {
OneTimePassword: "superOneTimePasssssss",
}
flag, store = lonelyCred.getInternal()
ctx = context.WithValue(context.Background(), flag, store)
ctx = account.DeployCredentialsToContext(context.Background(), lonelyCred)
b.API.CredentialsValidator.RequiresClientID = true
_, err = b.GetCredentials(ctx)
if !errors.Is(err, errRequiresAPIClientID) {
@@ -171,7 +79,8 @@ func TestGetCredentials(t *testing.T) {
b.API.SetKey("hello")
b.API.SetSecret("sir")
b.API.SetClientID("1337")
ctx = deploySubAccountOverrideToContext(context.Background(), "superaccount")
ctx = context.WithValue(context.Background(), account.ContextSubAccountFlag, "superaccount")
overridedSA, err := b.GetCredentials(ctx)
if !errors.Is(err, nil) {
t.Fatalf("received: %v but expected: %v", err, nil)
@@ -203,7 +112,7 @@ func TestAreCredentialsValid(t *testing.T) {
if b.AreCredentialsValid(context.Background()) {
t.Fatal("should not be valid")
}
ctx := DeployCredentialsToContext(context.Background(), &Credentials{Key: "hello"})
ctx := account.DeployCredentialsToContext(context.Background(), &account.Credentials{Key: "hello"})
if !b.AreCredentialsValid(ctx) {
t.Fatal("should be valid")
}
@@ -277,11 +186,11 @@ func TestCheckCredentials(t *testing.T) {
b := Base{
SkipAuthCheck: true,
API: API{credentials: &Credentials{}},
API: API{credentials: &account.Credentials{}},
}
// Test SkipAuthCheck
err := b.CheckCredentials(&Credentials{}, false)
err := b.CheckCredentials(&account.Credentials{}, false)
if !errors.Is(err, nil) {
t.Errorf("received '%v' expected '%v'", err, nil)
}
@@ -322,56 +231,35 @@ func TestCheckCredentials(t *testing.T) {
}
}
func TestGetInternal(t *testing.T) {
t.Parallel()
flag, store := (&Credentials{}).getInternal()
if flag != "" {
t.Fatal("unexpected value")
}
if store != nil {
t.Fatal("unexpected value")
}
flag, store = (&Credentials{Key: "wow"}).getInternal()
if flag != contextCredentialsFlag {
t.Fatal("unexpected value")
}
if store == nil {
t.Fatal("unexpected value")
}
if store.Get().Key != "wow" {
t.Fatal("unexpected value")
}
}
func TestAPISetters(t *testing.T) {
t.Parallel()
api := API{}
api.SetKey(key)
if api.credentials.Key != key {
api.SetKey(account.Key)
if api.credentials.Key != account.Key {
t.Fatal("unexpected value")
}
api = API{}
api.SetSecret(secret)
if api.credentials.Secret != secret {
api.SetSecret(account.Secret)
if api.credentials.Secret != account.Secret {
t.Fatal("unexpected value")
}
api = API{}
api.SetClientID((clientID))
if api.credentials.ClientID != clientID {
api.SetClientID(account.ClientID)
if api.credentials.ClientID != account.ClientID {
t.Fatal("unexpected value")
}
api = API{}
api.SetPEMKey(_PEMKey)
if api.credentials.PEMKey != _PEMKey {
api.SetPEMKey(account.PEMKey)
if api.credentials.PEMKey != account.PEMKey {
t.Fatal("unexpected value")
}
api = API{}
api.SetSubAccount(subAccount)
if api.credentials.SubAccount != subAccount {
api.SetSubAccount(account.SubAccountSTR)
if api.credentials.SubAccount != account.SubAccountSTR {
t.Fatal("unexpected value")
}
}
@@ -471,19 +359,3 @@ func TestGetAuthenticatedAPISupport(t *testing.T) {
t.Fatal("Expected WebsocketAuthentication to return true")
}
}
func TestIsEmpty(t *testing.T) {
var c *Credentials
if !c.IsEmpty() {
t.Fatalf("expected: %v but received: %v", true, c.IsEmpty())
}
c = new(Credentials)
if !c.IsEmpty() {
t.Fatalf("expected: %v but received: %v", true, c.IsEmpty())
}
c.SubAccount = "woow"
if c.IsEmpty() {
t.Fatalf("expected: %v but received: %v", false, c.IsEmpty())
}
}