├── .gitignore ├── .circleci └── config.yml ├── Makefile ├── go.mod ├── wallet └── wallet.go ├── token ├── errors.go ├── did_test.go └── did.go ├── LICENSE.txt ├── client └── api.go ├── user.go ├── magic.go ├── error.go ├── cmd └── magic-cli │ └── main.go ├── CHANGELOG.md ├── user ├── client.go └── client_test.go ├── README.md ├── CONTRIBUTING.md └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | _cache 3 | *_out/ 4 | VERSION 5 | .cache 6 | .gcache 7 | .idea/** 8 | *.key 9 | *.crt 10 | *.test 11 | .vscode 12 | bazel-bin 13 | bazel-out 14 | bazel-testlogs 15 | build_cache 16 | build_cache/** -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | 3 | jobs: 4 | build-and-test: 5 | docker: 6 | - image: circleci/golang:1.14 7 | steps: 8 | - checkout 9 | - run: 10 | command: make build 11 | name: Build command line utility 12 | - run: 13 | command: make test 14 | name: Run tests 15 | 16 | workflows: 17 | main: 18 | jobs: 19 | - build-and-test 20 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_PATH ?= $(shell pwd -P) 2 | 3 | deps: 4 | $(info * Installing dependencies) 5 | @go mod download 6 | 7 | .PHONY: build 8 | build: deps 9 | $(info * Building magic-cli) 10 | @go build ./cmd/magic-cli 11 | 12 | .PHONY: install 13 | install: deps 14 | $(info * Installing magic-cli) 15 | @go install ./cmd/magic-cli 16 | 17 | .PHONY: test 18 | test: deps 19 | $(info * Running tests) 20 | @go test ./... 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/magiclabs/magic-admin-go 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect 7 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect 8 | github.com/ethereum/go-ethereum v1.10.20 9 | github.com/go-resty/resty/v2 v2.7.0 10 | github.com/stretchr/testify v1.8.0 11 | github.com/urfave/cli/v2 v2.10.2 12 | golang.org/x/crypto v0.3.0 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /wallet/wallet.go: -------------------------------------------------------------------------------- 1 | package wallet 2 | 3 | type Type string 4 | 5 | const ( 6 | ETH Type = "ETH" 7 | HARMONY = "HARMONY" 8 | ICON = "ICON" 9 | FLOW = "FLOW" 10 | TEZOS = "TEZOS" 11 | ZILLIQA = "ZILLIQA" 12 | POLKADOT = "POLKADOT" 13 | SOLANA = "SOLANA" 14 | AVAX = "AVAX" 15 | ALGOD = "ALGOD" 16 | COSMOS = "COSMOS" 17 | CELO = "CELO" 18 | BITCOIN = "BITCOIN" 19 | NEAR = "NEAR" 20 | HELIUM = "HELIUM" 21 | CONFLUX = "CONFLUX" 22 | TERRA = "TERRA" 23 | TAQUITO = "TAQUITO" 24 | ED = "ED" 25 | HEDERA = "HEDERA" 26 | ANY = "ANY" 27 | NONE = "NONE" 28 | ) 29 | -------------------------------------------------------------------------------- /token/errors.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import "errors" 4 | 5 | var ( 6 | ErrNotValidPublicAddr = &DIDTokenError{errors.New("Invalid public address format.")} 7 | ErrNotValidProof = &DIDTokenError{errors.New("Signature mismatch between 'proof' and 'claim'. Please " + 8 | "generate a new token with an intended issuer.")} 9 | ErrExpired = &DIDTokenError{errors.New("Given DID token has expired. Please generate a new one.")} 10 | ErrNbfExpired = &DIDTokenError{errors.New("Given DID token cannot be used at this time. Please " + 11 | "check the 'nbf' field and regenerate a new token with a suitable value.")} 12 | ErrAudMismatch = &DIDTokenError{errors.New("Audience does not match client ID. Please ensure your " + 13 | "secret key matches the application which generated the DID token.")} 14 | ) 15 | 16 | type DIDTokenError struct { 17 | err error 18 | } 19 | 20 | func (e *DIDTokenError) Error() string { 21 | return e.err.Error() 22 | } 23 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Magic Labs Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /client/api.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "github.com/go-resty/resty/v2" 5 | 6 | "github.com/magiclabs/magic-admin-go" 7 | "github.com/magiclabs/magic-admin-go/user" 8 | ) 9 | 10 | const ( 11 | clientInfoV1 = "/v1/admin/client/get" 12 | ) 13 | 14 | type API struct { 15 | User magic.User 16 | ClientInfo magic.ClientInfo 17 | } 18 | 19 | func New(secret string, client *resty.Client) (*API, error) { 20 | clientInfo, err := getClientInfo(secret, client) 21 | if err != nil { 22 | return nil, err 23 | } 24 | return &API{ 25 | User: user.NewUserClient(secret, clientInfo.ClientId, client), 26 | ClientInfo: *clientInfo, 27 | }, nil 28 | } 29 | 30 | func getClientInfo(secret string, client *resty.Client) (*magic.ClientInfo, error) { 31 | meta := new(magic.ClientInfo) 32 | respData := new(magic.Response) 33 | respData.Data = meta 34 | 35 | r, err := client.R(). 36 | SetHeader(magic.APISecretHeader, secret). 37 | SetResult(respData). 38 | Get(clientInfoV1) 39 | if err != nil { 40 | return nil, &magic.APIConnectionError{Err: err} 41 | } 42 | if r.IsError() { 43 | return nil, magic.WrapError(r, r.Error().(*magic.Error)) 44 | } 45 | 46 | return meta, nil 47 | } 48 | -------------------------------------------------------------------------------- /user.go: -------------------------------------------------------------------------------- 1 | package magic 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/magiclabs/magic-admin-go/wallet" 7 | ) 8 | 9 | type User interface { 10 | GetMetadataByIssuer(issuer string) (*UserInfo, error) 11 | GetMetadataByPublicAddress(pubAddr string) (*UserInfo, error) 12 | GetMetadataByToken(didToken string) (*UserInfo, error) 13 | 14 | GetMetadataByIssuerAndWallet(issuer string, walletType wallet.Type) (*UserInfo, error) 15 | GetMetadataByPublicAddressAndWallet(pubAddr string, walletType wallet.Type) (*UserInfo, error) 16 | GetMetadataByTokenAndWallet(didToken string, walletType wallet.Type) (*UserInfo, error) 17 | 18 | LogoutByIssuer(issuer string) error 19 | LogoutByPublicAddress(pubAddr string) error 20 | LogoutByToken(didToken string) error 21 | } 22 | 23 | type UserInfo struct { 24 | Email string `json:"email"` 25 | Issuer string `json:"issuer"` 26 | PublicAddress string `json:"public_address"` 27 | Wallets *[]Wallet `json:"wallets,omitempty"` 28 | } 29 | 30 | type ClientInfo struct { 31 | ClientId string `json:"client_id"` 32 | AppScope string `json:"app_scope"` 33 | } 34 | 35 | type Wallet struct { 36 | Network string `json:"network"` 37 | PublicAddress string `json:"public_address"` 38 | Type string `json:"wallet_type"` 39 | } 40 | 41 | func (m *UserInfo) String() string { 42 | data, err := json.Marshal(m) 43 | if err != nil { 44 | panic(err) 45 | } 46 | 47 | return string(data) 48 | } 49 | -------------------------------------------------------------------------------- /token/did_test.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | const testDIDToken = "WyIweGFhNTBiZTcwNzI5Y2E3MDViYTdjOGQwMDE4NWM2ZjJkYTQ3OWQwZm" + 11 | "NkZTUzMTFjYTRjZTViMWJhNzE1YzhhNzIxYzVmMTk0ODQzNGY5NmZmNTc3ZDdiMmI2YWQ4MmQ" + 12 | "zZGQ1YTI0NTdmZTY5OThiMTM3ZWQ5YmMwOGQzNmU1NDljMWIiLCJ7XCJpYXRcIjoxNTg2NzY0" + 13 | "MjcwLFwiZXh0XCI6MTExNzM1Mjg1MDAsXCJpc3NcIjpcImRpZDpldGhyOjB4NEI3M0M1ODM3M" + 14 | "EFFZmNFZjg2QTYwMjFhZkNEZTU2NzM1MTEzNzZCMlwiLFwic3ViXCI6XCJOanJBNTNTY1E4SV" + 15 | "Y4ME5Kbng0dDNTaGk5LWtGZkY1cWF2RDJWcjBkMWRjPVwiLFwiYXVkXCI6XCJkaWQ6bWFnaWM" + 16 | "6NzMxODQ4Y2MtMDg0ZS00MWZmLWJiZGYtN2YxMDM4MTdlYTZiXCIsXCJuYmZcIjoxNTg2NzY0" + 17 | "MjcwLFwidGlkXCI6XCJlYmNjODgwYS1mZmM5LTQzNzUtODRhZS0xNTRjY2Q1Yzc0NmRcIixcI" + 18 | "mFkZFwiOlwiMHg4NGQ2ODM5MjY4YTFhZjkxMTFmZGVjY2QzOTZmMzAzODA1ZGNhMmJjMDM0NT" + 19 | "BiN2ViMTE2ZTJmNWZjOGM1YTcyMmQxZmI5YWYyMzNhYTczYzVjMTcwODM5Y2U1YWQ4MTQxYjl" + 20 | "iNDY0MzM4MDk4MmRhNGJmYmIwYjExMjg0OTg4ZjFiXCJ9Il0=" 21 | 22 | func TestDIDTokenDecode(t *testing.T) { 23 | issuer := "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2" 24 | proof := "0xaa50be70729ca705ba7c8d00185c6f2da479d0fcde5311ca4ce5b1ba715c8a721c5" + 25 | "f1948434f96ff577d7b2b6ad82d3dd5a2457fe6998b137ed9bc08d36e549c1b" 26 | 27 | claim := Claim{ 28 | Iat: 1586764270, 29 | Ext: 11173528500, 30 | Nbf: 1586764270, 31 | Iss: "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", 32 | Sub: "NjrA53ScQ8IV80NJnx4t3Shi9-kFfF5qavD2Vr0d1dc=", 33 | Aud: "did:magic:731848cc-084e-41ff-bbdf-7f103817ea6b", 34 | Tid: "ebcc880a-ffc9-4375-84ae-154ccd5c746d", 35 | Add: "0x84d6839268a1af9111fdeccd396f303805dca2bc03450b7eb116e2f5fc8c5a722" + 36 | "d1fb9af233aa73c5c170839ce5ad8141b9b4643380982da4bfbb0b11284988f1b", 37 | } 38 | 39 | token, err := NewToken(testDIDToken) 40 | require.NoError(t, err, "can't create new token") 41 | 42 | assert.Equal(t, claim, token.GetClaim()) 43 | assert.Equal(t, proof, token.GetProof()) 44 | assert.Equal(t, issuer, token.GetIssuer()) 45 | 46 | assert.NoError(t, token.Validate("did:magic:731848cc-084e-41ff-bbdf-7f103817ea6b"), "token is not valid") 47 | } 48 | -------------------------------------------------------------------------------- /magic.go: -------------------------------------------------------------------------------- 1 | package magic 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "time" 7 | 8 | "github.com/go-resty/resty/v2" 9 | ) 10 | 11 | const ( 12 | // APIVersion is the version of the library. 13 | APIVersion = "v0.1.0" 14 | 15 | // APIURL is the URL of the API service backend. 16 | APIURL = "https://api.magic.link" 17 | 18 | // APISecretHeader holds the header name for api authorization. 19 | APISecretHeader = "X-Magic-Secret-Key" 20 | ) 21 | 22 | var ( 23 | ErrRespQuotaExceeded = errors.New("quota exceeded") 24 | ) 25 | 26 | // Default response data structure of magic backend server. 27 | type Response struct { 28 | Data interface{} `json:"data"` 29 | ErrorCode ErrorCode `json:"error_code"` 30 | Message string `json:"message"` 31 | Status string `json:"status"` 32 | } 33 | 34 | // NewDefaultClient creates backend client with default configuration of retries. 35 | func NewDefaultClient() *resty.Client { 36 | return NewClientWithRetry(3, time.Second, 10*time.Second) 37 | } 38 | 39 | // NewClient creates new backend client with default api url. 40 | func NewClient() *resty.Client { 41 | return resty.New().SetHostURL(APIURL).SetError(new(Error)) 42 | } 43 | 44 | // NewClientWithRetry creates backend client with backoff retry configuration. 45 | func NewClientWithRetry(retries int, retryWait, timeout time.Duration) *resty.Client { 46 | client := NewClient() 47 | 48 | // Set retry count to non zero to enable retries 49 | client.SetRetryCount(retries). 50 | // Retry wait time till the next request is risen. 51 | SetRetryWaitTime(retryWait). 52 | // Wait time of backend response. 53 | SetRetryMaxWaitTime(timeout). 54 | // SetRetryAfter sets callback to calculate wait time between retries. 55 | // Default (nil) implies exponential backoff with jitter. 56 | SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) { 57 | return 0, ErrRespQuotaExceeded 58 | }). 59 | AddRetryCondition( 60 | // RetryConditionFunc identify which responses could be considered as retryable. 61 | func(r *resty.Response, err error) bool { 62 | return r.StatusCode() == http.StatusTooManyRequests 63 | }, 64 | ) 65 | 66 | return client 67 | } 68 | -------------------------------------------------------------------------------- /error.go: -------------------------------------------------------------------------------- 1 | package magic 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | 7 | "github.com/go-resty/resty/v2" 8 | ) 9 | 10 | type ErrorCode string 11 | 12 | type Error struct { 13 | Response 14 | } 15 | 16 | // Error serializes the error object to JSON and returns it as a string. 17 | func (e *Error) Error() string { 18 | ret, _ := json.Marshal(e) 19 | return string(ret) 20 | } 21 | 22 | // RateLimitError occurs when in case if API is hit with too many requests. 23 | type RateLimitingError struct { 24 | Err *Error 25 | } 26 | 27 | // Error serializes the error object to JSON and returns it as a string. 28 | func (e *RateLimitingError) Error() string { 29 | return e.Err.Error() 30 | } 31 | 32 | // BadRequestError occurs with not well formed request. 33 | type BadRequestError struct { 34 | Err *Error 35 | } 36 | 37 | // Error serializes the error object to JSON and returns it as a string. 38 | func (e *BadRequestError) Error() string { 39 | return e.Err.Error() 40 | } 41 | 42 | // AuthenticationError occurs if request is not authorized to proceed. 43 | type AuthenticationError struct { 44 | Err *Error 45 | } 46 | 47 | // Error serializes the error object to JSON and returns it as a string. 48 | func (e *AuthenticationError) Error() string { 49 | return e.Err.Error() 50 | } 51 | 52 | // ForbiddenError occurs if request is not permitted to be executed. 53 | type ForbiddenError struct { 54 | Err *Error 55 | } 56 | 57 | // Error serializes the error object to JSON and returns it as a string. 58 | func (e *ForbiddenError) Error() string { 59 | return e.Err.Error() 60 | } 61 | 62 | // APIError default unrecognized by any other errors. 63 | type APIError struct { 64 | Err *Error 65 | } 66 | 67 | // Error serializes the error object to JSON and returns it as a string. 68 | func (e *APIError) Error() string { 69 | return e.Err.Error() 70 | } 71 | 72 | // APIConnectionError occurs if request is not permitted to be executed. 73 | type APIConnectionError struct { 74 | Err error 75 | } 76 | 77 | // Error serializes the error object to JSON and returns it as a string. 78 | func (e *APIConnectionError) Error() string { 79 | return e.Err.Error() 80 | } 81 | 82 | // Wraps error into appropriate type. 83 | func WrapError(r *resty.Response, err *Error) error { 84 | switch r.StatusCode() { 85 | case http.StatusForbidden: 86 | return &ForbiddenError{Err: err} 87 | case http.StatusBadRequest: 88 | return &BadRequestError{Err: err} 89 | case http.StatusTooManyRequests: 90 | return &RateLimitingError{Err: err} 91 | case http.StatusUnauthorized: 92 | return &AuthenticationError{Err: err} 93 | default: 94 | return &APIError{Err: err} 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /cmd/magic-cli/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "time" 8 | 9 | "github.com/urfave/cli/v2" 10 | 11 | "github.com/magiclabs/magic-admin-go" 12 | "github.com/magiclabs/magic-admin-go/client" 13 | "github.com/magiclabs/magic-admin-go/token" 14 | ) 15 | 16 | func main() { 17 | app := &cli.App{ 18 | Name: "magic-cli", 19 | Usage: "command line utility to make requests to api and validate tokens", 20 | Compiled: time.Now(), 21 | Commands: []*cli.Command{ 22 | { 23 | Name: "token", 24 | Aliases: []string{"t"}, 25 | Usage: "magic-cli token [decode|validate] --did [--clientId ]", 26 | Subcommands: []*cli.Command{ 27 | { 28 | Name: "decode", 29 | Usage: "magic-cli token decode --did ", 30 | Flags: []cli.Flag{ 31 | &cli.StringFlag{ 32 | Name: "did", 33 | Usage: "Did token which must be decoded", 34 | }, 35 | }, 36 | Action: decodeDIDToken, 37 | }, 38 | { 39 | Name: "validate", 40 | Usage: "magic-cli token validate --did --clientId ", 41 | Flags: []cli.Flag{ 42 | &cli.StringFlag{ 43 | Name: "did", 44 | Usage: "Did token which must be validated", 45 | }, 46 | &cli.StringFlag{ 47 | Name: "clientId", 48 | Usage: "Magic Client ID to validate the aud field", 49 | EnvVars: []string{"MAGIC_CLIENT_ID"}, 50 | }, 51 | }, 52 | Action: validateDIDToken, 53 | }, 54 | }, 55 | }, 56 | { 57 | Name: "user", 58 | Aliases: []string{"u"}, 59 | Usage: "magic-cli -s user --did ", 60 | Flags: []cli.Flag{ 61 | &cli.StringFlag{ 62 | Name: "did", 63 | Usage: "Did token used for user info receiving", 64 | }, 65 | }, 66 | Action: userMetadata, 67 | }, 68 | }, 69 | Flags: []cli.Flag{ 70 | &cli.StringFlag{ 71 | Name: "secret", 72 | Usage: "Secret token which will be used for making request to backend api", 73 | Aliases: []string{"s"}, 74 | EnvVars: []string{"MAGIC_API_SECRET_KEY"}, 75 | }, 76 | }, 77 | } 78 | 79 | if err := app.Run(os.Args); err != nil { 80 | log.Fatal(err) 81 | } 82 | } 83 | 84 | func userMetadata(ctx *cli.Context) error { 85 | m, err := client.New(ctx.String("secret"), magic.NewDefaultClient()) 86 | 87 | if err != nil { 88 | return err 89 | } 90 | 91 | userInfo, err := m.User.GetMetadataByToken(ctx.String("did")) 92 | if err != nil { 93 | return err 94 | } 95 | 96 | fmt.Println(userInfo.String()) 97 | 98 | return nil 99 | } 100 | 101 | func decodeDIDToken(ctx *cli.Context) error { 102 | tk, err := token.NewToken(ctx.String("did")) 103 | if err != nil { 104 | return err 105 | } 106 | 107 | claim := tk.GetClaim() 108 | fmt.Println(claim.String()) 109 | 110 | return nil 111 | } 112 | 113 | func validateDIDToken(ctx *cli.Context) error { 114 | 115 | tk, err := token.NewToken(ctx.String("did")) 116 | if err != nil { 117 | return err 118 | } 119 | 120 | if err := tk.Validate(ctx.String("clientId")); err != nil { 121 | return err 122 | } 123 | 124 | return nil 125 | } 126 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | ## `1.0.0` - 07/05/2023 5 | 6 | ### Summary 7 | - 🚀 **Added:** Magic Connect developers can now use the Admin SDK to validate DID tokens. 8 | - ⚠️ **Changed:** After creating the Magic instance, it is now necessary to call a new initialize method for Magic Connect developers that want to utilize the Admin SDK. 9 | - 🛡️ **Security:** Additional validation of `aud` (client ID) is now being done during initialization of the SDK. 10 | 11 | ### Developer Notes 12 | 13 | #### 🚀 Added 14 | 15 | Magic Connect developers can now use the Admin SDK to validate DID tokens. 16 | 17 | **Details** 18 | There is full support for all `Token` SDK methods for MC. This is intended to be used with client side [`magic-js`](#) SDK which will now emit an `id-token-created` event with a DID token upon login via the [`connectWithUI`](#) method. 19 | 20 | This functionality is replicated on our other SDKs on Python and Ruby. 21 | 22 | #### ⚠️ Changed 23 | 24 | To validate tokens, a Magic clientId is now required in the `validate` method. 25 | Initializing the client will pull clientId from the Magic servers. 26 | Alternatively, you can get client ID from the magic dashboard and pass it in directly. 27 | 28 | **Previous Version** 29 | ```golang 30 | package main 31 | 32 | import ( 33 | "log" 34 | "fmt" 35 | 36 | "github.com/magiclabs/magic-admin-go/token" 37 | ) 38 | 39 | func main() { 40 | tk, err := token.NewToken("") 41 | if err != nil { 42 | log.Fatalf("DID token is malformed: %s", err.Error()) 43 | } 44 | 45 | if err := tk.Validate(); err != nil { 46 | log.Fatalf("DID token is invalid: %v", err) 47 | } 48 | 49 | fmt.Println(tk.GetClaim()) 50 | fmt.Println(tk.GetProof()) 51 | } 52 | ``` 53 | 54 | **New Version** 55 | ```golang 56 | package main 57 | 58 | import ( 59 | "log" 60 | "fmt" 61 | 62 | "github.com/magiclabs/magic-admin-go/client" 63 | "github.com/magiclabs/magic-admin-go/token" 64 | ) 65 | 66 | func main() { 67 | 68 | c, err := client.New("", magic.NewDefaultClient()) 69 | 70 | if err != nil { 71 | log.Fatalf("Unable to initialize client: %s", err.Error()) 72 | } 73 | 74 | tk, err := token.NewToken("") 75 | if err != nil { 76 | log.Fatalf("DID token is malformed: %s", err.Error()) 77 | } 78 | 79 | if err := tk.Validate(c.ClientInfo.ClientId); err != nil { 80 | log.Fatalf("DID token is invalid: %v", err) 81 | } 82 | 83 | fmt.Println(tk.GetClaim()) 84 | fmt.Println(tk.GetProof()) 85 | } 86 | ``` 87 | 88 | ### 🛡️ Security 89 | 90 | #### Client ID Validation 91 | 92 | Additional validation of `aud` (client ID) is now being done while validating DID tokens. This is for both Magic Connect and Magic Auth developers. 93 | 94 | 95 | ### 🚨 Breaking 96 | 97 | * Client initialization now makes a call to Magic servers to fetch `clientId` and will now return an error if there is an issue communicating to Magic's servers. 98 | * The `validate` method now takes in a clientId and validates it against the `aud` field in the DID token. 99 | 100 | ## `0.2.0` 101 | 102 | #### Changed 103 | 104 | - 105 | Dependency update for module. 106 | 107 | #### Added 108 | 109 | - 110 | Added multi-chain wallet for metadata retrieval calls. 111 | -------------------------------------------------------------------------------- /user/client.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-resty/resty/v2" 7 | 8 | "github.com/magiclabs/magic-admin-go" 9 | "github.com/magiclabs/magic-admin-go/token" 10 | "github.com/magiclabs/magic-admin-go/wallet" 11 | ) 12 | 13 | const ( 14 | userInfoV1 = "/v1/admin/auth/user/get" 15 | userLogoutV2 = "/v2/admin/auth/user/logout" 16 | ) 17 | 18 | type Client struct { 19 | secret string 20 | magicClientId string 21 | client *resty.Client 22 | } 23 | 24 | // NewUserClient constructor of user client api. 25 | func NewUserClient(secret string, magicClientId string, client *resty.Client) magic.User { 26 | return &Client{ 27 | secret: secret, 28 | magicClientId: magicClientId, 29 | client: client, 30 | } 31 | } 32 | 33 | // GetMetadataByIssuerAndWallet returns metadata by issuer and wallet type. 34 | func (u *Client) GetMetadataByIssuerAndWallet(issuer string, walletType wallet.Type) (*magic.UserInfo, error) { 35 | return u.getMetadataByIssuer(issuer, walletType) 36 | } 37 | 38 | // GetMetadataByPublicAddressAndWallet returns metadata by public address and wallet type. 39 | func (u *Client) GetMetadataByPublicAddressAndWallet(pubAddr string, walletType wallet.Type) (*magic.UserInfo, error) { 40 | return u.getMetadataByIssuer(fmt.Sprintf("did:ethr:%s", pubAddr), walletType) 41 | } 42 | 43 | // GetMetadataByTokenAndWallet returns metadata by DID token with decoding and validating it. 44 | func (u *Client) GetMetadataByTokenAndWallet(didToken string, walletType wallet.Type) (*magic.UserInfo, error) { 45 | tk, err := token.NewToken(didToken) 46 | if err != nil { 47 | return nil, err 48 | } 49 | if err := tk.Validate(u.magicClientId); err != nil { 50 | return nil, err 51 | } 52 | 53 | return u.getMetadataByIssuer(tk.GetIssuer(), walletType) 54 | } 55 | 56 | // GetMetadataByIssuer returns metadata by issuer. 57 | func (u *Client) GetMetadataByIssuer(issuer string) (*magic.UserInfo, error) { 58 | return u.GetMetadataByIssuerAndWallet(issuer, wallet.NONE) 59 | } 60 | 61 | // GetMetadataByPublicAddress returns metadata by public address. 62 | func (u *Client) GetMetadataByPublicAddress(pubAddr string) (*magic.UserInfo, error) { 63 | return u.GetMetadataByPublicAddressAndWallet(pubAddr, wallet.NONE) 64 | } 65 | 66 | // GetMetadataByToken returns metadata by DID token with decoding and validating it. 67 | func (u *Client) GetMetadataByToken(didToken string) (*magic.UserInfo, error) { 68 | return u.GetMetadataByTokenAndWallet(didToken, wallet.NONE) 69 | } 70 | 71 | // getMetadataByIssuer helper method to return metadata by issuer and wallet type. 72 | func (u *Client) getMetadataByIssuer(issuer string, walletType wallet.Type) (*magic.UserInfo, error) { 73 | meta := new(magic.UserInfo) 74 | respData := new(magic.Response) 75 | respData.Data = meta 76 | queryParams := map[string]string{"issuer": issuer} 77 | 78 | if walletType != wallet.NONE { 79 | queryParams["wallet_type"] = string(walletType) 80 | } 81 | 82 | r, err := u.client.R(). 83 | SetQueryParams(queryParams). 84 | SetHeader(magic.APISecretHeader, u.secret). 85 | SetResult(respData). 86 | Get(userInfoV1) 87 | if err != nil { 88 | return nil, &magic.APIConnectionError{Err: err} 89 | } 90 | if r.IsError() { 91 | return nil, magic.WrapError(r, r.Error().(*magic.Error)) 92 | } 93 | 94 | return meta, nil 95 | } 96 | 97 | // LogoutByIssuer logout user from magic.link service by issuer. 98 | func (u *Client) LogoutByIssuer(issuer string) error { 99 | r, err := u.client.R(). 100 | SetBody(map[string]interface{}{"issuer": issuer}). 101 | SetHeader(magic.APISecretHeader, u.secret). 102 | Post(userLogoutV2) 103 | if err != nil { 104 | return &magic.APIConnectionError{Err: err} 105 | } 106 | if r.IsError() { 107 | return magic.WrapError(r, r.Error().(*magic.Error)) 108 | } 109 | 110 | return nil 111 | } 112 | 113 | // LogoutByPublicAddress logout user from magic.link service by public address. 114 | func (u *Client) LogoutByPublicAddress(pubAddr string) error { 115 | return u.LogoutByIssuer(fmt.Sprintf("did:ethr:%s", pubAddr)) 116 | } 117 | 118 | // LogoutByToken logout user from magic.link service by DID token with decoding and validating it. 119 | func (u *Client) LogoutByToken(didToken string) error { 120 | tk, err := token.NewToken(didToken) 121 | if err != nil { 122 | return err 123 | } 124 | if err := tk.Validate(u.magicClientId); err != nil { 125 | return err 126 | } 127 | 128 | return u.LogoutByIssuer(tk.GetIssuer()) 129 | } 130 | -------------------------------------------------------------------------------- /token/did.go: -------------------------------------------------------------------------------- 1 | package token 2 | 3 | import ( 4 | "bytes" 5 | "encoding/base64" 6 | "encoding/json" 7 | "fmt" 8 | "strings" 9 | "time" 10 | 11 | "github.com/ethereum/go-ethereum/common" 12 | "github.com/ethereum/go-ethereum/common/hexutil" 13 | "github.com/ethereum/go-ethereum/crypto" 14 | ) 15 | 16 | const nbfGracePeriod = 300 17 | 18 | type Claim struct { 19 | Iat int64 `json:"iat"` 20 | Ext int64 `json:"ext"` 21 | Iss string `json:"iss"` 22 | Sub string `json:"sub"` 23 | Aud string `json:"aud"` 24 | Nbf int64 `json:"nbf"` 25 | Tid string `json:"tid"` 26 | Add string `json:"add,omitempty"` 27 | } 28 | 29 | // String returns string data of the claim in json format. 30 | func (c *Claim) String() string { 31 | data, err := json.Marshal(c) 32 | if err != nil { 33 | panic(err) 34 | } 35 | 36 | return string(data) 37 | } 38 | 39 | // Token is representation of the DID token which contains proof (hash) and the serialized claim. 40 | type Token struct { 41 | proof string 42 | claim Claim 43 | } 44 | 45 | // NewToken creates token decoder and validator. 46 | func NewToken(tk string) (*Token, error) { 47 | token := new(Token) 48 | 49 | decoded, err := base64.URLEncoding.DecodeString(tk) 50 | if err != nil { 51 | return nil, &DIDTokenError{err} 52 | } 53 | 54 | // Decode list of proof and serialized in json claim. 55 | var decodePieces []string 56 | if err := json.Unmarshal(decoded, &decodePieces); err != nil { 57 | return nil, &DIDTokenError{err} 58 | } 59 | 60 | token.proof = decodePieces[0] 61 | 62 | if err := json.Unmarshal([]byte(decodePieces[1]), &token.claim); err != nil { 63 | return nil, &DIDTokenError{err} 64 | } 65 | 66 | return token, err 67 | } 68 | 69 | // GetIssuer returns the claim issuer. 70 | func (t *Token) GetIssuer() string { 71 | return t.claim.Iss 72 | } 73 | 74 | // GetPublicAddress split issuer on parts and returns only public address. 75 | func (t *Token) GetPublicAddress() (string, error) { 76 | parts := strings.Split(t.GetIssuer(), ":") 77 | if len(parts) != 3 { 78 | return "", ErrNotValidPublicAddr 79 | } 80 | 81 | return parts[2], nil 82 | } 83 | 84 | // GetProof returns the hash of the Ethereum message with claim serialized in json. 85 | func (t *Token) GetProof() string { 86 | return t.proof 87 | } 88 | 89 | // GetClaim returns the claim structure with all data. 90 | func (t *Token) GetClaim() Claim { 91 | return t.claim 92 | } 93 | 94 | // GetNbfGracePeriod returns nbf time with grace period. 95 | func (t *Token) GetNbfGracePeriod() int64 { 96 | return t.claim.Nbf - nbfGracePeriod 97 | } 98 | 99 | // Validates DID token by recovering public key using signature data and the hash 100 | // of the claim message. 101 | func (t *Token) Validate(clientId string) error { 102 | jsonClaim, err := json.Marshal(t.claim) 103 | if err != nil { 104 | return &DIDTokenError{err} 105 | } 106 | compactedBuffer := new(bytes.Buffer) 107 | if err := json.Compact(compactedBuffer, jsonClaim); err != nil { 108 | return err 109 | } 110 | 111 | proof, err := hexutil.Decode(t.proof) 112 | if err != nil { 113 | return &DIDTokenError{err} 114 | } 115 | addr, err := ecRecover(signHash(compactedBuffer.Bytes()).Bytes(), proof) 116 | if err != nil { 117 | return &DIDTokenError{err} 118 | } 119 | 120 | // Validate public address that is matched which is specified in proof and claim. 121 | pubAddr, err := t.GetPublicAddress() 122 | if err != nil { 123 | return &DIDTokenError{err} 124 | } 125 | if addr.String() != pubAddr { 126 | return ErrNotValidProof 127 | } 128 | 129 | // Check that current token is not expired. 130 | now := time.Now().Unix() 131 | if now > t.claim.Ext { 132 | return ErrExpired 133 | } 134 | if now < t.GetNbfGracePeriod() { 135 | return ErrNbfExpired 136 | } 137 | 138 | if t.claim.Aud != clientId { 139 | return ErrAudMismatch 140 | } 141 | 142 | return nil 143 | } 144 | 145 | // signHash formats Ethereum signed message and takes keccak256 hash from it. 146 | func signHash(data []byte) common.Hash { 147 | msg := fmt.Sprintf("\x19Ethereum Signed Message:\n%d%s", len(data), data) 148 | return crypto.Keccak256Hash([]byte(msg)) 149 | } 150 | 151 | // ecRecover returns the address for the Account that was used to create the signature. 152 | // 153 | // Note, this function is compatible with eth_sign and personal_sign. As such it recovers 154 | // the address of: 155 | // 156 | // hash = Keccak256Hash("\x19${byteVersion}Ethereum Signed Message:\n${message length}${message}") 157 | // addr = ecRecover(hash, signature) 158 | func ecRecover(hash hexutil.Bytes, sig hexutil.Bytes) (common.Address, error) { 159 | if len(sig) != 65 { 160 | return common.Address{}, fmt.Errorf("Signature must be 65 bytes long") 161 | } 162 | if sig[64] != 27 && sig[64] != 28 { 163 | return common.Address{}, fmt.Errorf("Invalid Ethereum signature (V is not 27 or 28)") 164 | } 165 | sig[64] -= 27 166 | rpk, err := crypto.SigToPub(hash, sig) 167 | if err != nil { 168 | return common.Address{}, err 169 | } 170 | 171 | return crypto.PubkeyToAddress(*rpk), nil 172 | } 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Magic Admin Golang SDK 2 | 3 | The Magic Admin Golang SDK provides convenient ways for developers to interact with Magic API endpoints and an array of utilities to handle [DID Token](https://magic.link/docs/introduction/decentralized-id). 4 | 5 | ## Table of Contents 6 | 7 | * [Documentation](#documentation) 8 | * [Quick Start](#quick-start) 9 | * [Development](#development) 10 | * [Changelog](#changelog) 11 | * [License](#license) 12 | 13 | ## Documentation 14 | See the [Magic doc](https://magic.link/docs/api-reference/server-side-sdks/go)! 15 | 16 | ## Installation 17 | 18 | The SDK requires `Golang 1.13+` and Go Modules. To make sure your project is using Go Modules, you can look for `go.mod` file in your project's root directory. If it exits, then you are already using the Go Modules. If not, you can follow [this guide](https://blog.golang.org/migrating-to-go-modules) to migrate to Go Modules. 19 | 20 | Simply reference `magic-admin-go` in a Go program with an `import` of the SDK: 21 | 22 | ``` golang 23 | import ( 24 | ... 25 | "github.com/magiclabs/magic-admin-go" 26 | ... 27 | ) 28 | ``` 29 | 30 | Run any of the normal `go` commands (ex: `build`/`install`). The Go toolchain will take care of fetching the SDK automatically. 31 | 32 | Alternatively, you can explicitly `go get` the package into a project: 33 | 34 | ```sh 35 | go get github.com/magiclabs/magic-admin-go 36 | ``` 37 | 38 | ## Command line utility 39 | 40 | Command line utility is created for testing purposes and can be used for decoding and validating DID tokens. It also provides functionality to retrieve user info. 41 | 42 | You can simply install it by the command: 43 | ```bash 44 | go install github.com/magiclabs/magic-admin-go/cmd/magic-cli 45 | ``` 46 | 47 | Current available command supported: 48 | 49 | ```bash 50 | $ magic-cli -h 51 | NAME: 52 | magic-cli - command line utility to make requests to api and validate tokens 53 | 54 | USAGE: 55 | magic-cli [global options] command [command options] [arguments...] 56 | 57 | COMMANDS: 58 | token, t magic-cli token [decode|validate] --did [--clientId ] 59 | user, u magic-cli -s user --did 60 | help, h Shows a list of commands or help for one command 61 | 62 | GLOBAL OPTIONS: 63 | --secret value, -s value Secret token which will be used for making request to backend api [$MAGIC_API_SECRET_KEY] 64 | --help, -h show help (default: false) 65 | ``` 66 | 67 | ## Quick Start 68 | 69 | Before you start, you will need an API secret key. You can get one from the [Magic Dashboard](https://dashboard.magic.link/). Once you have the API secret key, you can instantiate a Magic object. 70 | 71 | Sample code to retrieve user info by a [DID token](https://docs.magic.link/decentralized-id): 72 | ```golang 73 | package main 74 | 75 | import ( 76 | "log" 77 | "fmt" 78 | 79 | "github.com/magiclabs/magic-admin-go" 80 | "github.com/magiclabs/magic-admin-go/client" 81 | ) 82 | 83 | func main() { 84 | m, err := client.New("", magic.NewDefaultClient()) 85 | userInfo, err := m.User.GetMetadataByToken("") 86 | if err != nil { 87 | log.Fatalf("Error: %s", err.Error()) 88 | } 89 | 90 | fmt.Println(userInfo) 91 | } 92 | ``` 93 | 94 | Sample code to validate a [DID token](https://docs.magic.link/decentralized-id) and retrieve the `claim` and `proof` from the token: 95 | ```golang 96 | package main 97 | 98 | import ( 99 | "log" 100 | "fmt" 101 | 102 | "github.com/magiclabs/magic-admin-go/client" 103 | "github.com/magiclabs/magic-admin-go/token" 104 | ) 105 | 106 | func main() { 107 | 108 | c, err := client.New("", magic.NewDefaultClient()) 109 | 110 | if err != nil { 111 | log.Fatalf("Unable to initialize client: %s", err.Error()) 112 | } 113 | 114 | tk, err := token.NewToken("") 115 | if err != nil { 116 | log.Fatalf("DID token is malformed: %s", err.Error()) 117 | } 118 | 119 | if err := tk.Validate(c.ClientInfo.ClientId); err != nil { 120 | log.Fatalf("DID token is invalid: %v", err) 121 | } 122 | 123 | fmt.Println(tk.GetClaim()) 124 | fmt.Println(tk.GetProof()) 125 | } 126 | ``` 127 | 128 | ### Configure Network Strategy 129 | 130 | The `NewClientWithRetry` method creates a client with `retries`, `retryWait`, `timeout` options. `NewClientWithRetry` returns a `*resty.Client` instance which can be used with the Magic client. 131 | 132 | ```golang 133 | cl := magic.NewClientWithRetry(5, time.Second, 10 * time.Second) 134 | m := client.New("", cl) 135 | ``` 136 | 137 | ## Development 138 | 139 | We would love to have you contribute to the SDK. To get started, you will need to clone this repository and fetch the dependencies. 140 | 141 | To run the existing tests: 142 | 143 | ```bash 144 | make test 145 | ``` 146 | 147 | To build and install magic-cli utility tool, you can run: 148 | 149 | ```bash 150 | make install 151 | ``` 152 | 153 | To build magic-cli utility tool separately as a binary, you can run: 154 | 155 | ```bash 156 | make build 157 | ``` 158 | 159 | Please also see our [CONTRIBUTING](CONTRIBUTING.md) guide for more information. 160 | 161 | ## Changelog 162 | See [Changelog](CHANGELOG.md) 163 | 164 | ## License 165 | See [License](LICENSE.txt) 166 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | When contributing to this repository, please first discuss the change you wish to make via an **issue**. This can be a feature request or a bug report. After a maintainer has triaged your issue, you are welcome to collaborate on a pull request. If your change is small or uncomplicated, you are welcome to open an issue and pull request simultaneously. 4 | 5 | Please note we have a **code of conduct**, please follow it in all your interactions with the project. 6 | 7 | ## Setting up for Local Development 8 | 9 | 1. Fork this repostiory. 10 | 2. Clone your fork. 11 | 3. Create a new branch in your local repository with the following pattern: 12 | 13 | - For bug fixes: `bug/#[issue_number]/[descriptive_bug_name]` 14 | - For features: `feature/#[issue_number]/[descriptive_feature_name]` 15 | - For chores/the rest: `chore/[descriptive_chore_name]` 16 | 17 | 4. Start building for development 18 | 19 | ## Opening a Pull Request 20 | 21 | 1. Update the **`Upcoming Changes`** section of [`CHANGELOG.md`](./CHANGELOG.md) with your fixes, changes, or additions. A maintainer will label your changes with a version number and release date once they are published. 22 | 2. Open a pull request from your fork/branch to the upstream `master` branch of _this_ repository. 23 | 3. A maintainer will review your code changes and offer feedback or suggestions if necessary. Once your changes are approved, a maintainer will merge the pull request for you and publish a release. 24 | 25 | ## Contributor Covenant Code of Conduct 26 | 27 | ### Our Pledge 28 | 29 | We as members, contributors, and leaders pledge to make participation in our 30 | community a harassment-free experience for everyone, regardless of age, body 31 | size, visible or invisible disability, ethnicity, sex characteristics, gender 32 | identity and expression, level of experience, education, socio-economic status, 33 | nationality, personal appearance, race, religion, or sexual identity 34 | and orientation. 35 | 36 | We pledge to act and interact in ways that contribute to an open, welcoming, 37 | diverse, inclusive, and healthy community. 38 | 39 | ### Our Standards 40 | 41 | Examples of behavior that contributes to a positive environment for our 42 | community include: 43 | 44 | - Demonstrating empathy and kindness toward other people 45 | - Being respectful of differing opinions, viewpoints, and experiences 46 | - Giving and gracefully accepting constructive feedback 47 | - Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience 48 | - Focusing on what is best not just for us as individuals, but for the overall community 49 | 50 | Examples of unacceptable behavior include: 51 | 52 | - The use of sexualized language or imagery, and sexual attention or advances of any kind 53 | - Trolling, insulting or derogatory comments, and personal or political attacks 54 | - Public or private harassment 55 | - Publishing others' private information, such as a physical or email address, without their explicit permission 56 | - Other conduct which could reasonably be considered inappropriate in a professional setting 57 | 58 | ### Enforcement Responsibilities 59 | 60 | Community leaders are responsible for clarifying and enforcing our standards of 61 | acceptable behavior and will take appropriate and fair corrective action in 62 | response to any behavior that they deem inappropriate, threatening, offensive, 63 | or harmful. 64 | 65 | Community leaders have the right and responsibility to remove, edit, or reject 66 | comments, commits, code, wiki edits, issues, and other contributions that are 67 | not aligned to this Code of Conduct, and will communicate reasons for moderation 68 | decisions when appropriate. 69 | 70 | ### Scope 71 | 72 | This Code of Conduct applies within all community spaces, and also applies when 73 | an individual is officially representing the community in public spaces. 74 | Examples of representing our community include using an official e-mail address, 75 | posting via an official social media account, or acting as an appointed 76 | representative at an online or offline event. 77 | 78 | ### Enforcement 79 | 80 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 81 | reported to the community leaders responsible for enforcement at [support@magic.link](mailto:support@magic.link). 82 | All complaints will be reviewed and investigated promptly and fairly. 83 | 84 | All community leaders are obligated to respect the privacy and security of the 85 | reporter of any incident. 86 | 87 | ### Enforcement Guidelines 88 | 89 | Community leaders will follow these Community Impact Guidelines in determining 90 | the consequences for any action they deem in violation of this Code of Conduct: 91 | 92 | #### 1. Correction 93 | 94 | **Community Impact**: Use of inappropriate language or other behavior deemed 95 | unprofessional or unwelcome in the community. 96 | 97 | **Consequence**: A private, written warning from community leaders, providing 98 | clarity around the nature of the violation and an explanation of why the 99 | behavior was inappropriate. A public apology may be requested. 100 | 101 | #### 2. Warning 102 | 103 | **Community Impact**: A violation through a single incident or series 104 | of actions. 105 | 106 | **Consequence**: A warning with consequences for continued behavior. No 107 | interaction with the people involved, including unsolicited interaction with 108 | those enforcing the Code of Conduct, for a specified period of time. This 109 | includes avoiding interactions in community spaces as well as external channels 110 | like social media. Violating these terms may lead to a temporary or 111 | permanent ban. 112 | 113 | #### 3. Temporary Ban 114 | 115 | **Community Impact**: A serious violation of community standards, including 116 | sustained inappropriate behavior. 117 | 118 | **Consequence**: A temporary ban from any sort of interaction or public 119 | communication with the community for a specified period of time. No public or 120 | private interaction with the people involved, including unsolicited interaction 121 | with those enforcing the Code of Conduct, is allowed during this period. 122 | Violating these terms may lead to a permanent ban. 123 | 124 | #### 4. Permanent Ban 125 | 126 | **Community Impact**: Demonstrating a pattern of violation of community 127 | standards, including sustained inappropriate behavior, harassment of an 128 | individual, or aggression toward or disparagement of classes of individuals. 129 | 130 | **Consequence**: A permanent ban from any sort of public interaction within 131 | the community. 132 | 133 | ### Attribution 134 | 135 | This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), 136 | version 2.0, available at 137 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 138 | 139 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 140 | enforcement ladder](https://github.com/mozilla/diversity). 141 | 142 | For answers to common questions about this code of conduct, see the FAQ at 143 | https://www.contributor-covenant.org/faq. Translations are available at 144 | https://www.contributor-covenant.org/translations. 145 | -------------------------------------------------------------------------------- /user/client_test.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "net/http/httptest" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/assert" 10 | "github.com/stretchr/testify/require" 11 | 12 | "github.com/magiclabs/magic-admin-go" 13 | "github.com/magiclabs/magic-admin-go/wallet" 14 | ) 15 | 16 | const testDIDToken = "WyIweGFhNTBiZTcwNzI5Y2E3MDViYTdjOGQwMDE4NWM2ZjJkYTQ3OWQwZm" + 17 | "NkZTUzMTFjYTRjZTViMWJhNzE1YzhhNzIxYzVmMTk0ODQzNGY5NmZmNTc3ZDdiMmI2YWQ4MmQ" + 18 | "zZGQ1YTI0NTdmZTY5OThiMTM3ZWQ5YmMwOGQzNmU1NDljMWIiLCJ7XCJpYXRcIjoxNTg2NzY0" + 19 | "MjcwLFwiZXh0XCI6MTExNzM1Mjg1MDAsXCJpc3NcIjpcImRpZDpldGhyOjB4NEI3M0M1ODM3M" + 20 | "EFFZmNFZjg2QTYwMjFhZkNEZTU2NzM1MTEzNzZCMlwiLFwic3ViXCI6XCJOanJBNTNTY1E4SV" + 21 | "Y4ME5Kbng0dDNTaGk5LWtGZkY1cWF2RDJWcjBkMWRjPVwiLFwiYXVkXCI6XCJkaWQ6bWFnaWM" + 22 | "6NzMxODQ4Y2MtMDg0ZS00MWZmLWJiZGYtN2YxMDM4MTdlYTZiXCIsXCJuYmZcIjoxNTg2NzY0" + 23 | "MjcwLFwidGlkXCI6XCJlYmNjODgwYS1mZmM5LTQzNzUtODRhZS0xNTRjY2Q1Yzc0NmRcIixcI" + 24 | "mFkZFwiOlwiMHg4NGQ2ODM5MjY4YTFhZjkxMTFmZGVjY2QzOTZmMzAzODA1ZGNhMmJjMDM0NT" + 25 | "BiN2ViMTE2ZTJmNWZjOGM1YTcyMmQxZmI5YWYyMzNhYTczYzVjMTcwODM5Y2U1YWQ4MTQxYjl" + 26 | "iNDY0MzM4MDk4MmRhNGJmYmIwYjExMjg0OTg4ZjFiXCJ9Il0=" 27 | 28 | const testSecret = "sk_test_E123E4567E8901D2" 29 | 30 | const testClientId = "did:magic:731848cc-084e-41ff-bbdf-7f103817ea6b" 31 | 32 | var ( 33 | testDataMagicWallets = []magic.Wallet{ 34 | { 35 | Type: "SOLANA", 36 | Network: "MAINNET", 37 | PublicAddress: "foobar", 38 | }, 39 | } 40 | testSuccessData = magic.UserInfo{ 41 | Email: "user@email.com", 42 | Issuer: "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", 43 | PublicAddress: "0x4B73C58370AEfcEf86A6021afCDe5673511376B2", 44 | } 45 | testSuccessDataWithWallets = magic.UserInfo{ 46 | Email: "user@email.com", 47 | Issuer: "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", 48 | PublicAddress: "0x4B73C58370AEfcEf86A6021afCDe5673511376B2", 49 | Wallets: &testDataMagicWallets, 50 | } 51 | ) 52 | 53 | func TestUserGetMetadata(t *testing.T) { 54 | srv := createServerSuccess(t, &testSuccessData) 55 | defer srv.Close() 56 | 57 | // Replace host url to test one. 58 | client := magic.NewDefaultClient() 59 | client.SetHostURL(srv.URL) 60 | 61 | uClient := NewUserClient(testSecret, testClientId, client) 62 | 63 | meta, err := uClient.GetMetadataByToken(testDIDToken) 64 | require.NoError(t, err, "can't create new token") 65 | 66 | assert.Equal(t, "user@email.com", meta.Email) 67 | assert.Equal(t, "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.Issuer) 68 | assert.Equal(t, "0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.PublicAddress) 69 | } 70 | 71 | func TestUserGetMetadataWithWallet(t *testing.T) { 72 | srv := createServerSuccess(t, &testSuccessDataWithWallets) 73 | defer srv.Close() 74 | 75 | // Replace host url to test one. 76 | client := magic.NewDefaultClient() 77 | client.SetHostURL(srv.URL) 78 | 79 | uClient := NewUserClient(testSecret, testClientId, client) 80 | 81 | meta, err := uClient.GetMetadataByTokenAndWallet(testDIDToken, wallet.SOLANA) 82 | require.NoError(t, err, "can't create new token") 83 | 84 | assert.Equal(t, "user@email.com", meta.Email) 85 | assert.Equal(t, "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.Issuer) 86 | assert.Equal(t, "0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.PublicAddress) 87 | assert.NotNil(t, meta.Wallets) 88 | assert.Len(t, *meta.Wallets, 1) 89 | assert.Equal(t, wallet.SOLANA, (*meta.Wallets)[0].Type) 90 | } 91 | 92 | func TestUserGetMetadataWithAny(t *testing.T) { 93 | srv := createServerSuccess(t, &testSuccessDataWithWallets) 94 | defer srv.Close() 95 | 96 | // Replace host url to test one. 97 | client := magic.NewDefaultClient() 98 | client.SetHostURL(srv.URL) 99 | 100 | uClient := NewUserClient(testSecret, testClientId, client) 101 | 102 | meta, err := uClient.GetMetadataByTokenAndWallet(testDIDToken, wallet.ANY) 103 | require.NoError(t, err, "can't create new token") 104 | 105 | assert.Equal(t, "user@email.com", meta.Email) 106 | assert.Equal(t, "did:ethr:0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.Issuer) 107 | assert.Equal(t, "0x4B73C58370AEfcEf86A6021afCDe5673511376B2", meta.PublicAddress) 108 | assert.NotNil(t, meta.Wallets) 109 | assert.Len(t, *meta.Wallets, 1) 110 | assert.Equal(t, wallet.SOLANA, (*meta.Wallets)[0].Type) 111 | } 112 | 113 | func TestUserGetMetadataWrongSecret(t *testing.T) { 114 | srv := createServerSuccess(t, &testSuccessData) 115 | defer srv.Close() 116 | 117 | // Replace host url to test one. 118 | client := magic.NewDefaultClient() 119 | client.SetHostURL(srv.URL) 120 | 121 | uClient := NewUserClient("wrong_secret", testClientId, client) 122 | 123 | _, err := uClient.GetMetadataByToken(testDIDToken) 124 | require.Error(t, err, "server must return error") 125 | _, ok := err.(*magic.AuthenticationError) 126 | require.True(t, ok, "Error type must be AuthenticationError") 127 | } 128 | 129 | func TestUserGetMetadataBackendFailure(t *testing.T) { 130 | srv := createServerFail(t) 131 | defer srv.Close() 132 | 133 | // Replace host url to test one. 134 | client := magic.NewDefaultClient() 135 | client.SetHostURL(srv.URL) 136 | 137 | uClient := NewUserClient("wrong_secret", testClientId, client) 138 | 139 | _, err := uClient.GetMetadataByToken(testDIDToken) 140 | require.Error(t, err, "server must return error") 141 | _, ok := err.(*magic.APIError) 142 | require.True(t, ok, "Error type must be APIError") 143 | } 144 | 145 | func TestUserLogout(t *testing.T) { 146 | srv := createServerSuccess(t, &testSuccessData) 147 | defer srv.Close() 148 | 149 | // Replace host url to test one. 150 | client := magic.NewDefaultClient() 151 | client.SetHostURL(srv.URL) 152 | 153 | uClient := NewUserClient(testSecret, testClientId, client) 154 | 155 | err := uClient.LogoutByToken(testDIDToken) 156 | require.NoError(t, err, "can't logout user by DID token") 157 | } 158 | 159 | func TestUserLogoutBackendFailure(t *testing.T) { 160 | srv := createServerFail(t) 161 | defer srv.Close() 162 | 163 | // Replace host url to test one. 164 | client := magic.NewDefaultClient() 165 | client.SetHostURL(srv.URL) 166 | 167 | uClient := NewUserClient("wrong_secret", testClientId, client) 168 | 169 | err := uClient.LogoutByToken(testDIDToken) 170 | require.Error(t, err, "server must return error") 171 | _, ok := err.(*magic.APIError) 172 | require.True(t, ok, "Error type must be APIError") 173 | } 174 | 175 | // createServerSuccess creates internal server which simulates positive case for backend api requests. 176 | func createServerSuccess(t *testing.T, data *magic.UserInfo) *httptest.Server { 177 | return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 178 | t.Logf("Method: %v", r.Method) 179 | t.Logf("Path: %v", r.URL.Path) 180 | 181 | w.Header().Add("Content-Type", "application/json") 182 | 183 | secret := r.Header.Get(magic.APISecretHeader) 184 | if secret != testSecret { 185 | w.WriteHeader(http.StatusUnauthorized) 186 | resp := magic.Response{ 187 | ErrorCode: "err_code_unauthorized", 188 | Message: "unauthorized", 189 | Status: "fail", 190 | } 191 | data, err := json.Marshal(resp) 192 | require.NoError(t, err, "can't marshal test data") 193 | _, _ = w.Write(data) 194 | t.Log("401 - Unauthorized") 195 | return 196 | } 197 | 198 | switch r.Method { 199 | case http.MethodGet: 200 | switch r.URL.Path { 201 | case userInfoV1: 202 | resp := magic.Response{ 203 | Data: data, 204 | Status: "ok", 205 | } 206 | data, err := json.Marshal(resp) 207 | require.NoError(t, err, "can't marshal test data") 208 | _, _ = w.Write(data) 209 | } 210 | 211 | case http.MethodPost: 212 | switch r.URL.Path { 213 | case userLogoutV2: 214 | resp := magic.Response{ 215 | Status: "ok", 216 | } 217 | data, err := json.Marshal(resp) 218 | require.NoError(t, err, "can't marshal test data") 219 | _, _ = w.Write(data) 220 | } 221 | } 222 | })) 223 | } 224 | 225 | // createServerFail creates internal server which simulates negative case for backend api requests. 226 | func createServerFail(t *testing.T) *httptest.Server { 227 | return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 228 | t.Logf("Method: %v", r.Method) 229 | t.Logf("Path: %v", r.URL.Path) 230 | 231 | w.Header().Add("Content-Type", "application/json") 232 | 233 | switch r.URL.Path { 234 | case userInfoV1, userLogoutV2: 235 | w.WriteHeader(http.StatusInternalServerError) 236 | resp := magic.Response{ 237 | ErrorCode: "err_code_internal_server_error", 238 | Message: "internal server error", 239 | Status: "fail", 240 | } 241 | data, err := json.Marshal(resp) 242 | require.NoError(t, err, "can't marshal test data") 243 | _, _ = w.Write(data) 244 | t.Log("500 - Internal server error") 245 | return 246 | } 247 | })) 248 | } 249 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 4 | cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg= 5 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 6 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 7 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 8 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 9 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 10 | cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw= 11 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 12 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 13 | cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o= 14 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 15 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 16 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 17 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 18 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 19 | collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE= 20 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 21 | github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1/go.mod h1:fBF9PQNqB8scdgpZ3ufzaLntG0AG7C1WjPMsiFOmfHM= 22 | github.com/Azure/azure-sdk-for-go/sdk/internal v0.8.3/go.mod h1:KLF4gFr6DcKFZwSuH8w8yEK6DpFl3LP5rhdvAb7Yz5I= 23 | github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.3.0/go.mod h1:tPaiy8S5bQ+S5sOiDlINkp7+Ef339+Nz5L5XO+cnOHo= 24 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 25 | github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 26 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 27 | github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= 28 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 29 | github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= 30 | github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw= 31 | github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= 32 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 33 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 34 | github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= 35 | github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= 36 | github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0= 37 | github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= 38 | github.com/aws/aws-sdk-go-v2/config v1.1.1/go.mod h1:0XsVy9lBI/BCXm+2Tuvt39YmdHwS5unDQmxZOYe8F5Y= 39 | github.com/aws/aws-sdk-go-v2/credentials v1.1.1/go.mod h1:mM2iIjwl7LULWtS6JCACyInboHirisUUdkBPoTHMOUo= 40 | github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2/go.mod h1:3hGg3PpiEjHnrkrlasTfxFqUsZ2GCk/fMUn4CbKgSkM= 41 | github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2/go.mod h1:45MfaXZ0cNbeuT0KQ1XJylq8A6+OpVV2E5kvY/Kq+u8= 42 | github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= 43 | github.com/aws/aws-sdk-go-v2/service/sso v1.1.1/go.mod h1:SuZJxklHxLAXgLTc1iFXbEWkXs7QRTQpCLGaKIprQW0= 44 | github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM= 45 | github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= 46 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 47 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 48 | github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c= 49 | github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= 50 | github.com/btcsuite/btcd/btcec/v2 v2.2.0/go.mod h1:U7MHm051Al6XmscBQ0BoNydpOTsFAn707034b5nY8zU= 51 | github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= 52 | github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= 53 | github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= 54 | github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= 55 | github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34= 56 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 57 | github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= 58 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 59 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 60 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 61 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 62 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 63 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 64 | github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304= 65 | github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= 66 | github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q= 67 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 68 | github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= 69 | github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 70 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 71 | github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= 72 | github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= 73 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 74 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 75 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 76 | github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= 77 | github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0= 78 | github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= 79 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= 80 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4= 81 | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= 82 | github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M= 83 | github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw= 84 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 85 | github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ= 86 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 87 | github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= 88 | github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= 89 | github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= 90 | github.com/docker/docker v1.6.2/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 91 | github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk= 92 | github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y= 93 | github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= 94 | github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= 95 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 96 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 97 | github.com/ethereum/go-ethereum v1.10.20 h1:75IW830ClSS40yrQC1ZCMZCt5I+zU16oqId2SiQwdQ4= 98 | github.com/ethereum/go-ethereum v1.10.20/go.mod h1:LWUN82TCHGpxB3En5HVmLLzPD7YSrEUFmFfN1nKkVN0= 99 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= 100 | github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= 101 | github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= 102 | github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= 103 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 104 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 105 | github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= 106 | github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61/go.mod h1:Q0X6pkwTILDlzrGEckF6HKjXe48EgsY/l7K7vhY4MW8= 107 | github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= 108 | github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= 109 | github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4= 110 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 111 | github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= 112 | github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= 113 | github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs= 114 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 115 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 116 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 117 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 118 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 119 | github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= 120 | github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= 121 | github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= 122 | github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= 123 | github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= 124 | github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= 125 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 126 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 127 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 128 | github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 129 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 130 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 131 | github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= 132 | github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= 133 | github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= 134 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 135 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 136 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 137 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 138 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 139 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 140 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 141 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 142 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 143 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 144 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 145 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 146 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 147 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 148 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 149 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 150 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 151 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 152 | github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 153 | github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 154 | github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y= 155 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 156 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 157 | github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= 158 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 159 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 160 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 161 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 162 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 163 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 164 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 165 | github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 166 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 167 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 168 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 169 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 170 | github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 171 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 172 | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 173 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 174 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 175 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= 176 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 177 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 178 | github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= 179 | github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0= 180 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 181 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 182 | github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= 183 | github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA= 184 | github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= 185 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 186 | github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y= 187 | github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= 188 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 189 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 190 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 191 | github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY= 192 | github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI= 193 | github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8= 194 | github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk= 195 | github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE= 196 | github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= 197 | github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= 198 | github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8= 199 | github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE= 200 | github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0= 201 | github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po= 202 | github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= 203 | github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= 204 | github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= 205 | github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= 206 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 207 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 208 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 209 | github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o= 210 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 211 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 212 | github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= 213 | github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0= 214 | github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= 215 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 216 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 217 | github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= 218 | github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= 219 | github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg= 220 | github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= 221 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 222 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 223 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 224 | github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= 225 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 226 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 227 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 228 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 229 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 230 | github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= 231 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 232 | github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg= 233 | github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= 234 | github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= 235 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 236 | github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 237 | github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 238 | github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ= 239 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 240 | github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 241 | github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 242 | github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 243 | github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 244 | github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= 245 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 246 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 247 | github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 248 | github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 249 | github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 250 | github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE= 251 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 252 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 253 | github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4= 254 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 255 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 256 | github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= 257 | github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= 258 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 259 | github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= 260 | github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= 261 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 262 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 263 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 264 | github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= 265 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 266 | github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 267 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 268 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 269 | github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 270 | github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= 271 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 272 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 273 | github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 274 | github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= 275 | github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 276 | github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 277 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 278 | github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE= 279 | github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= 280 | github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= 281 | github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= 282 | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= 283 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 284 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 285 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 286 | github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= 287 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 288 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 289 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 290 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 291 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 292 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 293 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 294 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 295 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 296 | github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 297 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 298 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 299 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 300 | github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc= 301 | github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= 302 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 303 | github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= 304 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 305 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 306 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 307 | github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= 308 | github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo= 309 | github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= 310 | github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= 311 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 312 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 313 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= 314 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= 315 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 316 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 317 | github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= 318 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 319 | github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= 320 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 321 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 322 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 323 | github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 324 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 325 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 326 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 327 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 328 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 329 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 330 | github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= 331 | github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= 332 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 333 | github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= 334 | github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= 335 | github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= 336 | github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= 337 | github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM= 338 | github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= 339 | github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= 340 | github.com/urfave/cli/v2 v2.10.2 h1:x3p8awjp/2arX+Nl/G2040AZpOCHS/eMJJ1/a+mye4Y= 341 | github.com/urfave/cli/v2 v2.10.2/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo= 342 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= 343 | github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= 344 | github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= 345 | github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= 346 | github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= 347 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= 348 | github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= 349 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 350 | github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 351 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 352 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 353 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 354 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 355 | go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 356 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 357 | go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 358 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 359 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 360 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 361 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 362 | golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 363 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 364 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 365 | golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 366 | golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= 367 | golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 368 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 369 | golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A= 370 | golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= 371 | golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 372 | golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 373 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 374 | golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 375 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 376 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 377 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 378 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 379 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 380 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 381 | golang.org/x/exp v0.0.0-20220426173459-3bcf042a4bf5/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= 382 | golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= 383 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 384 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 385 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 386 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 387 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 388 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 389 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 390 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 391 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 392 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 393 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 394 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 395 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 396 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 397 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 398 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 399 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 400 | golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 401 | golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= 402 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 403 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 404 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 405 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 406 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 407 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 408 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 409 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 410 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 411 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 412 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 413 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 414 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 415 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 416 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 417 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 418 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 419 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 420 | golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 421 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 422 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 423 | golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 424 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 425 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 426 | golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 427 | golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 428 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 429 | golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 430 | golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= 431 | golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 432 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 433 | golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= 434 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 435 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 436 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 437 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 438 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 439 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 440 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 441 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 442 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 443 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 444 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 445 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 446 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 447 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 448 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 449 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 450 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 451 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 452 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 453 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 454 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 455 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 456 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 457 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 458 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 459 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 460 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 461 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 462 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 463 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 465 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 466 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 467 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 474 | golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 479 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 483 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 485 | golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 486 | golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 487 | golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 488 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 489 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 490 | golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= 491 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 492 | golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 493 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 494 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 495 | golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 496 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 497 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 498 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 499 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 500 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 501 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 502 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 503 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 504 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 505 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 506 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 507 | golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 508 | golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 509 | golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 510 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 511 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 512 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 513 | golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 514 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 515 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 516 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 517 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 518 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 519 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 520 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 521 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 522 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 523 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 524 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 525 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 526 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 527 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 528 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 529 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 530 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 531 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 532 | golang.org/x/tools v0.0.0-20191126055441-b0650ceb63d9/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 533 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 534 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 535 | golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 536 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 537 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= 538 | golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= 539 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 540 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 541 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 542 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 543 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 544 | golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 545 | gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= 546 | gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= 547 | gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= 548 | gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 549 | gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= 550 | gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= 551 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 552 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 553 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 554 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 555 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 556 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 557 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 558 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 559 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 560 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 561 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 562 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 563 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 564 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 565 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 566 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 567 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 568 | google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 569 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 570 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 571 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 572 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 573 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 574 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 575 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 576 | google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 577 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 578 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 579 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 580 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 581 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 582 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 583 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 584 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 585 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 586 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 587 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 588 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 589 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 590 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 591 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 592 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 593 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 594 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 595 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 596 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 597 | gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= 598 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 599 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 600 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 601 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 602 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 603 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 604 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 605 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 606 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 607 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 608 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 609 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 610 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 611 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 612 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 613 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 614 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 615 | honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= 616 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 617 | rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= 618 | --------------------------------------------------------------------------------