mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-31 15:10:42 +00:00
context: Add authenticated HTTP credentials (#892)
* gRPC: context overide * exchanges: continue update * exchange: Update context handling *Add setter methods for API credentials *Shift credentials functionality to its own file in exchanges package *Add tests *Refactor function DeployCredentialsToContext for library usage *Add function to process credential metadata from API boundary to internal use context value. *Add OTP rpc handling * exchanges: reverts to old style in GetFeeByType, reverts some code I accidently deleted. Plus things and other. XD * template: update * exchanges: fix linter issues * REMOVE THAT AWESOME NEW LINE! * gct: fix some tests * I cant spell :( * exchanges/gctscript: fix more tests * coinnut: fix tests * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * glorious: nits * exchanges/gctcli: stop applying empty credentials * fix linters * exchanges: add test * rpceserver: actually check error for errors * rpcserver: fix up tests * Update exchanges/credentials.go Co-authored-by: Scott <gloriousCode@users.noreply.github.com> * exchanges/creds: move tests to corresponding files, add protection and segration for Credentials struct & ptr values * exchanges/creds: allow subaccount to override default credentials via gRPC * exchanges/credentials: don't return nil in GetCredentials * creds: spelling * exchanges: fix glorious NITS! * credentials: Add in test and refactor IsEmpty method. * credentials: change type positioning (glorious) * exchange_template: Fix template changes * DOCS: Refresh * docs: fix spelling * DOCS: fix alignment and add package * DOCS: ALIGN! 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:
@@ -318,8 +318,7 @@ func TestGetAuthAPISupportedExchanges(t *testing.T) {
|
||||
|
||||
b := exch.GetBase()
|
||||
b.API.AuthenticatedWebsocketSupport = true
|
||||
b.API.Credentials.Key = "test"
|
||||
b.API.Credentials.Secret = "test"
|
||||
b.SetCredentials("test", "test", "", "", "", "")
|
||||
if result := e.GetAuthAPISupportedExchanges(); len(result) != 1 {
|
||||
t.Fatal("Unexpected result", result)
|
||||
}
|
||||
|
||||
@@ -647,8 +647,8 @@ func TestSubmit(t *testing.T) {
|
||||
|
||||
m.cfg.AllowedPairs = nil
|
||||
_, err = m.Submit(context.Background(), o)
|
||||
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
|
||||
t.Errorf("error '%v', expected '%v'", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
||||
if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) {
|
||||
t.Errorf("received: %v but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled)
|
||||
}
|
||||
|
||||
err = m.orderStore.add(&order.Detail{
|
||||
|
||||
@@ -107,8 +107,7 @@ func (s *RPCServer) authenticateClient(ctx context.Context) (context.Context, er
|
||||
password != s.Config.RemoteControl.Password {
|
||||
return ctx, fmt.Errorf("username/password mismatch")
|
||||
}
|
||||
|
||||
return ctx, nil
|
||||
return exchange.ParseCredentialsMetadata(ctx, md)
|
||||
}
|
||||
|
||||
// StartRPCServer starts a gRPC server with TLS auth
|
||||
@@ -1553,7 +1552,7 @@ func (s *RPCServer) GetCryptocurrencyDepositAddresses(ctx context.Context, r *gc
|
||||
}
|
||||
|
||||
if !exch.GetAuthenticatedAPISupport(exchange.RestAuthentication) {
|
||||
return nil, exchange.ErrAuthenticatedRequestWithoutCredentialsSet
|
||||
return nil, fmt.Errorf("%s, %w", r.Exchange, exchange.ErrAuthenticationSupportNotEnabled)
|
||||
}
|
||||
|
||||
result, err := s.GetCryptocurrencyDepositAddressesByExchange(r.Exchange)
|
||||
@@ -1586,7 +1585,7 @@ func (s *RPCServer) GetCryptocurrencyDepositAddress(ctx context.Context, r *gctr
|
||||
}
|
||||
|
||||
if !exch.GetAuthenticatedAPISupport(exchange.RestAuthentication) {
|
||||
return nil, exchange.ErrAuthenticatedRequestWithoutCredentialsSet
|
||||
return nil, fmt.Errorf("%s, %w", r.Exchange, exchange.ErrAuthenticationSupportNotEnabled)
|
||||
}
|
||||
|
||||
addr, err := s.GetExchangeCryptocurrencyDepositAddress(ctx,
|
||||
@@ -4158,10 +4157,13 @@ func (s *RPCServer) GetFuturesPositions(ctx context.Context, r *gctrpc.GetFuture
|
||||
}
|
||||
|
||||
b := exch.GetBase()
|
||||
subAccount := b.API.Credentials.Subaccount
|
||||
creds, err := b.GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var subErr string
|
||||
if subAccount != "" {
|
||||
subErr = "for subaccount: " + subAccount
|
||||
if creds.SubAccount != "" {
|
||||
subErr = "for subaccount: " + creds.SubAccount
|
||||
}
|
||||
orders, err := exch.GetFuturesPositions(ctx, a, cp, start, end)
|
||||
if err != nil {
|
||||
@@ -4189,7 +4191,7 @@ func (s *RPCServer) GetFuturesPositions(ctx context.Context, r *gctrpc.GetFuture
|
||||
return nil, fmt.Errorf("%w %v", err, subErr)
|
||||
}
|
||||
response := &gctrpc.GetFuturesPositionsResponse{
|
||||
SubAccount: subAccount,
|
||||
SubAccount: creds.SubAccount,
|
||||
}
|
||||
var totalRealisedPNL, totalUnrealisedPNL decimal.Decimal
|
||||
for i := range pos {
|
||||
@@ -4310,24 +4312,29 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
|
||||
var calculators []order.CollateralCalculator
|
||||
var acc *account.SubAccount
|
||||
var subAccounts []string
|
||||
subAccount := r.SubAccount
|
||||
if subAccount == "" {
|
||||
b := exch.GetBase()
|
||||
subAccount = b.API.Credentials.Subaccount
|
||||
|
||||
creds, err := exch.GetBase().GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for i := range ai.Accounts {
|
||||
subAccounts = append(subAccounts, ai.Accounts[i].ID)
|
||||
if ai.Accounts[i].ID == "main" && subAccount == "" {
|
||||
if ai.Accounts[i].ID == "main" && creds.SubAccount == "" {
|
||||
acc = &ai.Accounts[i]
|
||||
break
|
||||
}
|
||||
if strings.EqualFold(subAccount, ai.Accounts[i].ID) {
|
||||
if strings.EqualFold(creds.SubAccount, ai.Accounts[i].ID) {
|
||||
acc = &ai.Accounts[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if acc == nil {
|
||||
return nil, fmt.Errorf("%w for %s %s and stored credentials - available subaccounts: %s", errNoAccountInformation, exch.GetName(), r.SubAccount, strings.Join(subAccounts, ","))
|
||||
return nil, fmt.Errorf("%w for %s %s and stored credentials - available subaccounts: %s",
|
||||
errNoAccountInformation,
|
||||
exch.GetName(),
|
||||
creds.SubAccount,
|
||||
strings.Join(subAccounts, ","))
|
||||
}
|
||||
var spotPairs currency.Pairs
|
||||
if r.CalculateOffline {
|
||||
@@ -4369,7 +4376,6 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
|
||||
}
|
||||
|
||||
calc := &order.TotalCollateralCalculator{
|
||||
SubAccount: r.SubAccount,
|
||||
CollateralAssets: calculators,
|
||||
CalculateOffline: r.CalculateOffline,
|
||||
FetchPositions: true,
|
||||
@@ -4382,7 +4388,7 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
|
||||
|
||||
var collateralDisplayCurrency = " " + collateral.CollateralCurrency.String()
|
||||
result := &gctrpc.GetCollateralResponse{
|
||||
SubAccount: subAccount,
|
||||
SubAccount: creds.SubAccount,
|
||||
CollateralCurrency: collateral.CollateralCurrency.String(),
|
||||
AvailableCollateral: collateral.AvailableCollateral.String() + collateralDisplayCurrency,
|
||||
UsedCollateral: collateral.UsedCollateral.String() + collateralDisplayCurrency,
|
||||
|
||||
@@ -1206,12 +1206,11 @@ func TestGetOrders(t *testing.T) {
|
||||
StartDate: time.Now().UTC().Add(-time.Hour).Format(common.SimpleTimeFormat),
|
||||
EndDate: time.Now().UTC().Add(time.Hour).Format(common.SimpleTimeFormat),
|
||||
})
|
||||
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
|
||||
t.Errorf("received '%v', expected '%v'", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
||||
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
|
||||
t.Errorf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
|
||||
b.API.Credentials.Key = "test"
|
||||
b.API.Credentials.Secret = "test"
|
||||
b.SetCredentials("test", "test", "", "", "", "")
|
||||
b.API.AuthenticatedSupport = true
|
||||
|
||||
_, err = s.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
|
||||
@@ -1310,8 +1309,8 @@ func TestGetOrder(t *testing.T) {
|
||||
Pair: p,
|
||||
Asset: asset.Spot.String(),
|
||||
})
|
||||
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
|
||||
t.Errorf("expected '%v' received '%v'", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
||||
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
|
||||
t.Errorf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2125,7 +2124,26 @@ func TestGetFuturesPositions(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
r, err := s.GetFuturesPositions(context.Background(), &gctrpc.GetFuturesPositionsRequest{
|
||||
_, err = s.GetFuturesPositions(context.Background(), &gctrpc.GetFuturesPositionsRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: currency.DashDelimiter,
|
||||
Base: cp.Base.String(),
|
||||
Quote: cp.Quote.String(),
|
||||
},
|
||||
Verbose: true,
|
||||
})
|
||||
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
|
||||
ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{
|
||||
Key: "wow",
|
||||
Secret: "super wow",
|
||||
})
|
||||
|
||||
r, err := s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2148,7 +2166,7 @@ func TestGetFuturesPositions(t *testing.T) {
|
||||
t.Fatal("expected 1 order")
|
||||
}
|
||||
|
||||
_, err = s.GetFuturesPositions(context.Background(), &gctrpc.GetFuturesPositionsRequest{
|
||||
_, err = s.GetFuturesPositions(ctx, &gctrpc.GetFuturesPositionsRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Spot.String(),
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
@@ -2209,18 +2227,29 @@ func TestGetCollateral(t *testing.T) {
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
})
|
||||
if !errors.Is(err, exchange.ErrCredentialsAreEmpty) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, exchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
|
||||
ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Key: "fakerino", Secret: "supafake"})
|
||||
|
||||
_, err = s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
})
|
||||
if !errors.Is(err, errNoAccountInformation) {
|
||||
t.Fatalf("received '%v', expected '%v'", err, errNoAccountInformation)
|
||||
}
|
||||
|
||||
r, err := s.GetCollateral(context.Background(), &gctrpc.GetCollateralRequest{
|
||||
ctx = exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Key: "fakerino", Secret: "supafake", SubAccount: "1337"})
|
||||
|
||||
r, err := s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
IncludeBreakdown: true,
|
||||
SubAccount: "1337",
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
t.Errorf("received '%v', expected '%v'", err, nil)
|
||||
t.Fatalf("received '%v', expected '%v'", err, nil)
|
||||
}
|
||||
if len(r.CurrencyBreakdown) != 3 {
|
||||
t.Errorf("expected 3 currencies, received '%v'", len(r.CurrencyBreakdown))
|
||||
@@ -2229,21 +2258,19 @@ func TestGetCollateral(t *testing.T) {
|
||||
t.Errorf("received '%v' expected '1337 USD'", r.AvailableCollateral)
|
||||
}
|
||||
|
||||
_, err = s.GetCollateral(context.Background(), &gctrpc.GetCollateralRequest{
|
||||
_, err = s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Spot.String(),
|
||||
IncludeBreakdown: true,
|
||||
SubAccount: "1337",
|
||||
})
|
||||
if !errors.Is(err, order.ErrNotFuturesAsset) {
|
||||
t.Errorf("received '%v', expected '%v'", err, order.ErrNotFuturesAsset)
|
||||
}
|
||||
|
||||
_, err = s.GetCollateral(context.Background(), &gctrpc.GetCollateralRequest{
|
||||
_, err = s.GetCollateral(ctx, &gctrpc.GetCollateralRequest{
|
||||
Exchange: fakeExchangeName,
|
||||
Asset: asset.Futures.String(),
|
||||
IncludeBreakdown: true,
|
||||
SubAccount: "1337",
|
||||
CalculateOffline: true,
|
||||
})
|
||||
if !errors.Is(err, nil) {
|
||||
|
||||
@@ -111,8 +111,8 @@ func TestSubmitWithdrawal(t *testing.T) {
|
||||
|
||||
adds[0].SupportedExchanges = exchangeName
|
||||
_, err = m.SubmitWithdrawal(context.Background(), req)
|
||||
if !errors.Is(err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) {
|
||||
t.Errorf("received %v, expected %v", err, exchange.ErrAuthenticatedRequestWithoutCredentialsSet)
|
||||
if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) {
|
||||
t.Errorf("received '%v', expected '%v'", err, exchange.ErrAuthenticationSupportNotEnabled)
|
||||
}
|
||||
|
||||
_, err = m.SubmitWithdrawal(context.Background(), nil)
|
||||
|
||||
Reference in New Issue
Block a user