diff --git a/backtester/backtest/backtest.go b/backtester/backtest/backtest.go index eb3ed167a5d..1f9bdae93c3 100644 --- a/backtester/backtest/backtest.go +++ b/backtester/backtest/backtest.go @@ -541,7 +541,7 @@ func (bt *BackTest) loadExchangePairAssetBase(exch, base, quote, ass string) (gc } exchangeBase := e.GetBase() - if !exchangeBase.ValidateAPICredentials() { + if exchangeBase.ValidateAPICredentials(exchangeBase.GetDefaultCredentials()) != nil { log.Warnf(log.BackTester, "no credentials set for %v, this is theoretical only", exchangeBase.Name) } @@ -801,21 +801,22 @@ func loadLiveData(cfg *config.Config, base *gctexchange.Base) error { } if cfg.DataSettings.LiveData.APIKeyOverride != "" { - base.API.Credentials.Key = cfg.DataSettings.LiveData.APIKeyOverride + base.API.SetKey(cfg.DataSettings.LiveData.APIKeyOverride) } if cfg.DataSettings.LiveData.APISecretOverride != "" { - base.API.Credentials.Secret = cfg.DataSettings.LiveData.APISecretOverride + base.API.SetSecret(cfg.DataSettings.LiveData.APISecretOverride) } if cfg.DataSettings.LiveData.APIClientIDOverride != "" { - base.API.Credentials.ClientID = cfg.DataSettings.LiveData.APIClientIDOverride + base.API.SetClientID(cfg.DataSettings.LiveData.APIClientIDOverride) } if cfg.DataSettings.LiveData.API2FAOverride != "" { - base.API.Credentials.PEMKey = cfg.DataSettings.LiveData.API2FAOverride + base.API.SetPEMKey(cfg.DataSettings.LiveData.API2FAOverride) } if cfg.DataSettings.LiveData.APISubAccountOverride != "" { - base.API.Credentials.Subaccount = cfg.DataSettings.LiveData.APISubAccountOverride + base.API.SetSubAccount(cfg.DataSettings.LiveData.APISubAccountOverride) } - validated := base.ValidateAPICredentials() + + validated := base.AreCredentialsValid(context.TODO()) base.API.AuthenticatedSupport = validated if !validated && cfg.DataSettings.LiveData.RealOrders { log.Warn(log.BackTester, "invalid API credentials set, real orders set to false") diff --git a/backtester/backtest/backtest_test.go b/backtester/backtest/backtest_test.go index 082cb70e785..b18b3039f0e 100644 --- a/backtester/backtest/backtest_test.go +++ b/backtester/backtest/backtest_test.go @@ -381,13 +381,6 @@ func TestLoadLiveData(t *testing.T) { AuthenticatedSupport: false, AuthenticatedWebsocketSupport: false, PEMKeySupport: false, - Credentials: struct { - Key string - Secret string - ClientID string - PEMKey string - Subaccount string - }{}, CredentialsValidator: struct { RequiresPEM bool RequiresKey bool @@ -403,6 +396,7 @@ func TestLoadLiveData(t *testing.T) { }, }, } + err = loadLiveData(cfg, b) if !errors.Is(err, common.ErrNilArguments) { t.Error(err) diff --git a/backtester/eventhandlers/exchange/exchange_test.go b/backtester/eventhandlers/exchange/exchange_test.go index e1accbca04d..c0cb684e66c 100644 --- a/backtester/eventhandlers/exchange/exchange_test.go +++ b/backtester/eventhandlers/exchange/exchange_test.go @@ -189,8 +189,8 @@ func TestPlaceOrder(t *testing.T) { } _, err = e.placeOrder(context.Background(), decimal.NewFromInt(1), decimal.NewFromInt(1), true, true, f, bot.OrderManager) - if err != nil && !strings.Contains(err.Error(), "unset/default API keys") { - t.Error(err) + if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) { + t.Errorf("received: %v but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled) } } @@ -293,8 +293,8 @@ func TestExecuteOrder(t *testing.T) { o.Direction = gctorder.Sell e.CurrencySettings = []Settings{cs} _, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{}) - if err != nil && !strings.Contains(err.Error(), "unset/default API keys") { - t.Error(err) + if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) { + t.Errorf("received: %v but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled) } } @@ -468,8 +468,8 @@ func TestExecuteOrderBuySellSizeLimit(t *testing.T) { o.Direction = gctorder.Sell e.CurrencySettings = []Settings{cs} _, err = e.ExecuteOrder(o, d, bot.OrderManager, &fakeFund{}) - 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 but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled) } } diff --git a/cmd/exchange_template/test_file.tmpl b/cmd/exchange_template/test_file.tmpl index 8312abd7b4d..a4ed4d39454 100644 --- a/cmd/exchange_template/test_file.tmpl +++ b/cmd/exchange_template/test_file.tmpl @@ -54,7 +54,7 @@ func TestInterface(t *testing.T) { } func areTestAPIKeysSet() bool { - return {{.Variable}}.ValidateAPICredentials() + return {{.Variable}}.ValidateAPICredentials({{.Variable}}.GetDefaultCredentials()) == nil } // Implement tests for API endpoints below diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl index 83143d71c0e..b5aeb733206 100644 --- a/cmd/exchange_template/wrapper_file.tmpl +++ b/cmd/exchange_template/wrapper_file.tmpl @@ -113,8 +113,11 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() { }, } // NOTE: SET THE EXCHANGES RATE LIMIT HERE - {{.Variable}}.Requester = request.New({{.Variable}}.Name, + {{.Variable}}.Requester, err = request.New({{.Variable}}.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) + if err != nil { + log.Errorln(log.ExchangeSys, err) + } // NOTE: SET THE URLs HERE {{.Variable}}.API.Endpoints = {{.Variable}}.NewEndpoints() diff --git a/cmd/exchange_wrapper_issues/main.go b/cmd/exchange_wrapper_issues/main.go index dbbcd9a4087..fad6a1036de 100644 --- a/cmd/exchange_wrapper_issues/main.go +++ b/cmd/exchange_wrapper_issues/main.go @@ -202,45 +202,43 @@ func shouldLoadExchange(name string) bool { func setExchangeAPIKeys(name string, keys map[string]*config.APICredentialsConfig, base *exchange.Base) bool { lowerExchangeName := strings.ToLower(name) - if base.API.CredentialsValidator.RequiresKey && keys[lowerExchangeName].Key == "" { - keys[lowerExchangeName].Key = config.DefaultAPIKey + creds, ok := keys[lowerExchangeName] + if !ok { + log.Printf("%s credentials not found in keys map\n", name) + return false } - if base.API.CredentialsValidator.RequiresSecret && keys[lowerExchangeName].Secret == "" { - keys[lowerExchangeName].Secret = config.DefaultAPISecret + + if base.API.CredentialsValidator.RequiresKey && creds.Key == "" { + creds.Key = config.DefaultAPIKey } - if base.API.CredentialsValidator.RequiresPEM && keys[lowerExchangeName].PEMKey == "" { - keys[lowerExchangeName].PEMKey = "PEM" + if base.API.CredentialsValidator.RequiresSecret && creds.Secret == "" { + creds.Secret = config.DefaultAPISecret } - if base.API.CredentialsValidator.RequiresClientID && keys[lowerExchangeName].ClientID == "" { - keys[lowerExchangeName].ClientID = config.DefaultAPIClientID + if base.API.CredentialsValidator.RequiresPEM && creds.PEMKey == "" { + creds.PEMKey = "PEM" } - if keys[lowerExchangeName].OTPSecret == "" { - keys[lowerExchangeName].OTPSecret = "-" // Ensure OTP is available for use + if base.API.CredentialsValidator.RequiresClientID && creds.ClientID == "" { + creds.ClientID = config.DefaultAPIClientID + } + if creds.OTPSecret == "" { + creds.OTPSecret = "-" // Ensure OTP is available for use } - base.API.Credentials.Key = keys[lowerExchangeName].Key - base.Config.API.Credentials.Key = keys[lowerExchangeName].Key - - base.API.Credentials.Secret = keys[lowerExchangeName].Secret - base.Config.API.Credentials.Secret = keys[lowerExchangeName].Secret - - base.API.Credentials.ClientID = keys[lowerExchangeName].ClientID - base.Config.API.Credentials.ClientID = keys[lowerExchangeName].ClientID + base.SetCredentials(creds.Key, creds.Secret, creds.ClientID, creds.Subaccount, creds.PEMKey, creds.OTPSecret) - if keys[lowerExchangeName].OTPSecret != "-" { - base.Config.API.Credentials.OTPSecret = keys[lowerExchangeName].OTPSecret - } - if keys[lowerExchangeName].Subaccount != "" { - base.API.Credentials.Subaccount = keys[lowerExchangeName].Subaccount - base.Config.API.Credentials.Subaccount = keys[lowerExchangeName].Subaccount - } + base.Config.API.Credentials.Key = creds.Key + base.Config.API.Credentials.Secret = creds.Secret + base.Config.API.Credentials.ClientID = creds.ClientID + base.Config.API.Credentials.Subaccount = creds.Subaccount + base.Config.API.Credentials.PEMKey = creds.PEMKey + base.Config.API.Credentials.OTPSecret = creds.OTPSecret base.API.AuthenticatedSupport = true base.API.AuthenticatedWebsocketSupport = true base.Config.API.AuthenticatedSupport = true base.Config.API.AuthenticatedWebsocketSupport = true - return base.ValidateAPICredentials() + return base.ValidateAPICredentials(base.GetDefaultCredentials()) == nil } func parseOrderSide(orderSide string) order.Side { diff --git a/cmd/gctcli/commands.go b/cmd/gctcli/commands.go index a96e1123223..caa1d192e48 100644 --- a/cmd/gctcli/commands.go +++ b/cmd/gctcli/commands.go @@ -4925,7 +4925,7 @@ func getFuturesPositions(c *cli.Context) error { var getCollateralCommand = &cli.Command{ Name: "getcollateral", Usage: "returns total collateral for an exchange asset, with optional per currency breakdown", - ArgsUsage: " ", + ArgsUsage: " ", Action: getCollateral, Flags: []cli.Flag{ &cli.StringFlag{ @@ -4953,11 +4953,6 @@ var getCollateralCommand = &cli.Command{ Aliases: []string{"z"}, Usage: "include collateral values that are zero", }, - &cli.StringFlag{ - Name: "subaccount", - Aliases: []string{"s"}, - Usage: "the subaccount to retrieve collateral data from, depending on individual exchange support", - }, }, } @@ -5015,13 +5010,6 @@ func getCollateral(c *cli.Context) error { } } - var subAccount string - if c.IsSet("subaccount") { - subAccount = c.String("subaccount") - } else if c.Args().Get(5) != "" { - subAccount = c.Args().Get(5) - } - conn, cancel, err := setupClient(c) if err != nil { return err @@ -5033,7 +5021,6 @@ func getCollateral(c *cli.Context) error { &gctrpc.GetCollateralRequest{ Exchange: exchangeName, Asset: assetType, - SubAccount: subAccount, IncludeBreakdown: includeBreakdown, CalculateOffline: calculateOffline, IncludeZeroValues: includeZeroValues, diff --git a/cmd/gctcli/main.go b/cmd/gctcli/main.go index 65ad498f86f..f1196d4c4b9 100644 --- a/cmd/gctcli/main.go +++ b/cmd/gctcli/main.go @@ -12,11 +12,13 @@ import ( "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/core" + exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/gctrpc/auth" "github.com/thrasher-corp/gocryptotrader/signaler" "github.com/urfave/cli/v2" "google.golang.org/grpc" "google.golang.org/grpc/credentials" + "google.golang.org/grpc/metadata" ) var ( @@ -26,6 +28,7 @@ var ( pairDelimiter string certPath string timeout time.Duration + exchangeCreds exchange.Credentials ) const defaultTimeout = time.Second * 30 @@ -53,6 +56,10 @@ func setupClient(c *cli.Context) (*grpc.ClientConn, context.CancelFunc, error) { var cancel context.CancelFunc c.Context, cancel = context.WithTimeout(c.Context, timeout) + if !exchangeCreds.IsEmpty() { + flag, values := exchangeCreds.GetMetaData() + c.Context = metadata.AppendToOutgoingContext(c.Context, flag, values) + } conn, err := grpc.DialContext(c.Context, host, opts...) return conn, cancel, err } @@ -100,6 +107,36 @@ func main() { Usage: "the default context timeout value for requests", Destination: &timeout, }, + &cli.StringFlag{ + Name: "apikey", + Usage: "override config API key for request", + Destination: &exchangeCreds.Key, + }, + &cli.StringFlag{ + Name: "apisecret", + Usage: "override config API Secret for request", + Destination: &exchangeCreds.Secret, + }, + &cli.StringFlag{ + Name: "apisubaccount", + Usage: "override config API sub account for request", + Destination: &exchangeCreds.SubAccount, + }, + &cli.StringFlag{ + Name: "apiclientid", + Usage: "override config API client ID for request", + Destination: &exchangeCreds.ClientID, + }, + &cli.StringFlag{ + Name: "apipemkey", + Usage: "override config API PEM key for request", + Destination: &exchangeCreds.PEMKey, + }, + &cli.StringFlag{ + Name: "apionetimepassword", + Usage: "override config API One Time Password (OTP) for request", + Destination: &exchangeCreds.OneTimePassword, + }, } app.Commands = []*cli.Command{ getInfoCommand, diff --git a/docs/ADD_NEW_EXCHANGE.md b/docs/ADD_NEW_EXCHANGE.md index 8bfe2df6b46..cac51361279 100644 --- a/docs/ADD_NEW_EXCHANGE.md +++ b/docs/ADD_NEW_EXCHANGE.md @@ -260,23 +260,21 @@ var Exchanges = []string{ func TestGetEnabledExchanges(t *testing.T) { cfg := GetConfig() err := cfg.LoadConfig(TestFile, true) - if err != nil { - t.Errorf( - "TestGetEnabledExchanges. LoadConfig Error: %s", err.Error(), - ) + if !errors.Is(err, errConfigDefineErrorExample) { + t.Errorf("received: '%v' but expected '%v'", err, errConfigDefineErrorExample) } exchanges := cfg.GetEnabledExchanges() - if len(exchanges) != defaultEnabledExchanges { // modify the value of defaultEnabledExchanges at the top of the config_test.go file to match the total count of exchanges - t.Error( - "TestGetEnabledExchanges. Enabled exchanges value mismatch", - ) + // modify the value of defaultEnabledExchanges at the top of the + // config_test.go file to match the total count of exchanges + if len(exchanges) != defaultEnabledExchanges { + t.Errorf("received: '%v' but expected '%v'", len(exchanges), defaultEnabledExchanges) } if !common.StringDataCompare(exchanges, "Bitfinex") { - t.Error( - "TestGetEnabledExchanges. Expected exchange Bitfinex not found", - ) + t.Errorf("received: '%v' but expected '%v'", + common.StringDataCompare(exchanges, "Bitfinex"), + true) } } ``` @@ -321,14 +319,16 @@ for i := range bot.Exchanges { // Public calls - wrapper functions +pair := currency.NewPair(currency.BTC, currency.USD) + // Fetches current ticker information -tick, err := e.FetchTicker() // e -> f +tick, err := e.FetchTicker(context.Background(), pair, asset.Spot) // e -> f if err != nil { // Handle error } // Fetches current orderbook information -ob, err := e.FetchOrderbook() // e -> f (do so for the rest of the functions too) +ob, err := e.FetchOrderbook(context.Background(), pair, asset.Spot) // e -> f (do so for the rest of the functions too) if err != nil { // Handle error } @@ -418,7 +418,7 @@ const ( Create a get function in ftx.go file and unmarshall the data in the created type: ```go // GetMarkets gets market data -func (f *FTX) GetMarkets() (Markets, error) { +func (f *FTX) GetMarkets(ctx context.Context) (Markets, error) { var resp Markets return resp, f.SendHTTPRequest(ctx, ftxAPIURL+getMarkets, &resp) } @@ -433,7 +433,7 @@ const( func TestGetMarket(t *testing.T) { t.Parallel() // adding t.Parralel() is preferred as it allows tests to run simultaneously, speeding up package test time f.Verbose = true // used for more detailed output - a, err := f.GetMarket(spotPair) // spotPair is just a const so it can be reused in other tests too + a, err := f.GetMarket(context.Background(), spotPair) // spotPair is just a const so it can be reused in other tests too t.Log(a) if err != nil { t.Error(err) @@ -443,7 +443,7 @@ func TestGetMarket(t *testing.T) { Verbose can be set to true to see the data received if there are errors unmarshalling Once testing is done remove verbose, variable a and t.Log(a) since they produce unnecessary output when GCT is run ```go -_, err := f.GetMarket(spotPair) +_, err := f.GetMarket(context.Background(), spotPair) ``` Ensure each endpoint is implemented and has an associated test to improve test coverage and increase confidence @@ -459,6 +459,14 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, method, path string, data // limiting. This is for when signatures are based on timestamps/nonces that are // within time receive windows. NOTE: This is not always necessary and the above // SendHTTPRequest example will suffice. + + // Fetches credentials, this can either use a context set credential or if + // not found, will default to the config.json exchange specific credentials. + creds, err := f.GetCredentials(ctx) + if err != nil { + return err + } + generate := func() (*request.Item, error) { ts := strconv.FormatInt(time.Now().UnixMilli(), 10) var body io.Reader @@ -471,13 +479,13 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, method, path string, data } body = bytes.NewBuffer(payload) sigPayload := ts + method + "/api" + path + string(payload) - hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(f.API.Credentials.Secret)) + hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(creds.Secret)) } else { sigPayload := ts + method + "/api" + path - hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(f.API.Credentials.Secret)) + hmac = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), []byte(creds.Secret)) } headers := make(map[string]string) - headers["FTX-KEY"] = f.API.Credentials.Key + headers["FTX-KEY"] = creds.Key headers["FTX-SIGN"] = crypto.HexEncodeToString(hmac) headers["FTX-TS"] = ts headers["Content-Type"] = "application/json" @@ -515,7 +523,7 @@ https://docs.ftx.com/#get-account-information: ```go // GetAccountInfo gets account info -func (f *FTX) GetAccountInfo() (AccountData, error) { +func (f *FTX) GetAccountInfo(ctx context.Context) (AccountData, error) { var resp AccountData return resp, f.SendAuthHTTPRequest(ctx, http.MethodGet, getAccountInfo, nil, &resp) } @@ -527,7 +535,7 @@ https://docs.ftx.com/#get-withdrawal-history: ```go // GetTriggerOrderHistory gets trigger orders that are currently open -func (f *FTX) GetTriggerOrderHistory(marketName string, startTime, endTime time.Time, side, orderType, limit string) (TriggerOrderHistory, error) { +func (f *FTX) GetTriggerOrderHistory(ctx context.Context, marketName string, startTime, endTime time.Time, side, orderType, limit string) (TriggerOrderHistory, error) { var resp TriggerOrderHistory params := url.Values{} if marketName != "" { @@ -589,7 +597,7 @@ For `POST` or `DELETE` requests, params are sent through a map[string]interface{ ```go // Order places an order -func (f *FTX) Order(marketName, side, orderType, reduceOnly, ioc, postOnly, clientID string, price, size float64) (PlaceOrder, error) { +func (f *FTX) Order(ctx context.Context, marketName, side, orderType, reduceOnly, ioc, postOnly, clientID string, price, size float64) (PlaceOrder, error) { req := make(map[string]interface{}) req["market"] = marketName req["side"] = side @@ -637,7 +645,7 @@ func (f *FTX) FetchTradablePairs(ctx context.Context, a asset.Item) ([]string, e if !f.SupportsAsset(a) { return nil, fmt.Errorf("asset type of %s is not supported by %s", a, f.Name) } - markets, err := f.GetMarkets() + markets, err := f.GetMarkets(ctx) if err != nil { return nil, err } @@ -709,7 +717,7 @@ func (f *FTX) WsConnect() error { // efficient processing. go f.wsReadData() if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = f.WsAuth() + err = f.WsAuth(context.TODO()) if err != nil { f.Websocket.DataHandler <- err f.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -1025,17 +1033,27 @@ https://docs.ftx.com/#private-channels ```go // WsAuth sends an authentication message to receive auth data -func (f *FTX) WsAuth() error { +func (f *FTX) WsAuth(ctx context.Context) error { + // Fetches credentials, this can either use a context set credential or if + // not found, will default to the config.json exchange specific credentials. + // NOTE: Websocket context values are not sufficiently propagated yet, so in + // most circumstances the calling function can call context.TODO() and will + // use default credentials. + creds, err := f.GetCredentials(ctx) + if err != nil { + return err + } + strNonce := strconv.FormatInt(time.Now().UnixMilli(), 10) hmac := crypto.GetHMAC( crypto.HashSHA256, []byte(strNonce+"websocket_login"), - []byte(f.API.Credentials.Secret), + []byte(creds.Secret), ) sign := crypto.HexEncodeToString(hmac) req := Authenticate{Operation: "login", Args: AuthenticationData{ - Key: f.API.Credentials.Key, + Key: creds.Key, Sign: sign, Time: intNonce, }, @@ -1193,8 +1211,8 @@ Initially the functions return nil or common.ErrNotYetImplemented ```go // AuthenticateWebsocket sends an authentication message to the websocket -func (f *FTX) AuthenticateWebsocket() error { - return f.WsAuth() +func (f *FTX) AuthenticateWebsocket(ctx context.Context) error { + return f.WsAuth(ctx) } ``` diff --git a/docs/EXCHANGE_API.md b/docs/EXCHANGE_API.md index edeef89d831..64e7598bda9 100644 --- a/docs/EXCHANGE_API.md +++ b/docs/EXCHANGE_API.md @@ -40,7 +40,7 @@ supplied meet the requirements to make an authenticated request. ```go var b bitstamp.Bitstamp b.SetDefaults() - ticker, err := b.FetchTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot) + ticker, err := b.FetchTicker(context.Background(), currency.NewPair(currency.BTC, currency.USD), asset.Spot) if err != nil { // Handle error } @@ -53,9 +53,26 @@ supplied meet the requirements to make an authenticated request. var b bitstamp.Bitstamp b.SetDefaults() - b.API.Credentials.Key = "your_key" - b.API.Credentials.Secret = "your_secret" - b.API.Credentials.ClientID = "your_clientid" + // Set default keys + b.API.SetKey("your_key") + b.API.SetSecret("your_secret") + b.API.SetClientID("your_clientid") + b.API.SetPEMKey("your_PEM_key") + b.API.SetSubAccount("your_specific_subaccount") + + // Set client/strategy/subsystem specific credentials that will override + // default credentials. + // Make a standard context and add credentials to it by using exchange + // package helper function DeployCredentialsToContext + ctx := context.Background() + ctx = exchange.DeployCredentialsToContext(ctx, &exchange.Credentials{ + Key: "your_key", + Secret: "your_secret", + ClientID: "your_clientid", + PEMKey: "your_PEM_key", + SubAccount: "your_specific_subaccount", + }) + o := &order.Submit{ Pair: currency.NewPair(currency.BTC, currency.USD), @@ -65,7 +82,9 @@ supplied meet the requirements to make an authenticated request. Amount: 0.1, AssetType: asset.Spot, } - resp, err := b.SubmitOrder(o) + + // Context will be intercepted when sending an authenticated HTTP request. + resp, err := b.SubmitOrder(ctx, o) if err != nil { // Handle error } diff --git a/engine/helpers_test.go b/engine/helpers_test.go index 0fe7d8b18bb..23dec7af378 100644 --- a/engine/helpers_test.go +++ b/engine/helpers_test.go @@ -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) } diff --git a/engine/order_manager_test.go b/engine/order_manager_test.go index 9dc4ece790a..9dc52595605 100644 --- a/engine/order_manager_test.go +++ b/engine/order_manager_test.go @@ -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{ diff --git a/engine/rpcserver.go b/engine/rpcserver.go index 22788a1671a..0ec5daf4ef8 100644 --- a/engine/rpcserver.go +++ b/engine/rpcserver.go @@ -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, diff --git a/engine/rpcserver_test.go b/engine/rpcserver_test.go index 37416228fe5..3a836107d39 100644 --- a/engine/rpcserver_test.go +++ b/engine/rpcserver_test.go @@ -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) { diff --git a/engine/withdraw_manager_test.go b/engine/withdraw_manager_test.go index c70f26a7b53..dec239788be 100644 --- a/engine/withdraw_manager_test.go +++ b/engine/withdraw_manager_test.go @@ -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) diff --git a/exchanges/alphapoint/alphapoint.go b/exchanges/alphapoint/alphapoint.go index 485879f15d4..0df11b62849 100644 --- a/exchanges/alphapoint/alphapoint.go +++ b/exchanges/alphapoint/alphapoint.go @@ -9,7 +9,6 @@ import ( "net/http" "strconv" "strings" - "time" "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common/crypto" @@ -39,10 +38,6 @@ const ( alphapointCancelAllOrders = "CancelAllOrders" alphapointOpenOrders = "GetAccountOpenOrders" alphapointOrderFee = "GetOrderFee" - - // alphapoint rate limit - alphapointRateInterval = time.Minute * 10 - alphapointRequestRate = 500 ) // Alphapoint is the overarching type across the alphapoint package @@ -576,8 +571,9 @@ func (a *Alphapoint) SendHTTPRequest(ctx context.Context, ep exchange.URL, metho // SendAuthenticatedHTTPRequest sends an authenticated request func (a *Alphapoint) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data map[string]interface{}, result interface{}) error { - if !a.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", a.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := a.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := a.API.Endpoints.GetURL(ep) @@ -589,12 +585,12 @@ func (a *Alphapoint) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchan headers := make(map[string]string) headers["Content-Type"] = "application/json" - data["apiKey"] = a.API.Credentials.Key + data["apiKey"] = creds.Key data["apiNonce"] = n hmac, err := crypto.GetHMAC(crypto.HashSHA256, - []byte(n.String()+a.API.Credentials.ClientID+a.API.Credentials.Key), - []byte(a.API.Credentials.Secret)) + []byte(n.String()+creds.ClientID+creds.Key), + []byte(creds.Secret)) if err != nil { return err } diff --git a/exchanges/alphapoint/alphapoint_test.go b/exchanges/alphapoint/alphapoint_test.go index a2a34d4f5ea..ea4b41e7281 100644 --- a/exchanges/alphapoint/alphapoint_test.go +++ b/exchanges/alphapoint/alphapoint_test.go @@ -27,14 +27,13 @@ var a Alphapoint func TestMain(m *testing.M) { a.SetDefaults() - a.API.Credentials.Key = apiKey - a.API.Credentials.Secret = apiSecret + a.SetCredentials(apiKey, apiSecret, "", "", "", "") a.API.AuthenticatedSupport = true os.Exit(m.Run()) } func areTestAPIKeysSet() bool { - return a.ValidateAPICredentials() + return a.ValidateAPICredentials(a.GetDefaultCredentials()) == nil } func TestGetTicker(t *testing.T) { diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index d2038c111cb..31794289d43 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -765,8 +765,14 @@ func (b *Binance) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, if err != nil { return err } + + creds, err := b.GetCredentials(ctx) + if err != nil { + return err + } + headers := make(map[string]string) - headers["X-MBX-APIKEY"] = b.API.Credentials.Key + headers["X-MBX-APIKEY"] = creds.Key item := &request.Item{ Method: http.MethodGet, Path: endpointPath + path, @@ -783,9 +789,11 @@ func (b *Binance) SendAPIKeyHTTPRequest(ctx context.Context, ePath exchange.URL, // SendAuthHTTPRequest sends an authenticated HTTP request func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, method, path string, params url.Values, f request.EndpointLimit, result interface{}) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } + endpointPath, err := b.API.Endpoints.GetURL(ePath) if err != nil { return err @@ -807,13 +815,13 @@ func (b *Binance) SendAuthHTTPRequest(ctx context.Context, ePath exchange.URL, m var hmacSigned []byte hmacSigned, err = crypto.GetHMAC(crypto.HashSHA256, []byte(signature), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } hmacSignedStr := crypto.HexEncodeToString(hmacSigned) headers := make(map[string]string) - headers["X-MBX-APIKEY"] = b.API.Credentials.Key + headers["X-MBX-APIKEY"] = creds.Key fullPath = common.EncodeURLValues(fullPath, params) fullPath += "&signature=" + hmacSignedStr return &request.Item{ @@ -1098,9 +1106,14 @@ func (b *Binance) GetWsAuthStreamKey(ctx context.Context) (string, error) { return "", err } + creds, err := b.GetCredentials(ctx) + if err != nil { + return "", err + } + var resp UserAccountStream headers := make(map[string]string) - headers["X-MBX-APIKEY"] = b.API.Credentials.Key + headers["X-MBX-APIKEY"] = creds.Key item := &request.Item{ Method: http.MethodPost, Path: endpointPath + userAccountStream, @@ -1131,12 +1144,18 @@ func (b *Binance) MaintainWsAuthStreamKey(ctx context.Context) error { listenKey, err = b.GetWsAuthStreamKey(ctx) return err } + + creds, err := b.GetCredentials(ctx) + if err != nil { + return err + } + path := endpointPath + userAccountStream params := url.Values{} params.Set("listenKey", listenKey) path = common.EncodeURLValues(path, params) headers := make(map[string]string) - headers["X-MBX-APIKEY"] = b.API.Credentials.Key + headers["X-MBX-APIKEY"] = creds.Key item := &request.Item{ Method: http.MethodPut, Path: path, diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index 032368c6d10..eb3da595239 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -36,7 +36,7 @@ var ( ) func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func setFeeBuilder() *exchange.FeeBuilder { diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 27e0062ca9f..c17dde40bd3 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -1316,7 +1316,7 @@ func (b *Binance) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuil if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!b.AllowAuthenticatedRequest() || b.SkipAuthCheck) && // Todo check connection status + if (!b.AreCredentialsValid(ctx) || b.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go index 93334234b90..f7a071ba1b6 100644 --- a/exchanges/bitfinex/bitfinex.go +++ b/exchanges/bitfinex/bitfinex.go @@ -1643,8 +1643,9 @@ func (b *Bitfinex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st // SendAuthenticatedHTTPRequest sends an autheticated http request and json // unmarshals result to a supplied variable func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := b.API.Endpoints.GetURL(ep) @@ -1671,12 +1672,12 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange PayloadBase64 := crypto.Base64Encode(PayloadJSON) hmac, err := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["X-BFX-APIKEY"] = b.API.Credentials.Key + headers["X-BFX-APIKEY"] = creds.Key headers["X-BFX-PAYLOAD"] = PayloadBase64 headers["X-BFX-SIGNATURE"] = crypto.HexEncodeToString(hmac) @@ -1696,8 +1697,9 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange // SendAuthenticatedHTTPRequestV2 sends an autheticated http request and json // unmarshals result to a supplied variable func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}, endpoint request.EndpointLimit) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := b.API.Endpoints.GetURL(ep) if err != nil { @@ -1719,13 +1721,13 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequestV2(ctx context.Context, ep exchan headers := make(map[string]string) headers["Content-Type"] = "application/json" headers["Accept"] = "application/json" - headers["bfx-apikey"] = b.API.Credentials.Key + headers["bfx-apikey"] = creds.Key headers["bfx-nonce"] = n sig := "/api" + bitfinexAPIVersion2 + path + n + string(payload) hmac, err := crypto.GetHMAC( crypto.HashSHA512_384, []byte(sig), - []byte(b.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return nil, err diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 6737dee729b..80209643292 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -50,8 +50,7 @@ func TestMain(m *testing.M) { if err != nil { log.Fatal("Bitfinex setup error", err) } - b.API.Credentials.Key = apiKey - b.API.Credentials.Secret = apiSecret + b.SetCredentials(apiKey, apiSecret, "", "", "", "") if !b.Enabled || b.API.AuthenticatedSupport || b.Verbose || b.Websocket.IsEnabled() || len(b.BaseCurrencies) < 1 { log.Fatal("Bitfinex Setup values not set correctly") @@ -341,7 +340,7 @@ func TestGetWithdrawalFee(t *testing.T) { } func TestGetAccountSummary(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -353,7 +352,7 @@ func TestGetAccountSummary(t *testing.T) { } func TestNewDeposit(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -374,7 +373,7 @@ func TestNewDeposit(t *testing.T) { } func TestGetKeyPermissions(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -386,7 +385,7 @@ func TestGetKeyPermissions(t *testing.T) { } func TestGetMarginInfo(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -398,7 +397,7 @@ func TestGetMarginInfo(t *testing.T) { } func TestGetAccountBalance(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -410,7 +409,7 @@ func TestGetAccountBalance(t *testing.T) { } func TestGetAccountInfo(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -422,7 +421,7 @@ func TestGetAccountInfo(t *testing.T) { } func TestWalletTransfer(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -434,7 +433,7 @@ func TestWalletTransfer(t *testing.T) { } func TestNewOrder(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -471,7 +470,7 @@ func TestUpdateTickers(t *testing.T) { } func TestNewOrderMulti(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -494,7 +493,7 @@ func TestNewOrderMulti(t *testing.T) { } func TestCancelOrder(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -506,7 +505,7 @@ func TestCancelOrder(t *testing.T) { } func TestCancelMultipleOrders(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -518,7 +517,7 @@ func TestCancelMultipleOrders(t *testing.T) { } func TestCancelAllOrders(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -530,7 +529,7 @@ func TestCancelAllOrders(t *testing.T) { } func TestReplaceOrder(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -543,7 +542,7 @@ func TestReplaceOrder(t *testing.T) { } func TestGetOrderStatus(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -555,7 +554,7 @@ func TestGetOrderStatus(t *testing.T) { } func TestGetOpenOrders(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -567,7 +566,7 @@ func TestGetOpenOrders(t *testing.T) { } func TestGetActivePositions(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -579,7 +578,7 @@ func TestGetActivePositions(t *testing.T) { } func TestClaimPosition(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -591,7 +590,7 @@ func TestClaimPosition(t *testing.T) { } func TestGetBalanceHistory(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -603,7 +602,7 @@ func TestGetBalanceHistory(t *testing.T) { } func TestGetMovementHistory(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -615,7 +614,7 @@ func TestGetMovementHistory(t *testing.T) { } func TestGetTradeHistory(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -627,7 +626,7 @@ func TestGetTradeHistory(t *testing.T) { } func TestNewOffer(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -639,7 +638,7 @@ func TestNewOffer(t *testing.T) { } func TestCancelOffer(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -651,7 +650,7 @@ func TestCancelOffer(t *testing.T) { } func TestGetOfferStatus(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -663,7 +662,7 @@ func TestGetOfferStatus(t *testing.T) { } func TestGetActiveCredits(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -675,7 +674,7 @@ func TestGetActiveCredits(t *testing.T) { } func TestGetActiveOffers(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -687,7 +686,7 @@ func TestGetActiveOffers(t *testing.T) { } func TestGetActiveMarginFunding(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -699,7 +698,7 @@ func TestGetActiveMarginFunding(t *testing.T) { } func TestGetUnusedMarginFunds(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -711,7 +710,7 @@ func TestGetUnusedMarginFunds(t *testing.T) { } func TestGetMarginTotalTakenFunds(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -723,7 +722,7 @@ func TestGetMarginTotalTakenFunds(t *testing.T) { } func TestCloseMarginFunding(t *testing.T) { - if !b.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.SkipNow() } t.Parallel() @@ -867,7 +866,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { @@ -1086,7 +1085,7 @@ func TestWsAuth(t *testing.T) { func runAuth(t *testing.T) { t.Helper() setupWs() - if err := b.WsSendAuth(); err != nil { + if err := b.WsSendAuth(context.Background()); err != nil { t.Error(err) } timer := time.NewTimer(sharedtestvalues.WebsocketResponseDefaultTimeout) diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index 7e23576cd30..9a84f19c8f5 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -1,6 +1,7 @@ package bitfinex import ( + "context" "encoding/json" "errors" "fmt" @@ -17,7 +18,6 @@ import ( "github.com/thrasher-corp/gocryptotrader/common/convert" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" - exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" @@ -67,7 +67,7 @@ func (b *Bitfinex) WsConnect() error { } b.Websocket.Wg.Add(1) go b.wsReadData(b.Websocket.AuthConn) - err = b.WsSendAuth() + err = b.WsSendAuth(context.TODO()) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", @@ -1317,10 +1317,10 @@ func (b *Bitfinex) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscriptio } // WsSendAuth sends a autheticated event payload -func (b *Bitfinex) WsSendAuth() error { - if !b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", - b.Name) +func (b *Bitfinex) WsSendAuth(ctx context.Context) error { + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } nonce := strconv.FormatInt(time.Now().Unix(), 10) @@ -1328,13 +1328,13 @@ func (b *Bitfinex) WsSendAuth() error { hmac, err := crypto.GetHMAC(crypto.HashSHA512_384, []byte(payload), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } request := WsAuthRequest{ Event: "auth", - APIKey: b.API.Credentials.Key, + APIKey: creds.Key, AuthPayload: payload, AuthSig: crypto.HexEncodeToString(hmac), AuthNonce: nonce, diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index 8983f3c7df6..769b3f15e5c 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -869,7 +869,7 @@ func (b *Bitfinex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -1018,8 +1018,8 @@ func (b *Bitfinex) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequ } // AuthenticateWebsocket sends an authentication message to the websocket -func (b *Bitfinex) AuthenticateWebsocket(_ context.Context) error { - return b.WsSendAuth() +func (b *Bitfinex) AuthenticateWebsocket(ctx context.Context) error { + return b.WsSendAuth(ctx) } // appendOptionalDelimiter ensures that a delimiter is present for long character currencies diff --git a/exchanges/bitflyer/bitflyer_test.go b/exchanges/bitflyer/bitflyer_test.go index 5fb038249ce..78afd28013e 100644 --- a/exchanges/bitflyer/bitflyer_test.go +++ b/exchanges/bitflyer/bitflyer_test.go @@ -323,7 +323,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go index 5007fe14886..0d41f5669f9 100644 --- a/exchanges/bitflyer/bitflyer_wrapper.go +++ b/exchanges/bitflyer/bitflyer_wrapper.go @@ -457,7 +457,7 @@ func (b *Bitflyer) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/bithumb/bithumb.go b/exchanges/bithumb/bithumb.go index 2ec49435031..397d026205d 100644 --- a/exchanges/bithumb/bithumb.go +++ b/exchanges/bithumb/bithumb.go @@ -542,8 +542,9 @@ func (b *Bithumb) SendHTTPRequest(ctx context.Context, ep exchange.URL, path str // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bithumb func (b *Bithumb) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result interface{}) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { @@ -567,14 +568,14 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange. var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA512, []byte(hmacPayload), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } hmacStr := crypto.HexEncodeToString(hmac) headers := make(map[string]string) - headers["Api-Key"] = b.API.Credentials.Key + headers["Api-Key"] = creds.Key headers["Api-Sign"] = crypto.Base64Encode([]byte(hmacStr)) headers["Api-Nonce"] = n headers["Content-Type"] = "application/x-www-form-urlencoded" diff --git a/exchanges/bithumb/bithumb_test.go b/exchanges/bithumb/bithumb_test.go index e0eb8cf1779..bb7faa5909c 100644 --- a/exchanges/bithumb/bithumb_test.go +++ b/exchanges/bithumb/bithumb_test.go @@ -406,7 +406,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index aca5bd1a849..56705ed7083 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -678,7 +678,7 @@ func (b *Bithumb) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuil if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/bitmex/bitmex.go b/exchanges/bitmex/bitmex.go index c8a35f9055e..a0db6e1d59d 100644 --- a/exchanges/bitmex/bitmex.go +++ b/exchanges/bitmex/bitmex.go @@ -847,8 +847,9 @@ func (b *Bitmex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bitmex func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, verb, path string, params Parameter, result interface{}) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { @@ -865,7 +866,7 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U headers := make(map[string]string) headers["Content-Type"] = "application/json" headers["api-expires"] = timestampNew - headers["api-key"] = b.API.Credentials.Key + headers["api-key"] = creds.Key var payload string if params != nil { @@ -884,7 +885,7 @@ func (b *Bitmex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(verb+"/api/v1"+path+timestampNew+payload), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go index 302d0ed8c83..ab1362bbdfe 100644 --- a/exchanges/bitmex/bitmex_test.go +++ b/exchanges/bitmex/bitmex_test.go @@ -652,7 +652,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { @@ -853,7 +853,7 @@ func TestWsAuth(t *testing.T) { } go b.wsReadData() - err = b.websocketSendAuth() + err = b.websocketSendAuth(context.Background()) if err != nil { t.Fatal(err) } diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go index ab2a390de4e..69d420a8a6f 100644 --- a/exchanges/bitmex/bitmex_websocket.go +++ b/exchanges/bitmex/bitmex_websocket.go @@ -1,6 +1,7 @@ package bitmex import ( + "context" "encoding/json" "errors" "fmt" @@ -12,7 +13,6 @@ import ( "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" - exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" @@ -97,7 +97,7 @@ func (b *Bitmex) WsConnect() error { b.Websocket.Wg.Add(1) go b.wsReadData() - err = b.websocketSendAuth() + err = b.websocketSendAuth(context.TODO()) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", @@ -659,16 +659,17 @@ func (b *Bitmex) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) } // WebsocketSendAuth sends an authenticated subscription -func (b *Bitmex) websocketSendAuth() error { - if !b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", b.Name) +func (b *Bitmex) websocketSendAuth(ctx context.Context) error { + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } b.Websocket.SetCanUseAuthenticatedEndpoints(true) timestamp := time.Now().Add(time.Hour * 1).Unix() newTimestamp := strconv.FormatInt(timestamp, 10) hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte("GET/realtime"+newTimestamp), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } @@ -676,7 +677,7 @@ func (b *Bitmex) websocketSendAuth() error { var sendAuth WebsocketRequest sendAuth.Command = "authKeyExpires" - sendAuth.Arguments = append(sendAuth.Arguments, b.API.Credentials.Key, timestamp, + sendAuth.Arguments = append(sendAuth.Arguments, creds.Key, timestamp, signature) err = b.Websocket.Conn.SendJSONMessage(sendAuth) if err != nil { diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go index f2f3675375d..011ba4d1751 100644 --- a/exchanges/bitmex/bitmex_wrapper.go +++ b/exchanges/bitmex/bitmex_wrapper.go @@ -731,7 +731,7 @@ func (b *Bitmex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -856,8 +856,8 @@ func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques } // AuthenticateWebsocket sends an authentication message to the websocket -func (b *Bitmex) AuthenticateWebsocket(_ context.Context) error { - return b.websocketSendAuth() +func (b *Bitmex) AuthenticateWebsocket(ctx context.Context) error { + return b.websocketSendAuth(ctx) } // ValidateCredentials validates current credentials used for wrapper diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index f69524516f9..119a4f40487 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -565,8 +565,9 @@ func (b *Bitstamp) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st // SendAuthenticatedHTTPRequest sends an authenticated request func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, v2 bool, values url.Values, result interface{}) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { @@ -581,13 +582,13 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange err = b.SendPayload(ctx, request.Unset, func() (*request.Item, error) { n := b.Requester.GetNonce(true).String() - values.Set("key", b.API.Credentials.Key) + values.Set("key", creds.Key) values.Set("nonce", n) var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, - []byte(n+b.API.Credentials.ClientID+b.API.Credentials.Key), - []byte(b.API.Credentials.Secret)) + []byte(n+creds.ClientID+creds.Key), + []byte(creds.Secret)) if err != nil { return nil, err } diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go index 6f81f626ccd..809b3fde10e 100644 --- a/exchanges/bitstamp/bitstamp_test.go +++ b/exchanges/bitstamp/bitstamp_test.go @@ -29,7 +29,7 @@ const ( var b Bitstamp func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func setFeeBuilder() *exchange.FeeBuilder { diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 17e40a6fb29..5b068a0ef0c 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -367,7 +367,7 @@ func (b *Bitstamp) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!b.AllowAuthenticatedRequest() || b.SkipAuthCheck) && // Todo check connection status + if (!b.AreCredentialsValid(ctx) || b.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/bittrex/bittrex.go b/exchanges/bittrex/bittrex.go index 391594473c8..c8a74899117 100644 --- a/exchanges/bittrex/bittrex.go +++ b/exchanges/bittrex/bittrex.go @@ -376,8 +376,9 @@ func (b *Bittrex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path str // SendAuthHTTPRequest sends an authenticated request func (b *Bittrex) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, action string, params url.Values, data, result interface{}, resultHeader *http.Header) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := b.API.Endpoints.GetURL(ep) if err != nil { @@ -409,13 +410,13 @@ func (b *Bittrex) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, meth sigPayload := ts + endpoint + path + method + contentHash hmac, err = crypto.GetHMAC(crypto.HashSHA512, []byte(sigPayload), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["Api-Key"] = b.API.Credentials.Key + headers["Api-Key"] = creds.Key headers["Api-Timestamp"] = ts headers["Api-Content-Hash"] = contentHash headers["Api-Signature"] = crypto.HexEncodeToString(hmac) diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go index 45ff98abb9d..76e56e6b276 100644 --- a/exchanges/bittrex/bittrex_test.go +++ b/exchanges/bittrex/bittrex_test.go @@ -516,7 +516,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/bittrex/bittrex_websocket.go b/exchanges/bittrex/bittrex_websocket.go index 907a1af3290..575f2a60d05 100644 --- a/exchanges/bittrex/bittrex_websocket.go +++ b/exchanges/bittrex/bittrex_websocket.go @@ -118,7 +118,7 @@ func (b *Bittrex) WsConnect() error { } if b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = b.WsAuth() + err = b.WsAuth(context.TODO()) if err != nil { b.Websocket.DataHandler <- err b.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -149,9 +149,13 @@ func (b *Bittrex) WsSignalRHandshake(ctx context.Context, result interface{}) er // WsAuth sends an authentication message to receive auth data // Authentications expire after 10 minutes -func (b *Bittrex) WsAuth() error { +func (b *Bittrex) WsAuth(ctx context.Context) error { + creds, err := b.GetCredentials(ctx) + if err != nil { + return err + } // [apiKey, timestamp in ms, random uuid, signed payload] - apiKey := b.API.Credentials.Key + apiKey := creds.Key randomContent, err := uuid.NewV4() if err != nil { return err @@ -160,7 +164,7 @@ func (b *Bittrex) WsAuth() error { hmac, err := crypto.GetHMAC( crypto.HashSHA512, []byte(timestamp+randomContent.String()), - []byte(b.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return err @@ -485,7 +489,7 @@ func (b *Bittrex) wsHandleData(respRaw []byte) error { if b.Verbose { log.Debugf(log.WebsocketMgr, "%s - Re-authenticating.\n", b.Name) } - err = b.WsAuth() + err = b.WsAuth(context.TODO()) if err != nil { b.Websocket.DataHandler <- err b.Websocket.SetCanUseAuthenticatedEndpoints(false) diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 6bda4f46cec..f1d97718d55 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -899,7 +899,7 @@ func (b *Bittrex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuil if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go index 7860ac6b2ae..4aa5f409bc8 100644 --- a/exchanges/btcmarkets/btcmarkets.go +++ b/exchanges/btcmarkets/btcmarkets.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" "net/url" @@ -711,8 +710,9 @@ func (b *BTCMarkets) SendHTTPRequest(ctx context.Context, path string, result in // SendAuthenticatedRequest sends an authenticated HTTP request func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path string, data, result interface{}, f request.EndpointLimit) (err error) { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } newRequest := func() (*request.Item, error) { @@ -729,7 +729,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path strMsg := method + btcMarketsAPIVersion + path + strTime + string(payload) hmac, err = crypto.GetHMAC(crypto.HashSHA512, []byte(strMsg), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } @@ -737,7 +737,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path strArray := strings.Split(path, "?") hmac, err = crypto.GetHMAC(crypto.HashSHA512, []byte(method+btcMarketsAPIVersion+strArray[0]+strTime), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } @@ -747,7 +747,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(ctx context.Context, method, path headers["Accept"] = "application/json" headers["Accept-Charset"] = "UTF-8" headers["Content-Type"] = "application/json" - headers["BM-AUTH-APIKEY"] = b.API.Credentials.Key + headers["BM-AUTH-APIKEY"] = creds.Key headers["BM-AUTH-TIMESTAMP"] = strTime headers["BM-AUTH-SIGNATURE"] = crypto.Base64Encode(hmac) diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go index 6b4a36549f8..2903933d299 100644 --- a/exchanges/btcmarkets/btcmarkets_test.go +++ b/exchanges/btcmarkets/btcmarkets_test.go @@ -62,7 +62,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return b.AllowAuthenticatedRequest() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go index 2ab016d62a6..29b137bd805 100644 --- a/exchanges/btcmarkets/btcmarkets_websocket.go +++ b/exchanges/btcmarkets/btcmarkets_websocket.go @@ -1,6 +1,7 @@ package btcmarkets import ( + "context" "encoding/json" "errors" "fmt" @@ -262,13 +263,22 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error { } } + creds, err := b.GetCredentials(context.TODO()) + if err != nil { + b.Websocket.DataHandler <- order.ClassificationError{ + Exchange: b.Name, + OrderID: orderID, + Err: err, + } + } + b.Websocket.DataHandler <- &order.Detail{ Price: price, Amount: originalAmount, RemainingAmount: orderData.OpenVolume, Exchange: b.Name, ID: orderID, - ClientID: b.API.Credentials.ClientID, + ClientID: creds.ClientID, Type: oType, Side: oSide, Status: oStatus, @@ -321,6 +331,10 @@ func (b *BTCMarkets) generateDefaultSubscriptions() ([]stream.ChannelSubscriptio // Subscribe sends a websocket message to receive data from the channel func (b *BTCMarkets) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error { + creds, err := b.GetCredentials(context.TODO()) + if err != nil { + return err + } var authChannels = []string{fundChange, heartbeat, orderChange} var payload WsSubscribe @@ -345,20 +359,21 @@ func (b *BTCMarkets) Subscribe(channelsToSubscribe []stream.ChannelSubscription) } signTime := strconv.FormatInt(time.Now().UnixMilli(), 10) strToSign := "/users/self/subscribe" + "\n" + signTime - tempSign, err := crypto.GetHMAC(crypto.HashSHA512, + var tempSign []byte + tempSign, err = crypto.GetHMAC(crypto.HashSHA512, []byte(strToSign), - []byte(b.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } sign := crypto.Base64Encode(tempSign) - payload.Key = b.API.Credentials.Key + payload.Key = creds.Key payload.Signature = sign payload.Timestamp = signTime break } - err := b.Websocket.Conn.SendJSONMessage(payload) + err = b.Websocket.Conn.SendJSONMessage(payload) if err != nil { return err } diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index c6d3652b2a3..b78476cdbaa 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -725,7 +725,7 @@ func (b *BTCMarkets) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeB if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/btse/btse.go b/exchanges/btse/btse.go index c333f96428c..915fc67934d 100644 --- a/exchanges/btse/btse.go +++ b/exchanges/btse/btse.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "io" "net/http" "net/url" @@ -452,8 +451,9 @@ func (b *BTSE) SendHTTPRequest(ctx context.Context, ep exchange.URL, method, end // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the desired endpoint func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, isSpot bool, values url.Values, req map[string]interface{}, result interface{}, f request.EndpointLimit) error { - if !b.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", b.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := b.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := b.API.Endpoints.GetURL(ep) @@ -479,7 +479,7 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL var body io.Reader nonce := strconv.FormatInt(time.Now().UnixMilli(), 10) headers := map[string]string{ - "btse-api": b.API.Credentials.Key, + "btse-api": creds.Key, "btse-nonce": nonce, } if req != nil { @@ -492,7 +492,7 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL hmac, err = crypto.GetHMAC( crypto.HashSHA512_384, []byte((expandedEndpoint + nonce + string(reqPayload))), - []byte(b.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return nil, err @@ -502,7 +502,7 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL hmac, err = crypto.GetHMAC( crypto.HashSHA512_384, []byte((expandedEndpoint + nonce)), - []byte(b.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return nil, err diff --git a/exchanges/btse/btse_test.go b/exchanges/btse/btse_test.go index 3055affc551..da6f4fbccdb 100644 --- a/exchanges/btse/btse_test.go +++ b/exchanges/btse/btse_test.go @@ -56,7 +56,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return b.ValidateAPICredentials() + return b.ValidateAPICredentials(b.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go index daf062c0a18..9dac4300af3 100644 --- a/exchanges/btse/btse_websocket.go +++ b/exchanges/btse/btse_websocket.go @@ -1,6 +1,7 @@ package btse import ( + "context" "encoding/json" "errors" "fmt" @@ -45,7 +46,7 @@ func (b *BTSE) WsConnect() error { go b.wsReadData() if b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = b.WsAuthenticate() + err = b.WsAuthenticate(context.TODO()) if err != nil { b.Websocket.DataHandler <- err b.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -56,13 +57,17 @@ func (b *BTSE) WsConnect() error { } // WsAuthenticate Send an authentication message to receive auth data -func (b *BTSE) WsAuthenticate() error { +func (b *BTSE) WsAuthenticate(ctx context.Context) error { + creds, err := b.GetCredentials(ctx) + if err != nil { + return err + } nonce := strconv.FormatInt(time.Now().UnixMilli(), 10) path := "/spotWS" + nonce hmac, err := crypto.GetHMAC(crypto.HashSHA512_384, []byte((path)), - []byte(b.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return err @@ -71,7 +76,7 @@ func (b *BTSE) WsAuthenticate() error { sign := crypto.HexEncodeToString(hmac) req := wsSub{ Operation: "authKeyExpires", - Arguments: []string{b.API.Credentials.Key, nonce, sign}, + Arguments: []string{creds.Key, nonce, sign}, } return b.Websocket.Conn.SendJSONMessage(req) } diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go index de266ed8fab..d992a724fd8 100644 --- a/exchanges/btse/btse_wrapper.go +++ b/exchanges/btse/btse_wrapper.go @@ -937,7 +937,7 @@ func (b *BTSE) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !b.AllowAuthenticatedRequest() && // Todo check connection status + if !b.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/coinbasepro/coinbasepro.go b/exchanges/coinbasepro/coinbasepro.go index 5bc2458fe4f..54f0757c2f4 100644 --- a/exchanges/coinbasepro/coinbasepro.go +++ b/exchanges/coinbasepro/coinbasepro.go @@ -702,8 +702,9 @@ func (c *CoinbasePro) SendHTTPRequest(ctx context.Context, ep exchange.URL, path // SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) { - if !c.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", c.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := c.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := c.API.Endpoints.GetURL(ep) if err != nil { @@ -724,7 +725,7 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep excha hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(message), - []byte(c.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } @@ -732,8 +733,8 @@ func (c *CoinbasePro) SendAuthenticatedHTTPRequest(ctx context.Context, ep excha headers := make(map[string]string) headers["CB-ACCESS-SIGN"] = crypto.Base64Encode(hmac) headers["CB-ACCESS-TIMESTAMP"] = n - headers["CB-ACCESS-KEY"] = c.API.Credentials.Key - headers["CB-ACCESS-PASSPHRASE"] = c.API.Credentials.ClientID + headers["CB-ACCESS-KEY"] = creds.Key + headers["CB-ACCESS-PASSPHRASE"] = creds.ClientID headers["Content-Type"] = "application/json" return &request.Item{ diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go index 99dead92a8b..65b34de71a7 100644 --- a/exchanges/coinbasepro/coinbasepro_test.go +++ b/exchanges/coinbasepro/coinbasepro_test.go @@ -462,7 +462,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return c.ValidateAPICredentials() + return c.ValidateAPICredentials(c.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/coinbasepro/coinbasepro_websocket.go b/exchanges/coinbasepro/coinbasepro_websocket.go index 9f7be8560f5..e448ff6a8d6 100644 --- a/exchanges/coinbasepro/coinbasepro_websocket.go +++ b/exchanges/coinbasepro/coinbasepro_websocket.go @@ -1,6 +1,7 @@ package coinbasepro import ( + "context" "encoding/json" "errors" "fmt" @@ -165,6 +166,15 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { ts = convert.TimeFromUnixTimestampDecimal(wsOrder.Timestamp) } + creds, err := c.GetCredentials(context.TODO()) + if err != nil { + c.Websocket.DataHandler <- order.ClassificationError{ + Exchange: c.Name, + OrderID: wsOrder.OrderID, + Err: err, + } + } + if wsOrder.UserID != "" { var p currency.Pair var a asset.Item @@ -183,7 +193,7 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error { Exchange: c.Name, ID: wsOrder.OrderID, AccountID: wsOrder.ProfileID, - ClientID: c.API.Credentials.ClientID, + ClientID: creds.ClientID, Type: oType, Side: oSide, Status: oStatus, @@ -388,6 +398,10 @@ func (c *CoinbasePro) GenerateDefaultSubscriptions() ([]stream.ChannelSubscripti // Subscribe sends a websocket message to receive data from the channel func (c *CoinbasePro) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error { + creds, err := c.GetCredentials(context.TODO()) + if err != nil { + return err + } subscribe := WebsocketSubscribe{ Type: "subscribe", } @@ -413,19 +427,20 @@ subscriptions: channelsToSubscribe[i].Channel == "full" { n := strconv.FormatInt(time.Now().Unix(), 10) message := n + http.MethodGet + "/users/self/verify" - hmac, err := crypto.GetHMAC(crypto.HashSHA256, + var hmac []byte + hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(message), - []byte(c.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } subscribe.Signature = crypto.Base64Encode(hmac) - subscribe.Key = c.API.Credentials.Key - subscribe.Passphrase = c.API.Credentials.ClientID + subscribe.Key = creds.Key + subscribe.Passphrase = creds.ClientID subscribe.Timestamp = n } } - err := c.Websocket.Conn.SendJSONMessage(subscribe) + err = c.Websocket.Conn.SendJSONMessage(subscribe) if err != nil { return err } diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index 4db5865fcc1..e67f3ee4576 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -736,7 +736,7 @@ func (c *CoinbasePro) GetFeeByType(ctx context.Context, feeBuilder *exchange.Fee if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !c.AllowAuthenticatedRequest() && // Todo check connection status + if !c.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go index b12f7fa2250..03ec6a20e38 100644 --- a/exchanges/coinut/coinut.go +++ b/exchanges/coinut/coinut.go @@ -253,10 +253,6 @@ func (c *COINUT) GetOpenPositions(ctx context.Context, instrumentID int) ([]Open // SendHTTPRequest sends either an authenticated or unauthenticated HTTP request func (c *COINUT) SendHTTPRequest(ctx context.Context, ep exchange.URL, apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) { - if !c.API.AuthenticatedSupport && authenticated { - return fmt.Errorf("%s %w", c.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) - } - endpoint, err := c.API.Endpoints.GetURL(ep) if err != nil { return err @@ -279,11 +275,16 @@ func (c *COINUT) SendHTTPRequest(ctx context.Context, ep exchange.URL, apiReques headers := make(map[string]string) if authenticated { - headers["X-USER"] = c.API.Credentials.ClientID + var creds *exchange.Credentials + creds, err = c.GetCredentials(ctx) + if err != nil { + return nil, err + } + headers["X-USER"] = creds.ClientID var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, payload, - []byte(c.API.Credentials.Key)) + []byte(creds.Key)) if err != nil { return nil, err } diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go index ab532345c4c..f0dc8f96d4c 100644 --- a/exchanges/coinut/coinut_test.go +++ b/exchanges/coinut/coinut_test.go @@ -79,7 +79,7 @@ func setupWSTestAuth(t *testing.T) { t.Fatal(err) } go c.wsReadData() - err = c.wsAuthenticate() + err = c.wsAuthenticate(context.Background()) if err != nil { t.Error(err) } @@ -288,7 +288,8 @@ func TestGetOrderHistoryWrapper(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return c.ValidateAPICredentials() + _, err := c.GetCredentials(context.Background()) + return err == nil } func TestSubmitOrder(t *testing.T) { @@ -676,7 +677,7 @@ func TestWsOrderbook(t *testing.T) { "reply": "inst_order_book", "status": [ "OK" ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -690,7 +691,7 @@ func TestWsOrderbook(t *testing.T) { "side": "BUY", "trans_id": 169384 }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -708,7 +709,7 @@ func TestWsTicker(t *testing.T) { "volume": "0.07650000", "volume24": "56.07650000" }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -740,7 +741,7 @@ func TestWsGetInstruments(t *testing.T) { "OK" ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -787,7 +788,7 @@ func TestWsTrades(t *testing.T) { "trans_id": 169502 }] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -800,7 +801,7 @@ func TestWsTrades(t *testing.T) { "timestamp": 0, "trans_id": 169478 }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -830,7 +831,8 @@ func TestWsLogin(t *testing.T) { "unverified_email":"", "username":"test" }`) - err := c.wsHandleData(pressXToJSON) + ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Key: "b46e658f-d4c4-433c-b032-093423b1aaa4", ClientID: "dummy"}) + err := c.wsHandleData(ctx, pressXToJSON) if err != nil { t.Error(err) } @@ -854,7 +856,7 @@ func TestWsAccountBalance(t *testing.T) { "reply": "user_balance", "trans_id": 15159032 }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -876,7 +878,7 @@ func TestWsOrder(t *testing.T) { "side":"SELL", "trans_id":127303 }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -906,7 +908,7 @@ func TestWsOrder(t *testing.T) { "timestamp": 1482903034617491, "trans_id": 20859252 }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -930,7 +932,7 @@ func TestWsOrder(t *testing.T) { "side": "BUY", "trans_id": 3282993 }`) - err = c.wsHandleData(pressXToJSON) + err = c.wsHandleData(context.Background(), pressXToJSON) if err == nil { t.Error("Expected not enough balance error") } @@ -971,7 +973,7 @@ func TestWsOrders(t *testing.T) { "trans_id": 15155497 } ]`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -1007,7 +1009,7 @@ func TestWsOpenOrders(t *testing.T) { } ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -1023,7 +1025,7 @@ func TestWsCancelOrder(t *testing.T) { "OK" ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -1052,7 +1054,7 @@ func TestWsCancelOrders(t *testing.T) { ], "trans_id": 15166063 }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } @@ -1109,7 +1111,7 @@ func TestWsOrderHistory(t *testing.T) { } ] }`) - err := c.wsHandleData(pressXToJSON) + err := c.wsHandleData(context.Background(), pressXToJSON) if err != nil { t.Error(err) } diff --git a/exchanges/coinut/coinut_types.go b/exchanges/coinut/coinut_types.go index 0edc40d9f3e..5ff4adb7d17 100644 --- a/exchanges/coinut/coinut_types.go +++ b/exchanges/coinut/coinut_types.go @@ -281,12 +281,6 @@ type wsResponse struct { Reply string `json:"reply"` } -type wsHeartbeatResp struct { - Nonce int64 `json:"nonce"` - Reply string `json:"reply"` - Status []interface{} `json:"status"` -} - // WsTicker defines the resp for ticker updates from the websocket connection type WsTicker struct { High24 float64 `json:"high24,string"` diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go index 1449fa1a595..ec43a342af5 100644 --- a/exchanges/coinut/coinut_websocket.go +++ b/exchanges/coinut/coinut_websocket.go @@ -1,6 +1,7 @@ package coinut import ( + "context" "encoding/json" "errors" "fmt" @@ -13,7 +14,6 @@ import ( "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" - exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" @@ -58,7 +58,7 @@ func (c *COINUT) WsConnect() error { return err } } - err = c.wsAuthenticate() + err = c.wsAuthenticate(context.TODO()) if err != nil { c.Websocket.SetCanUseAuthenticatedEndpoints(false) log.Error(log.WebsocketMgr, err) @@ -100,7 +100,7 @@ func (c *COINUT) wsReadData() { c.Websocket.DataHandler <- err continue } - err = c.wsHandleData(individualJSON) + err = c.wsHandleData(context.TODO(), individualJSON) if err != nil { c.Websocket.DataHandler <- err } @@ -112,7 +112,7 @@ func (c *COINUT) wsReadData() { c.Websocket.DataHandler <- err continue } - err = c.wsHandleData(resp.Raw) + err = c.wsHandleData(context.TODO(), resp.Raw) if err != nil { c.Websocket.DataHandler <- err } @@ -120,7 +120,7 @@ func (c *COINUT) wsReadData() { } } -func (c *COINUT) wsHandleData(respRaw []byte) error { +func (c *COINUT) wsHandleData(ctx context.Context, respRaw []byte) error { if strings.HasPrefix(string(respRaw), "[") { var orders []wsOrderContainer err := json.Unmarshal(respRaw, &orders) @@ -163,8 +163,13 @@ func (c *COINUT) wsHandleData(respRaw []byte) error { return err } + creds, err := c.GetCredentials(ctx) + if err != nil { + return err + } + var endpointFailure []byte - if login.APIKey != c.API.Credentials.Key { + if login.APIKey != creds.Key { endpointFailure = []byte("failed to authenticate") } @@ -681,20 +686,20 @@ func (c *COINUT) Unsubscribe(channelToUnsubscribe []stream.ChannelSubscription) return nil } -func (c *COINUT) wsAuthenticate() error { - if !c.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", - c.Name) +func (c *COINUT) wsAuthenticate(ctx context.Context) error { + creds, err := c.GetCredentials(ctx) + if err != nil { + return err } timestamp := time.Now().Unix() nonce := getNonce() - payload := c.API.Credentials.ClientID + "|" + + payload := creds.ClientID + "|" + strconv.FormatInt(timestamp, 10) + "|" + strconv.FormatInt(nonce, 10) hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(payload), - []byte(c.API.Credentials.Key)) + []byte(creds.Key)) if err != nil { return err } @@ -707,7 +712,7 @@ func (c *COINUT) wsAuthenticate() error { Timestamp int64 `json:"timestamp"` }{ Request: "login", - Username: c.API.Credentials.ClientID, + Username: creds.ClientID, Nonce: nonce, Hmac: crypto.HexEncodeToString(hmac), Timestamp: timestamp, diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index aefc5f8d680..f4a1db7dc83 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -843,7 +843,7 @@ func (c *COINUT) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !c.AllowAuthenticatedRequest() && // Todo check connection status + if !c.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -1074,8 +1074,8 @@ func (c *COINUT) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques } // AuthenticateWebsocket sends an authentication message to the websocket -func (c *COINUT) AuthenticateWebsocket(_ context.Context) error { - return c.wsAuthenticate() +func (c *COINUT) AuthenticateWebsocket(ctx context.Context) error { + return c.wsAuthenticate(ctx) } func (c *COINUT) loadInstrumentsIfNotLoaded() error { diff --git a/exchanges/credentials.go b/exchanges/credentials.go new file mode 100644 index 00000000000..ed90921c5f2 --- /dev/null +++ b/exchanges/credentials.go @@ -0,0 +1,425 @@ +package exchange + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + + "github.com/thrasher-corp/gocryptotrader/common/crypto" + "github.com/thrasher-corp/gocryptotrader/config" + "github.com/thrasher-corp/gocryptotrader/log" + "google.golang.org/grpc/metadata" +) + +// contextCredential is a string flag for use with context values when setting +// credentials internally or via gRPC. +type contextCredential string + +const ( + contextCredentialsFlag contextCredential = "apicredentials" + contextSubAccountFlag contextCredential = "subaccountoverride" + + key = "key" + secret = "secret" + subAccount = "subaccount" + clientID = "clientid" + oneTimePassword = "otp" + _PEMKey = "pemkey" +) + +var ( + // ErrAuthenticationSupportNotEnabled defines an error when + // authenticatedSupport and authenticatedWebsocketApiSupport are set to + // false in config.json + ErrAuthenticationSupportNotEnabled = errors.New("REST or Websocket authentication support is not enabled") + // ErrCredentialsAreEmpty defines an error for when the credentials are + // completely empty but an attempt at retrieving credentials was made to + // undertake an authenticated HTTP request. + ErrCredentialsAreEmpty = errors.New("credentials are empty") + + errRequiresAPIKey = errors.New("requires API key but default/empty one set") + errRequiresAPISecret = errors.New("requires API secret but default/empty one set") + errRequiresAPIPEMKey = errors.New("requires API PEM key but default/empty one set") + errRequiresAPIClientID = errors.New("requires API Client ID but default/empty one set") + errBase64DecodeFailure = errors.New("base64 decode has failed") + errMissingInfo = errors.New("cannot parse meta data missing information in key value pair") + errInvalidCredentialMetaDataLength = errors.New("invalid meta data to process credentials") + errContextCredentialsFailure = errors.New("context credentials type assertion failure") + errMetaDataIsNil = errors.New("meta data is nil") +) + +// ParseCredentialsMetadata intercepts and converts credentials metadata to a +// static type for authentication processing and protection. +func ParseCredentialsMetadata(ctx context.Context, md metadata.MD) (context.Context, error) { + if md == nil { + return ctx, errMetaDataIsNil + } + + credMD, ok := md[string(contextCredentialsFlag)] + if !ok || len(credMD) == 0 { + return ctx, nil + } + + if len(credMD) != 1 { + return ctx, errInvalidCredentialMetaDataLength + } + + segregatedCreds := strings.Split(credMD[0], ",") + var ctxCreds Credentials + var subAccountHere string + for x := range segregatedCreds { + keyVals := strings.Split(segregatedCreds[x], ":") + if len(keyVals) != 2 { + return ctx, fmt.Errorf("%w received %v fields, expected 2 contains: %s", + errMissingInfo, + len(keyVals), + keyVals) + } + switch keyVals[0] { + case key: + ctxCreds.Key = keyVals[1] + case secret: + ctxCreds.Secret = keyVals[1] + case subAccount: + // Capture sub account as this can override if other values are + // not included in metadata. + subAccountHere = keyVals[1] + case clientID: + ctxCreds.ClientID = keyVals[1] + case _PEMKey: + ctxCreds.PEMKey = keyVals[1] + case oneTimePassword: + ctxCreds.OneTimePassword = keyVals[1] + } + } + if ctxCreds.IsEmpty() && subAccountHere != "" { + // This will override default sub account details if needed. + return deploySubAccountOverrideToContext(ctx, subAccountHere), nil + } + // merge sub account to main context credentials + ctxCreds.SubAccount = subAccountHere + return DeployCredentialsToContext(ctx, &ctxCreds), nil +} + +// Credentials define parameters that allow for an authenticated request. +type Credentials struct { + Key string + Secret string + ClientID string + PEMKey string + SubAccount string + OneTimePassword string +} + +// DeployCredentialsToContext sets credentials for internal use to context which +// can override default credential values. +func DeployCredentialsToContext(ctx context.Context, creds *Credentials) context.Context { + flag, store := creds.getInternal() + return context.WithValue(ctx, flag, store) +} + +// deploySubAccountOverrideToContext sets subaccount as override to credentials +// as a separate flag. +func deploySubAccountOverrideToContext(ctx context.Context, subAccount string) context.Context { + return context.WithValue(ctx, contextSubAccountFlag, subAccount) +} + +// GetMetaData returns the credentials for metadata context deployment +func (c *Credentials) GetMetaData() (flag, values string) { + vals := make([]string, 0, 6) + if c.Key != "" { + vals = append(vals, key+":"+c.Key) + } + if c.Secret != "" { + vals = append(vals, secret+":"+c.Secret) + } + if c.SubAccount != "" { + vals = append(vals, subAccount+":"+c.SubAccount) + } + if c.ClientID != "" { + vals = append(vals, clientID+":"+c.ClientID) + } + if c.PEMKey != "" { + vals = append(vals, _PEMKey+":"+c.PEMKey) + } + if c.OneTimePassword != "" { + vals = append(vals, oneTimePassword+":"+c.OneTimePassword) + } + return string(contextCredentialsFlag), strings.Join(vals, ",") +} + +// IsEmpty return true if the underlying credentials type has not been filled +// with at least one item. +func (c *Credentials) IsEmpty() bool { + return c == nil || c.ClientID == "" && + c.Key == "" && + c.OneTimePassword == "" && + c.PEMKey == "" && + c.Secret == "" && + c.SubAccount == "" +} + +// contextCredentialsStore protects the stored credentials for use in a context +type contextCredentialsStore struct { + creds *Credentials + mu sync.RWMutex +} + +// getInternal returns the values for assignment to an internal context +func (c *Credentials) getInternal() (contextCredential, *contextCredentialsStore) { + if c.IsEmpty() { + return "", nil + } + store := &contextCredentialsStore{} + store.Load(c) + return contextCredentialsFlag, store +} + +// Load stores provided credentials +func (c *contextCredentialsStore) Load(creds *Credentials) { + // Segregate from external call + cpy := *creds + c.mu.Lock() + c.creds = &cpy + c.mu.Unlock() +} + +// Get returns the full credentials from the store +func (c *contextCredentialsStore) Get() *Credentials { + c.mu.RLock() + creds := *c.creds + c.mu.RUnlock() + return &creds +} + +// SetKey sets new key for the default credentials +func (a *API) SetKey(key string) { + a.credMu.Lock() + defer a.credMu.Unlock() + if a.credentials == nil { + a.credentials = &Credentials{} + } + a.credentials.Key = key +} + +// SetSecret sets new secret for the default credentials +func (a *API) SetSecret(secret string) { + a.credMu.Lock() + defer a.credMu.Unlock() + if a.credentials == nil { + a.credentials = &Credentials{} + } + a.credentials.Secret = secret +} + +// SetClientID sets new clientID for the default credentials +func (a *API) SetClientID(clientID string) { + a.credMu.Lock() + defer a.credMu.Unlock() + if a.credentials == nil { + a.credentials = &Credentials{} + } + a.credentials.ClientID = clientID +} + +// SetPEMKey sets pem key for the default credentials +func (a *API) SetPEMKey(pem string) { + a.credMu.Lock() + defer a.credMu.Unlock() + if a.credentials == nil { + a.credentials = &Credentials{} + } + a.credentials.PEMKey = pem +} + +// SetSubAccount sets sub account for the default credentials +func (a *API) SetSubAccount(sub string) { + a.credMu.Lock() + defer a.credMu.Unlock() + if a.credentials == nil { + a.credentials = &Credentials{} + } + a.credentials.SubAccount = sub +} + +// CheckCredentials checks to see if the required fields have been set before +// sending an authenticated API request +func (b *Base) CheckCredentials(creds *Credentials, isContext bool) error { + if b.SkipAuthCheck { + return nil + } + + // Individual package usage, allow request if API credentials are valid a + // and without needing to set AuthenticatedSupport to true + if !b.LoadedByConfig { + return b.ValidateAPICredentials(creds) + } + + // Bot usage, AuthenticatedSupport can be disabled by user if desired, so + // don't allow authenticated requests. Context credentials set will override + // default credentials and supported checks. + if !b.API.AuthenticatedSupport && !b.API.AuthenticatedWebsocketSupport && !isContext { + return fmt.Errorf("%s %w", b.Name, ErrAuthenticationSupportNotEnabled) + } + + // Check to see if the user has enabled AuthenticatedSupport, but has + // invalid API credentials set and loaded by config + return b.ValidateAPICredentials(creds) +} + +// AreCredentialsValid returns if the supplied credentials are valid. +func (b *Base) AreCredentialsValid(ctx context.Context) bool { + creds, err := b.GetCredentials(ctx) + return err == nil && b.ValidateAPICredentials(creds) == nil +} + +// GetDefaultCredentials returns the exchange.Base api credentials loaded by +// config.json +func (b *Base) GetDefaultCredentials() *Credentials { + b.API.credMu.RLock() + defer b.API.credMu.RUnlock() + if b.API.credentials == nil { + return nil + } + creds := *b.API.credentials + return &creds +} + +// GetCredentials checks and validates current credentials, context credentials +// override default credentials, if no credentials found, will return an error. +func (b *Base) GetCredentials(ctx context.Context) (*Credentials, error) { + value := ctx.Value(contextCredentialsFlag) + if value != nil { + ctxCredStore, ok := value.(*contextCredentialsStore) + if !ok { + return &Credentials{}, errContextCredentialsFailure + } + + creds := ctxCredStore.Get() + if err := b.CheckCredentials(creds, true); err != nil { + return creds, fmt.Errorf("context credentials issue: %w", err) + } + return creds, nil + } + + err := b.CheckCredentials(b.API.credentials, false) + if err != nil { + return &Credentials{}, err + } + subAccountOverride, ok := ctx.Value(contextSubAccountFlag).(string) + b.API.credMu.RLock() + defer b.API.credMu.RUnlock() + creds := *b.API.credentials + if ok { + creds.SubAccount = subAccountOverride + } + return &creds, nil +} + +// ValidateAPICredentials validates the exchanges API credentials +func (b *Base) ValidateAPICredentials(creds *Credentials) error { + b.API.credMu.RLock() + defer b.API.credMu.RUnlock() + if creds.IsEmpty() { + return fmt.Errorf("%s %w", b.Name, ErrCredentialsAreEmpty) + } + if b.API.CredentialsValidator.RequiresKey && + (creds.Key == "" || creds.Key == config.DefaultAPIKey) { + return fmt.Errorf("%s %w", b.Name, errRequiresAPIKey) + } + + if b.API.CredentialsValidator.RequiresSecret && + (creds.Secret == "" || creds.Secret == config.DefaultAPISecret) { + return fmt.Errorf("%s %w", b.Name, errRequiresAPISecret) + } + + if b.API.CredentialsValidator.RequiresPEM && + (creds.PEMKey == "" || strings.Contains(creds.PEMKey, "JUSTADUMMY")) { + return fmt.Errorf("%s %w", b.Name, errRequiresAPIPEMKey) + } + + if b.API.CredentialsValidator.RequiresClientID && + (creds.ClientID == "" || creds.ClientID == config.DefaultAPIClientID) { + return fmt.Errorf("%s %w", b.Name, errRequiresAPIClientID) + } + + if b.API.CredentialsValidator.RequiresBase64DecodeSecret && !b.LoadedByConfig { + _, err := crypto.Base64Decode(creds.Secret) + if err != nil { + return fmt.Errorf("%s API secret %w: %s", b.Name, errBase64DecodeFailure, err) + } + } + return nil +} + +// SetCredentials is a method that sets the current API keys for the exchange +func (b *Base) SetCredentials(apiKey, apiSecret, clientID, subaccount, pemKey, oneTimePassword string) { + b.API.credMu.Lock() + defer b.API.credMu.Unlock() + if b.API.credentials == nil { + b.API.credentials = &Credentials{} + } + b.API.credentials.Key = apiKey + b.API.credentials.ClientID = clientID + b.API.credentials.SubAccount = subaccount + b.API.credentials.PEMKey = pemKey + b.API.credentials.OneTimePassword = oneTimePassword + + if b.API.CredentialsValidator.RequiresBase64DecodeSecret { + result, err := crypto.Base64Decode(apiSecret) + if err != nil { + b.API.AuthenticatedSupport = false + b.API.AuthenticatedWebsocketSupport = false + log.Warnf(log.ExchangeSys, + warningBase64DecryptSecretKeyFailed, + b.Name) + return + } + b.API.credentials.Secret = string(result) + } else { + b.API.credentials.Secret = apiSecret + } +} + +// SetAPICredentialDefaults sets the API Credential validator defaults +func (b *Base) SetAPICredentialDefaults() { + b.API.credMu.Lock() + defer b.API.credMu.Unlock() + // Exchange hardcoded settings take precedence and overwrite the config settings + if b.Config.API.CredentialsValidator == nil { + b.Config.API.CredentialsValidator = new(config.APICredentialsValidatorConfig) + } + if b.Config.API.CredentialsValidator.RequiresKey != b.API.CredentialsValidator.RequiresKey { + b.Config.API.CredentialsValidator.RequiresKey = b.API.CredentialsValidator.RequiresKey + } + + if b.Config.API.CredentialsValidator.RequiresSecret != b.API.CredentialsValidator.RequiresSecret { + b.Config.API.CredentialsValidator.RequiresSecret = b.API.CredentialsValidator.RequiresSecret + } + + if b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret != b.API.CredentialsValidator.RequiresBase64DecodeSecret { + b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret = b.API.CredentialsValidator.RequiresBase64DecodeSecret + } + + if b.Config.API.CredentialsValidator.RequiresClientID != b.API.CredentialsValidator.RequiresClientID { + b.Config.API.CredentialsValidator.RequiresClientID = b.API.CredentialsValidator.RequiresClientID + } + + if b.Config.API.CredentialsValidator.RequiresPEM != b.API.CredentialsValidator.RequiresPEM { + b.Config.API.CredentialsValidator.RequiresPEM = b.API.CredentialsValidator.RequiresPEM + } +} + +// GetAuthenticatedAPISupport returns whether the exchange supports +// authenticated API requests +func (b *Base) GetAuthenticatedAPISupport(endpoint uint8) bool { + switch endpoint { + case RestAuthentication: + return b.API.AuthenticatedSupport + case WebsocketAuthentication: + return b.API.AuthenticatedWebsocketSupport + } + return false +} diff --git a/exchanges/credentials_test.go b/exchanges/credentials_test.go new file mode 100644 index 00000000000..42b2b2f13a9 --- /dev/null +++ b/exchanges/credentials_test.go @@ -0,0 +1,487 @@ +package exchange + +import ( + "context" + "errors" + "testing" + + "github.com/thrasher-corp/gocryptotrader/config" + "google.golang.org/grpc/metadata" +) + +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 + _, err := b.GetCredentials(context.Background()) + if !errors.Is(err, ErrCredentialsAreEmpty) { + t.Fatalf("received: %v but expected: %v", err, ErrCredentialsAreEmpty) + } + + b.API.CredentialsValidator.RequiresKey = true + ctx := DeployCredentialsToContext(context.Background(), &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"}) + _, 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") + _, err = b.GetCredentials(ctx) + if !errors.Is(err, errContextCredentialsFailure) { + t.Fatalf("received: %v but expected: %v", err, errContextCredentialsFailure) + } + + fullCred := Credentials{ + Key: "superkey", + Secret: "supersecret", + SubAccount: "supersub", + ClientID: "superclient", + PEMKey: "superpem", + OneTimePassword: "superOneTimePasssssss", + } + + flag, store := fullCred.getInternal() + + ctx = context.WithValue(context.Background(), flag, store) + creds, err := b.GetCredentials(ctx) + if !errors.Is(err, nil) { + t.Fatalf("received: %v but expected: %v", err, nil) + } + + if creds.Key != "superkey" && + creds.Secret != "supersecret" && + creds.SubAccount != "supersub" && + creds.ClientID != "superclient" && + creds.PEMKey != "superpem" && + creds.OneTimePassword != "superOneTimePasssssss" { + t.Fatal("unexpected values") + } + + lonelyCred := Credentials{ + Key: "superkey", + Secret: "supersecret", + SubAccount: "supersub", + PEMKey: "superpem", + OneTimePassword: "superOneTimePasssssss", + } + + flag, store = lonelyCred.getInternal() + + ctx = context.WithValue(context.Background(), flag, store) + b.API.CredentialsValidator.RequiresClientID = true + _, err = b.GetCredentials(ctx) + if !errors.Is(err, errRequiresAPIClientID) { + t.Fatalf("received: %v but expected: %v", err, errRequiresAPIClientID) + } + + b.API.SetKey("hello") + b.API.SetSecret("sir") + b.API.SetClientID("1337") + ctx = deploySubAccountOverrideToContext(context.Background(), "superaccount") + overridedSA, err := b.GetCredentials(ctx) + if !errors.Is(err, nil) { + t.Fatalf("received: %v but expected: %v", err, nil) + } + + if overridedSA.Key != "hello" && + overridedSA.Secret != "sir" && + overridedSA.ClientID != "1337" && + overridedSA.SubAccount != "superaccount" { + t.Fatal("unexpected values") + } + + notOverrided, err := b.GetCredentials(context.Background()) + if !errors.Is(err, nil) { + t.Fatalf("received: %v but expected: %v", err, nil) + } + + if notOverrided.Key != "hello" && + notOverrided.Secret != "sir" && + notOverrided.ClientID != "1337" && + notOverrided.SubAccount != "" { + t.Fatal("unexpected values") + } +} + +func TestAreCredentialsValid(t *testing.T) { + t.Parallel() + var b Base + if b.AreCredentialsValid(context.Background()) { + t.Fatal("should not be valid") + } + ctx := DeployCredentialsToContext(context.Background(), &Credentials{Key: "hello"}) + if !b.AreCredentialsValid(ctx) { + t.Fatal("should be valid") + } +} + +func TestValidateAPICredentials(t *testing.T) { + t.Parallel() + + var b Base + type tester struct { + Key string + Secret string + ClientID string + PEMKey string + RequiresPEM bool + RequiresKey bool + RequiresSecret bool + RequiresClientID bool + RequiresBase64DecodeSecret bool + Expected error + } + + testCases := []tester{ + // Empty credentials + {Expected: ErrCredentialsAreEmpty}, + // test key + {RequiresKey: true, Expected: errRequiresAPIKey, Secret: "bruh"}, + {RequiresKey: true, Key: "k3y"}, + // test secret + {RequiresSecret: true, Expected: errRequiresAPISecret, Key: "bruh"}, + {RequiresSecret: true, Secret: "s3cr3t"}, + // test pem + {RequiresPEM: true, Expected: errRequiresAPIPEMKey, Key: "bruh"}, + {RequiresPEM: true, PEMKey: "p3mK3y"}, + // test clientID + {RequiresClientID: true, Expected: errRequiresAPIClientID, Key: "bruh"}, + {RequiresClientID: true, ClientID: "cli3nt1D"}, + // test requires base64 decode secret + {RequiresBase64DecodeSecret: true, RequiresSecret: true, Expected: errRequiresAPISecret, Key: "bruh"}, + {RequiresBase64DecodeSecret: true, Secret: "%%", Expected: errBase64DecodeFailure}, + {RequiresBase64DecodeSecret: true, Secret: "aGVsbG8gd29ybGQ="}, + } + + setupBase := func(b *Base, tData *tester) { + b.API.SetKey(tData.Key) + b.API.SetSecret(tData.Secret) + b.API.SetClientID(tData.ClientID) + b.API.SetPEMKey(tData.PEMKey) + b.API.CredentialsValidator.RequiresKey = tData.RequiresKey + b.API.CredentialsValidator.RequiresSecret = tData.RequiresSecret + b.API.CredentialsValidator.RequiresPEM = tData.RequiresPEM + b.API.CredentialsValidator.RequiresClientID = tData.RequiresClientID + b.API.CredentialsValidator.RequiresBase64DecodeSecret = tData.RequiresBase64DecodeSecret + } + + for x := range testCases { + testData := &testCases[x] + t.Run("", func(t *testing.T) { + t.Parallel() + setupBase(&b, testData) + if err := b.ValidateAPICredentials(b.API.credentials); !errors.Is(err, testData.Expected) { + t.Errorf("Test %d: expected: %v: got %v", x+1, testData.Expected, err) + } + }) + } +} + +func TestCheckCredentials(t *testing.T) { + t.Parallel() + + b := Base{ + SkipAuthCheck: true, + API: API{credentials: &Credentials{}}, + } + + // Test SkipAuthCheck + err := b.CheckCredentials(&Credentials{}, false) + if !errors.Is(err, nil) { + t.Errorf("received '%v' expected '%v'", err, nil) + } + + // Test credentials failure + b.SkipAuthCheck = false + b.API.CredentialsValidator.RequiresKey = true + b.API.credentials.OneTimePassword = "wow" + err = b.CheckCredentials(b.API.credentials, false) + if !errors.Is(err, errRequiresAPIKey) { + t.Errorf("received '%v' expected '%v'", err, errRequiresAPIKey) + } + b.API.credentials.OneTimePassword = "" + + // Test bot usage with authenticated API support disabled, but with + // valid credentials + b.LoadedByConfig = true + b.API.credentials.Key = "k3y" + err = b.CheckCredentials(b.API.credentials, false) + if !errors.Is(err, ErrAuthenticationSupportNotEnabled) { + t.Errorf("received '%v' expected '%v'", err, ErrAuthenticationSupportNotEnabled) + } + + // Test enabled authenticated API support and loaded by config + // but invalid credentials + b.API.AuthenticatedSupport = true + b.API.credentials.Key = "" + err = b.CheckCredentials(b.API.credentials, false) + if !errors.Is(err, ErrCredentialsAreEmpty) { + t.Errorf("received '%v' expected '%v'", err, ErrCredentialsAreEmpty) + } + + // Finally a valid one + b.API.credentials.Key = "k3y" + err = b.CheckCredentials(b.API.credentials, false) + if !errors.Is(err, nil) { + t.Errorf("received '%v' expected '%v'", err, nil) + } +} + +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 { + t.Fatal("unexpected value") + } + + api = API{} + api.SetSecret(secret) + if api.credentials.Secret != secret { + t.Fatal("unexpected value") + } + + api = API{} + api.SetClientID((clientID)) + if api.credentials.ClientID != clientID { + t.Fatal("unexpected value") + } + + api = API{} + api.SetPEMKey(_PEMKey) + if api.credentials.PEMKey != _PEMKey { + t.Fatal("unexpected value") + } + + api = API{} + api.SetSubAccount(subAccount) + if api.credentials.SubAccount != subAccount { + t.Fatal("unexpected value") + } +} + +func TestSetCredentials(t *testing.T) { + t.Parallel() + + b := Base{ + Name: "TESTNAME", + Enabled: false, + API: API{ + AuthenticatedSupport: false, + AuthenticatedWebsocketSupport: false, + }, + } + + b.SetCredentials("RocketMan", "Digereedoo", "007", "", "", "") + if b.API.credentials.Key != "RocketMan" && + b.API.credentials.Secret != "Digereedoo" && + b.API.credentials.ClientID != "007" { + t.Error("invalid API credentials") + } + + // Invalid secret + b.API.CredentialsValidator.RequiresBase64DecodeSecret = true + b.API.AuthenticatedSupport = true + b.SetCredentials("RocketMan", "%%", "007", "", "", "") + if b.API.AuthenticatedSupport || b.API.AuthenticatedWebsocketSupport { + t.Error("invalid secret should disable authenticated API support") + } + + // valid secret + b.API.CredentialsValidator.RequiresBase64DecodeSecret = true + b.API.AuthenticatedSupport = true + b.SetCredentials("RocketMan", "aGVsbG8gd29ybGQ=", "007", "", "", "") + if !b.API.AuthenticatedSupport && b.API.credentials.Secret != "hello world" { + t.Error("invalid secret should disable authenticated API support") + } +} + +func TestGetDefaultCredentials(t *testing.T) { + var b Base + if b.GetDefaultCredentials() != nil { + t.Fatal("unexpected return") + } + b.SetCredentials("test", "", "", "", "", "") + if b.GetDefaultCredentials() == nil { + t.Fatal("unexpected return") + } +} + +func TestSetAPICredentialDefaults(t *testing.T) { + t.Parallel() + + b := Base{ + Config: &config.Exchange{}, + } + b.API.CredentialsValidator.RequiresKey = true + b.API.CredentialsValidator.RequiresSecret = true + b.API.CredentialsValidator.RequiresBase64DecodeSecret = true + b.API.CredentialsValidator.RequiresClientID = true + b.API.CredentialsValidator.RequiresPEM = true + b.SetAPICredentialDefaults() + + if !b.Config.API.CredentialsValidator.RequiresKey || + !b.Config.API.CredentialsValidator.RequiresSecret || + !b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret || + !b.Config.API.CredentialsValidator.RequiresClientID || + !b.Config.API.CredentialsValidator.RequiresPEM { + t.Error("incorrect values") + } +} + +// TestGetAuthenticatedAPISupport logic test +func TestGetAuthenticatedAPISupport(t *testing.T) { + t.Parallel() + + base := Base{ + API: API{ + AuthenticatedSupport: true, + AuthenticatedWebsocketSupport: false, + }, + } + + if !base.GetAuthenticatedAPISupport(RestAuthentication) { + t.Fatal("Expected RestAuthentication to return true") + } + if base.GetAuthenticatedAPISupport(WebsocketAuthentication) { + t.Fatal("Expected WebsocketAuthentication to return false") + } + base.API.AuthenticatedWebsocketSupport = true + if !base.GetAuthenticatedAPISupport(WebsocketAuthentication) { + t.Fatal("Expected WebsocketAuthentication to return true") + } + if base.GetAuthenticatedAPISupport(2) { + t.Fatal("Expected default case of 'false' to be returned") + } +} + +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()) + } +} diff --git a/exchanges/exchange.go b/exchanges/exchange.go index c3d5b991c49..a0580d866b9 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -12,7 +12,6 @@ import ( "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/convert" - "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/config" "github.com/thrasher-corp/gocryptotrader/currency" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" @@ -40,12 +39,7 @@ const ( ResetConfigPairsWarningMessage = "%s Enabled and available pairs for %s reset due to config upgrade, please enable the ones you would like to use again. Defaulting to %v" ) -var ( - // ErrAuthenticatedRequestWithoutCredentialsSet error message for authenticated request without credentials set - ErrAuthenticatedRequestWithoutCredentialsSet = errors.New("authenticated HTTP request called but not supported due to unset/default API keys") - - errEndpointStringNotFound = errors.New("endpoint string not found") -) +var errEndpointStringNotFound = errors.New("endpoint string not found") // SetClientProxyAddress sets a proxy address for REST and websocket requests func (b *Base) SetClientProxyAddress(addr string) error { @@ -135,33 +129,6 @@ func (b *Base) SetFeatureDefaults() { } } -// SetAPICredentialDefaults sets the API Credential validator defaults -func (b *Base) SetAPICredentialDefaults() { - // Exchange hardcoded settings take precedence and overwrite the config settings - if b.Config.API.CredentialsValidator == nil { - b.Config.API.CredentialsValidator = new(config.APICredentialsValidatorConfig) - } - if b.Config.API.CredentialsValidator.RequiresKey != b.API.CredentialsValidator.RequiresKey { - b.Config.API.CredentialsValidator.RequiresKey = b.API.CredentialsValidator.RequiresKey - } - - if b.Config.API.CredentialsValidator.RequiresSecret != b.API.CredentialsValidator.RequiresSecret { - b.Config.API.CredentialsValidator.RequiresSecret = b.API.CredentialsValidator.RequiresSecret - } - - if b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret != b.API.CredentialsValidator.RequiresBase64DecodeSecret { - b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret = b.API.CredentialsValidator.RequiresBase64DecodeSecret - } - - if b.Config.API.CredentialsValidator.RequiresClientID != b.API.CredentialsValidator.RequiresClientID { - b.Config.API.CredentialsValidator.RequiresClientID = b.API.CredentialsValidator.RequiresClientID - } - - if b.Config.API.CredentialsValidator.RequiresPEM != b.API.CredentialsValidator.RequiresPEM { - b.Config.API.CredentialsValidator.RequiresPEM = b.API.CredentialsValidator.RequiresPEM - } -} - // SupportsRESTTickerBatchUpdates returns whether or not the // exhange supports REST batch ticker fetching func (b *Base) SupportsRESTTickerBatchUpdates() bool { @@ -301,18 +268,6 @@ func (b *Base) SetConfigPairs() error { return nil } -// GetAuthenticatedAPISupport returns whether the exchange supports -// authenticated API requests -func (b *Base) GetAuthenticatedAPISupport(endpoint uint8) bool { - switch endpoint { - case RestAuthentication: - return b.API.AuthenticatedSupport - case WebsocketAuthentication: - return b.API.AuthenticatedWebsocketSupport - } - return false -} - // GetName is a method that returns the name of the exchange base func (b *Base) GetName() string { return b.Name @@ -499,27 +454,6 @@ func (b *Base) IsEnabled() bool { return b.Enabled } -// SetAPIKeys is a method that sets the current API keys for the exchange -func (b *Base) SetAPIKeys(apiKey, apiSecret, clientID string) { - b.API.Credentials.Key = apiKey - b.API.Credentials.ClientID = clientID - - if b.API.CredentialsValidator.RequiresBase64DecodeSecret { - result, err := crypto.Base64Decode(apiSecret) - if err != nil { - b.API.AuthenticatedSupport = false - b.API.AuthenticatedWebsocketSupport = false - log.Warnf(log.ExchangeSys, - warningBase64DecryptSecretKeyFailed, - b.Name) - return - } - b.API.Credentials.Secret = string(result) - } else { - b.API.Credentials.Secret = apiSecret - } -} - // SetupDefaults sets the exchange settings based on the supplied config func (b *Base) SetupDefaults(exch *config.Exchange) error { err := exch.Validate() @@ -534,11 +468,18 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error { b.API.AuthenticatedSupport = exch.API.AuthenticatedSupport b.API.AuthenticatedWebsocketSupport = exch.API.AuthenticatedWebsocketSupport - b.API.Credentials.Subaccount = exch.API.Credentials.Subaccount + if b.API.credentials == nil { + b.API.credentials = &Credentials{} + } + b.API.credentials.SubAccount = exch.API.Credentials.Subaccount if b.API.AuthenticatedSupport || b.API.AuthenticatedWebsocketSupport { - b.SetAPIKeys(exch.API.Credentials.Key, + b.SetCredentials(exch.API.Credentials.Key, exch.API.Credentials.Secret, - exch.API.Credentials.ClientID) + exch.API.Credentials.ClientID, + exch.API.Credentials.Subaccount, + exch.API.Credentials.PEMKey, + exch.API.Credentials.OTPSecret, + ) } if exch.HTTPTimeout <= time.Duration(0) { @@ -596,84 +537,6 @@ func (b *Base) SetupDefaults(exch *config.Exchange) error { return err } -// AllowAuthenticatedRequest checks to see if the required fields have been set -// before sending an authenticated API request -func (b *Base) AllowAuthenticatedRequest() bool { - if b.SkipAuthCheck { - return true - } - - // Individual package usage, allow request if API credentials are valid a - // and without needing to set AuthenticatedSupport to true - if !b.LoadedByConfig { - return b.ValidateAPICredentials() - } - - // Bot usage, AuthenticatedSupport can be disabled by user if desired, so - // don't allow authenticated requests. - if !b.API.AuthenticatedSupport && !b.API.AuthenticatedWebsocketSupport { - return false - } - - // Check to see if the user has enabled AuthenticatedSupport, but has - // invalid API credentials set and loaded by config - return b.ValidateAPICredentials() -} - -// ValidateAPICredentials validates the exchanges API credentials -func (b *Base) ValidateAPICredentials() bool { - if b.API.CredentialsValidator.RequiresKey { - if b.API.Credentials.Key == "" || - b.API.Credentials.Key == config.DefaultAPIKey { - log.Warnf(log.ExchangeSys, - "exchange %s requires API key but default/empty one set", - b.Name) - return false - } - } - - if b.API.CredentialsValidator.RequiresSecret { - if b.API.Credentials.Secret == "" || - b.API.Credentials.Secret == config.DefaultAPISecret { - log.Warnf(log.ExchangeSys, - "exchange %s requires API secret but default/empty one set", - b.Name) - return false - } - } - - if b.API.CredentialsValidator.RequiresPEM { - if b.API.Credentials.PEMKey == "" || - strings.Contains(b.API.Credentials.PEMKey, "JUSTADUMMY") { - log.Warnf(log.ExchangeSys, - "exchange %s requires API PEM key but default/empty one set", - b.Name) - return false - } - } - - if b.API.CredentialsValidator.RequiresClientID { - if b.API.Credentials.ClientID == "" || - b.API.Credentials.ClientID == config.DefaultAPIClientID { - log.Warnf(log.ExchangeSys, - "exchange %s requires API ClientID but default/empty one set", - b.Name) - return false - } - } - - if b.API.CredentialsValidator.RequiresBase64DecodeSecret && !b.LoadedByConfig { - _, err := crypto.Base64Decode(b.API.Credentials.Secret) - if err != nil { - log.Warnf(log.ExchangeSys, - "exchange %s API secret base64 decode failed: %s", - b.Name, err) - return false - } - } - return true -} - // SetPairs sets the exchange currency pairs for either enabledPairs or // availablePairs func (b *Base) SetPairs(pairs currency.Pairs, assetType asset.Item, enabled bool) error { @@ -1423,7 +1286,7 @@ func (b *Base) CalculatePNL(context.Context, *order.PNLCalculatorRequest) (*orde // ScaleCollateral is an overridable function to determine how much // collateral is usable in futures positions -func (b *Base) ScaleCollateral(context.Context, string, *order.CollateralCalculator) (*order.CollateralByCurrency, error) { +func (b *Base) ScaleCollateral(context.Context, *order.CollateralCalculator) (*order.CollateralByCurrency, error) { return nil, common.ErrNotYetImplemented } diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 38d8f6fc0f8..04cef071ced 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -280,28 +280,6 @@ func TestSetFeatureDefaults(t *testing.T) { } } -func TestSetAPICredentialDefaults(t *testing.T) { - t.Parallel() - - b := Base{ - Config: &config.Exchange{}, - } - b.API.CredentialsValidator.RequiresKey = true - b.API.CredentialsValidator.RequiresSecret = true - b.API.CredentialsValidator.RequiresBase64DecodeSecret = true - b.API.CredentialsValidator.RequiresClientID = true - b.API.CredentialsValidator.RequiresPEM = true - b.SetAPICredentialDefaults() - - if !b.Config.API.CredentialsValidator.RequiresKey || - !b.Config.API.CredentialsValidator.RequiresSecret || - !b.Config.API.CredentialsValidator.RequiresBase64DecodeSecret || - !b.Config.API.CredentialsValidator.RequiresClientID || - !b.Config.API.CredentialsValidator.RequiresPEM { - t.Error("incorrect values") - } -} - func TestSetAutoPairDefaults(t *testing.T) { t.Parallel() bs := "Bitstamp" @@ -658,32 +636,6 @@ func TestLoadConfigPairs(t *testing.T) { } } -// TestGetAuthenticatedAPISupport logic test -func TestGetAuthenticatedAPISupport(t *testing.T) { - t.Parallel() - - base := Base{ - API: API{ - AuthenticatedSupport: true, - AuthenticatedWebsocketSupport: false, - }, - } - - if !base.GetAuthenticatedAPISupport(RestAuthentication) { - t.Fatal("Expected RestAuthentication to return true") - } - if base.GetAuthenticatedAPISupport(WebsocketAuthentication) { - t.Fatal("Expected WebsocketAuthentication to return false") - } - base.API.AuthenticatedWebsocketSupport = true - if !base.GetAuthenticatedAPISupport(WebsocketAuthentication) { - t.Fatal("Expected WebsocketAuthentication to return true") - } - if base.GetAuthenticatedAPISupport(2) { - t.Fatal("Expected default case of 'false' to be returned") - } -} - func TestGetName(t *testing.T) { t.Parallel() @@ -1166,41 +1118,6 @@ func TestIsEnabled(t *testing.T) { } } -// TestSetAPIKeys logic test -func TestSetAPIKeys(t *testing.T) { - t.Parallel() - - b := Base{ - Name: "TESTNAME", - Enabled: false, - API: API{ - AuthenticatedSupport: false, - AuthenticatedWebsocketSupport: false, - }, - } - - b.SetAPIKeys("RocketMan", "Digereedoo", "007") - if b.API.Credentials.Key != "RocketMan" && b.API.Credentials.Secret != "Digereedoo" && b.API.Credentials.ClientID != "007" { - t.Error("invalid API credentials") - } - - // Invalid secret - b.API.CredentialsValidator.RequiresBase64DecodeSecret = true - b.API.AuthenticatedSupport = true - b.SetAPIKeys("RocketMan", "%%", "007") - if b.API.AuthenticatedSupport || b.API.AuthenticatedWebsocketSupport { - t.Error("invalid secret should disable authenticated API support") - } - - // valid secret - b.API.CredentialsValidator.RequiresBase64DecodeSecret = true - b.API.AuthenticatedSupport = true - b.SetAPIKeys("RocketMan", "aGVsbG8gd29ybGQ=", "007") - if !b.API.AuthenticatedSupport && b.API.Credentials.Secret != "hello world" { - t.Error("invalid secret should disable authenticated API support") - } -} - func TestSetupDefaults(t *testing.T) { t.Parallel() @@ -1291,105 +1208,6 @@ func TestSetupDefaults(t *testing.T) { } } -func TestAllowAuthenticatedRequest(t *testing.T) { - t.Parallel() - - b := Base{ - SkipAuthCheck: true, - } - - // Test SkipAuthCheck - if r := b.AllowAuthenticatedRequest(); !r { - t.Error("skip auth check should allow authenticated requests") - } - - // Test credentials failure - b.SkipAuthCheck = false - b.API.CredentialsValidator.RequiresKey = true - if r := b.AllowAuthenticatedRequest(); r { - t.Error("should fail with an empty key") - } - - // Test bot usage with authenticated API support disabled, but with - // valid credentials - b.LoadedByConfig = true - b.API.Credentials.Key = "k3y" - if r := b.AllowAuthenticatedRequest(); r { - t.Error("should fail when authenticated support is disabled") - } - - // Test enabled authenticated API support and loaded by config - // but invalid credentials - b.API.AuthenticatedSupport = true - b.API.Credentials.Key = "" - if r := b.AllowAuthenticatedRequest(); r { - t.Error("should fail with invalid credentials") - } - - // Finally a valid one - b.API.Credentials.Key = "k3y" - if r := b.AllowAuthenticatedRequest(); !r { - t.Error("show allow an authenticated request") - } -} - -func TestValidateAPICredentials(t *testing.T) { - t.Parallel() - - var b Base - type tester struct { - Key string - Secret string - ClientID string - PEMKey string - RequiresPEM bool - RequiresKey bool - RequiresSecret bool - RequiresClientID bool - RequiresBase64DecodeSecret bool - Expected bool - Result bool - } - - tests := []tester{ - // test key - {RequiresKey: true}, - {RequiresKey: true, Key: "k3y", Expected: true}, - // test secret - {RequiresSecret: true}, - {RequiresSecret: true, Secret: "s3cr3t", Expected: true}, - // test pem - {RequiresPEM: true}, - {RequiresPEM: true, PEMKey: "p3mK3y", Expected: true}, - // test clientID - {RequiresClientID: true}, - {RequiresClientID: true, ClientID: "cli3nt1D", Expected: true}, - // test requires base64 decode secret - {RequiresBase64DecodeSecret: true, RequiresSecret: true}, - {RequiresBase64DecodeSecret: true, Secret: "%%", Expected: false}, - {RequiresBase64DecodeSecret: true, Secret: "aGVsbG8gd29ybGQ=", Expected: true}, - } - - for x := range tests { - setupBase := func(b *Base, tData tester) { - b.API.Credentials.Key = tData.Key - b.API.Credentials.Secret = tData.Secret - b.API.Credentials.ClientID = tData.ClientID - b.API.Credentials.PEMKey = tData.PEMKey - b.API.CredentialsValidator.RequiresKey = tData.RequiresKey - b.API.CredentialsValidator.RequiresSecret = tData.RequiresSecret - b.API.CredentialsValidator.RequiresPEM = tData.RequiresPEM - b.API.CredentialsValidator.RequiresClientID = tData.RequiresClientID - b.API.CredentialsValidator.RequiresBase64DecodeSecret = tData.RequiresBase64DecodeSecret - } - - setupBase(&b, tests[x]) - if r := b.ValidateAPICredentials(); r != tests[x].Expected { - t.Errorf("Test %d: expected: %v: got %v", x, tests[x].Expected, r) - } - } -} - func TestSetPairs(t *testing.T) { t.Parallel() @@ -2430,7 +2248,7 @@ func TestCalculatePNL(t *testing.T) { func TestScaleCollateral(t *testing.T) { t.Parallel() var b Base - if _, err := b.ScaleCollateral(context.Background(), "", nil); !errors.Is(err, common.ErrNotYetImplemented) { + if _, err := b.ScaleCollateral(context.Background(), nil); !errors.Is(err, common.ErrNotYetImplemented) { t.Errorf("received: %v, expected: %v", err, common.ErrNotYetImplemented) } } diff --git a/exchanges/exchange_types.go b/exchanges/exchange_types.go index 887df7ea805..d4636ad6150 100644 --- a/exchanges/exchange_types.go +++ b/exchanges/exchange_types.go @@ -188,13 +188,8 @@ type API struct { Endpoints *Endpoints - Credentials struct { - Key string - Secret string - ClientID string - PEMKey string - Subaccount string - } + credentials *Credentials + credMu sync.RWMutex CredentialsValidator struct { // For Huobi (optional) diff --git a/exchanges/exmo/exmo.go b/exchanges/exmo/exmo.go index 4a73ca1965b..a756b58c707 100644 --- a/exchanges/exmo/exmo.go +++ b/exchanges/exmo/exmo.go @@ -329,8 +329,9 @@ func (e *EXMO) SendHTTPRequest(ctx context.Context, endpoint exchange.URL, path // SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (e *EXMO) SendAuthenticatedHTTPRequest(ctx context.Context, epath exchange.URL, method, endpoint string, vals url.Values, result interface{}) error { - if !e.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", e.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := e.GetCredentials(ctx) + if err != nil { + return err } urlPath, err := e.API.Endpoints.GetURL(epath) @@ -347,13 +348,13 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(ctx context.Context, epath exchange. payload := vals.Encode() hash, err := crypto.GetHMAC(crypto.HashSHA512, []byte(payload), - []byte(e.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["Key"] = e.API.Credentials.Key + headers["Key"] = creds.Key headers["Sign"] = crypto.HexEncodeToString(hash) headers["Content-Type"] = "application/x-www-form-urlencoded" diff --git a/exchanges/exmo/exmo_test.go b/exchanges/exmo/exmo_test.go index 243e061b53d..f06cfed60cf 100644 --- a/exchanges/exmo/exmo_test.go +++ b/exchanges/exmo/exmo_test.go @@ -47,9 +47,7 @@ func TestMain(m *testing.M) { } e.API.AuthenticatedSupport = true - e.API.Credentials.Key = APIKey - e.API.Credentials.Secret = APISecret - + e.SetCredentials(APIKey, APISecret, "", "", "", "") os.Exit(m.Run()) } @@ -303,7 +301,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return e.ValidateAPICredentials() + return e.ValidateAPICredentials(e.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index 0cce9b52635..a5a4e28b5dd 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -620,7 +620,7 @@ func (e *EXMO) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !e.AllowAuthenticatedRequest() && // Todo check connection status + if !e.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/ftx/ftx.go b/exchanges/ftx/ftx.go index 18ae72dfd48..1676890d07a 100644 --- a/exchanges/ftx/ftx.go +++ b/exchanges/ftx/ftx.go @@ -388,7 +388,7 @@ func (f *FTX) GetMarginBorrowRates(ctx context.Context) ([]MarginFundingData, er r := struct { Data []MarginFundingData `json:"result"` }{} - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginBorrowRates, "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginBorrowRates, nil, &r) } // GetMarginLendingRates gets lending rates for margin trading @@ -396,7 +396,7 @@ func (f *FTX) GetMarginLendingRates(ctx context.Context) ([]MarginFundingData, e r := struct { Data []MarginFundingData `json:"result"` }{} - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingRates, "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingRates, nil, &r) } // MarginDailyBorrowedAmounts gets daily borrowed amounts for margin @@ -412,7 +412,7 @@ func (f *FTX) GetMarginMarketInfo(ctx context.Context, market string) ([]MarginM r := struct { Data []MarginMarketInfo `json:"result"` }{} - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(marginMarketInfo, market), "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(marginMarketInfo, market), nil, &r) } // GetMarginBorrowHistory gets the margin borrow history data @@ -430,7 +430,7 @@ func (f *FTX) GetMarginBorrowHistory(ctx context.Context, startTime, endTime tim params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } endpoint := common.EncodeURLValues(marginBorrowHistory, params) - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &r) } // GetMarginMarketLendingHistory gets the markets margin lending rate history @@ -450,7 +450,7 @@ func (f *FTX) GetMarginMarketLendingHistory(ctx context.Context, coin currency.C params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } endpoint := common.EncodeURLValues(marginLendingHistory, params) - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", params, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, params, &r) } // GetMarginLendingHistory gets margin lending history @@ -470,7 +470,7 @@ func (f *FTX) GetMarginLendingHistory(ctx context.Context, coin currency.Code, s params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10)) } endpoint := common.EncodeURLValues(marginLendHistory, params) - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendHistory, "", endpoint, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendHistory, endpoint, &r) } // GetMarginLendingOffers gets margin lending offers @@ -478,7 +478,7 @@ func (f *FTX) GetMarginLendingOffers(ctx context.Context) ([]LendingOffersData, r := struct { Data []LendingOffersData `json:"result"` }{} - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingOffers, "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingOffers, nil, &r) } // GetLendingInfo gets margin lending info @@ -486,7 +486,7 @@ func (f *FTX) GetLendingInfo(ctx context.Context) ([]LendingInfoData, error) { r := struct { Data []LendingInfoData `json:"result"` }{} - return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingInfo, "", nil, &r) + return r.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, marginLendingInfo, nil, &r) } // SubmitLendingOffer submits an offer for margin lending @@ -500,7 +500,7 @@ func (f *FTX) SubmitLendingOffer(ctx context.Context, coin currency.Code, size, req["size"] = size req["rate"] = rate - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, marginLendingOffers, "", req, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, marginLendingOffers, req, &resp); err != nil { return err } @@ -511,11 +511,11 @@ func (f *FTX) SubmitLendingOffer(ctx context.Context, coin currency.Code, size, } // GetAccountInfo gets account info -func (f *FTX) GetAccountInfo(ctx context.Context, subAccount string) (AccountInfoData, error) { +func (f *FTX) GetAccountInfo(ctx context.Context) (AccountInfoData, error) { resp := struct { Data AccountInfoData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAccountInfo, subAccount, nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAccountInfo, nil, &resp) } // GetPositions gets the users positions @@ -523,26 +523,26 @@ func (f *FTX) GetPositions(ctx context.Context) ([]PositionData, error) { resp := struct { Data []PositionData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getPositions, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getPositions, nil, &resp) } // ChangeAccountLeverage changes default leverage used by account func (f *FTX) ChangeAccountLeverage(ctx context.Context, leverage float64) error { req := make(map[string]interface{}) req["leverage"] = leverage - return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, setLeverage, "", req, nil) + return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, setLeverage, req, nil) } // GetCoins gets coins' data in the account wallet -func (f *FTX) GetCoins(ctx context.Context, subAccount string) ([]WalletCoinsData, error) { +func (f *FTX) GetCoins(ctx context.Context) ([]WalletCoinsData, error) { resp := struct { Data []WalletCoinsData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getCoins, subAccount, nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getCoins, nil, &resp) } // GetBalances gets balances of the account -func (f *FTX) GetBalances(ctx context.Context, subAccount string, includeLockedBreakdown, includeFreeIgnoringCollateral bool) ([]WalletBalance, error) { +func (f *FTX) GetBalances(ctx context.Context, includeLockedBreakdown, includeFreeIgnoringCollateral bool) ([]WalletBalance, error) { resp := struct { Data []WalletBalance `json:"result"` }{} @@ -554,7 +554,7 @@ func (f *FTX) GetBalances(ctx context.Context, subAccount string, includeLockedB vals.Set("includeFreeIgnoringCollateral", strconv.FormatBool(includeFreeIgnoringCollateral)) } balanceURL := common.EncodeURLValues(getBalances, vals) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, balanceURL, subAccount, nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, balanceURL, nil, &resp) } // GetAllWalletBalances gets all wallets' balances @@ -562,7 +562,7 @@ func (f *FTX) GetAllWalletBalances(ctx context.Context) (AllWalletBalances, erro resp := struct { Data AllWalletBalances `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAllWalletBalances, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getAllWalletBalances, nil, &resp) } // FetchDepositAddress gets deposit address for a given coin @@ -575,7 +575,7 @@ func (f *FTX) FetchDepositAddress(ctx context.Context, coin currency.Code, chain vals.Set("method", strings.ToLower(chain)) } path := common.EncodeURLValues(getDepositAddress+coin.Upper().String(), vals) - return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, "", nil, &resp) + return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp) } // FetchDepositHistory gets deposit history @@ -583,7 +583,7 @@ func (f *FTX) FetchDepositHistory(ctx context.Context) ([]DepositItem, error) { resp := struct { Data []DepositItem `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getDepositHistory, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getDepositHistory, nil, &resp) } // FetchWithdrawalHistory gets withdrawal history @@ -591,7 +591,7 @@ func (f *FTX) FetchWithdrawalHistory(ctx context.Context) ([]WithdrawItem, error resp := struct { Data []WithdrawItem `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getWithdrawalHistory, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getWithdrawalHistory, nil, &resp) } // Withdraw sends a withdrawal request @@ -619,7 +619,7 @@ func (f *FTX) Withdraw(ctx context.Context, coin currency.Code, address, tag, pa resp := struct { Data WithdrawItem `json:"result"` }{} - return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, withdrawRequest, "", req, &resp) + return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, withdrawRequest, req, &resp) } // GetOpenOrders gets open orders @@ -632,7 +632,7 @@ func (f *FTX) GetOpenOrders(ctx context.Context, marketName string) ([]OrderData Data []OrderData `json:"result"` }{} endpoint := common.EncodeURLValues(getOpenOrders, params) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp) } // FetchOrderHistory gets order history @@ -655,7 +655,7 @@ func (f *FTX) FetchOrderHistory(ctx context.Context, marketName string, startTim params.Set("limit", limit) } endpoint := common.EncodeURLValues(getOrderHistory, params) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp) } // GetOpenTriggerOrders gets trigger orders that are currently open @@ -671,7 +671,7 @@ func (f *FTX) GetOpenTriggerOrders(ctx context.Context, marketName, orderType st Data []TriggerOrderData `json:"result"` }{} endpoint := common.EncodeURLValues(getOpenTriggerOrders, params) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp) } // GetTriggerOrderTriggers gets trigger orders that are currently open @@ -679,7 +679,7 @@ func (f *FTX) GetTriggerOrderTriggers(ctx context.Context, orderID string) ([]Tr resp := struct { Data []TriggerData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(getTriggerOrderTriggers, orderID), nil, &resp) } // GetTriggerOrderHistory gets trigger orders that are currently open @@ -708,7 +708,7 @@ func (f *FTX) GetTriggerOrderHistory(ctx context.Context, marketName string, sta Data []TriggerOrderData `json:"result"` }{} endpoint := common.EncodeURLValues(getTriggerOrderHistory, params) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp) } // Order places an order @@ -740,7 +740,7 @@ func (f *FTX) Order( resp := struct { Data OrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeOrder, "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeOrder, req, &resp) } // TriggerOrder places an order @@ -770,7 +770,7 @@ func (f *FTX) TriggerOrder(ctx context.Context, marketName, side, orderType, red resp := struct { Data TriggerOrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeTriggerOrder, "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, placeTriggerOrder, req, &resp) } // ModifyPlacedOrder modifies a placed order @@ -784,7 +784,7 @@ func (f *FTX) ModifyPlacedOrder(ctx context.Context, orderID, clientID string, p resp := struct { Data OrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrder, orderID), "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrder, orderID), req, &resp) } // ModifyOrderByClientID modifies a placed order via clientOrderID @@ -798,7 +798,7 @@ func (f *FTX) ModifyOrderByClientID(ctx context.Context, clientOrderID, clientID resp := struct { Data OrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyOrderByClientID, clientOrderID), req, &resp) } // ModifyTriggerOrder modifies an existing trigger order @@ -820,7 +820,7 @@ func (f *FTX) ModifyTriggerOrder(ctx context.Context, orderID, orderType string, resp := struct { Data TriggerOrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(modifyTriggerOrder, orderID), req, &resp) } // GetOrderStatus gets the order status of a given orderID @@ -828,7 +828,7 @@ func (f *FTX) GetOrderStatus(ctx context.Context, orderID string) (OrderData, er resp := struct { Data OrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatus+orderID, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatus+orderID, nil, &resp) } // GetOrderStatusByClientID gets the order status of a given clientOrderID @@ -836,7 +836,7 @@ func (f *FTX) GetOrderStatusByClientID(ctx context.Context, clientOrderID string resp := struct { Data OrderData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatusByClientID+clientOrderID, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOrderStatusByClientID+clientOrderID, nil, &resp) } func (f *FTX) deleteOrderByPath(ctx context.Context, path string) (string, error) { @@ -845,7 +845,7 @@ func (f *FTX) deleteOrderByPath(ctx context.Context, path string) (string, error Success bool `json:"success"` Error string `json:"error"` }{} - err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, "", nil, &resp) + err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, nil, &resp) // If there is an error reported, but the resp struct reports one of a very few // specific error causes, we still consider this a successful cancellation. if err != nil && !resp.Success && (resp.Error == "Order already closed" || resp.Error == "Order already queued for cancellation") { @@ -905,7 +905,7 @@ func (f *FTX) GetFills(ctx context.Context, market currency.Pair, item asset.Ite params.Set("end_time", strconv.FormatInt(nextEnd.Unix(), 10)) } endpoint := common.EncodeURLValues(getFills, params) - err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &data) + err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &data) if err != nil { return nil, err } @@ -950,7 +950,7 @@ func (f *FTX) GetFundingPayments(ctx context.Context, startTime, endTime time.Ti params.Set("future", future) } endpoint := common.EncodeURLValues(getFundingPayments, params) - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, endpoint, nil, &resp) } // ListLeveragedTokens lists leveraged tokens @@ -958,7 +958,7 @@ func (f *FTX) ListLeveragedTokens(ctx context.Context) ([]LeveragedTokensData, e resp := struct { Data []LeveragedTokensData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLeveragedTokens, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLeveragedTokens, nil, &resp) } // GetTokenInfo gets token info @@ -966,7 +966,7 @@ func (f *FTX) GetTokenInfo(ctx context.Context, tokenName string) ([]LeveragedTo resp := struct { Data []LeveragedTokensData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getTokenInfo+tokenName, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getTokenInfo+tokenName, nil, &resp) } // ListLTBalances gets leveraged tokens' balances @@ -974,7 +974,7 @@ func (f *FTX) ListLTBalances(ctx context.Context) ([]LTBalanceData, error) { resp := struct { Data []LTBalanceData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTBalances, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTBalances, nil, &resp) } // ListLTCreations lists the leveraged tokens' creation requests @@ -982,7 +982,7 @@ func (f *FTX) ListLTCreations(ctx context.Context) ([]LTCreationData, error) { resp := struct { Data []LTCreationData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTCreations, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTCreations, nil, &resp) } // RequestLTCreation sends a request to create a leveraged token @@ -992,7 +992,7 @@ func (f *FTX) RequestLTCreation(ctx context.Context, tokenName string, size floa resp := struct { Data RequestTokenCreationData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTCreation, tokenName), req, &resp) } // ListLTRedemptions lists the leveraged tokens' redemption requests @@ -1000,7 +1000,7 @@ func (f *FTX) ListLTRedemptions(ctx context.Context) ([]LTRedemptionData, error) resp := struct { Data []LTRedemptionData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTRedemptions, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getLTRedemptions, nil, &resp) } // RequestLTRedemption sends a request to redeem a leveraged token @@ -1010,7 +1010,7 @@ func (f *FTX) RequestLTRedemption(ctx context.Context, tokenName string, size fl resp := struct { Data LTRedemptionRequestData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(requestLTRedemption, tokenName), req, &resp) } // GetQuoteRequests gets a list of quote requests @@ -1018,7 +1018,7 @@ func (f *FTX) GetQuoteRequests(ctx context.Context) ([]QuoteRequestData, error) resp := struct { Data []QuoteRequestData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getListQuotes, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getListQuotes, nil, &resp) } // GetYourQuoteRequests gets a list of your quote requests @@ -1026,7 +1026,7 @@ func (f *FTX) GetYourQuoteRequests(ctx context.Context) ([]PersonalQuotesData, e resp := struct { Data []PersonalQuotesData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotesRequests, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotesRequests, nil, &resp) } // CreateQuoteRequest sends a request to create a quote @@ -1051,7 +1051,7 @@ func (f *FTX) CreateQuoteRequest(ctx context.Context, underlying currency.Code, resp := struct { Data CreateQuoteRequestData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, createQuoteRequest, "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, createQuoteRequest, req, &resp) } // DeleteQuote sends request to cancel a quote @@ -1059,13 +1059,13 @@ func (f *FTX) DeleteQuote(ctx context.Context, requestID string) (CancelQuoteReq resp := struct { Data CancelQuoteRequestData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteQuote+requestID, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteQuote+requestID, nil, &resp) } // GetQuotesForYourQuote gets a list of quotes for your quote func (f *FTX) GetQuotesForYourQuote(ctx context.Context, requestID string) (QuoteForQuoteData, error) { var resp QuoteForQuoteData - return resp, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(endpointQuote, requestID), "", nil, &resp) + return resp, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(endpointQuote, requestID), nil, &resp) } // MakeQuote makes a quote for a quote @@ -1075,7 +1075,7 @@ func (f *FTX) MakeQuote(ctx context.Context, requestID, price string) ([]QuoteFo resp := struct { Data []QuoteForQuoteData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(endpointQuote, requestID), "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(endpointQuote, requestID), nil, &resp) } // MyQuotes gets a list of my quotes for quotes @@ -1083,7 +1083,7 @@ func (f *FTX) MyQuotes(ctx context.Context) ([]QuoteForQuoteData, error) { resp := struct { Data []QuoteForQuoteData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotes, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getMyQuotes, nil, &resp) } // DeleteMyQuote deletes my quote for quotes @@ -1091,7 +1091,7 @@ func (f *FTX) DeleteMyQuote(ctx context.Context, quoteID string) ([]QuoteForQuot resp := struct { Data []QuoteForQuoteData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteMyQuote+quoteID, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, deleteMyQuote+quoteID, nil, &resp) } // AcceptQuote accepts the quote for quote @@ -1099,7 +1099,7 @@ func (f *FTX) AcceptQuote(ctx context.Context, quoteID string) ([]QuoteForQuoteD resp := struct { Data []QuoteForQuoteData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptQuote, quoteID), nil, &resp) } // GetAccountOptionsInfo gets account's options' info @@ -1107,7 +1107,7 @@ func (f *FTX) GetAccountOptionsInfo(ctx context.Context) (AccountOptionsInfoData resp := struct { Data AccountOptionsInfoData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsInfo, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsInfo, nil, &resp) } // GetOptionsPositions gets options' positions @@ -1115,7 +1115,7 @@ func (f *FTX) GetOptionsPositions(ctx context.Context) ([]OptionsPositionsData, resp := struct { Data []OptionsPositionsData `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsPositions, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsPositions, nil, &resp) } // GetPublicOptionsTrades gets options' trades from public @@ -1154,7 +1154,7 @@ func (f *FTX) GetOptionsFills(ctx context.Context, startTime, endTime time.Time, if limit != "" { req["limit"] = limit } - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsFills, "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOptionsFills, req, &resp) } // GetStakes returns a list of staked assets @@ -1162,7 +1162,7 @@ func (f *FTX) GetStakes(ctx context.Context) ([]Stake, error) { resp := struct { Data []Stake `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakes, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakes, nil, &resp) } // GetUnstakeRequests returns a collection of unstake requests @@ -1170,7 +1170,7 @@ func (f *FTX) GetUnstakeRequests(ctx context.Context) ([]UnstakeRequest, error) resp := struct { Data []UnstakeRequest `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, unstakeRequests, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, unstakeRequests, nil, &resp) } // GetStakeBalances returns a collection of staked coin balances @@ -1178,7 +1178,7 @@ func (f *FTX) GetStakeBalances(ctx context.Context) ([]StakeBalance, error) { resp := struct { Data []StakeBalance `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakeBalances, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakeBalances, nil, &resp) } // UnstakeRequest unstakes an existing staked coin @@ -1189,7 +1189,7 @@ func (f *FTX) UnstakeRequest(ctx context.Context, coin currency.Code, size float req := make(map[string]interface{}) req["coin"] = coin.Upper().String() req["size"] = strconv.FormatFloat(size, 'f', -1, 64) - return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, unstakeRequests, "", req, &resp) + return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, unstakeRequests, req, &resp) } // CancelUnstakeRequest cancels a pending unstake request @@ -1198,7 +1198,7 @@ func (f *FTX) CancelUnstakeRequest(ctx context.Context, requestID int64) (bool, Result string }{} path := unstakeRequests + "/" + strconv.FormatInt(requestID, 10) - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, "", nil, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, path, nil, &resp); err != nil { return false, err } @@ -1213,7 +1213,7 @@ func (f *FTX) GetStakingRewards(ctx context.Context) ([]StakeReward, error) { resp := struct { Data []StakeReward `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakingRewards, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, stakingRewards, nil, &resp) } // StakeRequest submits a stake request based on the specified currency and size @@ -1224,13 +1224,14 @@ func (f *FTX) StakeRequest(ctx context.Context, coin currency.Code, size float64 req := make(map[string]interface{}) req["coin"] = coin.Upper().String() req["size"] = strconv.FormatFloat(size, 'f', -1, 64) - return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, serumStakes, "", req, &resp) + return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, serumStakes, req, &resp) } // SendAuthHTTPRequest sends an authenticated request -func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, path, subAccount string, data, result interface{}) error { - if !f.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", f.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) +func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, data, result interface{}) error { + creds, err := f.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := f.API.Endpoints.GetURL(ep) @@ -1255,20 +1256,17 @@ func (f *FTX) SendAuthHTTPRequest(ctx context.Context, ep exchange.URL, method, hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPayload), - []byte(f.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["FTX-KEY"] = f.API.Credentials.Key + headers["FTX-KEY"] = creds.Key headers["FTX-SIGN"] = crypto.HexEncodeToString(hmac) headers["FTX-TS"] = ts - if subAccount == "" && f.API.Credentials.Subaccount != "" { - subAccount = f.API.Credentials.Subaccount - } - if subAccount != "" { - headers["FTX-SUBACCOUNT"] = url.QueryEscape(subAccount) + if creds.SubAccount != "" { + headers["FTX-SUBACCOUNT"] = url.QueryEscape(creds.SubAccount) } headers["Content-Type"] = "application/json" @@ -1297,7 +1295,7 @@ func (f *FTX) GetFee(ctx context.Context, feeBuilder *exchange.FeeBuilder) (floa case exchange.OfflineTradeFee: fee = getOfflineTradeFee(feeBuilder) default: - feeData, err := f.GetAccountInfo(ctx, "") + feeData, err := f.GetAccountInfo(ctx) if err != nil { return 0, err } @@ -1382,7 +1380,7 @@ func (f *FTX) RequestForQuotes(ctx context.Context, base, quote currency.Code, a req["fromCoin"] = base.Upper().String() req["toCoin"] = quote.Upper().String() req["size"] = amount - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, requestOTCQuote, "", req, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, requestOTCQuote, req, &resp) } // GetOTCQuoteStatus gets quote status of a quote @@ -1392,12 +1390,12 @@ func (f *FTX) GetOTCQuoteStatus(ctx context.Context, marketName, quoteID string) }{} params := url.Values{} params.Set("market", marketName) - return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOTCQuoteStatus+quoteID, "", params, &resp) + return &resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, getOTCQuoteStatus+quoteID, params, &resp) } // AcceptOTCQuote requests for otc quotes func (f *FTX) AcceptOTCQuote(ctx context.Context, quoteID string) error { - return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), "", nil, nil) + return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, fmt.Sprintf(acceptOTCQuote, quoteID), nil, nil) } // GetSubaccounts returns the users subaccounts @@ -1405,7 +1403,7 @@ func (f *FTX) GetSubaccounts(ctx context.Context) ([]Subaccount, error) { resp := struct { Data []Subaccount `json:"result"` }{} - return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, subaccounts, "", nil, &resp) + return resp.Data, f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, subaccounts, nil, &resp) } // CreateSubaccount creates a new subaccount @@ -1419,7 +1417,7 @@ func (f *FTX) CreateSubaccount(ctx context.Context, name string) (*Subaccount, e resp := struct { Data Subaccount `json:"result"` }{} - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccounts, "", d, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccounts, d, &resp); err != nil { return nil, err } return &resp.Data, nil @@ -1437,7 +1435,7 @@ func (f *FTX) UpdateSubaccountName(ctx context.Context, oldName, newName string) resp := struct { Data Subaccount `json:"result"` }{} - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsUpdateName, "", d, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsUpdateName, d, &resp); err != nil { return nil, err } return &resp.Data, nil @@ -1453,7 +1451,7 @@ func (f *FTX) DeleteSubaccount(ctx context.Context, name string) error { resp := struct { Data Subaccount `json:"result"` }{} - return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, subaccounts, "", d, &resp) + return f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodDelete, subaccounts, d, &resp) } // SubaccountBalances returns the user's subaccount balances @@ -1464,7 +1462,7 @@ func (f *FTX) SubaccountBalances(ctx context.Context, name string) ([]Subaccount resp := struct { Data []SubaccountBalance `json:"result"` }{} - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(subaccountsBalance, name), "", nil, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, fmt.Sprintf(subaccountsBalance, name), nil, &resp); err != nil { return nil, err } return resp.Data, nil @@ -1495,7 +1493,7 @@ func (f *FTX) SubaccountTransfer(ctx context.Context, coin currency.Code, source resp := struct { Data SubaccountTransferStatus `json:"result"` }{} - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsTransfer, "", d, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, subaccountsTransfer, d, &resp); err != nil { return nil, err } return &resp.Data, nil @@ -1557,7 +1555,7 @@ func (f *FTX) GetCollateral(ctx context.Context, maintenance bool) (*CollateralR u.Add("marginType", "initial") } url := common.EncodeURLValues(collateral, u) - if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, url, "", nil, &resp); err != nil { + if err := f.SendAuthHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, url, nil, &resp); err != nil { return nil, err } return &resp.Data, nil @@ -1700,7 +1698,7 @@ func (f *FTX) LoadCollateralWeightings(ctx context.Context) error { if !f.GetAuthenticatedAPISupport(exchange.RestAuthentication) { return nil } - coins, err := f.GetCoins(ctx, "") + coins, err := f.GetCoins(ctx) if err != nil { return err } diff --git a/exchanges/ftx/ftx_test.go b/exchanges/ftx/ftx_test.go index d36326e677f..ca11698d90f 100644 --- a/exchanges/ftx/ftx_test.go +++ b/exchanges/ftx/ftx_test.go @@ -78,7 +78,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return f.ValidateAPICredentials() + return f.ValidateAPICredentials(f.GetDefaultCredentials()) == nil } // Implement tests for API endpoints below @@ -264,7 +264,7 @@ func TestGetAccountInfo(t *testing.T) { if !areTestAPIKeysSet() { t.Skip() } - _, err := f.GetAccountInfo(context.Background(), subaccount) + _, err := f.GetAccountInfo(context.Background()) if err != nil { t.Error(err) } @@ -286,19 +286,19 @@ func TestGetBalances(t *testing.T) { if !areTestAPIKeysSet() { t.Skip() } - _, err := f.GetBalances(context.Background(), subaccount, false, false) + _, err := f.GetBalances(context.Background(), false, false) if err != nil { t.Error(err) } - _, err = f.GetBalances(context.Background(), subaccount, true, false) + _, err = f.GetBalances(context.Background(), true, false) if err != nil { t.Error(err) } - _, err = f.GetBalances(context.Background(), subaccount, false, true) + _, err = f.GetBalances(context.Background(), false, true) if err != nil { t.Error(err) } - _, err = f.GetBalances(context.Background(), subaccount, true, true) + _, err = f.GetBalances(context.Background(), true, true) if err != nil { t.Error(err) } @@ -331,7 +331,7 @@ func TestGetCoins(t *testing.T) { if !areTestAPIKeysSet() { t.Skip() } - _, err := f.GetCoins(context.Background(), subaccount) + _, err := f.GetCoins(context.Background()) if err != nil { t.Error(err) } @@ -1767,7 +1767,6 @@ func TestScaleCollateral(t *testing.T) { result, err := f.ScaleCollateral( context.Background(), - "", &order.CollateralCalculator{ CollateralCurrency: currency.USDT, Asset: asset.Spot, @@ -1787,7 +1786,7 @@ func TestScaleCollateral(t *testing.T) { if !areTestAPIKeysSet() { return } - accountInfo, err := f.GetAccountInfo(context.Background(), subaccount) + accountInfo, err := f.GetAccountInfo(context.Background()) if err != nil { t.Error(err) } @@ -1813,7 +1812,6 @@ func TestScaleCollateral(t *testing.T) { } _, err = f.ScaleCollateral( context.Background(), - "", &order.CollateralCalculator{ CollateralCurrency: coin, Asset: asset.Spot, @@ -1831,7 +1829,6 @@ func TestScaleCollateral(t *testing.T) { } providedUSDValue += v[v2].USDValue _, err = f.ScaleCollateral(context.Background(), - subaccount, &order.CollateralCalculator{ CollateralCurrency: coin, Asset: asset.Spot, @@ -1845,7 +1842,6 @@ func TestScaleCollateral(t *testing.T) { t.Error(err) } _, err = f.ScaleCollateral(context.Background(), - subaccount, &order.CollateralCalculator{ CollateralCurrency: coin, Asset: asset.Spot, @@ -1861,7 +1857,6 @@ func TestScaleCollateral(t *testing.T) { _, err = f.ScaleCollateral( context.Background(), - "", &order.CollateralCalculator{ CollateralCurrency: coin, Asset: asset.Spot, @@ -1926,7 +1921,6 @@ func TestCalculateTotalCollateral(t *testing.T) { } } calc := &order.TotalCollateralCalculator{ - SubAccount: subaccount, CollateralAssets: scales, FetchPositions: false, CalculateOffline: true, @@ -1936,7 +1930,7 @@ func TestCalculateTotalCollateral(t *testing.T) { t.Fatal(err) } localScaling := total.AvailableCollateral.InexactFloat64() - accountInfo, err := f.GetAccountInfo(context.Background(), subaccount) + accountInfo, err := f.GetAccountInfo(context.Background()) if err != nil { t.Error(err) } diff --git a/exchanges/ftx/ftx_websocket.go b/exchanges/ftx/ftx_websocket.go index 2c2c6fa42d5..280a4e4ecbf 100644 --- a/exchanges/ftx/ftx_websocket.go +++ b/exchanges/ftx/ftx_websocket.go @@ -66,7 +66,7 @@ func (f *FTX) WsConnect() error { go f.wsReadData() if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = f.WsAuth() + err = f.WsAuth(context.TODO()) if err != nil { f.Websocket.DataHandler <- err f.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -77,13 +77,17 @@ func (f *FTX) WsConnect() error { } // WsAuth sends an authentication message to receive auth data -func (f *FTX) WsAuth() error { +func (f *FTX) WsAuth(ctx context.Context) error { + creds, err := f.GetCredentials(ctx) + if err != nil { + return err + } intNonce := time.Now().UnixMilli() strNonce := strconv.FormatInt(intNonce, 10) hmac, err := crypto.GetHMAC( crypto.HashSHA256, []byte(strNonce+"websocket_login"), - []byte(f.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return err @@ -91,10 +95,10 @@ func (f *FTX) WsAuth() error { sign := crypto.HexEncodeToString(hmac) req := Authenticate{Operation: "login", Args: AuthenticationData{ - Key: f.API.Credentials.Key, + Key: creds.Key, Sign: sign, Time: intNonce, - SubAccount: f.API.Credentials.Subaccount, + SubAccount: creds.SubAccount, }, } diff --git a/exchanges/ftx/ftx_wrapper.go b/exchanges/ftx/ftx_wrapper.go index db10affc1c1..fc42c809e88 100644 --- a/exchanges/ftx/ftx_wrapper.go +++ b/exchanges/ftx/ftx_wrapper.go @@ -458,16 +458,20 @@ func (f *FTX) UpdateOrderbook(ctx context.Context, p currency.Pair, assetType as // UpdateAccountInfo retrieves balances for all enabled currencies func (f *FTX) UpdateAccountInfo(ctx context.Context, a asset.Item) (account.Holdings, error) { + creds, err := f.GetCredentials(ctx) + if err != nil { + return account.Holdings{}, err + } var resp account.Holdings var data AllWalletBalances - if f.API.Credentials.Subaccount != "" { - balances, err := f.GetBalances(ctx, "", false, false) + if creds.SubAccount != "" { + balances, err := f.GetBalances(ctx, false, false) if err != nil { return resp, err } data = make(AllWalletBalances) - data[f.API.Credentials.Subaccount] = balances + data[creds.SubAccount] = balances } else { // Get all wallet balances used so we can transfer between accounts if // needed. @@ -1147,8 +1151,8 @@ func (f *FTX) UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscripti } // AuthenticateWebsocket sends an authentication message to the websocket -func (f *FTX) AuthenticateWebsocket(_ context.Context) error { - return f.WsAuth() +func (f *FTX) AuthenticateWebsocket(ctx context.Context) error { + return f.WsAuth(ctx) } // ValidateCredentials validates current credentials used for wrapper @@ -1268,7 +1272,7 @@ func (f *FTX) UpdateOrderExecutionLimits(ctx context.Context, _ asset.Item) erro // GetAvailableTransferChains returns the available transfer blockchains for the specific // cryptocurrency func (f *FTX) GetAvailableTransferChains(ctx context.Context, cryptocurrency currency.Code) ([]string, error) { - coins, err := f.GetCoins(ctx, "") + coins, err := f.GetCoins(ctx) if err != nil { return nil, err } @@ -1292,24 +1296,27 @@ func (f *FTX) CalculatePNL(ctx context.Context, pnl *order.PNLCalculatorRequest) result := &order.PNLResult{ Time: pnl.Time, } - var err error + creds, err := f.GetCredentials(ctx) + if err != nil { + return nil, err + } if pnl.CalculateOffline { // PNLCalculator matches FTX's pnl calculation method calc := order.PNLCalculator{} result, err = calc.CalculatePNL(ctx, pnl) if err != nil { - return nil, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, err) + return nil, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, err) } } ep := pnl.EntryPrice.InexactFloat64() - info, err := f.GetAccountInfo(ctx, "") + info, err := f.GetAccountInfo(ctx) if err != nil { return nil, err } if info.Liquidating || info.Collateral == 0 { result.IsLiquidated = true - return result, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, order.ErrPositionLiquidated) + return result, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, order.ErrPositionLiquidated) } for i := range info.Positions { if !pnl.Pair.Equal(info.Positions[i].Future) { @@ -1327,13 +1334,13 @@ func (f *FTX) CalculatePNL(ctx context.Context, pnl *order.PNLCalculatorRequest) calc := order.PNLCalculator{} result, err = calc.CalculatePNL(ctx, pnl) if err != nil { - return nil, fmt.Errorf("%s %s %w", f.Name, f.API.Credentials.Subaccount, err) + return nil, fmt.Errorf("%s %s %w", f.Name, creds.SubAccount, err) } return result, nil } // ScaleCollateral takes your totals and scales them according to FTX's rules -func (f *FTX) ScaleCollateral(ctx context.Context, subAccount string, calc *order.CollateralCalculator) (*order.CollateralByCurrency, error) { +func (f *FTX) ScaleCollateral(ctx context.Context, calc *order.CollateralCalculator) (*order.CollateralByCurrency, error) { if calc.CalculateOffline { result := &order.CollateralByCurrency{ Currency: calc.CollateralCurrency, @@ -1398,7 +1405,6 @@ func (f *FTX) ScaleCollateral(ctx context.Context, subAccount string, calc *orde } resp, err := f.calculateTotalCollateralOnline(ctx, &order.TotalCollateralCalculator{ - SubAccount: subAccount, CollateralAssets: []order.CollateralCalculator{*calc}, }, nil, @@ -1444,7 +1450,7 @@ func (f *FTX) CalculateTotalCollateral(ctx context.Context, calc *order.TotalCol } } var collateralByCurrency *order.CollateralByCurrency - collateralByCurrency, err = f.ScaleCollateral(ctx, calc.SubAccount, &calc.CollateralAssets[i]) + collateralByCurrency, err = f.ScaleCollateral(ctx, &calc.CollateralAssets[i]) if err != nil { if errors.Is(err, errCollateralCurrencyNotFound) { log.Error(log.ExchangeSys, err) @@ -1501,7 +1507,7 @@ func (f *FTX) calculateTotalCollateralOnline(ctx context.Context, calc *order.To TotalValueOfPositiveSpotBalances: c.PositiveSpotBalanceTotal, CollateralContributedByPositiveSpotBalances: c.CollateralFromPositiveSpotBalances, } - balances, err := f.GetBalances(ctx, calc.SubAccount, true, true) + balances, err := f.GetBalances(ctx, true, true) if err != nil { return nil, fmt.Errorf("%s %w", f.Name, err) } diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go index 53cd4029936..557ab21187c 100644 --- a/exchanges/gateio/gateio.go +++ b/exchanges/gateio/gateio.go @@ -401,16 +401,16 @@ func (g *Gateio) GetTradeHistory(ctx context.Context, symbol string) (TradHistor } // GenerateSignature returns hash for authenticated requests -func (g *Gateio) GenerateSignature(message string) ([]byte, error) { - return crypto.GetHMAC(crypto.HashSHA512, []byte(message), - []byte(g.API.Credentials.Secret)) +func (g *Gateio) GenerateSignature(secret, message string) ([]byte, error) { + return crypto.GetHMAC(crypto.HashSHA512, []byte(message), []byte(secret)) } // SendAuthenticatedHTTPRequest sends authenticated requests to the Gateio API // To use this you must setup an APIKey and APISecret from the exchange func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint, param string, result interface{}) error { - if !g.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", g.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := g.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := g.API.Endpoints.GetURL(ep) if err != nil { @@ -418,9 +418,9 @@ func (g *Gateio) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U } headers := make(map[string]string) headers["Content-Type"] = "application/x-www-form-urlencoded" - headers["key"] = g.API.Credentials.Key + headers["key"] = creds.Key - hmac, err := g.GenerateSignature(param) + hmac, err := g.GenerateSignature(creds.Secret, param) if err != nil { return err } diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go index 705c8f0277b..e4cd3c2210d 100644 --- a/exchanges/gateio/gateio_test.go +++ b/exchanges/gateio/gateio_test.go @@ -332,7 +332,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return g.ValidateAPICredentials() + return g.ValidateAPICredentials(g.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { @@ -525,7 +525,7 @@ func TestWsGetBalance(t *testing.T) { t.Fatal(err) } go g.wsReadData() - err = g.wsServerSignIn() + err = g.wsServerSignIn(context.Background()) if err != nil { t.Fatal(err) } @@ -550,7 +550,7 @@ func TestWsGetOrderInfo(t *testing.T) { t.Fatal(err) } go g.wsReadData() - err = g.wsServerSignIn() + err = g.wsServerSignIn(context.Background()) if err != nil { t.Fatal(err) } diff --git a/exchanges/gateio/gateio_websocket.go b/exchanges/gateio/gateio_websocket.go index c33544bbed7..0ef07b2e504 100644 --- a/exchanges/gateio/gateio_websocket.go +++ b/exchanges/gateio/gateio_websocket.go @@ -1,6 +1,7 @@ package gateio import ( + "context" "encoding/json" "errors" "fmt" @@ -44,7 +45,7 @@ func (g *Gateio) WsConnect() error { go g.wsReadData() if g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = g.wsServerSignIn() + err = g.wsServerSignIn(context.TODO()) if err != nil { g.Websocket.DataHandler <- err g.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -67,9 +68,13 @@ func (g *Gateio) WsConnect() error { return nil } -func (g *Gateio) wsServerSignIn() error { +func (g *Gateio) wsServerSignIn(ctx context.Context) error { + creds, err := g.GetCredentials(ctx) + if err != nil { + return err + } nonce := int(time.Now().Unix() * 1000) - sigTemp, err := g.GenerateSignature(strconv.Itoa(nonce)) + sigTemp, err := g.GenerateSignature(creds.Secret, strconv.Itoa(nonce)) if err != nil { return err } @@ -77,7 +82,7 @@ func (g *Gateio) wsServerSignIn() error { signinWsRequest := WebsocketRequest{ ID: g.Websocket.Conn.GenerateMessageID(false), Method: "server.sign", - Params: []interface{}{g.API.Credentials.Key, signature, nonce}, + Params: []interface{}{creds.Key, signature, nonce}, } resp, err := g.Websocket.Conn.SendMessageReturnResponse(signinWsRequest.ID, signinWsRequest) diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go index ebf97e5be7d..98ca36971bc 100644 --- a/exchanges/gateio/gateio_wrapper.go +++ b/exchanges/gateio/gateio_wrapper.go @@ -701,7 +701,7 @@ func (g *Gateio) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !g.AllowAuthenticatedRequest() && // Todo check connection status + if !g.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -859,8 +859,8 @@ func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques } // AuthenticateWebsocket sends an authentication message to the websocket -func (g *Gateio) AuthenticateWebsocket(_ context.Context) error { - return g.wsServerSignIn() +func (g *Gateio) AuthenticateWebsocket(ctx context.Context) error { + return g.wsServerSignIn(ctx) } // ValidateCredentials validates current credentials used for wrapper diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index 5187555741f..d9d27507c15 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -361,8 +361,9 @@ func (g *Gemini) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the // exchange and returns an error func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) (err error) { - if !g.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", g.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := g.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := g.API.Endpoints.GetURL(ep) @@ -387,7 +388,7 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U PayloadBase64 := crypto.Base64Encode(PayloadJSON) hmac, err := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), - []byte(g.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } @@ -395,7 +396,7 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U headers := make(map[string]string) headers["Content-Length"] = "0" headers["Content-Type"] = "text/plain" - headers["X-GEMINI-APIKEY"] = g.API.Credentials.Key + headers["X-GEMINI-APIKEY"] = creds.Key headers["X-GEMINI-PAYLOAD"] = PayloadBase64 headers["X-GEMINI-SIGNATURE"] = crypto.HexEncodeToString(hmac) headers["Cache-Control"] = "no-cache" diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go index a1bad1583a9..f4cdd5f5dd0 100644 --- a/exchanges/gemini/gemini_test.go +++ b/exchanges/gemini/gemini_test.go @@ -403,7 +403,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return g.ValidateAPICredentials() + return g.ValidateAPICredentials(g.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { @@ -580,7 +580,7 @@ func TestWsAuth(t *testing.T) { } var dialer websocket.Dialer go g.wsReadData() - err = g.WsAuth(&dialer) + err = g.WsAuth(context.Background(), &dialer) if err != nil { t.Error(err) } diff --git a/exchanges/gemini/gemini_websocket.go b/exchanges/gemini/gemini_websocket.go index b647b5f0bc7..deb59d08691 100644 --- a/exchanges/gemini/gemini_websocket.go +++ b/exchanges/gemini/gemini_websocket.go @@ -3,6 +3,7 @@ package gemini import ( + "context" "encoding/json" "errors" "fmt" @@ -52,7 +53,7 @@ func (g *Gemini) WsConnect() error { go g.wsFunnelConnectionData(g.Websocket.Conn) if g.Websocket.CanUseAuthenticatedEndpoints() { - err := g.WsAuth(&dialer) + err := g.WsAuth(context.TODO(), &dialer) if err != nil { log.Errorf(log.ExchangeSys, "%v - websocket authentication failed: %v\n", g.Name, err) g.Websocket.SetCanUseAuthenticatedEndpoints(false) @@ -176,10 +177,14 @@ func (g *Gemini) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) } // WsAuth will connect to Gemini's secure endpoint -func (g *Gemini) WsAuth(dialer *websocket.Dialer) error { +func (g *Gemini) WsAuth(ctx context.Context, dialer *websocket.Dialer) error { if !g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name) } + creds, err := g.GetCredentials(ctx) + if err != nil { + return err + } payload := WsRequestPayload{ Request: "/v1/" + geminiWsOrderEvents, Nonce: time.Now().UnixNano(), @@ -196,7 +201,7 @@ func (g *Gemini) WsAuth(dialer *websocket.Dialer) error { PayloadBase64 := crypto.Base64Encode(PayloadJSON) hmac, err := crypto.GetHMAC(crypto.HashSHA512_384, []byte(PayloadBase64), - []byte(g.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } @@ -205,7 +210,7 @@ func (g *Gemini) WsAuth(dialer *websocket.Dialer) error { headers.Add("Content-Length", "0") headers.Add("Content-Type", "text/plain") headers.Add("X-GEMINI-PAYLOAD", PayloadBase64) - headers.Add("X-GEMINI-APIKEY", g.API.Credentials.Key) + headers.Add("X-GEMINI-APIKEY", creds.Key) headers.Add("X-GEMINI-SIGNATURE", crypto.HexEncodeToString(hmac)) headers.Add("Cache-Control", "no-cache") diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index f0f0d2cb891..7382dd026be 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -664,7 +664,7 @@ func (g *Gemini) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!g.AllowAuthenticatedRequest() || g.SkipAuthCheck) && // Todo check connection status + if (!g.AreCredentialsValid(ctx) || g.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go index 2e25efbfdd3..e801b244d4a 100644 --- a/exchanges/hitbtc/hitbtc.go +++ b/exchanges/hitbtc/hitbtc.go @@ -544,15 +544,16 @@ func (h *HitBTC) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri // SendAuthenticatedHTTPRequest sends an authenticated http request func (h *HitBTC) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, f request.EndpointLimit, result interface{}) error { - if !h.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", h.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := h.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := h.API.Endpoints.GetURL(ep) if err != nil { return err } headers := make(map[string]string) - headers["Authorization"] = "Basic " + crypto.Base64Encode([]byte(h.API.Credentials.Key+":"+h.API.Credentials.Secret)) + headers["Authorization"] = "Basic " + crypto.Base64Encode([]byte(creds.Key+":"+creds.Secret)) path := fmt.Sprintf("%s/%s", ePoint, endpoint) diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go index 5b728dcbb54..55f9c623afd 100644 --- a/exchanges/hitbtc/hitbtc_test.go +++ b/exchanges/hitbtc/hitbtc_test.go @@ -318,7 +318,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return h.ValidateAPICredentials() + return h.ValidateAPICredentials(h.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { @@ -486,7 +486,7 @@ func setupWsAuth(t *testing.T) { t.Fatal(err) } go h.wsReadData() - err = h.wsLogin() + err = h.wsLogin(context.Background()) if err != nil { t.Fatal(err) } diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index a5e54490a46..f88fecc9ba1 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -1,6 +1,7 @@ package hitbtc import ( + "context" "encoding/json" "errors" "fmt" @@ -45,7 +46,7 @@ func (h *HitBTC) WsConnect() error { h.Websocket.Wg.Add(1) go h.wsReadData() - err = h.wsLogin() + err = h.wsLogin(context.TODO()) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", h.Name, err) } @@ -560,15 +561,19 @@ func (h *HitBTC) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) } // Unsubscribe sends a websocket message to stop receiving data from the channel -func (h *HitBTC) wsLogin() error { +func (h *HitBTC) wsLogin(ctx context.Context) error { if !h.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", h.Name) } + creds, err := h.GetCredentials(ctx) + if err != nil { + return err + } h.Websocket.SetCanUseAuthenticatedEndpoints(true) n := strconv.FormatInt(time.Now().Unix(), 10) hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(n), - []byte(h.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return err } @@ -577,7 +582,7 @@ func (h *HitBTC) wsLogin() error { Method: "login", Params: WsLoginData{ Algo: "HS256", - PKey: h.API.Credentials.Key, + PKey: creds.Key, Nonce: n, Signature: crypto.HexEncodeToString(hmac), }, diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 725d46897b9..cd329c261c2 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -700,7 +700,7 @@ func (h *HitBTC) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !h.AllowAuthenticatedRequest() && // Todo check connection status + if !h.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -818,8 +818,8 @@ func (h *HitBTC) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques } // AuthenticateWebsocket sends an authentication message to the websocket -func (h *HitBTC) AuthenticateWebsocket(_ context.Context) error { - return h.wsLogin() +func (h *HitBTC) AuthenticateWebsocket(ctx context.Context) error { + return h.wsLogin(ctx) } // ValidateCredentials validates current credentials used for wrapper diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go index 095b9f510b7..7f009b00577 100644 --- a/exchanges/huobi/huobi.go +++ b/exchanges/huobi/huobi.go @@ -859,8 +859,9 @@ func (h *HUOBI) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin // SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API func (h *HUOBI) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result interface{}, isVersion2API bool) error { - if !h.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", h.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := h.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := h.API.Endpoints.GetURL(ep) if err != nil { @@ -872,7 +873,7 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.UR interim := json.RawMessage{} newRequest := func() (*request.Item, error) { - values.Set("AccessKeyId", h.API.Credentials.Key) + values.Set("AccessKeyId", creds.Key) values.Set("SignatureMethod", "HmacSHA256") values.Set("SignatureVersion", "2") values.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05")) @@ -897,7 +898,7 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.UR var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(payload), - []byte(h.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } diff --git a/exchanges/huobi/huobi_futures.go b/exchanges/huobi/huobi_futures.go index e9d5bc4967c..de3b52b0b7d 100644 --- a/exchanges/huobi/huobi_futures.go +++ b/exchanges/huobi/huobi_futures.go @@ -1115,8 +1115,9 @@ func (h *HUOBI) FQueryTriggerOrderHistory(ctx context.Context, contractCode curr // FuturesAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, data, result interface{}) error { - if !h.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", h.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := h.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := h.API.Endpoints.GetURL(ep) if err != nil { @@ -1133,7 +1134,7 @@ func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep exchange var tempResp json.RawMessage newRequest := func() (*request.Item, error) { - values.Set("AccessKeyId", h.API.Credentials.Key) + values.Set("AccessKeyId", creds.Key) values.Set("SignatureMethod", "HmacSHA256") values.Set("SignatureVersion", "2") values.Set("Timestamp", time.Now().UTC().Format("2006-01-02T15:04:05")) @@ -1149,7 +1150,7 @@ func (h *HUOBI) FuturesAuthenticatedHTTPRequest(ctx context.Context, ep exchange var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(sigPath), - []byte(h.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go index 5a36b1c9716..c7a25e13458 100644 --- a/exchanges/huobi/huobi_test.go +++ b/exchanges/huobi/huobi_test.go @@ -77,7 +77,7 @@ func setupWsTests(t *testing.T) { if err != nil { t.Fatal(err) } - err = h.wsLogin() + err = h.wsLogin(context.Background()) if err != nil { t.Fatal(err) } @@ -1760,7 +1760,7 @@ func TestGetTimestamp(t *testing.T) { func TestGetAccounts(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } _, err := h.GetAccounts(context.Background()) @@ -1771,7 +1771,7 @@ func TestGetAccounts(t *testing.T) { func TestGetAccountBalance(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip() } result, err := h.GetAccounts(context.Background()) @@ -1788,7 +1788,7 @@ func TestGetAccountBalance(t *testing.T) { func TestGetAggregatedBalance(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip() } @@ -1800,7 +1800,7 @@ func TestGetAggregatedBalance(t *testing.T) { func TestSpotNewOrder(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } cp, err := currency.NewPairFromString(testSymbol) @@ -1823,7 +1823,7 @@ func TestSpotNewOrder(t *testing.T) { func TestCancelExistingOrder(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } _, err := h.CancelExistingOrder(context.Background(), 1337) @@ -1834,7 +1834,7 @@ func TestCancelExistingOrder(t *testing.T) { func TestGetOrder(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } _, err := h.GetOrder(context.Background(), 1337) @@ -1845,7 +1845,7 @@ func TestGetOrder(t *testing.T) { func TestGetMarginLoanOrders(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip() } cp, err := currency.NewPairFromString(testSymbol) @@ -1861,7 +1861,7 @@ func TestGetMarginLoanOrders(t *testing.T) { func TestGetMarginAccountBalance(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip() } cp, err := currency.NewPairFromString(testSymbol) @@ -1876,7 +1876,7 @@ func TestGetMarginAccountBalance(t *testing.T) { func TestCancelWithdraw(t *testing.T) { t.Parallel() - if !h.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } _, err := h.CancelWithdraw(context.Background(), 1337) @@ -2003,11 +2003,11 @@ func TestGetActiveOrders(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return h.ValidateAPICredentials() + return h.ValidateAPICredentials(h.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { - if !h.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip() } @@ -2215,7 +2215,7 @@ func TestQueryWithdrawQuota(t *testing.T) { // TestWsGetAccountsList connects to WS, logs in, gets account list func TestWsGetAccountsList(t *testing.T) { setupWsTests(t) - if _, err := h.wsGetAccountsList(); err != nil { + if _, err := h.wsGetAccountsList(context.Background()); err != nil { t.Fatal(err) } } @@ -2227,7 +2227,7 @@ func TestWsGetOrderList(t *testing.T) { if err != nil { t.Fatal(err) } - _, err = h.wsGetOrdersList(1, p) + _, err = h.wsGetOrdersList(context.Background(), 1, p) if err != nil { t.Fatal(err) } @@ -2237,7 +2237,7 @@ func TestWsGetOrderList(t *testing.T) { func TestWsGetOrderDetails(t *testing.T) { setupWsTests(t) orderID := "123" - _, err := h.wsGetOrderDetails(orderID) + _, err := h.wsGetOrderDetails(context.Background(), orderID) if err != nil { t.Fatal(err) } diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go index e6d67677ca2..5887a8a8888 100644 --- a/exchanges/huobi/huobi_websocket.go +++ b/exchanges/huobi/huobi_websocket.go @@ -1,6 +1,7 @@ package huobi import ( + "context" "encoding/json" "errors" "fmt" @@ -74,7 +75,7 @@ func (h *HUOBI) WsConnect() error { h.Name, err) } - err = h.wsLogin() + err = h.wsLogin(context.TODO()) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", @@ -524,11 +525,16 @@ func (h *HUOBI) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, er // Subscribe sends a websocket message to receive data from the channel func (h *HUOBI) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error { + creds, err := h.GetCredentials(context.TODO()) + if err != nil { + return err + } var errs common.Errors for i := range channelsToSubscribe { if strings.Contains(channelsToSubscribe[i].Channel, "orders.") || strings.Contains(channelsToSubscribe[i].Channel, "accounts") { - err := h.wsAuthenticatedSubscribe("sub", + err := h.wsAuthenticatedSubscribe(creds, + "sub", wsAccountsOrdersEndPoint+channelsToSubscribe[i].Channel, channelsToSubscribe[i].Channel) if err != nil { @@ -555,11 +561,16 @@ func (h *HUOBI) Subscribe(channelsToSubscribe []stream.ChannelSubscription) erro // Unsubscribe sends a websocket message to stop receiving data from the channel func (h *HUOBI) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error { + creds, err := h.GetCredentials(context.TODO()) + if err != nil { + return err + } var errs common.Errors for i := range channelsToUnsubscribe { if strings.Contains(channelsToUnsubscribe[i].Channel, "orders.") || strings.Contains(channelsToUnsubscribe[i].Channel, "accounts") { - err := h.wsAuthenticatedSubscribe("unsub", + err := h.wsAuthenticatedSubscribe(creds, + "unsub", wsAccountsOrdersEndPoint+channelsToUnsubscribe[i].Channel, channelsToUnsubscribe[i].Channel) if err != nil { @@ -584,32 +595,37 @@ func (h *HUOBI) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) return nil } -func (h *HUOBI) wsGenerateSignature(timestamp, endpoint string) ([]byte, error) { +func (h *HUOBI) wsGenerateSignature(creds *exchange.Credentials, timestamp, endpoint string) ([]byte, error) { values := url.Values{} - values.Set("AccessKeyId", h.API.Credentials.Key) + values.Set("AccessKeyId", creds.Key) values.Set("SignatureMethod", signatureMethod) values.Set("SignatureVersion", signatureVersion) values.Set("Timestamp", timestamp) host := "api.huobi.pro" payload := fmt.Sprintf("%s\n%s\n%s\n%s", http.MethodGet, host, endpoint, values.Encode()) - return crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(h.API.Credentials.Secret)) + return crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(creds.Secret)) } -func (h *HUOBI) wsLogin() error { +func (h *HUOBI) wsLogin(ctx context.Context) error { if !h.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", h.Name) } + creds, err := h.GetCredentials(ctx) + if err != nil { + return err + } + h.Websocket.SetCanUseAuthenticatedEndpoints(true) timestamp := time.Now().UTC().Format(wsDateTimeFormatting) request := WsAuthenticationRequest{ Op: authOp, - AccessKeyID: h.API.Credentials.Key, + AccessKeyID: creds.Key, SignatureMethod: signatureMethod, SignatureVersion: signatureVersion, Timestamp: timestamp, } - hmac, err := h.wsGenerateSignature(timestamp, wsAccountsOrdersEndPoint) + hmac, err := h.wsGenerateSignature(creds, timestamp, wsAccountsOrdersEndPoint) if err != nil { return err } @@ -624,17 +640,17 @@ func (h *HUOBI) wsLogin() error { return nil } -func (h *HUOBI) wsAuthenticatedSubscribe(operation, endpoint, topic string) error { +func (h *HUOBI) wsAuthenticatedSubscribe(creds *exchange.Credentials, operation, endpoint, topic string) error { timestamp := time.Now().UTC().Format(wsDateTimeFormatting) request := WsAuthenticatedSubscriptionRequest{ Op: operation, - AccessKeyID: h.API.Credentials.Key, + AccessKeyID: creds.Key, SignatureMethod: signatureMethod, SignatureVersion: signatureVersion, Timestamp: timestamp, Topic: topic, } - hmac, err := h.wsGenerateSignature(timestamp, endpoint) + hmac, err := h.wsGenerateSignature(creds, timestamp, endpoint) if err != nil { return err } @@ -642,20 +658,25 @@ func (h *HUOBI) wsAuthenticatedSubscribe(operation, endpoint, topic string) erro return h.Websocket.AuthConn.SendJSONMessage(request) } -func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error) { +func (h *HUOBI) wsGetAccountsList(ctx context.Context) (*WsAuthenticatedAccountsListResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated cannot get accounts list", h.Name) } + creds, err := h.GetCredentials(ctx) + if err != nil { + return nil, err + } + timestamp := time.Now().UTC().Format(wsDateTimeFormatting) request := WsAuthenticatedAccountsListRequest{ Op: requestOp, - AccessKeyID: h.API.Credentials.Key, + AccessKeyID: creds.Key, SignatureMethod: signatureMethod, SignatureVersion: signatureVersion, Timestamp: timestamp, Topic: wsAccountsList, } - hmac, err := h.wsGenerateSignature(timestamp, wsAccountListEndpoint) + hmac, err := h.wsGenerateSignature(creds, timestamp, wsAccountListEndpoint) if err != nil { return nil, err } @@ -678,11 +699,16 @@ func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error return &response, nil } -func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthenticatedOrdersResponse, error) { +func (h *HUOBI) wsGetOrdersList(ctx context.Context, accountID int64, pair currency.Pair) (*WsAuthenticatedOrdersResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated cannot get orders list", h.Name) } + creds, err := h.GetCredentials(ctx) + if err != nil { + return nil, err + } + fpair, err := h.FormatExchangeCurrency(pair, asset.Spot) if err != nil { return nil, err @@ -691,7 +717,7 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent timestamp := time.Now().UTC().Format(wsDateTimeFormatting) request := WsAuthenticatedOrdersListRequest{ Op: requestOp, - AccessKeyID: h.API.Credentials.Key, + AccessKeyID: creds.Key, SignatureMethod: signatureMethod, SignatureVersion: signatureVersion, Timestamp: timestamp, @@ -701,7 +727,7 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent States: "submitted,partial-filled", } - hmac, err := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint) + hmac, err := h.wsGenerateSignature(creds, timestamp, wsOrdersListEndpoint) if err != nil { return nil, err } @@ -726,21 +752,25 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent return &response, nil } -func (h *HUOBI) wsGetOrderDetails(orderID string) (*WsAuthenticatedOrderDetailResponse, error) { +func (h *HUOBI) wsGetOrderDetails(ctx context.Context, orderID string) (*WsAuthenticatedOrderDetailResponse, error) { if !h.Websocket.CanUseAuthenticatedEndpoints() { return nil, fmt.Errorf("%v not authenticated cannot get order details", h.Name) } + creds, err := h.GetCredentials(ctx) + if err != nil { + return nil, err + } timestamp := time.Now().UTC().Format(wsDateTimeFormatting) request := WsAuthenticatedOrderDetailsRequest{ Op: requestOp, - AccessKeyID: h.API.Credentials.Key, + AccessKeyID: creds.Key, SignatureMethod: signatureMethod, SignatureVersion: signatureVersion, Timestamp: timestamp, Topic: wsOrdersDetail, OrderID: orderID, } - hmac, err := h.wsGenerateSignature(timestamp, wsOrdersDetailEndpoint) + hmac, err := h.wsGenerateSignature(creds, timestamp, wsOrdersDetailEndpoint) if err != nil { return nil, err } diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index 97170c28b7f..97a8a66ab2a 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -641,7 +641,7 @@ func (h *HUOBI) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (ac switch assetType { case asset.Spot: if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - resp, err := h.wsGetAccountsList() + resp, err := h.wsGetAccountsList(ctx) if err != nil { return info, err } @@ -1129,7 +1129,7 @@ func (h *HUOBI) GetOrderInfo(ctx context.Context, orderID string, pair currency. case asset.Spot: var respData *OrderInfo if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - resp, err := h.wsGetOrderDetails(orderID) + resp, err := h.wsGetOrderDetails(ctx, orderID) if err != nil { return orderDetail, err } @@ -1325,7 +1325,7 @@ func (h *HUOBI) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilde if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !h.AllowAuthenticatedRequest() && // Todo check connection status + if !h.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -1351,7 +1351,7 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest } if h.Websocket.CanUseAuthenticatedWebsocketForWrapper() { for i := range req.Pairs { - resp, err := h.wsGetOrdersList(-1, req.Pairs[i]) + resp, err := h.wsGetOrdersList(ctx, -1, req.Pairs[i]) if err != nil { return orders, err } @@ -1401,10 +1401,14 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest } } } else { + creds, err := h.GetCredentials(ctx) + if err != nil { + return nil, err + } for i := range req.Pairs { resp, err := h.GetOpenOrders(ctx, req.Pairs[i], - h.API.Credentials.ClientID, + creds.ClientID, side, 500) if err != nil { @@ -1703,8 +1707,8 @@ func setOrderSideStatusAndType(orderState, requestType string, orderDetail *orde } // AuthenticateWebsocket sends an authentication message to the websocket -func (h *HUOBI) AuthenticateWebsocket(_ context.Context) error { - return h.wsLogin() +func (h *HUOBI) AuthenticateWebsocket(ctx context.Context) error { + return h.wsLogin(ctx) } // ValidateCredentials validates current credentials used for wrapper diff --git a/exchanges/itbit/itbit.go b/exchanges/itbit/itbit.go index 5886330f21b..4d2100f79c2 100644 --- a/exchanges/itbit/itbit.go +++ b/exchanges/itbit/itbit.go @@ -78,20 +78,28 @@ func (i *ItBit) GetTradeHistory(ctx context.Context, currencyPair, tradeID strin // page - [optional] page to return example 1. default 1 // perPage - [optional] items per page example 50, default 50 max 50 func (i *ItBit) GetWallets(ctx context.Context, params url.Values) ([]Wallet, error) { + creds, err := i.GetCredentials(ctx) + if err != nil { + return nil, err + } var resp []Wallet - params.Set("userId", i.API.Credentials.ClientID) + params.Set("userId", creds.ClientID) path := fmt.Sprintf("/%s?%s", itbitWallets, params.Encode()) return resp, i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodGet, path, nil, &resp) } // CreateWallet creates a new wallet with a specified name. func (i *ItBit) CreateWallet(ctx context.Context, walletName string) (Wallet, error) { + creds, err := i.GetCredentials(ctx) + if err != nil { + return Wallet{}, err + } resp := Wallet{} params := make(map[string]interface{}) - params["userId"] = i.API.Credentials.ClientID + params["userId"] = creds.ClientID params["name"] = walletName - err := i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, "/"+itbitWallets, params, &resp) + err = i.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, http.MethodPost, "/"+itbitWallets, params, &resp) if err != nil { return resp, err } @@ -299,8 +307,9 @@ func (i *ItBit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin // SendAuthenticatedHTTPRequest sends an authenticated request to itBit func (i *ItBit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params map[string]interface{}, result interface{}) error { - if !i.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", i.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := i.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := i.API.Endpoints.GetURL(ep) if err != nil { @@ -340,14 +349,14 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.UR var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA512, []byte(urlPath+string(hash)), - []byte(i.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } signature := crypto.Base64Encode(hmac) headers := make(map[string]string) - headers["Authorization"] = i.API.Credentials.ClientID + ":" + signature + headers["Authorization"] = creds.ClientID + ":" + signature headers["X-Auth-Timestamp"] = timestamp headers["X-Auth-Nonce"] = n headers["Content-Type"] = "application/json" diff --git a/exchanges/itbit/itbit_test.go b/exchanges/itbit/itbit_test.go index 3ece000afee..ff47c986822 100644 --- a/exchanges/itbit/itbit_test.go +++ b/exchanges/itbit/itbit_test.go @@ -311,7 +311,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return i.ValidateAPICredentials() + return i.ValidateAPICredentials(i.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index a88b07e0a9e..c81bd463656 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -515,7 +515,7 @@ func (i *ItBit) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilde if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !i.AllowAuthenticatedRequest() && // Todo check connection status + if !i.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go index ee5a77851ea..ec355efc13f 100644 --- a/exchanges/kraken/kraken.go +++ b/exchanges/kraken/kraken.go @@ -1019,8 +1019,9 @@ func (k *Kraken) SendHTTPRequest(ctx context.Context, ep exchange.URL, path stri // SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (k *Kraken) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method string, params url.Values, result interface{}) error { - if !k.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", k.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := k.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := k.API.Endpoints.GetURL(ep) if err != nil { @@ -1042,7 +1043,7 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA512, append([]byte(path), shasum...), - []byte(k.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } @@ -1050,7 +1051,7 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.U signature := crypto.Base64Encode(hmac) headers := make(map[string]string) - headers["API-Key"] = k.API.Credentials.Key + headers["API-Key"] = creds.Key headers["API-Sign"] = signature return &request.Item{ diff --git a/exchanges/kraken/kraken_futures.go b/exchanges/kraken/kraken_futures.go index a0175c6c0b6..e83f660af9c 100644 --- a/exchanges/kraken/kraken_futures.go +++ b/exchanges/kraken/kraken_futures.go @@ -271,7 +271,7 @@ func (k *Kraken) GetFuturesAccountData(ctx context.Context) (FuturesAccountsData return resp, k.SendFuturesAuthRequest(ctx, http.MethodGet, futuresAccountData, nil, &resp) } -func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) (string, error) { +func (k *Kraken) signFuturesRequest(secret, endpoint, nonce, data string) (string, error) { message := data + nonce + endpoint hash, err := crypto.GetSHA256([]byte(message)) if err != nil { @@ -279,7 +279,7 @@ func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) (string, error } hc, err := crypto.GetHMAC(crypto.HashSHA512, hash, - []byte(k.API.Credentials.Secret)) + []byte(secret)) if err != nil { return "", err } @@ -288,8 +288,9 @@ func (k *Kraken) signFuturesRequest(endpoint, nonce, data string) (string, error // SendFuturesAuthRequest will send an auth req func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string, data url.Values, result interface{}) error { - if !k.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", k.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := k.GetCredentials(ctx) + if err != nil { + return err } if data == nil { data = url.Values{} @@ -304,13 +305,13 @@ func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string interim := json.RawMessage{} newRequest := func() (*request.Item, error) { nonce := strconv.FormatInt(time.Now().UnixNano(), 10) - - sig, err := k.signFuturesRequest(path, nonce, dataToSign) + var sig string + sig, err = k.signFuturesRequest(creds.Secret, path, nonce, dataToSign) if err != nil { return nil, err } headers := map[string]string{ - "APIKey": k.API.Credentials.Key, + "APIKey": creds.Key, "Authent": sig, "Nonce": nonce, } @@ -327,7 +328,7 @@ func (k *Kraken) SendFuturesAuthRequest(ctx context.Context, method, path string }, nil } - err := k.SendPayload(ctx, request.Unset, newRequest) + err = k.SendPayload(ctx, request.Unset, newRequest) if err != nil { return err } diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go index dccdc104b2e..fb3dc0b7091 100644 --- a/exchanges/kraken/kraken_test.go +++ b/exchanges/kraken/kraken_test.go @@ -898,7 +898,7 @@ func TestGetOrderInfo(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return k.ValidateAPICredentials() + return k.ValidateAPICredentials(k.GetDefaultCredentials()) == nil } // TestSubmitOrder wrapper test diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index 2cf42d12a00..00229f5835c 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -1081,7 +1081,7 @@ func (k *Kraken) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuild if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !k.AllowAuthenticatedRequest() && // Todo check connection status + if !k.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/lbank/lbank.go b/exchanges/lbank/lbank.go index 586ff63795b..f33c2d2940a 100644 --- a/exchanges/lbank/lbank.go +++ b/exchanges/lbank/lbank.go @@ -482,10 +482,14 @@ func (l *Lbank) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin }) } -func (l *Lbank) loadPrivKey() error { +func (l *Lbank) loadPrivKey(ctx context.Context) error { + creds, err := l.GetCredentials(ctx) + if err != nil { + return err + } key := strings.Join([]string{ "-----BEGIN RSA PRIVATE KEY-----", - l.API.Credentials.Secret, + creds.Secret, "-----END RSA PRIVATE KEY-----", }, "\n") @@ -529,15 +533,16 @@ func (l *Lbank) sign(data string) (string, error) { // SendAuthHTTPRequest sends an authenticated request func (l *Lbank) SendAuthHTTPRequest(ctx context.Context, method, endpoint string, vals url.Values, result interface{}) error { - if !l.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", l.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := l.GetCredentials(ctx) + if err != nil { + return err } if vals == nil { vals = url.Values{} } - vals.Set("api_key", l.API.Credentials.Key) + vals.Set("api_key", creds.Key) sig, err := l.sign(vals.Encode()) if err != nil { return err diff --git a/exchanges/lbank/lbank_test.go b/exchanges/lbank/lbank_test.go index 7cf5225c237..31501f70c05 100644 --- a/exchanges/lbank/lbank_test.go +++ b/exchanges/lbank/lbank_test.go @@ -51,7 +51,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return l.AllowAuthenticatedRequest() + return l.ValidateAPICredentials(l.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { @@ -305,12 +305,13 @@ func TestLoadPrivKey(t *testing.T) { if !areTestAPIKeysSet() { t.Skip("API keys required but not set, skipping test") } - err := l.loadPrivKey() + err := l.loadPrivKey(context.Background()) if err != nil { t.Error(err) } - l.API.Credentials.Secret = "errortest" - err = l.loadPrivKey() + + ctx := exchange.DeployCredentialsToContext(context.Background(), &exchange.Credentials{Secret: "errortest"}) + err = l.loadPrivKey(ctx) if err == nil { t.Errorf("Expected error due to pemblock nil") } @@ -321,8 +322,7 @@ func TestSign(t *testing.T) { if !areTestAPIKeysSet() { t.Skip("API keys required but not set, skipping test") } - l.API.Credentials.Secret = testAPISecret - err := l.loadPrivKey() + err := l.loadPrivKey(context.Background()) if err != nil { t.Fatal(err) } diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go index 8186548e850..20fc593ebb0 100644 --- a/exchanges/lbank/lbank_wrapper.go +++ b/exchanges/lbank/lbank_wrapper.go @@ -138,7 +138,7 @@ func (l *Lbank) Setup(exch *config.Exchange) error { } if l.API.AuthenticatedSupport { - err = l.loadPrivKey() + err = l.loadPrivKey(context.TODO()) if err != nil { l.API.AuthenticatedSupport = false log.Errorf(log.ExchangeSys, "%s couldn't load private key, setting authenticated support to false", l.Name) diff --git a/exchanges/localbitcoins/localbitcoins.go b/exchanges/localbitcoins/localbitcoins.go index cff4e8283f9..2e92a705d39 100644 --- a/exchanges/localbitcoins/localbitcoins.go +++ b/exchanges/localbitcoins/localbitcoins.go @@ -750,8 +750,9 @@ func (l *LocalBitcoins) SendHTTPRequest(ctx context.Context, endpoint exchange.U // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to // localbitcoins func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, path string, params url.Values, result interface{}) (err error) { - if !l.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", l.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := l.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := l.API.Endpoints.GetURL(ep) if err != nil { @@ -763,15 +764,15 @@ func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(ctx context.Context, ep exc fullPath := "/api/" + path encoded := params.Encode() - message := n + l.API.Credentials.Key + fullPath + encoded + message := n + creds.Key + fullPath + encoded hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(message), - []byte(l.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["Apiauth-Key"] = l.API.Credentials.Key + headers["Apiauth-Key"] = creds.Key headers["Apiauth-Nonce"] = n headers["Apiauth-Signature"] = strings.ToUpper(crypto.HexEncodeToString(hmac)) headers["Content-Type"] = "application/x-www-form-urlencoded" diff --git a/exchanges/localbitcoins/localbitcoins_test.go b/exchanges/localbitcoins/localbitcoins_test.go index fd49cf0cfb0..a9a8d3cf6ec 100644 --- a/exchanges/localbitcoins/localbitcoins_test.go +++ b/exchanges/localbitcoins/localbitcoins_test.go @@ -272,7 +272,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return l.ValidateAPICredentials() + return l.ValidateAPICredentials(l.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index 5a4e17d2db5..83e6c3a2599 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -528,7 +528,7 @@ func (l *LocalBitcoins) GetFeeByType(ctx context.Context, feeBuilder *exchange.F if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!l.AllowAuthenticatedRequest() || l.SkipAuthCheck) && // Todo check connection status + if (!l.AreCredentialsValid(ctx) || l.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go index fcdc46176b7..8eec31459b6 100644 --- a/exchanges/okcoin/okcoin_test.go +++ b/exchanges/okcoin/okcoin_test.go @@ -80,7 +80,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return o.ValidateAPICredentials() + return o.ValidateAPICredentials(o.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { @@ -792,7 +792,7 @@ func TestSendWsMessages(t *testing.T) { t.Error("Expecting OKEX error - 30040 message: Channel badChannel doesn't exist") } } - err = o.WsLogin() + err = o.WsLogin(context.Background()) if err != nil { t.Error(err) } diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index d8882241f13..7084abb7685 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -80,7 +80,7 @@ func TestMain(m *testing.M) { } func areTestAPIKeysSet() bool { - return o.ValidateAPICredentials() + return o.ValidateAPICredentials(o.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { @@ -1661,7 +1661,7 @@ func TestSendWsMessages(t *testing.T) { t.Error("Expecting OKEX error - 30040 message: Channel badChannel doesn't exist") } } - err = o.WsLogin() + err = o.WsLogin(context.Background()) if err != nil { t.Error(err) } diff --git a/exchanges/okgroup/okgroup.go b/exchanges/okgroup/okgroup.go index a6de9d2bc58..337dd163279 100644 --- a/exchanges/okgroup/okgroup.go +++ b/exchanges/okgroup/okgroup.go @@ -565,9 +565,6 @@ func (o *OKGroup) GetErrorCode(code interface{}) error { // path with a JSON payload (of present) // URL arguments must be in the request path and not as url.URL values func (o *OKGroup) SendHTTPRequest(ctx context.Context, ep exchange.URL, httpMethod, requestType, requestPath string, data, result interface{}, authenticated bool) (err error) { - if authenticated && !o.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", o.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) - } endpoint, err := o.API.Endpoints.GetURL(ep) if err != nil { return err @@ -589,20 +586,25 @@ func (o *OKGroup) SendHTTPRequest(ctx context.Context, ep exchange.URL, httpMeth headers := make(map[string]string) headers["Content-Type"] = "application/json" if authenticated { + var creds *exchange.Credentials + creds, err = o.GetCredentials(ctx) + if err != nil { + return nil, err + } signPath := fmt.Sprintf("/%v%v%v%v", OKGroupAPIPath, requestType, o.APIVersion, requestPath) var hmac []byte hmac, err = crypto.GetHMAC(crypto.HashSHA256, []byte(utcTime+httpMethod+signPath+string(payload)), - []byte(o.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } - headers["OK-ACCESS-KEY"] = o.API.Credentials.Key + headers["OK-ACCESS-KEY"] = creds.Key headers["OK-ACCESS-SIGN"] = crypto.Base64Encode(hmac) headers["OK-ACCESS-TIMESTAMP"] = utcTime - headers["OK-ACCESS-PASSPHRASE"] = o.API.Credentials.ClientID + headers["OK-ACCESS-PASSPHRASE"] = creds.ClientID } return &request.Item{ diff --git a/exchanges/okgroup/okgroup_websocket.go b/exchanges/okgroup/okgroup_websocket.go index 0951aab99e6..238b9ebdef1 100644 --- a/exchanges/okgroup/okgroup_websocket.go +++ b/exchanges/okgroup/okgroup_websocket.go @@ -1,6 +1,7 @@ package okgroup import ( + "context" "encoding/json" "errors" "fmt" @@ -196,7 +197,7 @@ func (o *OKGroup) WsConnect() error { go o.WsReadData() if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { - err = o.WsLogin() + err = o.WsLogin(context.TODO()) if err != nil { log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", @@ -209,13 +210,17 @@ func (o *OKGroup) WsConnect() error { } // WsLogin sends a login request to websocket to enable access to authenticated endpoints -func (o *OKGroup) WsLogin() error { +func (o *OKGroup) WsLogin(ctx context.Context) error { + creds, err := o.GetCredentials(ctx) + if err != nil { + return err + } o.Websocket.SetCanUseAuthenticatedEndpoints(true) unixTime := time.Now().UTC().Unix() signPath := "/users/self/verify" hmac, err := crypto.GetHMAC(crypto.HashSHA256, []byte(strconv.FormatInt(unixTime, 10)+http.MethodGet+signPath), - []byte(o.API.Credentials.Secret), + []byte(creds.Secret), ) if err != nil { return err @@ -224,8 +229,8 @@ func (o *OKGroup) WsLogin() error { request := WebsocketEventRequest{ Operation: "login", Arguments: []string{ - o.API.Credentials.Key, - o.API.Credentials.ClientID, + creds.Key, + creds.ClientID, strconv.FormatInt(unixTime, 10), base64, }, diff --git a/exchanges/okgroup/okgroup_wrapper.go b/exchanges/okgroup/okgroup_wrapper.go index 41102e2d1e5..bfbfb6e56b8 100644 --- a/exchanges/okgroup/okgroup_wrapper.go +++ b/exchanges/okgroup/okgroup_wrapper.go @@ -593,7 +593,7 @@ func (o *OKGroup) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuil if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !o.AllowAuthenticatedRequest() && // Todo check connection status + if !o.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -606,8 +606,8 @@ func (o *OKGroup) GetWithdrawCapabilities() uint32 { } // AuthenticateWebsocket sends an authentication message to the websocket -func (o *OKGroup) AuthenticateWebsocket(_ context.Context) error { - return o.WsLogin() +func (o *OKGroup) AuthenticateWebsocket(ctx context.Context) error { + return o.WsLogin(ctx) } // ValidateCredentials validates current credentials used for wrapper diff --git a/exchanges/order/futures_types.go b/exchanges/order/futures_types.go index e920a4fdce1..ac878187020 100644 --- a/exchanges/order/futures_types.go +++ b/exchanges/order/futures_types.go @@ -56,7 +56,7 @@ type PNLCalculation interface { // multiple ways of calculating the size of collateral // on an exchange type CollateralManagement interface { - ScaleCollateral(ctx context.Context, subAccount string, calculator *CollateralCalculator) (*CollateralByCurrency, error) + ScaleCollateral(ctx context.Context, calculator *CollateralCalculator) (*CollateralByCurrency, error) CalculateTotalCollateral(context.Context, *TotalCollateralCalculator) (*TotalCollateralResponse, error) } @@ -204,7 +204,6 @@ type PositionTrackerSetup struct { // TotalCollateralCalculator holds many collateral calculators // to calculate total collateral standing with one struct type TotalCollateralCalculator struct { - SubAccount string CollateralAssets []CollateralCalculator CalculateOffline bool FetchPositions bool diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index dd0064817ee..6fc92e0b837 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -865,8 +865,9 @@ func (p *Poloniex) SendHTTPRequest(ctx context.Context, ep exchange.URL, path st // SendAuthenticatedHTTPRequest sends an authenticated HTTP request func (p *Poloniex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, method, endpoint string, values url.Values, result interface{}) error { - if !p.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", p.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := p.GetCredentials(ctx) + if err != nil { + return err } ePoint, err := p.API.Endpoints.GetURL(ep) if err != nil { @@ -876,13 +877,13 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange return p.SendPayload(ctx, request.Unset, func() (*request.Item, error) { headers := make(map[string]string) headers["Content-Type"] = "application/x-www-form-urlencoded" - headers["Key"] = p.API.Credentials.Key + headers["Key"] = creds.Key values.Set("nonce", p.Requester.GetNonce(true).String()) values.Set("command", endpoint) hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(values.Encode()), - []byte(p.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go index 5cf1c21ba76..b68a59d16b3 100644 --- a/exchanges/poloniex/poloniex_test.go +++ b/exchanges/poloniex/poloniex_test.go @@ -32,7 +32,7 @@ const ( var p Poloniex func areTestAPIKeysSet() bool { - return p.ValidateAPICredentials() + return p.ValidateAPICredentials(p.GetDefaultCredentials()) == nil } func TestStart(t *testing.T) { @@ -563,7 +563,11 @@ func TestWsAuth(t *testing.T) { t.Fatal(err) } go p.wsReadData() - err = p.wsSendAuthorisedCommand("subscribe") + creds, err := p.GetCredentials(context.Background()) + if err != nil { + t.Fatal(err) + } + err = p.wsSendAuthorisedCommand(creds.Secret, creds.Key, "subscribe") if err != nil { t.Fatal(err) } diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 6207a8254b1..c96f123daf6 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -540,6 +540,10 @@ func (p *Poloniex) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, // Subscribe sends a websocket message to receive data from the channel func (p *Poloniex) Subscribe(sub []stream.ChannelSubscription) error { + creds, err := p.GetCredentials(context.TODO()) + if err != nil { + return err + } var errs common.Errors channels: for i := range sub { @@ -549,7 +553,7 @@ channels: switch { case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), sub[i].Channel): - err := p.wsSendAuthorisedCommand("subscribe") + err := p.wsSendAuthorisedCommand(creds.Secret, creds.Key, "subscribe") if err != nil { errs = append(errs, err) continue channels @@ -579,6 +583,10 @@ channels: // Unsubscribe sends a websocket message to stop receiving data from the channel func (p *Poloniex) Unsubscribe(unsub []stream.ChannelSubscription) error { + creds, err := p.GetCredentials(context.TODO()) + if err != nil { + return err + } var errs common.Errors channels: for i := range unsub { @@ -588,7 +596,7 @@ channels: switch { case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), unsub[i].Channel): - err := p.wsSendAuthorisedCommand("unsubscribe") + err := p.wsSendAuthorisedCommand(creds.Secret, creds.Key, "unsubscribe") if err != nil { errs = append(errs, err) continue channels @@ -614,11 +622,11 @@ channels: return nil } -func (p *Poloniex) wsSendAuthorisedCommand(command string) error { +func (p *Poloniex) wsSendAuthorisedCommand(secret, key, command string) error { nonce := fmt.Sprintf("nonce=%v", time.Now().UnixNano()) hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(nonce), - []byte(p.API.Credentials.Secret)) + []byte(secret)) if err != nil { return err } @@ -626,7 +634,7 @@ func (p *Poloniex) wsSendAuthorisedCommand(command string) error { Command: command, Channel: 1000, Sign: crypto.HexEncodeToString(hmac), - Key: p.API.Credentials.Key, + Key: key, Payload: nonce, } return p.Websocket.Conn.SendJSONMessage(request) diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index 2a652790c4f..bfb509caecc 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -806,7 +806,7 @@ func (p *Poloniex) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBui if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!p.AllowAuthenticatedRequest() || p.SkipAuthCheck) && // Todo check connection status + if (!p.AreCredentialsValid(ctx) || p.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/yobit/yobit.go b/exchanges/yobit/yobit.go index e36e82bb84e..0e891836e86 100644 --- a/exchanges/yobit/yobit.go +++ b/exchanges/yobit/yobit.go @@ -289,8 +289,9 @@ func (y *Yobit) SendHTTPRequest(ctx context.Context, ep exchange.URL, path strin // SendAuthenticatedHTTPRequest sends an authenticated HTTP request to Yobit func (y *Yobit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, path string, params url.Values, result interface{}) (err error) { - if !y.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", y.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := y.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := y.API.Endpoints.GetURL(ep) if err != nil { @@ -309,13 +310,13 @@ func (y *Yobit) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.UR encoded := params.Encode() hmac, err := crypto.GetHMAC(crypto.HashSHA512, []byte(encoded), - []byte(y.API.Credentials.Secret)) + []byte(creds.Secret)) if err != nil { return nil, err } headers := make(map[string]string) - headers["Key"] = y.API.Credentials.Key + headers["Key"] = creds.Key headers["Sign"] = crypto.HexEncodeToString(hmac) headers["Content-Type"] = "application/x-www-form-urlencoded" diff --git a/exchanges/yobit/yobit_test.go b/exchanges/yobit/yobit_test.go index 6a0e51de3ba..231ed88ebef 100644 --- a/exchanges/yobit/yobit_test.go +++ b/exchanges/yobit/yobit_test.go @@ -369,7 +369,7 @@ func TestGetOrderHistory(t *testing.T) { // Any tests below this line have the ability to impact your orders on the exchange. Enable canManipulateRealOrders to run them // ---------------------------------------------------------------------------------------------------------------------------- func areTestAPIKeysSet() bool { - return y.ValidateAPICredentials() + return y.ValidateAPICredentials(y.GetDefaultCredentials()) == nil } func TestSubmitOrder(t *testing.T) { diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index 832c7cb047e..f41c8f7a2ee 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -558,7 +558,7 @@ func (y *Yobit) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilde if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if !y.AllowAuthenticatedRequest() && // Todo check connection status + if !y.AreCredentialsValid(ctx) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } diff --git a/exchanges/zb/zb.go b/exchanges/zb/zb.go index 32aae2f43c8..e35760ff2bb 100644 --- a/exchanges/zb/zb.go +++ b/exchanges/zb/zb.go @@ -48,17 +48,22 @@ type ZB struct { // SpotNewOrder submits an order to ZB func (z *ZB) SpotNewOrder(ctx context.Context, arg SpotNewOrderRequestParams) (int64, error) { + creds, err := z.GetCredentials(ctx) + if err != nil { + return 0, err + } + var result SpotNewOrderResponse vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("method", "order") vals.Set("amount", strconv.FormatFloat(arg.Amount, 'f', -1, 64)) vals.Set("currency", arg.Symbol) vals.Set("price", strconv.FormatFloat(arg.Price, 'f', -1, 64)) vals.Set("tradeType", string(arg.Type)) - err := z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) + err = z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) if err != nil { return 0, err } @@ -74,19 +79,24 @@ func (z *ZB) SpotNewOrder(ctx context.Context, arg SpotNewOrderRequestParams) (i // CancelExistingOrder cancels an order func (z *ZB) CancelExistingOrder(ctx context.Context, orderID int64, symbol string) error { + creds, err := z.GetCredentials(ctx) + if err != nil { + return err + } + type response struct { Code int `json:"code"` // Result code Message string `json:"message"` // Result Message } vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("method", "cancelOrder") vals.Set("id", strconv.FormatInt(orderID, 10)) vals.Set("currency", symbol) var result response - err := z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) + err = z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) if err != nil { return err } @@ -100,10 +110,14 @@ func (z *ZB) CancelExistingOrder(ctx context.Context, orderID int64, symbol stri // GetAccountInformation returns account information including coin information // and pricing func (z *ZB) GetAccountInformation(ctx context.Context) (AccountsResponse, error) { - var result AccountsResponse + creds, err := z.GetCredentials(ctx) + if err != nil { + return AccountsResponse{}, err + } + var result AccountsResponse vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("method", "getAccountInfo") return result, z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) @@ -111,23 +125,31 @@ func (z *ZB) GetAccountInformation(ctx context.Context) (AccountsResponse, error // GetUnfinishedOrdersIgnoreTradeType returns unfinished orders func (z *ZB) GetUnfinishedOrdersIgnoreTradeType(ctx context.Context, currency string, pageindex, pagesize int64) ([]Order, error) { + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } var result []Order vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("method", zbUnfinishedOrdersIgnoreTradeType) vals.Set("currency", currency) vals.Set("pageIndex", strconv.FormatInt(pageindex, 10)) vals.Set("pageSize", strconv.FormatInt(pagesize, 10)) - err := z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) + err = z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &result, request.Auth) return result, err } // GetOrders returns finished orders func (z *ZB) GetOrders(ctx context.Context, currency string, pageindex, side int64) ([]Order, error) { + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } var response []Order vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("method", zbGetOrdersGet) vals.Set("currency", currency) vals.Set("pageIndex", strconv.FormatInt(pageindex, 10)) @@ -343,16 +365,17 @@ func (z *ZB) SendHTTPRequest(ctx context.Context, ep exchange.URL, path string, // SendAuthenticatedHTTPRequest sends authenticated requests to the zb API func (z *ZB) SendAuthenticatedHTTPRequest(ctx context.Context, ep exchange.URL, httpMethod string, params url.Values, result interface{}, f request.EndpointLimit) error { - if !z.AllowAuthenticatedRequest() { - return fmt.Errorf("%s %w", z.Name, exchange.ErrAuthenticatedRequestWithoutCredentialsSet) + creds, err := z.GetCredentials(ctx) + if err != nil { + return err } endpoint, err := z.API.Endpoints.GetURL(ep) if err != nil { return err } - params.Set("accesskey", z.API.Credentials.Key) + params.Set("accesskey", creds.Key) - hex, err := crypto.Sha1ToHex(z.API.Credentials.Secret) + hex, err := crypto.Sha1ToHex(creds.Secret) if err != nil { return err } @@ -473,6 +496,11 @@ var errorCode = map[int64]string{ // Withdraw transfers funds func (z *ZB) Withdraw(ctx context.Context, currency, address, safepassword string, amount, fees float64, itransfer bool) (string, error) { + creds, err := z.GetCredentials(ctx) + if err != nil { + return "", err + } + type response struct { Code int `json:"code"` // Result code Message string `json:"message"` // Result Message @@ -480,7 +508,7 @@ func (z *ZB) Withdraw(ctx context.Context, currency, address, safepassword strin } vals := url.Values{} - vals.Set("accesskey", z.API.Credentials.Key) + vals.Set("accesskey", creds.Key) vals.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64)) vals.Set("currency", currency) vals.Set("fees", strconv.FormatFloat(fees, 'f', -1, 64)) @@ -490,7 +518,7 @@ func (z *ZB) Withdraw(ctx context.Context, currency, address, safepassword strin vals.Set("safePwd", safepassword) var resp response - err := z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &resp, request.Auth) + err = z.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpotSupplementary, http.MethodGet, vals, &resp, request.Auth) if err != nil { return "", err } diff --git a/exchanges/zb/zb_test.go b/exchanges/zb/zb_test.go index c691e068613..57be32b0535 100644 --- a/exchanges/zb/zb_test.go +++ b/exchanges/zb/zb_test.go @@ -34,6 +34,10 @@ const ( var z ZB var wsSetupRan bool +func areTestAPIKeysSet() bool { + return z.ValidateAPICredentials(z.GetDefaultCredentials()) == nil +} + func setupWsAuth(t *testing.T) { t.Helper() if wsSetupRan { @@ -41,7 +45,7 @@ func setupWsAuth(t *testing.T) { } if !z.Websocket.IsEnabled() && !z.API.AuthenticatedWebsocketSupport || - !z.ValidateAPICredentials() || + !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip(stream.WebsocketNotEnabled) } @@ -71,7 +75,7 @@ func TestStart(t *testing.T) { func TestSpotNewOrder(t *testing.T) { t.Parallel() - if !z.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } @@ -90,7 +94,7 @@ func TestSpotNewOrder(t *testing.T) { func TestCancelExistingOrder(t *testing.T) { t.Parallel() - if !z.ValidateAPICredentials() || !canManipulateRealOrders { + if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip() } @@ -161,7 +165,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) { if err != nil { t.Fatal(err) } - if !z.ValidateAPICredentials() { + if !areTestAPIKeysSet() { if feeBuilder.FeeType != exchange.OfflineTradeFee { t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType) } @@ -252,9 +256,9 @@ func TestGetActiveOrders(t *testing.T) { } _, err := z.GetActiveOrders(context.Background(), &getOrdersRequest) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } @@ -272,9 +276,9 @@ func TestGetOrderHistory(t *testing.T) { } _, err := z.GetOrderHistory(context.Background(), &getOrdersRequest) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } @@ -283,7 +287,7 @@ func TestGetOrderHistory(t *testing.T) { // ---------------------------------------------------------------------------------------------------------------------------- func TestSubmitOrder(t *testing.T) { - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip(fmt.Sprintf("Can place orders: %v", canManipulateRealOrders)) } @@ -305,18 +309,18 @@ func TestSubmitOrder(t *testing.T) { AssetType: asset.Spot, } response, err := z.SubmitOrder(context.Background(), orderSubmission) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } - if z.ValidateAPICredentials() && response.OrderID == "" { + if areTestAPIKeysSet() && response.OrderID == "" { t.Error("expected order id") } } func TestCancelExchangeOrder(t *testing.T) { - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } if mockTests { @@ -333,15 +337,15 @@ func TestCancelExchangeOrder(t *testing.T) { } err := z.CancelOrder(context.Background(), orderCancellation) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } func TestCancelAllExchangeOrders(t *testing.T) { - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } if mockTests { @@ -359,9 +363,9 @@ func TestCancelAllExchangeOrders(t *testing.T) { resp, err := z.CancelAllOrders(context.Background(), orderCancellation) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } if len(resp.Status) > 0 { @@ -373,7 +377,7 @@ func TestGetAccountInfo(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() { + if areTestAPIKeysSet() { _, err := z.UpdateAccountInfo(context.Background(), asset.Spot) if err != nil { t.Error("GetAccountInfo() error", err) @@ -390,7 +394,7 @@ func TestModifyOrder(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } _, err := z.ModifyOrder(context.Background(), @@ -404,7 +408,7 @@ func TestWithdraw(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -421,9 +425,9 @@ func TestWithdraw(t *testing.T) { _, err := z.WithdrawCryptocurrencyFunds(context.Background(), &withdrawCryptoRequest) - if z.ValidateAPICredentials() && err != nil { + if areTestAPIKeysSet() && err != nil { t.Error(err) - } else if !z.ValidateAPICredentials() && err == nil { + } else if !areTestAPIKeysSet() && err == nil { t.Error("expecting an error when no keys are set") } } @@ -432,7 +436,7 @@ func TestWithdrawFiat(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -447,7 +451,7 @@ func TestWithdrawInternationalBank(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() && !canManipulateRealOrders { + if areTestAPIKeysSet() && !canManipulateRealOrders { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } @@ -463,7 +467,7 @@ func TestGetDepositAddress(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() { + if areTestAPIKeysSet() { _, err := z.GetDepositAddress(context.Background(), currency.XRP, "", "") if err != nil { t.Error("GetDepositAddress() error PLEASE MAKE SURE YOU CREATE DEPOSIT ADDRESSES VIA ZB.COM", @@ -481,7 +485,7 @@ func TestGetMultiChainDepositAddress(t *testing.T) { if mockTests { t.Skip("skipping authenticated function for mock testing") } - if z.ValidateAPICredentials() { + if areTestAPIKeysSet() { _, err := z.GetMultiChainDepositAddress(context.Background(), currency.USDT) if err != nil { t.Error("GetDepositAddress() error PLEASE MAKE SURE YOU CREATE DEPOSIT ADDRESSES VIA ZB.COM", @@ -521,7 +525,7 @@ func TestZBInvalidJSON(t *testing.T) { // TestWsTransferFunds ws test func TestWsTransferFunds(t *testing.T) { setupWsAuth(t) - _, err := z.wsDoTransferFunds(currency.BTC, + _, err := z.wsDoTransferFunds(context.Background(), currency.BTC, 0.0001, "username1", "username2", @@ -534,7 +538,7 @@ func TestWsTransferFunds(t *testing.T) { // TestGetSubUserList ws test func TestGetSubUserList(t *testing.T) { setupWsAuth(t) - if _, err := z.wsGetSubUserList(); err != nil { + if _, err := z.wsGetSubUserList(context.Background()); err != nil { t.Fatal(err) } } @@ -542,7 +546,7 @@ func TestGetSubUserList(t *testing.T) { // TestAddSubUser ws test func TestAddSubUser(t *testing.T) { setupWsAuth(t) - _, err := z.wsAddSubUser("1", "123456789101112aA!") + _, err := z.wsAddSubUser(context.Background(), "1", "123456789101112aA!") if err != nil { t.Fatal(err) } @@ -551,7 +555,7 @@ func TestAddSubUser(t *testing.T) { // TestWsCreateSuUserKey ws test func TestWsCreateSuUserKey(t *testing.T) { setupWsAuth(t) - subUsers, err := z.wsGetSubUserList() + subUsers, err := z.wsGetSubUserList(context.Background()) if err != nil { t.Fatal(err) } @@ -559,7 +563,8 @@ func TestWsCreateSuUserKey(t *testing.T) { t.Skip("User ID required for test to continue. Create a subuser first") } userID := subUsers.Message[0].UserID - _, err = z.wsCreateSubUserKey(true, true, true, true, "subu", strconv.FormatInt(userID, 10)) + _, err = z.wsCreateSubUserKey(context.Background(), + true, true, true, true, "subu", strconv.FormatInt(userID, 10)) if err != nil { t.Fatal(err) } @@ -568,7 +573,8 @@ func TestWsCreateSuUserKey(t *testing.T) { // TestWsSubmitOrder ws test func TestWsSubmitOrder(t *testing.T) { setupWsAuth(t) - _, err := z.wsSubmitOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1, 1) + _, err := z.wsSubmitOrder(context.Background(), + currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1, 1) if err != nil { t.Fatal(err) } @@ -577,7 +583,8 @@ func TestWsSubmitOrder(t *testing.T) { // TestWsCancelOrder ws test func TestWsCancelOrder(t *testing.T) { setupWsAuth(t) - _, err := z.wsCancelOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) + _, err := z.wsCancelOrder(context.Background(), + currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) if err != nil { t.Fatal(err) } @@ -586,7 +593,7 @@ func TestWsCancelOrder(t *testing.T) { // TestWsGetAccountInfo ws test func TestWsGetAccountInfo(t *testing.T) { setupWsAuth(t) - _, err := z.wsGetAccountInfoRequest() + _, err := z.wsGetAccountInfoRequest(context.Background()) if err != nil { t.Fatal(err) } @@ -595,7 +602,8 @@ func TestWsGetAccountInfo(t *testing.T) { // TestWsGetOrder ws test func TestWsGetOrder(t *testing.T) { setupWsAuth(t) - _, err := z.wsGetOrder(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) + _, err := z.wsGetOrder(context.Background(), + currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1234) if err != nil { t.Fatal(err) } @@ -604,7 +612,8 @@ func TestWsGetOrder(t *testing.T) { // TestWsGetOrders ws test func TestWsGetOrders(t *testing.T) { setupWsAuth(t) - _, err := z.wsGetOrders(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) + _, err := z.wsGetOrders(context.Background(), + currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) if err != nil { t.Fatal(err) } @@ -613,7 +622,8 @@ func TestWsGetOrders(t *testing.T) { // TestWsGetOrdersIgnoreTradeType ws test func TestWsGetOrdersIgnoreTradeType(t *testing.T) { setupWsAuth(t) - _, err := z.wsGetOrdersIgnoreTradeType(currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) + _, err := z.wsGetOrdersIgnoreTradeType(context.Background(), + currency.NewPairWithDelimiter(currency.LTC.String(), currency.BTC.String(), "").Lower(), 1, 1) if err != nil { t.Fatal(err) } @@ -1066,7 +1076,7 @@ func TestUpdateTickers(t *testing.T) { func TestGetAvailableTransferChains(t *testing.T) { t.Parallel() - if !z.ValidateAPICredentials() { + if !areTestAPIKeysSet() { t.Skip("api keys not set") } _, err := z.GetAvailableTransferChains(context.Background(), currency.BTC) diff --git a/exchanges/zb/zb_websocket.go b/exchanges/zb/zb_websocket.go index df7e454bd5a..aeb3d8a29f8 100644 --- a/exchanges/zb/zb_websocket.go +++ b/exchanges/zb/zb_websocket.go @@ -1,6 +1,7 @@ package zb import ( + "context" "encoding/json" "errors" "fmt" @@ -299,12 +300,12 @@ func (z *ZB) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error { return nil } -func (z *ZB) wsGenerateSignature(request interface{}) (string, error) { +func (z *ZB) wsGenerateSignature(secret string, request interface{}) (string, error) { jsonResponse, err := json.Marshal(request) if err != nil { return "", err } - hex, err := crypto.Sha1ToHex(z.API.Credentials.Secret) + hex, err := crypto.Sha1ToHex(secret) if err != nil { return "", err } @@ -331,10 +332,14 @@ func (z *ZB) wsFixInvalidJSON(json []byte) []byte { return []byte(strings.Replace(string(json), string(matchingResults), fixedJSON, 1)) } -func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse, error) { +func (z *ZB) wsAddSubUser(ctx context.Context, username, password string) (*WsGetSubUserListResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } request := WsAddSubUserRequest{ Memo: "memo", Password: password, @@ -342,11 +347,10 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse, } request.Channel = "addSubUser" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key + request.Accesskey = creds.Key request.No = z.Websocket.Conn.GenerateMessageID(true) - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -374,19 +378,22 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse, return &response, nil } -func (z *ZB) wsGetSubUserList() (*WsGetSubUserListResponse, error) { +func (z *ZB) wsGetSubUserList(ctx context.Context) (*WsGetSubUserListResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } request := WsAuthenticatedRequest{} request.Channel = "getSubUserList" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key + request.Accesskey = creds.Key request.No = z.Websocket.Conn.GenerateMessageID(true) - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -410,11 +417,16 @@ func (z *ZB) wsGetSubUserList() (*WsGetSubUserListResponse, error) { return &response, nil } -func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName, toUserName string) (*WsRequestResponse, error) { +func (z *ZB) wsDoTransferFunds(ctx context.Context, pair currency.Code, amount float64, fromUserName, toUserName string) (*WsRequestResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } + request := WsDoTransferFundsRequest{ Amount: amount, Currency: pair, @@ -424,10 +436,8 @@ func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName, } request.Channel = "doTransferFunds" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key - - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Accesskey = creds.Key + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -451,11 +461,15 @@ func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName, return &response, nil } -func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm bool, keyName, toUserID string) (*WsRequestResponse, error) { +func (z *ZB) wsCreateSubUserKey(ctx context.Context, assetPerm, entrustPerm, leverPerm, moneyPerm bool, keyName, toUserID string) (*WsRequestResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } request := WsCreateSubUserKeyRequest{ AssetPerm: assetPerm, EntrustPerm: entrustPerm, @@ -467,10 +481,9 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo } request.Channel = "createSubUserKey" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key + request.Accesskey = creds.Key - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -494,11 +507,15 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo return &response, nil } -func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType int64) (*WsSubmitOrderResponse, error) { +func (z *ZB) wsSubmitOrder(ctx context.Context, pair currency.Pair, amount, price float64, tradeType int64) (*WsSubmitOrderResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } request := WsSubmitOrderRequest{ Amount: amount, Price: price, @@ -507,10 +524,8 @@ func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType } request.Channel = pair.String() + "_order" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key - - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Accesskey = creds.Key + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -534,21 +549,25 @@ func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType return &response, nil } -func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) (*WsCancelOrderResponse, error) { +func (z *ZB) wsCancelOrder(ctx context.Context, pair currency.Pair, orderID int64) (*WsCancelOrderResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } + request := WsCancelOrderRequest{ ID: orderID, No: z.Websocket.Conn.GenerateMessageID(true), } request.Channel = pair.String() + "_cancelorder" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key + request.Accesskey = creds.Key - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -572,21 +591,23 @@ func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) (*WsCancelOrderRes return &response, nil } -func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) (*WsGetOrderResponse, error) { +func (z *ZB) wsGetOrder(ctx context.Context, pair currency.Pair, orderID int64) (*WsGetOrderResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } request := WsGetOrderRequest{ ID: orderID, No: z.Websocket.Conn.GenerateMessageID(true), } request.Channel = pair.String() + "_getorder" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key - - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Accesskey = creds.Key + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -610,11 +631,16 @@ func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) (*WsGetOrderResponse, return &response, nil } -func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGetOrdersResponse, error) { +func (z *ZB) wsGetOrders(ctx context.Context, pair currency.Pair, pageIndex, tradeType int64) (*WsGetOrdersResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } + request := WsGetOrdersRequest{ PageIndex: pageIndex, TradeType: tradeType, @@ -622,10 +648,9 @@ func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGet } request.Channel = pair.String() + "_getorders" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key + request.Accesskey = creds.Key - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -649,11 +674,16 @@ func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGet return &response, nil } -func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize int64) (*WsGetOrdersIgnoreTradeTypeResponse, error) { +func (z *ZB) wsGetOrdersIgnoreTradeType(ctx context.Context, pair currency.Pair, pageIndex, pageSize int64) (*WsGetOrdersIgnoreTradeTypeResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } + request := WsGetOrdersIgnoreTradeTypeRequest{ PageIndex: pageIndex, PageSize: pageSize, @@ -661,10 +691,8 @@ func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize } request.Channel = pair.String() + "_getordersignoretradetype" request.Event = zWebsocketAddChannel - request.Accesskey = z.API.Credentials.Key - - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Accesskey = creds.Key + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } @@ -688,20 +716,24 @@ func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize return &response, nil } -func (z *ZB) wsGetAccountInfoRequest() (*WsGetAccountInfoResponse, error) { +func (z *ZB) wsGetAccountInfoRequest(ctx context.Context) (*WsGetAccountInfoResponse, error) { if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) { return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name) } + creds, err := z.GetCredentials(ctx) + if err != nil { + return nil, err + } + request := WsAuthenticatedRequest{ Channel: "getaccountinfo", Event: zWebsocketAddChannel, - Accesskey: z.API.Credentials.Key, + Accesskey: creds.Key, No: z.Websocket.Conn.GenerateMessageID(true), } - var err error - request.Sign, err = z.wsGenerateSignature(request) + request.Sign, err = z.wsGenerateSignature(creds.Secret, request) if err != nil { return nil, err } diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index e278a2d102c..2325ab2139a 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -357,7 +357,7 @@ func (z *ZB) UpdateAccountInfo(ctx context.Context, assetType asset.Item) (accou var balances []account.Balance var coins []AccountsResponseCoin if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() { - resp, err := z.wsGetAccountInfoRequest() + resp, err := z.wsGetAccountInfoRequest(ctx) if err != nil { return info, err } @@ -483,7 +483,7 @@ func (z *ZB) SubmitOrder(ctx context.Context, o *order.Submit) (order.SubmitResp isBuyOrder = 0 } var response *WsSubmitOrderResponse - response, err = z.wsSubmitOrder(o.Pair, o.Amount, o.Price, isBuyOrder) + response, err = z.wsSubmitOrder(ctx, o.Pair, o.Amount, o.Price, isBuyOrder) if err != nil { return submitOrderResponse, err } @@ -542,7 +542,7 @@ func (z *ZB) CancelOrder(ctx context.Context, o *order.Cancel) error { if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() { var response *WsCancelOrderResponse - response, err = z.wsCancelOrder(o.Pair, orderIDInt) + response, err = z.wsCancelOrder(ctx, o.Pair, orderIDInt) if err != nil { return err } @@ -694,7 +694,7 @@ func (z *ZB) GetFeeByType(ctx context.Context, feeBuilder *exchange.FeeBuilder) if feeBuilder == nil { return 0, fmt.Errorf("%T %w", feeBuilder, common.ErrNilPointer) } - if (!z.AllowAuthenticatedRequest() || z.SkipAuthCheck) && // Todo check connection status + if (!z.AreCredentialsValid(ctx) || z.SkipAuthCheck) && // Todo check connection status feeBuilder.FeeType == exchange.CryptocurrencyTradeFee { feeBuilder.FeeType = exchange.OfflineTradeFee } @@ -785,7 +785,7 @@ func (z *ZB) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest) ( if z.Websocket.CanUseAuthenticatedWebsocketForWrapper() { for x := range req.Pairs { for y := int64(1); ; y++ { - resp, err := z.wsGetOrdersIgnoreTradeType(req.Pairs[x], y, 10) + resp, err := z.wsGetOrdersIgnoreTradeType(ctx, req.Pairs[x], y, 10) if err != nil { return nil, err } diff --git a/gctrpc/rpc.pb.go b/gctrpc/rpc.pb.go index 34f0bd3787d..2dc595f1d89 100644 --- a/gctrpc/rpc.pb.go +++ b/gctrpc/rpc.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.27.1 -// protoc v3.15.1 +// protoc-gen-go v1.26.0 +// protoc v3.11.2 // source: rpc.proto package gctrpc @@ -11089,10 +11089,9 @@ type GetCollateralRequest struct { Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"` Asset string `protobuf:"bytes,2,opt,name=asset,proto3" json:"asset,omitempty"` - SubAccount string `protobuf:"bytes,3,opt,name=sub_account,json=subAccount,proto3" json:"sub_account,omitempty"` - IncludeBreakdown bool `protobuf:"varint,4,opt,name=include_breakdown,json=includeBreakdown,proto3" json:"include_breakdown,omitempty"` - CalculateOffline bool `protobuf:"varint,5,opt,name=calculate_offline,json=calculateOffline,proto3" json:"calculate_offline,omitempty"` - IncludeZeroValues bool `protobuf:"varint,6,opt,name=include_zero_values,json=includeZeroValues,proto3" json:"include_zero_values,omitempty"` + IncludeBreakdown bool `protobuf:"varint,3,opt,name=include_breakdown,json=includeBreakdown,proto3" json:"include_breakdown,omitempty"` + CalculateOffline bool `protobuf:"varint,4,opt,name=calculate_offline,json=calculateOffline,proto3" json:"calculate_offline,omitempty"` + IncludeZeroValues bool `protobuf:"varint,5,opt,name=include_zero_values,json=includeZeroValues,proto3" json:"include_zero_values,omitempty"` } func (x *GetCollateralRequest) Reset() { @@ -11141,13 +11140,6 @@ func (x *GetCollateralRequest) GetAsset() string { return "" } -func (x *GetCollateralRequest) GetSubAccount() string { - if x != nil { - return x.SubAccount - } - return "" -} - func (x *GetCollateralRequest) GetIncludeBreakdown() bool { if x != nil { return x.IncludeBreakdown @@ -13236,867 +13228,864 @@ var file_rpc_proto_rawDesc = []byte{ 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x6f, 0x73, 0x69, 0x6e, 0x67, 0x44, 0x61, 0x74, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x22, 0xf3, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x22, 0xd2, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x75, 0x62, - 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x73, 0x75, 0x62, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x61, 0x6c, 0x63, 0x75, - 0x6c, 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x10, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x66, 0x66, - 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x7a, 0x65, 0x72, 0x6f, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5a, 0x65, 0x72, 0x6f, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x73, 0x22, 0xbd, 0x05, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, - 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, - 0x2f, 0x0a, 0x13, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, - 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, - 0x12, 0x4f, 0x0a, 0x25, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, - 0x6f, 0x66, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x6f, 0x74, - 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x20, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x66, 0x50, 0x6f, 0x73, - 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x6f, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x12, 0x65, 0x0a, 0x30, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x70, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x62, 0x61, 0x6c, - 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x2b, 0x63, 0x6f, 0x6c, - 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x64, 0x42, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x6f, 0x74, - 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x64, - 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, - 0x6c, 0x12, 0x46, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, - 0x6f, 0x77, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, - 0x64, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x64, - 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x61, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, - 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x35, 0x0a, 0x16, - 0x6d, 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, - 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6d, 0x61, - 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, - 0x72, 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x6c, 0x69, 0x73, 0x65, - 0x64, 0x50, 0x4e, 0x4c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x75, 0x6e, 0x72, 0x65, - 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x50, 0x4e, 0x4c, 0x12, 0x4c, 0x0a, 0x12, 0x63, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, - 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x52, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x72, - 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x4b, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6c, - 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x11, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x65, 0x61, 0x6b, - 0x64, 0x6f, 0x77, 0x6e, 0x22, 0xf7, 0x04, 0x0a, 0x15, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, - 0x72, 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, - 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, - 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x65, 0x78, - 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, - 0x65, 0x72, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x75, - 0x6e, 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x6f, - 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, - 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x41, - 0x73, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x37, 0x0a, 0x18, 0x61, - 0x70, 0x70, 0x72, 0x6f, 0x78, 0x5f, 0x66, 0x61, 0x69, 0x72, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, - 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x61, - 0x70, 0x70, 0x72, 0x6f, 0x78, 0x46, 0x61, 0x69, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, - 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x69, - 0x6e, 0x67, 0x12, 0x37, 0x0a, 0x17, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x73, - 0x63, 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x54, - 0x6f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x72, - 0x65, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x50, 0x4e, 0x4c, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x50, 0x4e, 0x4c, - 0x12, 0x20, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x49, 0x6e, 0x55, - 0x73, 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x64, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x61, 0x6c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, + 0x28, 0x09, 0x52, 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x69, 0x6e, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x42, 0x72, 0x65, + 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, + 0x61, 0x74, 0x65, 0x5f, 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x10, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x66, 0x66, 0x6c, + 0x69, 0x6e, 0x65, 0x12, 0x2e, 0x0a, 0x13, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x7a, + 0x65, 0x72, 0x6f, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x11, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5a, 0x65, 0x72, 0x6f, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x73, 0x22, 0xbd, 0x05, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, + 0x74, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x75, 0x62, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x73, 0x75, 0x62, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f, + 0x0a, 0x13, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6f, 0x6c, + 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, + 0x4f, 0x0a, 0x25, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x6f, + 0x66, 0x5f, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, + 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x20, + 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x66, 0x50, 0x6f, 0x73, 0x69, + 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x6f, 0x74, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x12, 0x65, 0x0a, 0x30, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x5f, 0x70, 0x6f, + 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x62, 0x61, 0x6c, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x2b, 0x63, 0x6f, 0x6c, 0x6c, + 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x64, 0x42, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x53, 0x70, 0x6f, 0x74, 0x42, + 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x64, 0x5f, + 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x75, 0x73, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x46, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, - 0x77, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x77, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x64, 0x42, - 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x8f, - 0x02, 0x0a, 0x14, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x79, 0x50, - 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, 0x5f, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, - 0x23, 0x0a, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, - 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, - 0x69, 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, - 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x12, 0x32, 0x0a, 0x15, - 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, - 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, - 0x22, 0xae, 0x03, 0x0a, 0x17, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, - 0x73, 0x65, 0x64, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x28, 0x0a, 0x10, - 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, - 0x53, 0x74, 0x61, 0x6b, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, - 0x5f, 0x69, 0x6e, 0x5f, 0x4e, 0x46, 0x54, 0x5f, 0x62, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x4e, 0x46, 0x54, 0x42, - 0x69, 0x64, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, - 0x5f, 0x66, 0x65, 0x65, 0x5f, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x46, 0x65, 0x65, 0x56, - 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x24, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, - 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, - 0x66, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x1f, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, - 0x6f, 0x74, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, - 0x66, 0x66, 0x65, 0x72, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, - 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, - 0x6f, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x6f, 0x63, 0x6b, - 0x65, 0x64, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x41, 0x73, - 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, - 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x07, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x64, 0x49, 0x6e, 0x46, 0x75, 0x74, 0x75, 0x72, - 0x65, 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, - 0x6f, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x10, 0x75, 0x73, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, 0x6f, 0x74, 0x4d, 0x61, 0x72, 0x67, 0x69, - 0x6e, 0x32, 0x83, 0x59, 0x0a, 0x0e, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72, - 0x61, 0x64, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, - 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, - 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, - 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x53, 0x75, 0x73, 0x62, 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x68, - 0x0a, 0x0f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, - 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x73, - 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6a, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, - 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, - 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, - 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x72, 0x70, 0x63, 0x65, 0x6e, 0x64, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, - 0x72, 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, - 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, - 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, - 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, - 0x12, 0x6e, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, - 0x73, 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, - 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x12, 0x73, 0x0a, 0x13, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, - 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x73, - 0x12, 0x6c, 0x0a, 0x0e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x31, 0x0a, 0x14, 0x61, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, + 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x35, 0x0a, 0x16, 0x6d, + 0x61, 0x69, 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, + 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x6d, 0x61, 0x69, + 0x6e, 0x74, 0x65, 0x6e, 0x61, 0x6e, 0x63, 0x65, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, + 0x61, 0x6c, 0x12, 0x24, 0x0a, 0x0d, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, + 0x50, 0x4e, 0x4c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x75, 0x6e, 0x72, 0x65, 0x61, + 0x6c, 0x69, 0x73, 0x65, 0x64, 0x50, 0x4e, 0x4c, 0x12, 0x4c, 0x0a, 0x12, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x0a, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, + 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x63, 0x79, 0x52, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x42, 0x72, 0x65, + 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x4b, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x18, 0x0b, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6c, 0x6c, + 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x79, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x11, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, + 0x6f, 0x77, 0x6e, 0x22, 0xf7, 0x04, 0x0a, 0x15, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, + 0x61, 0x6c, 0x46, 0x6f, 0x72, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, 0x0a, + 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x38, 0x0a, 0x18, 0x65, 0x78, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, + 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x16, 0x65, 0x78, 0x63, + 0x6c, 0x75, 0x64, 0x65, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, + 0x72, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x66, 0x75, 0x6e, + 0x64, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x46, + 0x75, 0x6e, 0x64, 0x73, 0x12, 0x44, 0x0a, 0x1f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x6c, + 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x46, 0x6f, 0x72, 0x55, 0x73, 0x65, 0x41, 0x73, + 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x37, 0x0a, 0x18, 0x61, 0x70, + 0x70, 0x72, 0x6f, 0x78, 0x5f, 0x66, 0x61, 0x69, 0x72, 0x5f, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x61, 0x70, + 0x70, 0x72, 0x6f, 0x78, 0x46, 0x61, 0x69, 0x72, 0x4d, 0x61, 0x72, 0x6b, 0x65, 0x74, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, 0x67, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x69, 0x6e, + 0x67, 0x12, 0x37, 0x0a, 0x17, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x16, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x43, 0x6f, + 0x6e, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x63, + 0x61, 0x6c, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x64, 0x54, 0x6f, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x75, 0x6e, 0x72, 0x65, + 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x5f, 0x50, 0x4e, 0x4c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0d, 0x75, 0x6e, 0x72, 0x65, 0x61, 0x6c, 0x69, 0x73, 0x65, 0x64, 0x50, 0x4e, 0x4c, 0x12, + 0x20, 0x0a, 0x0c, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x75, 0x73, 0x65, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x49, 0x6e, 0x55, 0x73, + 0x65, 0x12, 0x3c, 0x0a, 0x1a, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, + 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x18, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, 0x12, + 0x46, 0x0a, 0x0e, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, + 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, 0x42, + 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x64, 0x42, 0x72, + 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x8f, 0x02, + 0x0a, 0x14, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x79, 0x50, 0x6f, + 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x6f, 0x70, 0x65, 0x6e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x23, + 0x0a, 0x0d, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x53, + 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6d, 0x61, 0x72, 0x6b, 0x5f, 0x70, 0x72, 0x69, 0x63, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6d, 0x61, 0x72, 0x6b, 0x50, 0x72, 0x69, + 0x63, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x6d, + 0x61, 0x72, 0x67, 0x69, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x64, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x12, 0x32, 0x0a, 0x15, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x5f, + 0x75, 0x73, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x64, 0x22, + 0xae, 0x03, 0x0a, 0x17, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x55, 0x73, + 0x65, 0x64, 0x42, 0x72, 0x65, 0x61, 0x6b, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x28, 0x0a, 0x10, 0x6c, + 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x6b, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x53, + 0x74, 0x61, 0x6b, 0x65, 0x73, 0x12, 0x2b, 0x0a, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, + 0x69, 0x6e, 0x5f, 0x4e, 0x46, 0x54, 0x5f, 0x62, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0f, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x4e, 0x46, 0x54, 0x42, 0x69, + 0x64, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, + 0x66, 0x65, 0x65, 0x5f, 0x76, 0x6f, 0x75, 0x63, 0x68, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x46, 0x65, 0x65, 0x56, 0x6f, + 0x75, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4d, 0x0a, 0x24, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, + 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x66, + 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x1f, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, 0x6f, + 0x74, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x46, 0x75, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x4f, 0x66, + 0x66, 0x65, 0x72, 0x73, 0x12, 0x31, 0x0a, 0x15, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, + 0x6e, 0x5f, 0x73, 0x70, 0x6f, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, 0x6f, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6c, 0x6f, 0x63, 0x6b, 0x65, + 0x64, 0x5f, 0x61, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6c, 0x6f, 0x63, 0x6b, 0x65, 0x64, 0x41, 0x73, 0x43, + 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x75, 0x73, 0x65, + 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x66, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x75, 0x73, 0x65, 0x64, 0x49, 0x6e, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, + 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x75, 0x73, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x73, 0x70, 0x6f, + 0x74, 0x5f, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, + 0x75, 0x73, 0x65, 0x64, 0x49, 0x6e, 0x53, 0x70, 0x6f, 0x74, 0x4d, 0x61, 0x72, 0x67, 0x69, 0x6e, + 0x32, 0x83, 0x59, 0x0a, 0x0e, 0x47, 0x6f, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72, 0x61, + 0x64, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, + 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, + 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x53, 0x75, 0x73, 0x62, 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, + 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x68, 0x0a, + 0x0f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, + 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, + 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, + 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6a, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62, + 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, + 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, + 0x74, 0x65, 0x6d, 0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, + 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x72, 0x70, 0x63, 0x65, 0x6e, 0x64, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, + 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, + 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, + 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, + 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, + 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, + 0x6e, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x57, - 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, - 0x63, 0x6b, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x69, - 0x63, 0x6b, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x62, 0x6f, 0x6f, 0x6b, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x15, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, - 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, - 0x6b, 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, - 0x71, 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, - 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, - 0x66, 0x6f, 0x12, 0x79, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, + 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, + 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, + 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, + 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, + 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x12, 0x73, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, + 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, + 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x73, 0x12, + 0x6c, 0x0a, 0x0e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, + 0x09, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, + 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, + 0x6b, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, + 0x6b, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, + 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, + 0x6f, 0x6f, 0x6b, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, + 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x15, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, + 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, + 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x71, + 0x0a, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, + 0x6f, 0x12, 0x79, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x57, 0x0a, - 0x09, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, - 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x7f, 0x0a, 0x13, 0x47, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, + 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x69, 0x6e, 0x66, 0x6f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x09, + 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, + 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x7f, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, + 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, - 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, - 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, - 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x76, 0x0a, 0x13, - 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, - 0x65, 0x73, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, - 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, - 0x64, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, - 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, - 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, - 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x66, 0x6f, 0x72, 0x65, 0x78, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x67, - 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, - 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, - 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, - 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, - 0x65, 0x78, 0x72, 0x61, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, + 0x6f, 0x6c, 0x69, 0x6f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x76, 0x0a, 0x13, 0x41, + 0x64, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x50, + 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, + 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x3a, 0x01, 0x2a, 0x12, 0x7f, 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, + 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, + 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, + 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, + 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, + 0x6f, 0x72, 0x65, 0x78, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x67, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, + 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, + 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, + 0x78, 0x72, 0x61, 0x74, 0x65, 0x73, 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, + 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, + 0x01, 0x2a, 0x12, 0x52, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, - 0x3a, 0x01, 0x2a, 0x12, 0x52, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, - 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x17, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x62, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, - 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, - 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0d, 0x53, - 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x09, 0x57, 0x68, 0x61, 0x6c, 0x65, - 0x42, 0x6f, 0x6d, 0x62, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x68, - 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x68, 0x61, 0x6c, 0x65, - 0x62, 0x6f, 0x6d, 0x62, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x17, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x62, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x75, 0x62, 0x6d, + 0x69, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x69, + 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, + 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x09, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, + 0x6f, 0x6d, 0x62, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x68, 0x61, + 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x62, + 0x6f, 0x6d, 0x62, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x7a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, + 0x6e, 0x63, 0x65, 0x6c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, + 0x01, 0x2a, 0x12, 0x72, 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, + 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x61, 0x6c, 0x6c, 0x6f, 0x72, 0x64, + 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, + 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x56, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x52, 0x65, 0x6d, 0x6f, 0x76, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6f, - 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x7a, 0x0a, 0x11, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x42, 0x61, 0x74, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x61, 0x74, 0x63, - 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x61, - 0x74, 0x63, 0x68, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x63, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, - 0x3a, 0x01, 0x2a, 0x12, 0x72, 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, - 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x61, 0x6c, 0x6c, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x56, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, - 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x5e, 0x0a, 0x0b, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, - 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, - 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, - 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x30, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x31, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, - 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, - 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x76, 0x31, - 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, - 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xaa, 0x01, - 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x2e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, - 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, - 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, + 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0xb2, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, + 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, + 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x30, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x31, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, + 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, + 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9e, 0x01, 0x0a, 0x1a, 0x47, - 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, - 0x66, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0xaa, 0x01, 0x0a, + 0x1f, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x2e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, + 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, + 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, + 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x67, + 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9e, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, - 0x74, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, - 0x65, 0x72, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6c, 0x0a, 0x11, 0x57, - 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, - 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, - 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, - 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x66, 0x69, 0x61, - 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x8b, 0x01, 0x0a, 0x1b, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x79, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, - 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x63, - 0x72, 0x79, 0x70, 0x74, 0x6f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, - 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, - 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, - 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, - 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, - 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x97, 0x01, 0x0a, - 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, + 0x72, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, + 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, + 0x72, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6c, 0x0a, 0x11, 0x57, 0x69, + 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, + 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, + 0x77, 0x46, 0x69, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x22, 0x15, + 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x66, 0x69, 0x61, 0x74, + 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x8b, 0x01, 0x0a, 0x1b, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x63, 0x79, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x28, 0x2f, 0x76, 0x31, 0x2f, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x6f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, 0x75, + 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, + 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x12, 0x22, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, + 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, + 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x97, 0x01, 0x0a, 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, - 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x91, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, - 0x65, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, - 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x76, - 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x62, 0x79, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, + 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, + 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, + 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x91, 0x01, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65, + 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, + 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x19, 0x2f, 0x76, 0x31, + 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x62, 0x79, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, + 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, - 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, - 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, - 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, - 0x76, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, - 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, - 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, - 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x78, - 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, + 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, + 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x76, + 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x4c, + 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, + 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61, + 0x69, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x76, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, + 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, - 0x6a, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, - 0x69, 0x72, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x12, 0x47, - 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, - 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, - 0x01, 0x12, 0x8c, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, + 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x6a, + 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, + 0x72, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x12, 0x47, 0x65, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, + 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, - 0x12, 0x68, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, - 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47, + 0x12, 0x8c, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, + 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x72, + 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, + 0x68, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, + 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b, 0x65, + 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47, 0x65, + 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, - 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, - 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x67, 0x0a, - 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x0f, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, - 0x12, 0x78, 0x0a, 0x13, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, - 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x43, - 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b, 0x2f, + 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, 0x69, + 0x63, 0x6b, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x67, 0x0a, 0x0d, + 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x0f, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, + 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, + 0x78, 0x0a, 0x13, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, + 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x70, 0x0a, 0x0f, 0x47, 0x43, 0x54, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x6c, 0x0a, 0x0e, 0x47, + 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x6c, 0x0a, 0x0e, - 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1d, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x0d, 0x47, 0x43, 0x54, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, + 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, + 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, + 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, + 0x70, 0x41, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, + 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, + 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, + 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, + 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, + 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, + 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x65, 0x0a, 0x0d, 0x47, 0x43, - 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x1c, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, - 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, - 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, - 0x2a, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, - 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x73, - 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, - 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, - 0x3a, 0x01, 0x2a, 0x12, 0x77, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x12, 0x20, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, - 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1b, 0x22, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x2f, 0x61, 0x75, 0x74, 0x6f, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x7b, 0x0a, 0x12, - 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x73, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, + 0x22, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, + 0x61, 0x75, 0x74, 0x6f, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x7b, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x69, 0x63, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x10, 0x53, 0x65, 0x74, - 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x1f, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, - 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x61, 0x73, 0x73, 0x65, 0x74, 0x12, 0x73, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x22, 0x2e, 0x67, + 0x73, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, + 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, + 0x63, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x45, + 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, - 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x1c, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x75, 0x70, - 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x77, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, - 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, - 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x73, - 0x73, 0x65, 0x74, 0x73, 0x12, 0x73, 0x0a, 0x10, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, - 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, - 0x65, 0x74, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x13, 0x57, 0x65, 0x62, - 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, - 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x97, - 0x01, 0x0a, 0x19, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, - 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, - 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x57, 0x65, 0x62, 0x73, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x20, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, - 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, + 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, + 0x73, 0x73, 0x65, 0x74, 0x12, 0x73, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x41, 0x6c, 0x6c, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, - 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, - 0x65, 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x67, 0x0a, 0x0f, 0x57, 0x65, 0x62, 0x73, 0x6f, - 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, - 0x55, 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, - 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x75, 0x72, 0x6c, - 0x12, 0x69, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, - 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, - 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, - 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x47, - 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, - 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, - 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, - 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x0e, 0x47, 0x65, - 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, - 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, - 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, - 0x61, 0x64, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, - 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, - 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, - 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1c, 0x12, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x74, - 0x72, 0x61, 0x64, 0x65, 0x73, 0x74, 0x6f, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x9d, - 0x01, 0x0a, 0x1f, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, - 0x76, 0x65, 0x64, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, - 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, - 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, 0x72, - 0x69, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, - 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x66, - 0x69, 0x6e, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x63, - 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x9a, - 0x01, 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, - 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, - 0x73, 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, - 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, - 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x2a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, - 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, - 0x64, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x1a, - 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, - 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, - 0x72, 0x61, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, - 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x63, - 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x86, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x12, - 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, - 0x73, 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, - 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1d, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x70, 0x73, 0x65, 0x72, 0x74, 0x64, 0x61, - 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x3a, 0x01, 0x2a, 0x12, - 0x81, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, - 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x22, 0x24, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x64, 0x61, - 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x64, 0x65, 0x74, 0x61, - 0x69, 0x6c, 0x73, 0x12, 0x71, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, - 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x12, - 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, + 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x8e, 0x01, 0x0a, 0x1c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, - 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, - 0x74, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x44, 0x61, - 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x42, 0x65, 0x74, - 0x77, 0x65, 0x65, 0x6e, 0x12, 0x28, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, - 0x42, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, - 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, - 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x12, 0x81, + 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x75, 0x70, 0x70, + 0x6f, 0x72, 0x74, 0x65, 0x64, 0x70, 0x61, 0x69, 0x72, 0x73, 0x12, 0x77, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x12, + 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, + 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x73, 0x12, 0x73, 0x0a, 0x10, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, + 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, + 0x74, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x13, 0x57, 0x65, 0x62, 0x73, + 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, + 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, + 0x65, 0x74, 0x53, 0x65, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x97, 0x01, + 0x0a, 0x19, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, + 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x28, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, + 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, + 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, + 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x57, 0x65, 0x62, 0x73, 0x6f, + 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x20, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, + 0x65, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, + 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, + 0x74, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x67, 0x0a, 0x0f, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, + 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, 0x52, 0x4c, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x57, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x53, 0x65, 0x74, 0x55, + 0x52, 0x4c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, + 0x77, 0x65, 0x62, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x74, 0x75, 0x72, 0x6c, 0x12, + 0x69, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x52, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x61, 0x64, + 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, + 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, + 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x6d, 0x0a, 0x11, 0x47, 0x65, + 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, + 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, + 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, + 0x64, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x30, 0x01, 0x12, 0x68, 0x0a, 0x0e, 0x47, 0x65, 0x74, + 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x12, 0x1d, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, + 0x64, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, + 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, + 0x64, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, + 0x72, 0x61, 0x64, 0x65, 0x73, 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x25, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x54, + 0x72, 0x61, 0x64, 0x65, 0x73, 0x54, 0x6f, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1c, 0x12, 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x74, 0x72, + 0x61, 0x64, 0x65, 0x73, 0x74, 0x6f, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x12, 0x9d, 0x01, + 0x0a, 0x1f, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x76, + 0x65, 0x64, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, + 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x69, + 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x2b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x25, 0x12, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, + 0x6e, 0x64, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x63, 0x61, + 0x6e, 0x64, 0x6c, 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x9a, 0x01, + 0x0a, 0x1e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x76, + 0x65, 0x64, 0x54, 0x72, 0x61, 0x64, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, + 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, + 0x73, 0x73, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x46, 0x69, 0x6e, 0x64, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x49, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x24, 0x12, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x69, 0x6e, 0x64, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x73, 0x61, 0x76, 0x65, 0x64, 0x74, 0x72, 0x61, 0x64, + 0x65, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x88, 0x01, 0x0a, 0x1a, 0x53, + 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x72, 0x61, 0x64, 0x65, 0x50, + 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x72, + 0x61, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x65, 0x78, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74, 0x72, 0x61, 0x64, 0x65, 0x70, 0x72, 0x6f, 0x63, 0x65, + 0x73, 0x73, 0x69, 0x6e, 0x67, 0x12, 0x86, 0x01, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x12, 0x23, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x44, 0x61, + 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x73, + 0x65, 0x72, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, + 0x62, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1d, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x70, 0x73, 0x65, 0x72, 0x74, 0x64, 0x61, 0x74, + 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x3a, 0x01, 0x2a, 0x12, 0x81, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, - 0x79, 0x4a, 0x6f, 0x62, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x67, 0x63, + 0x79, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x64, 0x61, 0x74, - 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x75, 0x6d, 0x6d, 0x61, - 0x72, 0x79, 0x12, 0x82, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, - 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, - 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, + 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x64, 0x65, 0x74, 0x61, 0x69, + 0x6c, 0x73, 0x12, 0x71, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, + 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x16, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, - 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9d, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, - 0x50, 0x72, 0x65, 0x72, 0x65, 0x71, 0x75, 0x69, 0x73, 0x69, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, - 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x50, 0x72, 0x65, 0x72, 0x65, 0x71, - 0x75, 0x69, 0x73, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x24, - 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, - 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x70, 0x72, 0x65, 0x72, 0x65, 0x71, 0x75, 0x69, - 0x73, 0x69, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x68, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x64, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, - 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, - 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, - 0x74, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, - 0x2a, 0x12, 0x5f, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, - 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, - 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, - 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4f, 0x72, 0x64, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x12, 0x79, 0x0a, 0x13, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, - 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x67, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x76, 0x0a, - 0x14, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, - 0x61, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, - 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, - 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, - 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x74, 0x72, - 0x61, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x76, 0x0a, 0x14, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x23, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, - 0x74, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, - 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x79, 0x0a, - 0x15, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x57, 0x69, - 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, - 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, - 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, + 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x22, + 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, + 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x12, 0x85, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x42, 0x65, 0x74, 0x77, + 0x65, 0x65, 0x6e, 0x12, 0x28, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x42, + 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x12, 0x1d, + 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x12, 0x81, 0x01, + 0x0a, 0x18, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, + 0x4a, 0x6f, 0x62, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, + 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x22, 0x24, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x64, 0x61, 0x74, 0x61, + 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, + 0x79, 0x12, 0x82, 0x01, 0x0a, 0x17, 0x53, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x26, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, + 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22, 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x64, + 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x9d, 0x01, 0x0a, 0x20, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x44, 0x61, 0x74, 0x61, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x50, + 0x72, 0x65, 0x72, 0x65, 0x71, 0x75, 0x69, 0x73, 0x69, 0x74, 0x65, 0x12, 0x2f, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x44, 0x61, 0x74, 0x61, 0x48, + 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x4a, 0x6f, 0x62, 0x50, 0x72, 0x65, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x73, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, - 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x82, 0x01, 0x0a, 0x18, 0x43, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, 0x69, 0x6e, - 0x67, 0x50, 0x61, 0x69, 0x72, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, - 0x69, 0x6e, 0x67, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, - 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, - 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, - 0x74, 0x65, 0x74, 0x72, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x70, 0x61, 0x69, 0x72, 0x12, 0x7f, 0x0a, - 0x13, 0x47, 0x65, 0x74, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, - 0x74, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, - 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x75, - 0x74, 0x75, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x67, - 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, - 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, - 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, - 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6c, - 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x68, 0x72, 0x61, 0x73, 0x68, 0x65, 0x72, 0x2d, 0x63, - 0x6f, 0x72, 0x70, 0x2f, 0x67, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x74, 0x72, 0x61, 0x64, - 0x65, 0x72, 0x2f, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x24, 0x2f, + 0x76, 0x31, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x61, 0x74, 0x61, 0x68, 0x69, 0x73, + 0x74, 0x6f, 0x72, 0x79, 0x6a, 0x6f, 0x62, 0x70, 0x72, 0x65, 0x72, 0x65, 0x71, 0x75, 0x69, 0x73, + 0x69, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x68, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x64, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, + 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x64, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, + 0x12, 0x5f, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, + 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4f, + 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, + 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x12, 0x79, 0x0a, 0x13, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x47, 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x47, + 0x65, 0x74, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, + 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x67, 0x65, 0x74, 0x61, 0x6c, 0x6c, 0x12, 0x76, 0x0a, 0x14, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x74, 0x72, 0x61, + 0x64, 0x69, 0x6e, 0x67, 0x12, 0x76, 0x0a, 0x14, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x23, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x64, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x12, 0x79, 0x0a, 0x15, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, + 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x24, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x57, 0x69, 0x74, 0x68, + 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x67, 0x63, + 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x76, + 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, 0x65, 0x77, + 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x12, 0x82, 0x01, 0x0a, 0x18, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, 0x69, 0x6e, 0x67, + 0x50, 0x61, 0x69, 0x72, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x53, 0x74, 0x61, 0x74, 0x65, 0x54, 0x72, 0x61, 0x64, 0x69, + 0x6e, 0x67, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, + 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, + 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x74, 0x72, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x70, 0x61, 0x69, 0x72, 0x12, 0x7f, 0x0a, 0x13, + 0x47, 0x65, 0x74, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, + 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, + 0x2e, 0x47, 0x65, 0x74, 0x46, 0x75, 0x74, 0x75, 0x72, 0x65, 0x73, 0x50, 0x6f, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x75, 0x74, + 0x75, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x67, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x12, 0x1c, + 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, + 0x74, 0x65, 0x72, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, + 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6c, 0x61, 0x74, 0x65, + 0x72, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6c, 0x6c, + 0x61, 0x74, 0x65, 0x72, 0x61, 0x6c, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x68, 0x72, 0x61, 0x73, 0x68, 0x65, 0x72, 0x2d, 0x63, 0x6f, + 0x72, 0x70, 0x2f, 0x67, 0x6f, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x74, 0x72, 0x61, 0x64, 0x65, + 0x72, 0x2f, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/gctrpc/rpc.pb.gw.go b/gctrpc/rpc.pb.gw.go index 763502513d5..50887ecc3b6 100644 --- a/gctrpc/rpc.pb.gw.go +++ b/gctrpc/rpc.pb.gw.go @@ -3107,7 +3107,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetInfo", runtime.WithHTTPPathPattern("/v1/getinfo")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3130,7 +3130,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSubsystems", runtime.WithHTTPPathPattern("/v1/getsubsystems")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSubsystems") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3153,7 +3153,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableSubsystem", runtime.WithHTTPPathPattern("/v1/enablesubsystem")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableSubsystem") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3176,7 +3176,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableSubsystem", runtime.WithHTTPPathPattern("/v1/disablesubsystem")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableSubsystem") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3199,7 +3199,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRPCEndpoints", runtime.WithHTTPPathPattern("/v1/getrpcendpoints")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRPCEndpoints") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3222,7 +3222,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCommunicationRelayers", runtime.WithHTTPPathPattern("/v1/getcommunicationrelayers")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCommunicationRelayers") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3245,7 +3245,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchanges", runtime.WithHTTPPathPattern("/v1/getexchanges")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchanges") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3268,7 +3268,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableExchange", runtime.WithHTTPPathPattern("/v1/disableexchange")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3291,7 +3291,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeInfo", runtime.WithHTTPPathPattern("/v1/getexchangeinfo")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3314,7 +3314,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCode", runtime.WithHTTPPathPattern("/v1/getexchangeotp")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCode") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3337,7 +3337,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCodes", runtime.WithHTTPPathPattern("/v1/getexchangeotps")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCodes") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3360,7 +3360,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableExchange", runtime.WithHTTPPathPattern("/v1/enableexchange")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3383,7 +3383,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTicker", runtime.WithHTTPPathPattern("/v1/getticker")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTicker") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3406,7 +3406,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickers", runtime.WithHTTPPathPattern("/v1/gettickers")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickers") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3429,7 +3429,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbook", runtime.WithHTTPPathPattern("/v1/getorderbook")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbook") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3452,7 +3452,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbooks", runtime.WithHTTPPathPattern("/v1/getorderbooks")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbooks") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3475,7 +3475,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfo", runtime.WithHTTPPathPattern("/v1/getaccountinfo")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3498,7 +3498,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateAccountInfo", runtime.WithHTTPPathPattern("/v1/updateaccountinfo")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateAccountInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3528,7 +3528,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetConfig", runtime.WithHTTPPathPattern("/v1/getconfig")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetConfig") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3551,7 +3551,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolio", runtime.WithHTTPPathPattern("/v1/getportfolio")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolio") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3574,7 +3574,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolioSummary", runtime.WithHTTPPathPattern("/v1/getportfoliosummary")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolioSummary") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3597,7 +3597,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddPortfolioAddress", runtime.WithHTTPPathPattern("/v1/addportfolioaddress")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddPortfolioAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3620,7 +3620,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemovePortfolioAddress", runtime.WithHTTPPathPattern("/v1/removeportfolioaddress")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemovePortfolioAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3643,7 +3643,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexProviders", runtime.WithHTTPPathPattern("/v1/getforexproviders")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexProviders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3666,7 +3666,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexRates", runtime.WithHTTPPathPattern("/v1/getforexrates")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexRates") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3689,7 +3689,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrders", runtime.WithHTTPPathPattern("/v1/getorders")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3712,7 +3712,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrder", runtime.WithHTTPPathPattern("/v1/getorder")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3735,7 +3735,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SubmitOrder", runtime.WithHTTPPathPattern("/v1/submitorder")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SubmitOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3758,7 +3758,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SimulateOrder", runtime.WithHTTPPathPattern("/v1/simulateorder")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SimulateOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3781,7 +3781,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WhaleBomb", runtime.WithHTTPPathPattern("/v1/whalebomb")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WhaleBomb") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3804,7 +3804,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelOrder", runtime.WithHTTPPathPattern("/v1/cancelorder")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3827,7 +3827,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelBatchOrders", runtime.WithHTTPPathPattern("/v1/cancelbatchorders")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelBatchOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3850,7 +3850,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelAllOrders", runtime.WithHTTPPathPattern("/v1/cancelallorders")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelAllOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3873,7 +3873,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetEvents", runtime.WithHTTPPathPattern("/v1/getevents")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetEvents") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3896,7 +3896,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddEvent", runtime.WithHTTPPathPattern("/v1/addevent")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3919,7 +3919,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemoveEvent", runtime.WithHTTPPathPattern("/v1/removeevent")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemoveEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3942,7 +3942,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddresses", runtime.WithHTTPPathPattern("/v1/getcryptodepositaddresses")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddresses") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3965,7 +3965,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddress", runtime.WithHTTPPathPattern("/v1/getcryptodepositaddress")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -3988,7 +3988,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAvailableTransferChains", runtime.WithHTTPPathPattern("/v1/getavailabletransferchains")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAvailableTransferChains") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4011,7 +4011,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawFiatFunds", runtime.WithHTTPPathPattern("/v1/withdrawfiatfunds")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawFiatFunds") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4034,7 +4034,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawCryptocurrencyFunds", runtime.WithHTTPPathPattern("/v1/withdrawithdrawcryptofundswfiatfunds")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawCryptocurrencyFunds") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4057,7 +4057,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventByID", runtime.WithHTTPPathPattern("/v1/withdrawaleventbyid")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventByID") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4080,7 +4080,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByExchange", runtime.WithHTTPPathPattern("/v1/withdrawaleventbyid")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4103,7 +4103,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByDate", runtime.WithHTTPPathPattern("/v1/withdrawaleventbydate")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByDate") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4126,7 +4126,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetLoggerDetails", runtime.WithHTTPPathPattern("/v1/getloggerdetails")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetLoggerDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4149,7 +4149,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetLoggerDetails", runtime.WithHTTPPathPattern("/v1/setloggerdetails")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetLoggerDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4172,7 +4172,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangePairs", runtime.WithHTTPPathPattern("/v1/getexchangepairs")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangePairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4195,7 +4195,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangePair", runtime.WithHTTPPathPattern("/v1/setexchangepair")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangePair") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4246,7 +4246,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAuditEvent", runtime.WithHTTPPathPattern("/v1/getauditevent")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAuditEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4269,7 +4269,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptExecute", runtime.WithHTTPPathPattern("/v1/gctscript/execute")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptExecute") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4292,7 +4292,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptUpload", runtime.WithHTTPPathPattern("/v1/gctscript/upload")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptUpload") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4315,7 +4315,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptReadScript", runtime.WithHTTPPathPattern("/v1/gctscript/read")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptReadScript") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4338,7 +4338,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStatus", runtime.WithHTTPPathPattern("/v1/gctscript/status")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStatus") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4361,7 +4361,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptQuery", runtime.WithHTTPPathPattern("/v1/gctscript/query")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptQuery") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4384,7 +4384,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStop", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStop") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4407,7 +4407,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStopAll", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStopAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4430,7 +4430,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptListAll", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptListAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4453,7 +4453,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptAutoLoadToggle", runtime.WithHTTPPathPattern("/v1/gctscript/autoload")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptAutoLoadToggle") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4476,7 +4476,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricCandles", runtime.WithHTTPPathPattern("/v1/gethistoriccandles")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricCandles") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4499,7 +4499,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeAsset", runtime.WithHTTPPathPattern("/v1/setexchangeasset")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeAsset") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4522,7 +4522,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetAllExchangePairs", runtime.WithHTTPPathPattern("/v1/setallexchangepairs")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetAllExchangePairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4545,7 +4545,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs", runtime.WithHTTPPathPattern("/v1/updateexchangesupportedpairs")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4568,7 +4568,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeAssets", runtime.WithHTTPPathPattern("/v1/getexchangeassets")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeAssets") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4591,7 +4591,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetInfo", runtime.WithHTTPPathPattern("/v1/websocketgetinfo")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4614,7 +4614,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetEnabled", runtime.WithHTTPPathPattern("/v1/websocketsetenabled")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetEnabled") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4637,7 +4637,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions", runtime.WithHTTPPathPattern("/v1/websocketgetsubscriptions")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4660,7 +4660,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetProxy", runtime.WithHTTPPathPattern("/v1/websocketsetproxy")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetProxy") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4683,7 +4683,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetURL", runtime.WithHTTPPathPattern("/v1/websocketseturl")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetURL") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4706,7 +4706,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRecentTrades", runtime.WithHTTPPathPattern("/v1/getsavedtrades")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRecentTrades") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4736,7 +4736,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSavedTrades", runtime.WithHTTPPathPattern("/v1/getsavedtrades")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSavedTrades") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4759,7 +4759,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ConvertTradesToCandles", runtime.WithHTTPPathPattern("/v1/converttradestocandles")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ConvertTradesToCandles") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4782,7 +4782,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals", runtime.WithHTTPPathPattern("/v1/findmissingsavedcandleintervals")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4805,7 +4805,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals", runtime.WithHTTPPathPattern("/v1/findmissingsavedtradeintervals")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4828,7 +4828,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing", runtime.WithHTTPPathPattern("/v1/setexchangetradeprocessing")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4851,7 +4851,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpsertDataHistoryJob", runtime.WithHTTPPathPattern("/v1/upsertdatahistoryjob")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpsertDataHistoryJob") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4874,7 +4874,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobDetails", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobdetails")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4897,7 +4897,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetActiveDataHistoryJobs", runtime.WithHTTPPathPattern("/v1/getactivedatahistoryjobs")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetActiveDataHistoryJobs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4920,7 +4920,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobsBetween", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobsbetween")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobsBetween") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4943,7 +4943,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobSummary", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobsummary")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobSummary") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4966,7 +4966,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetDataHistoryJobStatus", runtime.WithHTTPPathPattern("/v1/setdatahistoryjobstatus")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetDataHistoryJobStatus") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -4989,7 +4989,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateDataHistoryJobPrerequisite", runtime.WithHTTPPathPattern("/v1/updatedatahistoryjobprerequisite")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateDataHistoryJobPrerequisite") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5012,7 +5012,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetManagedOrders", runtime.WithHTTPPathPattern("/v1/getmanagedorders")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetManagedOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5035,7 +5035,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ModifyOrder", runtime.WithHTTPPathPattern("/v1/modifyorder")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ModifyOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5058,7 +5058,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateGetAll", runtime.WithHTTPPathPattern("/v1/currencystategetall")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateGetAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5081,7 +5081,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTrading", runtime.WithHTTPPathPattern("/v1/currencystatetrading")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTrading") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5104,7 +5104,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateDeposit", runtime.WithHTTPPathPattern("/v1/currencystatedeposit")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateDeposit") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5127,7 +5127,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateWithdraw", runtime.WithHTTPPathPattern("/v1/currencystatewithdraw")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateWithdraw") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5150,7 +5150,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTradingPair", runtime.WithHTTPPathPattern("/v1/currencystatetradingpair")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTradingPair") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5173,7 +5173,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetFuturesPositions", runtime.WithHTTPPathPattern("/v1/getfuturespositions")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetFuturesPositions") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5196,7 +5196,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve var stream runtime.ServerTransportStream ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCollateral", runtime.WithHTTPPathPattern("/v1/getcollateral")) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCollateral") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5258,7 +5258,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetInfo", runtime.WithHTTPPathPattern("/v1/getinfo")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5278,7 +5278,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSubsystems", runtime.WithHTTPPathPattern("/v1/getsubsystems")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSubsystems") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5298,7 +5298,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableSubsystem", runtime.WithHTTPPathPattern("/v1/enablesubsystem")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableSubsystem") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5318,7 +5318,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableSubsystem", runtime.WithHTTPPathPattern("/v1/disablesubsystem")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableSubsystem") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5338,7 +5338,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRPCEndpoints", runtime.WithHTTPPathPattern("/v1/getrpcendpoints")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRPCEndpoints") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5358,7 +5358,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCommunicationRelayers", runtime.WithHTTPPathPattern("/v1/getcommunicationrelayers")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCommunicationRelayers") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5378,7 +5378,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchanges", runtime.WithHTTPPathPattern("/v1/getexchanges")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchanges") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5398,7 +5398,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableExchange", runtime.WithHTTPPathPattern("/v1/disableexchange")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/DisableExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5418,7 +5418,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeInfo", runtime.WithHTTPPathPattern("/v1/getexchangeinfo")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5438,7 +5438,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCode", runtime.WithHTTPPathPattern("/v1/getexchangeotp")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCode") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5458,7 +5458,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCodes", runtime.WithHTTPPathPattern("/v1/getexchangeotps")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOTPCodes") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5478,7 +5478,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableExchange", runtime.WithHTTPPathPattern("/v1/enableexchange")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/EnableExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5498,7 +5498,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTicker", runtime.WithHTTPPathPattern("/v1/getticker")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTicker") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5518,7 +5518,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickers", runtime.WithHTTPPathPattern("/v1/gettickers")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickers") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5538,7 +5538,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbook", runtime.WithHTTPPathPattern("/v1/getorderbook")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbook") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5558,7 +5558,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbooks", runtime.WithHTTPPathPattern("/v1/getorderbooks")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbooks") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5578,7 +5578,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfo", runtime.WithHTTPPathPattern("/v1/getaccountinfo")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5598,7 +5598,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateAccountInfo", runtime.WithHTTPPathPattern("/v1/updateaccountinfo")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateAccountInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5618,7 +5618,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfoStream", runtime.WithHTTPPathPattern("/v1/getaccountinfostream")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAccountInfoStream") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5638,7 +5638,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetConfig", runtime.WithHTTPPathPattern("/v1/getconfig")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetConfig") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5658,7 +5658,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolio", runtime.WithHTTPPathPattern("/v1/getportfolio")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolio") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5678,7 +5678,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolioSummary", runtime.WithHTTPPathPattern("/v1/getportfoliosummary")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetPortfolioSummary") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5698,7 +5698,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddPortfolioAddress", runtime.WithHTTPPathPattern("/v1/addportfolioaddress")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddPortfolioAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5718,7 +5718,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemovePortfolioAddress", runtime.WithHTTPPathPattern("/v1/removeportfolioaddress")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemovePortfolioAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5738,7 +5738,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexProviders", runtime.WithHTTPPathPattern("/v1/getforexproviders")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexProviders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5758,7 +5758,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexRates", runtime.WithHTTPPathPattern("/v1/getforexrates")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetForexRates") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5778,7 +5778,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrders", runtime.WithHTTPPathPattern("/v1/getorders")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5798,7 +5798,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrder", runtime.WithHTTPPathPattern("/v1/getorder")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5818,7 +5818,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SubmitOrder", runtime.WithHTTPPathPattern("/v1/submitorder")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SubmitOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5838,7 +5838,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SimulateOrder", runtime.WithHTTPPathPattern("/v1/simulateorder")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SimulateOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5858,7 +5858,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WhaleBomb", runtime.WithHTTPPathPattern("/v1/whalebomb")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WhaleBomb") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5878,7 +5878,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelOrder", runtime.WithHTTPPathPattern("/v1/cancelorder")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5898,7 +5898,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelBatchOrders", runtime.WithHTTPPathPattern("/v1/cancelbatchorders")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelBatchOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5918,7 +5918,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelAllOrders", runtime.WithHTTPPathPattern("/v1/cancelallorders")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CancelAllOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5938,7 +5938,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetEvents", runtime.WithHTTPPathPattern("/v1/getevents")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetEvents") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5958,7 +5958,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddEvent", runtime.WithHTTPPathPattern("/v1/addevent")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/AddEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5978,7 +5978,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemoveEvent", runtime.WithHTTPPathPattern("/v1/removeevent")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/RemoveEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -5998,7 +5998,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddresses", runtime.WithHTTPPathPattern("/v1/getcryptodepositaddresses")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddresses") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6018,7 +6018,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddress", runtime.WithHTTPPathPattern("/v1/getcryptodepositaddress")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCryptocurrencyDepositAddress") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6038,7 +6038,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAvailableTransferChains", runtime.WithHTTPPathPattern("/v1/getavailabletransferchains")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAvailableTransferChains") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6058,7 +6058,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawFiatFunds", runtime.WithHTTPPathPattern("/v1/withdrawfiatfunds")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawFiatFunds") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6078,7 +6078,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawCryptocurrencyFunds", runtime.WithHTTPPathPattern("/v1/withdrawithdrawcryptofundswfiatfunds")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawCryptocurrencyFunds") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6098,7 +6098,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventByID", runtime.WithHTTPPathPattern("/v1/withdrawaleventbyid")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventByID") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6118,7 +6118,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByExchange", runtime.WithHTTPPathPattern("/v1/withdrawaleventbyid")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByExchange") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6138,7 +6138,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByDate", runtime.WithHTTPPathPattern("/v1/withdrawaleventbydate")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WithdrawalEventsByDate") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6158,7 +6158,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetLoggerDetails", runtime.WithHTTPPathPattern("/v1/getloggerdetails")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetLoggerDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6178,7 +6178,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetLoggerDetails", runtime.WithHTTPPathPattern("/v1/setloggerdetails")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetLoggerDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6198,7 +6198,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangePairs", runtime.WithHTTPPathPattern("/v1/getexchangepairs")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangePairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6218,7 +6218,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangePair", runtime.WithHTTPPathPattern("/v1/setexchangepair")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangePair") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6238,7 +6238,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbookStream", runtime.WithHTTPPathPattern("/v1/getorderbookstream")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetOrderbookStream") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6258,7 +6258,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream", runtime.WithHTTPPathPattern("/v1/getexchangeorderbookstream")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeOrderbookStream") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6278,7 +6278,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickerStream", runtime.WithHTTPPathPattern("/v1/gettickerstream")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetTickerStream") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6298,7 +6298,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeTickerStream", runtime.WithHTTPPathPattern("/v1/getexchangetickerstream")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeTickerStream") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6318,7 +6318,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAuditEvent", runtime.WithHTTPPathPattern("/v1/getauditevent")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetAuditEvent") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6338,7 +6338,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptExecute", runtime.WithHTTPPathPattern("/v1/gctscript/execute")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptExecute") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6358,7 +6358,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptUpload", runtime.WithHTTPPathPattern("/v1/gctscript/upload")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptUpload") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6378,7 +6378,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptReadScript", runtime.WithHTTPPathPattern("/v1/gctscript/read")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptReadScript") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6398,7 +6398,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStatus", runtime.WithHTTPPathPattern("/v1/gctscript/status")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStatus") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6418,7 +6418,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptQuery", runtime.WithHTTPPathPattern("/v1/gctscript/query")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptQuery") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6438,7 +6438,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStop", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStop") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6458,7 +6458,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStopAll", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptStopAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6478,7 +6478,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptListAll", runtime.WithHTTPPathPattern("/v1/gctscript/stop")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptListAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6498,7 +6498,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptAutoLoadToggle", runtime.WithHTTPPathPattern("/v1/gctscript/autoload")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GCTScriptAutoLoadToggle") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6518,7 +6518,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricCandles", runtime.WithHTTPPathPattern("/v1/gethistoriccandles")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricCandles") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6538,7 +6538,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeAsset", runtime.WithHTTPPathPattern("/v1/setexchangeasset")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeAsset") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6558,7 +6558,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetAllExchangePairs", runtime.WithHTTPPathPattern("/v1/setallexchangepairs")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetAllExchangePairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6578,7 +6578,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs", runtime.WithHTTPPathPattern("/v1/updateexchangesupportedpairs")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6598,7 +6598,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeAssets", runtime.WithHTTPPathPattern("/v1/getexchangeassets")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetExchangeAssets") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6618,7 +6618,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetInfo", runtime.WithHTTPPathPattern("/v1/websocketgetinfo")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetInfo") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6638,7 +6638,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetEnabled", runtime.WithHTTPPathPattern("/v1/websocketsetenabled")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetEnabled") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6658,7 +6658,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions", runtime.WithHTTPPathPattern("/v1/websocketgetsubscriptions")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6678,7 +6678,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetProxy", runtime.WithHTTPPathPattern("/v1/websocketsetproxy")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetProxy") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6698,7 +6698,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetURL", runtime.WithHTTPPathPattern("/v1/websocketseturl")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/WebsocketSetURL") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6718,7 +6718,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRecentTrades", runtime.WithHTTPPathPattern("/v1/getsavedtrades")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetRecentTrades") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6738,7 +6738,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricTrades", runtime.WithHTTPPathPattern("/v1/getsavedtrades")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetHistoricTrades") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6758,7 +6758,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSavedTrades", runtime.WithHTTPPathPattern("/v1/getsavedtrades")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetSavedTrades") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6778,7 +6778,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ConvertTradesToCandles", runtime.WithHTTPPathPattern("/v1/converttradestocandles")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ConvertTradesToCandles") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6798,7 +6798,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals", runtime.WithHTTPPathPattern("/v1/findmissingsavedcandleintervals")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedCandleIntervals") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6818,7 +6818,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals", runtime.WithHTTPPathPattern("/v1/findmissingsavedtradeintervals")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/FindMissingSavedTradeIntervals") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6838,7 +6838,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing", runtime.WithHTTPPathPattern("/v1/setexchangetradeprocessing")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetExchangeTradeProcessing") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6858,7 +6858,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpsertDataHistoryJob", runtime.WithHTTPPathPattern("/v1/upsertdatahistoryjob")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpsertDataHistoryJob") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6878,7 +6878,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobDetails", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobdetails")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobDetails") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6898,7 +6898,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetActiveDataHistoryJobs", runtime.WithHTTPPathPattern("/v1/getactivedatahistoryjobs")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetActiveDataHistoryJobs") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6918,7 +6918,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobsBetween", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobsbetween")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobsBetween") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6938,7 +6938,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobSummary", runtime.WithHTTPPathPattern("/v1/getdatahistoryjobsummary")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetDataHistoryJobSummary") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6958,7 +6958,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetDataHistoryJobStatus", runtime.WithHTTPPathPattern("/v1/setdatahistoryjobstatus")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/SetDataHistoryJobStatus") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6978,7 +6978,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateDataHistoryJobPrerequisite", runtime.WithHTTPPathPattern("/v1/updatedatahistoryjobprerequisite")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/UpdateDataHistoryJobPrerequisite") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -6998,7 +6998,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetManagedOrders", runtime.WithHTTPPathPattern("/v1/getmanagedorders")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetManagedOrders") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7018,7 +7018,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ModifyOrder", runtime.WithHTTPPathPattern("/v1/modifyorder")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/ModifyOrder") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7038,7 +7038,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateGetAll", runtime.WithHTTPPathPattern("/v1/currencystategetall")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateGetAll") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7058,7 +7058,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTrading", runtime.WithHTTPPathPattern("/v1/currencystatetrading")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTrading") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7078,7 +7078,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateDeposit", runtime.WithHTTPPathPattern("/v1/currencystatedeposit")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateDeposit") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7098,7 +7098,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateWithdraw", runtime.WithHTTPPathPattern("/v1/currencystatewithdraw")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateWithdraw") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7118,7 +7118,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTradingPair", runtime.WithHTTPPathPattern("/v1/currencystatetradingpair")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/CurrencyStateTradingPair") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7138,7 +7138,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetFuturesPositions", runtime.WithHTTPPathPattern("/v1/getfuturespositions")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetFuturesPositions") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return @@ -7158,7 +7158,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve ctx, cancel := context.WithCancel(req.Context()) defer cancel() inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCollateral", runtime.WithHTTPPathPattern("/v1/getcollateral")) + rctx, err := runtime.AnnotateContext(ctx, mux, req, "/gctrpc.GoCryptoTrader/GetCollateral") if err != nil { runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) return diff --git a/gctrpc/rpc.proto b/gctrpc/rpc.proto index bbf9af4e9ec..b2accb8e3f8 100644 --- a/gctrpc/rpc.proto +++ b/gctrpc/rpc.proto @@ -1058,12 +1058,11 @@ message FuturePosition { } message GetCollateralRequest { - string exchange =1; + string exchange = 1; string asset = 2; - string sub_account = 3; - bool include_breakdown = 4; - bool calculate_offline = 5; - bool include_zero_values = 6; + bool include_breakdown = 3; + bool calculate_offline = 4; + bool include_zero_values = 5; } message GetCollateralResponse { diff --git a/gctrpc/rpc.swagger.json b/gctrpc/rpc.swagger.json index 3e9278cf024..7d85060d0b7 100644 --- a/gctrpc/rpc.swagger.json +++ b/gctrpc/rpc.swagger.json @@ -1189,12 +1189,6 @@ "required": false, "type": "string" }, - { - "name": "subAccount", - "in": "query", - "required": false, - "type": "string" - }, { "name": "includeBreakdown", "in": "query", diff --git a/gctscript/wrappers/gct/exchange/exchange_test.go b/gctscript/wrappers/gct/exchange/exchange_test.go index ebd1991356d..13b51be151a 100644 --- a/gctscript/wrappers/gct/exchange/exchange_test.go +++ b/gctscript/wrappers/gct/exchange/exchange_test.go @@ -226,7 +226,7 @@ func configureExchangeKeys() bool { return false } b := ex.GetBase() - b.SetAPIKeys(exchAPIKEY, exchAPISECRET, exchClientID) + b.SetCredentials(exchAPIKEY, exchAPISECRET, exchClientID, "", "", "") b.SkipAuthCheck = true - return b.ValidateAPICredentials() + return b.AreCredentialsValid(context.Background()) } diff --git a/gctscript/wrappers/gct/gctwrapper_test.go b/gctscript/wrappers/gct/gctwrapper_test.go index 52f318f6386..42bf07e39af 100644 --- a/gctscript/wrappers/gct/gctwrapper_test.go +++ b/gctscript/wrappers/gct/gctwrapper_test.go @@ -6,12 +6,12 @@ import ( "os" "path/filepath" "reflect" - "strings" "testing" objects "github.com/d5/tengo/v2" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/engine" + exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" "github.com/thrasher-corp/gocryptotrader/gctscript/modules" "github.com/thrasher-corp/gocryptotrader/gctscript/modules/gct" @@ -191,9 +191,8 @@ func TestAccountInfo(t *testing.T) { t.Fatal(err) } _, err = gct.ExchangeAccountInfo(exch, assetType) - if err != nil && - !strings.Contains(err.Error(), "unset/default API keys") { - t.Error(err) + if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) { + t.Errorf("received: %v but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled) } } @@ -238,9 +237,8 @@ func TestExchangeOrderSubmit(t *testing.T) { _, err = gct.ExchangeOrderSubmit(exch, currencyPair, delimiter, orderType, orderSide, orderPrice, orderAmount, orderID, orderAsset) - if err != nil && - !strings.Contains(err.Error(), "unset/default API keys") { - t.Error(err) + if !errors.Is(err, exchange.ErrAuthenticationSupportNotEnabled) { + t.Errorf("received: %v but expected: %v", err, exchange.ErrAuthenticationSupportNotEnabled) } }