commit c8099af2c9c0e648f9cc863268db928000810449 Author: Laurent Le Houerou Date: Thu Apr 7 10:19:24 2022 +0400 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6791597 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +*.exe +go.work +.idea/ +cmd/ +Dockerfile +Dockerfile.* +.dockerignore \ No newline at end of file diff --git a/LICENCE b/LICENCE new file mode 100644 index 0000000..b31ceb6 --- /dev/null +++ b/LICENCE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 galacticship + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/asset_info.go b/asset_info.go new file mode 100644 index 0000000..98d335c --- /dev/null +++ b/asset_info.go @@ -0,0 +1,88 @@ +package terra + +import ( + "context" + "encoding/json" + + "github.com/pkg/errors" +) + +type AssetInfo interface { + IsNative() bool + Id() string +} + +func GetTokenFromAssetInfo(ctx context.Context, querier *Querier, ai AssetInfo) (Token, error) { + var res Token + if ai.IsNative() { + return NativeTokenFromDenom(ai.Id()), nil + } + var err error + res, err = Cw20TokenFromAddress(ctx, querier, ai.Id()) + if err != nil { + return nil, errors.Wrapf(err, "invalid token %s", ai.Id()) + } + return res, nil +} + +type AssetInfoFactory interface { + DecodeFromJson(raw json.RawMessage) (AssetInfo, error) + NewFromToken(token Token) AssetInfo +} + +type assetInfoFactory struct { +} + +func (a assetInfoFactory) NewFromToken(token Token) AssetInfo { + var res StandardAssetInfo + if token.IsNative() { + res.NativeToken = &nativeTokenAssetInfo{ + Denom: token.Id(), + } + } else { + res.Token = &cw20TokenAssetInfo{ + ContractAddr: token.Id(), + } + } + return res +} + +func (a assetInfoFactory) DecodeFromJson(raw json.RawMessage) (AssetInfo, error) { + var res StandardAssetInfo + err := json.Unmarshal(raw, &res) + if err != nil { + return nil, err + } + return res, nil +} + +func NewAssetInfoFactory() AssetInfoFactory { + return &assetInfoFactory{} +} + +type nativeTokenAssetInfo struct { + Denom string `json:"denom"` +} + +type cw20TokenAssetInfo struct { + ContractAddr string `json:"contract_addr"` +} + +type StandardAssetInfo struct { + Token *cw20TokenAssetInfo `json:"token,omitempty"` + NativeToken *nativeTokenAssetInfo `json:"native_token,omitempty"` +} + +func (ai StandardAssetInfo) IsNative() bool { + return ai.NativeToken != nil +} + +func (ai StandardAssetInfo) Id() string { + if ai.IsNative() { + return ai.NativeToken.Denom + } else if ai.Token != nil { + return ai.Token.ContractAddr + } else { + panic(errors.New("invalid asset info")) + } +} diff --git a/contract.go b/contract.go new file mode 100644 index 0000000..f7dd436 --- /dev/null +++ b/contract.go @@ -0,0 +1,64 @@ +package terra + +import ( + "context" + "encoding/base64" + "encoding/json" + "fmt" + "net/url" + + "github.com/galacticship/terra/cosmos" + "github.com/galacticship/terra/terra" + "github.com/pkg/errors" +) + +type Contract struct { + q *Querier + contractAddress cosmos.AccAddress +} + +func NewContract(querier *Querier, contractAddress string) (*Contract, error) { + accAddress, err := cosmos.AccAddressFromBech32(contractAddress) + if err != nil { + return nil, errors.Wrap(err, "validating address") + } + return &Contract{ + q: querier, + contractAddress: accAddress, + }, nil +} + +func (c *Contract) Querier() *Querier { + return c.q +} + +func (c *Contract) Address() cosmos.AccAddress { + return c.contractAddress +} + +func (c *Contract) QueryStore(ctx context.Context, query interface{}, result interface{}) error { + var envelope struct { + QueryResult json.RawMessage `json:"query_result"` + } + queryBytes, err := json.Marshal(query) + if err != nil { + return errors.Wrap(err, "marshalling query execmsg") + } + params := url.Values{} + params.Set("query_msg", base64.StdEncoding.EncodeToString(queryBytes)) + err = c.q.GET(ctx, fmt.Sprintf("terra/wasm/v1beta1/contracts/%s/store", c.contractAddress.String()), params, &envelope) + if err != nil { + return errors.Wrap(err, "executing get request") + } + if result != nil { + err = json.Unmarshal(envelope.QueryResult, result) + if err != nil { + return errors.Wrap(err, "unmarshalling query result") + } + } + return nil +} + +func (c Contract) NewMsgExecuteContract(sender cosmos.AccAddress, execMsg interface{}) (*terra.MsgExecuteContract, error) { + return terra.NewMsgExecuteContract(sender, c.Address(), execMsg, nil) +} diff --git a/cosmos/address.go b/cosmos/address.go new file mode 100644 index 0000000..2e49118 --- /dev/null +++ b/cosmos/address.go @@ -0,0 +1,18 @@ +package cosmos + +import sdktypes "github.com/cosmos/cosmos-sdk/types" + +type ( + AccAddress = sdktypes.AccAddress + ValAddress = sdktypes.ValAddress + ConsAddress = sdktypes.ConsAddress +) + +var ( + AccAddressFromBech32 = sdktypes.AccAddressFromBech32 + AccAddressFromHex = sdktypes.AccAddressFromHex + ValAddressFromBech32 = sdktypes.ValAddressFromBech32 + ValAddressFromHex = sdktypes.ValAddressFromHex + ConsAddressFromBech32 = sdktypes.ConsAddressFromBech32 + ConsAddressFromHex = sdktypes.ConsAddressFromHex +) diff --git a/cosmos/coin.go b/cosmos/coin.go new file mode 100644 index 0000000..b5d0c28 --- /dev/null +++ b/cosmos/coin.go @@ -0,0 +1,19 @@ +package cosmos + +import sdktypes "github.com/cosmos/cosmos-sdk/types" + +type ( + Coin = sdktypes.Coin + Coins = sdktypes.Coins + DecCoin = sdktypes.DecCoin + DecCoins = sdktypes.DecCoins +) + +var ( + NewCoin = sdktypes.NewCoin + NewInt64Coin = sdktypes.NewInt64Coin + NewCoins = sdktypes.NewCoins + NewDecCoin = sdktypes.NewDecCoin + NewInt64DecCoin = sdktypes.NewInt64DecCoin + NewDecCoins = sdktypes.NewDecCoins +) diff --git a/cosmos/msg.go b/cosmos/msg.go new file mode 100644 index 0000000..b89e4e3 --- /dev/null +++ b/cosmos/msg.go @@ -0,0 +1,17 @@ +package cosmos + +import ( + sdktypes "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +type ( + Msg = sdktypes.Msg + Send = banktypes.MsgSend + MultiSend = banktypes.MsgMultiSend +) + +var ( + NewMsgSend = banktypes.NewMsgSend + NewMsgMultiSend = banktypes.NewMsgMultiSend +) diff --git a/cosmos/signing.go b/cosmos/signing.go new file mode 100644 index 0000000..cd497ab --- /dev/null +++ b/cosmos/signing.go @@ -0,0 +1,48 @@ +package cosmos + +import ( + clienttx "github.com/cosmos/cosmos-sdk/client/tx" + "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" +) + +type ( + // SignerData is the specific information needed to sign a transaction that generally + // isn't included in the transaction body itself + SignerData = authsigning.SignerData + + // SignMode represents a signing mode with its own security guarantees. + SignMode = signing.SignMode + + // SignatureV2 is a convenience type that is easier to use in application logic + // than the protobuf SignerInfo's and raw signature bytes. It goes beyond the + // first sdk.Signature types by supporting sign modes and explicitly nested + // multi-signatures. It is intended to be used for both building and verifying + // signatures. + SignatureV2 = signing.SignatureV2 + SingleSignatureData = signing.SingleSignatureData + + // Tx defines a transaction interface that supports all standard message, signature + // fee, memo, and auxiliary interfaces. + Tx = authsigning.Tx +) + +const ( + // SignModeUnspecified specifies an unknown signing mode and will be + // rejected + SignModeUnspecified SignMode = 0 + // SignModeDirect specifies a signing mode which uses SignDoc and is + // verified with raw bytes from Tx + SignModeDirect SignMode = 1 + // SignModeTexture is a future signing mode that will verify some + // human-readable textual representation on top of the binary representation + // from SIGN_MODE_DIRECT + SignModeTexture SignMode = 2 + // SignModeLegacyAminoJSON is a backwards compatibility mode which uses + // Amino JSON and will be removed in the future + SignModeLegacyAminoJSON SignMode = 127 +) + +var ( + SignWithPrivKey = clienttx.SignWithPrivKey +) diff --git a/cosmos/tx.go b/cosmos/tx.go new file mode 100644 index 0000000..c74b1c8 --- /dev/null +++ b/cosmos/tx.go @@ -0,0 +1,42 @@ +package cosmos + +import ( + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/types" + txtypes "github.com/cosmos/cosmos-sdk/types/tx" +) + +type ( + TxBuilder = client.TxBuilder + TxConfig = client.TxConfig + + SimulateRequest = txtypes.SimulateRequest + SimulateResponse = txtypes.SimulateResponse + + BroadcastTxRequest = txtypes.BroadcastTxRequest + BroadcastTxResponse = txtypes.BroadcastTxResponse + + TxResponse = types.TxResponse + + BroadcastMode = txtypes.BroadcastMode +) + +const ( + BroadcastModeUnspecified BroadcastMode = 0 + BroadcastModeBlock BroadcastMode = 1 + BroadcastModeSync BroadcastMode = 2 + BroadcastModeAsync BroadcastMode = 3 +) + +func NewBroadcastTxRequest(txBytes []byte, broadcastMode BroadcastMode) *BroadcastTxRequest { + return &BroadcastTxRequest{ + TxBytes: txBytes, + Mode: broadcastMode, + } +} + +func NewSimulateRequest(txBytes []byte) *SimulateRequest { + return &SimulateRequest{ + TxBytes: txBytes, + } +} diff --git a/cosmos/types.go b/cosmos/types.go new file mode 100644 index 0000000..424eb99 --- /dev/null +++ b/cosmos/types.go @@ -0,0 +1,25 @@ +package cosmos + +import sdktypes "github.com/cosmos/cosmos-sdk/types" + +type ( + Int = sdktypes.Int + Dec = sdktypes.Dec +) + +var ( + NewInt = sdktypes.NewInt + NewIntFromBigInt = sdktypes.NewIntFromBigInt + NewIntFromString = sdktypes.NewIntFromString + NewIntFromUint64 = sdktypes.NewIntFromUint64 + NewIntWithDecimal = sdktypes.NewIntWithDecimal + NewDec = sdktypes.NewDec + NewDecCoinFromCoin = sdktypes.NewDecCoinFromCoin + NewDecCoinFromDec = sdktypes.NewDecCoinFromDec + NewDecFromBigInt = sdktypes.NewDecFromBigInt + NewDecFromBigIntWithPrec = sdktypes.NewDecFromBigIntWithPrec + NewDecFromInt = sdktypes.NewDecFromInt + NewDecFromIntWithPrec = sdktypes.NewDecFromIntWithPrec + NewDecFromStr = sdktypes.NewDecFromStr + NewDecWithPrec = sdktypes.NewDecWithPrec +) diff --git a/crypto/mnemonic.go b/crypto/mnemonic.go new file mode 100644 index 0000000..2ee1498 --- /dev/null +++ b/crypto/mnemonic.go @@ -0,0 +1,59 @@ +package crypto + +import ( + "errors" + + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/go-bip39" +) + +type ( + PubKey = secp256k1.PubKey + PrivKey = types.PrivKey +) + +// CreateMnemonic - create new mnemonic +func CreateMnemonic() (string, error) { + // Default number of words (24): This generates a mnemonic directly from the + // number of words by reading system entropy. + entropy, err := bip39.NewEntropy(256) + if err != nil { + return "", err + } + + return bip39.NewMnemonic(entropy) +} + +// CreateHDPath returns BIP 44 object from account and index parameters. +func CreateHDPath(account uint32, index uint32) string { + return hd.CreateHDPath(330, account, index).String() +} + +// DerivePrivKeyBz - derive private key bytes +func DerivePrivKeyBz(mnemonic string, hdPath string) ([]byte, error) { + if !bip39.IsMnemonicValid(mnemonic) { + return nil, errors.New("invalid mnemonic") + } + + algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyring.SigningAlgoList{hd.Secp256k1}) + if err != nil { + return nil, err + } + + // create master key and derive first key for keyring + return algo.Derive()(mnemonic, "", hdPath) +} + +// PrivKeyGen is the default PrivKeyGen function in the keybase. +// For now, it only supports Secp256k1 +func PrivKeyGen(bz []byte) (types.PrivKey, error) { + algo, err := keyring.NewSigningAlgoFromString(string(hd.Secp256k1Type), keyring.SigningAlgoList{hd.Secp256k1}) + if err != nil { + return nil, err + } + + return algo.Generate()(bz), nil +} diff --git a/factory.go b/factory.go new file mode 100644 index 0000000..c77ace9 --- /dev/null +++ b/factory.go @@ -0,0 +1,80 @@ +package terra + +import ( + "context" + "fmt" + "github.com/pkg/errors" +) + +type Factory struct { + *Contract +} + +func NewFactory(querier *Querier, contractAddress string) (*Factory, error) { + contract, err := NewContract(querier, contractAddress) + if err != nil { + return nil, errors.Wrap(err, "creating base contract") + } + + return &Factory{ + contract, + }, nil +} + +func (f *Factory) Pairs(ctx context.Context) ([]string, error) { + const limit = 30 + var res []string + var startAfter []StandardAssetInfo + cpt := 1 + for { + select { + case <-ctx.Done(): + return nil, errors.New("context canceled") + default: + pagePairs, lastAssets, err := f.pairsPage(ctx, startAfter, limit) + if err != nil { + return nil, errors.Wrapf(err, "querying page %d", cpt) + } + if pagePairs == nil { + return res, nil + } + res = append(res, pagePairs...) + startAfter = lastAssets + cpt++ + } + } +} + +func (f *Factory) pairsPage(ctx context.Context, startAfter []StandardAssetInfo, limit int) ([]string, []StandardAssetInfo, error) { + var q struct { + Pairs struct { + StartAfter []StandardAssetInfo `json:"start_after,omitempty"` + Limit *int `json:"limit,omitempty"` + } `json:"pairs"` + } + q.Pairs.StartAfter = startAfter + q.Pairs.Limit = &limit + + type response struct { + Pairs []struct { + AssetInfos []StandardAssetInfo `json:"asset_infos"` + ContractAddr string `json:"contract_addr"` + } `json:"pairs"` + } + var resp response + err := f.QueryStore(ctx, q, &resp) + if err != nil { + return nil, nil, errors.Wrap(err, "querying contract store") + } + + var res []string + var lastAssets []StandardAssetInfo + for _, pair := range resp.Pairs { + res = append(res, pair.ContractAddr) + fmt.Println(pair.ContractAddr) + lastAssets = pair.AssetInfos + } + fmt.Println("") + + return res, lastAssets, nil +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..f656174 --- /dev/null +++ b/go.mod @@ -0,0 +1,117 @@ +module github.com/galacticship/terra + +go 1.18 + +require ( + github.com/cosmos/cosmos-sdk v0.44.5 + github.com/cosmos/go-bip39 v1.0.0 + github.com/gogo/protobuf v1.3.3 + github.com/hashicorp/go-multierror v1.0.0 + github.com/pkg/errors v0.9.1 + github.com/shopspring/decimal v1.3.1 + github.com/terra-money/core v0.5.17 + golang.org/x/net v0.0.0-20211216030914-fe4d6282115f +) + +require ( + filippo.io/edwards25519 v1.0.0-beta.2 // indirect + github.com/99designs/keyring v1.1.6 // indirect + github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d // indirect + github.com/CosmWasm/wasmvm v0.16.3 // indirect + github.com/DataDog/zstd v1.4.5 // indirect + github.com/armon/go-metrics v0.3.9 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect + github.com/btcsuite/btcd v0.22.0-beta // indirect + github.com/cespare/xxhash v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/confio/ics23/go v0.6.6 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/iavl v0.17.3 // indirect + github.com/cosmos/ibc-go v1.1.5 // indirect + github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect + github.com/cosmos/ledger-go v0.9.2 // indirect + github.com/danieljoos/wincred v1.0.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgraph-io/badger/v2 v2.2007.2 // indirect + github.com/dgraph-io/ristretto v0.0.3 // indirect + github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect + github.com/dustin/go-humanize v1.0.0 // indirect + github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect + github.com/go-kit/kit v0.10.0 // indirect + github.com/go-logfmt/logfmt v0.5.0 // indirect + github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.3 // indirect + github.com/google/btree v1.0.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect + github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/gtank/ristretto255 v0.1.2 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 // indirect + github.com/inconshreveable/mousetrap v1.0.0 // indirect + github.com/jmhodges/levigo v1.0.0 // indirect + github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d // indirect + github.com/libp2p/go-buffer-pool v0.0.2 // indirect + github.com/magiconair/properties v1.8.5 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect + github.com/mitchellh/mapstructure v1.4.2 // indirect + github.com/mtibben/percent v0.2.1 // indirect + github.com/pelletier/go-toml v1.9.4 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_model v0.2.0 // indirect + github.com/prometheus/common v0.29.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect + github.com/regen-network/cosmos-proto v0.3.1 // indirect + github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cobra v1.2.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/spf13/viper v1.8.1 // indirect + github.com/stretchr/testify v1.7.0 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect + github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect + github.com/tendermint/btcd v0.1.1 // indirect + github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect + github.com/tendermint/go-amino v0.16.0 // indirect + github.com/tendermint/tendermint v0.34.14 // indirect + github.com/tendermint/tm-db v0.6.6 // indirect + github.com/zondax/hid v0.9.0 // indirect + go.etcd.io/bbolt v1.3.6 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/sys v0.0.0-20210903071746-97244b99971b // indirect + golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect + golang.org/x/text v0.3.6 // indirect + google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 // indirect + google.golang.org/grpc v1.42.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/ini.v1 v1.63.2 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect +) + +replace ( + github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 + github.com/cosmos/cosmos-sdk => github.com/terra-money/cosmos-sdk v0.44.5-terra.2 + github.com/cosmos/ledger-cosmos-go => github.com/terra-money/ledger-terra-go v0.11.2 + github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1 + github.com/tecbot/gorocksdb => github.com/cosmos/gorocksdb v1.2.0 + github.com/tendermint/tendermint => github.com/terra-money/tendermint v0.34.14-terra.2 + google.golang.org/grpc => google.golang.org/grpc v1.33.2 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..501ae88 --- /dev/null +++ b/go.sum @@ -0,0 +1,1283 @@ +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= +filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= +github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= +github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc= +github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= +github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1:URdX5+vg25ts3aCh8H5IFZybJYKWhJHYMTnf+ULtoC4= +github.com/CosmWasm/wasmvm v0.16.3 h1:hUf33EHRmyyvKMhwVl7nMaAOY0vYJVB4bhU+HPfHfBM= +github.com/CosmWasm/wasmvm v0.16.3/go.mod h1:Id107qllDJyJjVQQsKMOy2YYF98sqPJ2t+jX1QES40A= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.4.1/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ= +github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI= +github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA= +github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20201201074141-dd0ecada1be6/go.mod h1:eSYp2T6f0apnuW8TzhV3f6Aff2SE8Dwio++U4ha4yEM= +github.com/adlio/schema v1.1.13/go.mod h1:L5Z7tw+7lRK1Fnpi/LT/ooCP1elkXn0krMWBQHUhEDE= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= +github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ= +github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0= +github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= +github.com/btcsuite/btcd v0.22.0-beta h1:LTDpDKUM5EeOFBPM8IXpinEcmZ6FWfNZbE3lfrfdnWo= +github.com/btcsuite/btcd v0.22.0-beta/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= +github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= +github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= +github.com/confio/ics23/go v0.6.6/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= +github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= +github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= +github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= +github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= +github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= +github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= +github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= +github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= +github.com/cosmos/ibc-go v1.1.5 h1:H+q6G0szM5lePgLDQbTAaKQU5UR28ZjOIA3JJjNhuPQ= +github.com/cosmos/ibc-go v1.1.5/go.mod h1:wkGkkX8Ou6yXgE8lO2xP9NOwo+Tl5x1dJaTTE6jBDpg= +github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU= +github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8= +github.com/cosmos/ledger-go v0.9.2 h1:Nnao/dLwaVTk1Q5U9THldpUMMXU94BOTWPddSmVB6pI= +github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/danieljoos/wincred v1.0.2 h1:zf4bhty2iLuwgjgpraD2E9UbvO+fe54XXGJbOwe23fU= +github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= +github.com/dgraph-io/badger/v2 v2.2007.2 h1:EjjK0KqwaFMlPin1ajhP943VPENHJdEz1KLIegjaI3k= +github.com/dgraph-io/badger/v2 v2.2007.2/go.mod h1:26P/7fbL4kUZVEVKLAKXkBXKOydDmM2p1e+NhhnBCAE= +github.com/dgraph-io/ristretto v0.0.3-0.20200630154024-f66de99634de/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgraph-io/ristretto v0.0.3 h1:jh22xisGBjrEVnRZ1DVTpBVQm0Xndu8sMl0CWDzSIBI= +github.com/dgraph-io/ristretto v0.0.3/go.mod h1:KPxhHT9ZxKefz+PCeOGsrHpl1qZ7i70dGTu2u+Ahh6E= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= +github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b h1:HBah4D48ypg3J7Np4N+HY/ZR76fx3HEUGxDU6Uk39oQ= +github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b/go.mod h1:7BvyPhdbLxMXIYTFPLsyJRFMsKmOZnQmzh6Gb+uquuM= +github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= +github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= +github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= +github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= +github.com/gogo/gateway v1.1.0/go.mod h1:S7rR8FRQyG3QFESeSv4l2WnsyzlCLG0CzBbUUo/mbic= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3-0.20201103224600-674baa8c7fc3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa h1:Q75Upo5UN4JbPFURXZ8nLKYUvF85dyFRop/vQ0Rv+64= +github.com/google/gofuzz v1.1.1-0.20200604201612-c04b05f3adfa/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/orderedcode v0.0.1 h1:UzfcAexk9Vhv8+9pNOgRu41f16lHq725vPwnSeiG/Us= +github.com/google/orderedcode v0.0.1/go.mod h1:iVyU4/qPKHY5h/wSd6rZZCDcLJNxiWO6dvsYES2Sb20= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= +github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= +github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc= +github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87 h1:uUjLpLt6bVvZ72SQc/B4dXcPBw4Vgd7soowdRl52qEM= +github.com/hdevalence/ed25519consensus v0.0.0-20210204194344-59a8610d2b87/go.mod h1:XGsKKeXxeRr95aEOgipvluMPlgjr7dGlk9ZTWOjcUcg= +github.com/holiman/uint256 v1.1.1/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc= +github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/improbable-eng/grpc-web v0.14.1 h1:NrN4PY71A6tAz2sKDvC5JCauENWp0ykG8Oq1H3cpFvw= +github.com/improbable-eng/grpc-web v0.14.1/go.mod h1:zEjGHa8DAlkoOXmswrNvhUGEYQA9UI7DhrGeHR1DMGU= +github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jhump/protoreflect v1.9.0/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= +github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU= +github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d h1:Z+RDyXzjKE0i2sTjZ/b1uxiGtPhFy34Ou/Tk0qwN0kM= +github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOSqcmlfs= +github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lucasjones/reggen v0.0.0-20180717132126-cdb49ff09d77/go.mod h1:5ELEyG+X8f+meRWHuqUOewBOhvHkl7M76pdGEansxW4= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= +github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= +github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= +github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0= +github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/neilotoole/errgroup v0.1.5/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= +github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= +github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs= +github.com/otiai10/copy v1.6.0 h1:IinKAryFFuPONZ7cm6T6E2QX/vcJwSnlaA5lfoaXIiQ= +github.com/otiai10/copy v1.6.0/go.mod h1:XWfuS3CrI0R6IE0FbgHsEazaXO8G0LpMp9o8tos0x4E= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.3.2/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.29.0 h1:3jqPBvKT4OHAbje2Ql7KeaaSicDBCxMYwEJU1zRJceE= +github.com/prometheus/common v0.29.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= +github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= +github.com/regen-network/cosmos-proto v0.3.1/go.mod h1:jO0sVX6a1B36nmE8C9xBFXpNwWejXC7QqCOnH3O0+YM= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1 h1:OHEc+q5iIAXpqiqFKeLpu5NwTIkVXUs48vFMwzqpqY4= +github.com/regen-network/protobuf v1.3.3-alpha.regen.1/go.mod h1:2DjTFR1HhMQhiWC5sZ4OhQ3+NtdbZ6oBDKQwq5Ou+FI= +github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.23.0 h1:UskrK+saS9P9Y789yNNulYKdARjPZuS35B8gJF2x60g= +github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa h1:0U2s5loxrTy6/VgfVoLuVLFJcURKLH49ie0zSch7gh4= +github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= +github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= +github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa/go.mod h1:oJyF+mSPHbB5mVY2iO9KV3pTt/QbIkGaO8gQ2WrDbP4= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= +github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= +github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw= +github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= +github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca h1:Ld/zXl5t4+D69SiV4JoN7kkfvJdOWlPpfxrzxpLMoUk= +github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKkTVTVJWe5D1rCvame8WqhBd88EuIwODJZ1VHCPM= +github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= +github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 h1:hqAk8riJvK4RMWx1aInLzndwxKalgi5rTqgfXxOxbEI= +github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk= +github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= +github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= +github.com/tendermint/tm-db v0.5.1/go.mod h1:g92zWjHpCYlEvQXvy9M168Su8V1IBEeawpXVVBaK4f4= +github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= +github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= +github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= +github.com/terra-money/core v0.5.17 h1:LyQKVLEawSqn+AV+BcslP9H6qFUvFJxDBHzjvm3yl+Q= +github.com/terra-money/core v0.5.17/go.mod h1:MEpq9DsEr2lBs8P7GiIJLfBqCZZKHfdl5qEs0nOcQkg= +github.com/terra-money/cosmos-sdk v0.44.5-terra.2 h1:v56ZIECZAWerXHE++7JY8GM+oR+W5nt37tKWgEfvl8o= +github.com/terra-money/cosmos-sdk v0.44.5-terra.2/go.mod h1:/tqCMnVCrX7F7iL2ALCsGdYmhx0jfgFG/50gP8jt6bI= +github.com/terra-money/ledger-terra-go v0.11.2 h1:BVXZl+OhJOri6vFNjjVaTabRLApw9MuG7mxWL4V718c= +github.com/terra-money/ledger-terra-go v0.11.2/go.mod h1:ClJ2XMj1ptcnONzKH+GhVPi7Y8pXIT+UzJ0TNt0tfZE= +github.com/terra-money/tendermint v0.34.14-terra.2 h1:UYDDCI001ZNhs+aX09HjKVldUcz084q3RwLHUOSSZQU= +github.com/terra-money/tendermint v0.34.14-terra.2/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= +github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/sjson v1.1.4/go.mod h1:wXpKXu8CtDjKAZ+3DrKY5ROCorDFahq8l0tey/Lx1fg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/tyler-smith/go-bip39 v1.0.2/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= +github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= +github.com/vmihailenco/msgpack/v5 v5.1.4/go.mod h1:C5gboKD0TJPqWDTVTtrQNfRbiBwHZGo8UTqP/9/XvLI= +github.com/vmihailenco/tagparser v0.1.2/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= +github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/zondax/hid v0.9.0 h1:eiT3P6vNxAEVxXMw66eZUAAnU2zD33JBkfG/EnfAKl8= +github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b h1:3Dq0eVHn0uaQJmPO+/aYPI/fRMqdrVDbu7MQcku54gg= +golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200324203455-a04cca1dde73/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= +gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= +gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/pair.go b/pair.go new file mode 100644 index 0000000..b4e78d2 --- /dev/null +++ b/pair.go @@ -0,0 +1,310 @@ +package terra + +import ( + "context" + "encoding/json" + "fmt" + + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Pair interface { + CommissionRate() decimal.Decimal + LpToken() Cw20Token + Token1() Token + Token2() Token + ContractAddressString() string + ContractAddress() cosmos.AccAddress + + PoolInfo(ctx context.Context) (PoolInfo, error) + NewWithdrawLiquidityMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) + Share(ctx context.Context, lpAmount decimal.Decimal) (token1Amount decimal.Decimal, token2Amount decimal.Decimal, err error) + NewSimpleSwapMessage(sender cosmos.AccAddress, offerToken Token, amount decimal.Decimal) (cosmos.Msg, error) + NewSwapMessage(sender cosmos.AccAddress, offerToken Token, amount decimal.Decimal, spread string, beliefPrice decimal.Decimal) (cosmos.Msg, error) + SimulateSwap(ctx context.Context, offer Token, amount decimal.Decimal) (decimal.Decimal, decimal.Decimal, decimal.Decimal, error) + Equals(pair Pair) bool + String() string +} + +type BasePair struct { + *Contract + + token1 Token + token2 Token + lpToken Cw20Token + commissionRate decimal.Decimal + + aiFactory AssetInfoFactory +} + +func NewBasePair(querier *Querier, contractAddress string, token1 Token, token2 Token, lpToken Cw20Token, commissionRate decimal.Decimal, aiFactory AssetInfoFactory) (*BasePair, error) { + contract, err := NewContract(querier, contractAddress) + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + p := &BasePair{ + Contract: contract, + commissionRate: commissionRate, + aiFactory: aiFactory, + token1: token1, + token2: token2, + lpToken: lpToken, + } + return p, nil +} + +func (p BasePair) CommissionRate() decimal.Decimal { + return p.commissionRate +} + +func (p BasePair) LpToken() Cw20Token { + return p.lpToken +} + +func (p BasePair) Token1() Token { + return p.token1 +} + +func (p BasePair) Token2() Token { + return p.token2 +} + +func (p BasePair) ContractAddressString() string { + return p.contractAddress.String() +} +func (p BasePair) ContractAddress() cosmos.AccAddress { + return p.contractAddress +} + +func (p *BasePair) SetToken1(token Token) { + p.token1 = token +} +func (p *BasePair) SetToken2(token Token) { + p.token2 = token +} +func (p *BasePair) SetLpToken(token Cw20Token) { + p.lpToken = token +} + +func (p *BasePair) Config(ctx context.Context) (tokens []Token, lpToken Token, err error) { + var q struct { + Pair struct { + } `json:"pair"` + } + type response struct { + AssetInfos []json.RawMessage `json:"asset_infos"` + ContractAddr string `json:"contract_addr"` + LiquidityToken string `json:"liquidity_token"` + } + var r response + err = p.QueryStore(ctx, q, &r) + if err != nil { + return nil, nil, errors.Wrap(err, "querying contract store") + } + + var assets []AssetInfo + for _, info := range r.AssetInfos { + a, err := p.aiFactory.DecodeFromJson(info) + if err != nil { + return nil, nil, errors.Wrap(err, "decoding asset json") + } + assets = append(assets, a) + } + + if len(assets) < 2 { + return nil, nil, errors.Errorf("not enough token in pair config: %d", len(assets)) + } + t1, err := GetTokenFromAssetInfo(ctx, p.Contract.Querier(), assets[0]) + if err != nil { + return nil, nil, errors.Wrap(err, "getting token1 from asset info") + } + + t2, err := GetTokenFromAssetInfo(ctx, p.Contract.Querier(), assets[1]) + if err != nil { + return nil, nil, errors.Wrap(err, "getting token2 from asset info") + } + + lptoken, err := Cw20TokenFromAddress(ctx, p.Contract.Querier(), r.LiquidityToken) + if err != nil { + return nil, nil, errors.Wrapf(err, "getting lp token: %s", r.LiquidityToken) + } + + return []Token{t1, t2}, lptoken, nil +} + +type PoolInfo map[string]decimal.Decimal + +func (p BasePair) PoolInfo(ctx context.Context) (PoolInfo, error) { + type query struct { + Pool struct { + } `json:"pool"` + } + type response struct { + Assets []struct { + Info json.RawMessage `json:"info"` + Amount decimal.Decimal `json:"amount"` + } `json:"assets"` + TotalShare decimal.Decimal `json:"total_share"` + } + var r response + err := p.QueryStore(ctx, query{}, &r) + if err != nil { + return PoolInfo{}, errors.Wrap(err, "querying contract store") + } + res := make(map[string]decimal.Decimal) + for _, a := range r.Assets { + ai, err := p.aiFactory.DecodeFromJson(a.Info) + if err != nil { + return PoolInfo{}, errors.Wrap(err, "decoding asset info") + } + if p.token1.Id() == ai.Id() { + res[ai.Id()] = p.token1.ValueFromTerra(a.Amount) + } else if p.token2.Id() == ai.Id() { + res[ai.Id()] = p.token2.ValueFromTerra(a.Amount) + } else { + return PoolInfo{}, errors.New("asset unknown") + } + } + return res, nil +} + +func (p BasePair) NewWithdrawLiquidityMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + WithdrawLiquidity struct { + } `json:"withdraw_liquidity"` + } + var q query + return p.lpToken.NewMsgSendExecute(sender, p.Contract, amount, q) +} + +func (p BasePair) Share(ctx context.Context, lpAmount decimal.Decimal) (token1Amount decimal.Decimal, token2Amount decimal.Decimal, err error) { + type query struct { + Share struct { + Amount decimal.Decimal `json:"amount"` + } `json:"share"` + } + type response []struct { + Info json.RawMessage `json:"info"` + Amount decimal.Decimal `json:"amount"` + } + var q query + q.Share.Amount = p.lpToken.ValueToTerra(lpAmount) + var r response + err = p.QueryStore(ctx, q, &r) + if err != nil { + return decimal.Zero, decimal.Zero, errors.Wrap(err, "querying contract store") + } + if len(r) < 2 { + return decimal.Zero, decimal.Zero, errors.Errorf("not enough token in share response: %d", len(r)) + } + + for _, a := range r { + ai, err := p.aiFactory.DecodeFromJson(a.Info) + if err != nil { + return decimal.Zero, decimal.Zero, errors.Wrap(err, "decoding asset info") + } + if p.token1.Id() == ai.Id() { + token1Amount = p.token1.ValueFromTerra(a.Amount) + } else if p.token2.Id() == ai.Id() { + token2Amount = p.token2.ValueFromTerra(a.Amount) + } else { + return decimal.Zero, decimal.Zero, errors.New("asset unknown") + } + } + return token1Amount, token2Amount, nil + +} + +func (p BasePair) NewSimpleSwapMessage(sender cosmos.AccAddress, offerToken Token, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + Swap struct { + OfferAsset struct { + Info AssetInfo `json:"info"` + Amount decimal.Decimal `json:"amount"` + } `json:"offer_asset"` + } `json:"swap"` + } + + var q query + q.Swap.OfferAsset.Amount = offerToken.ValueToTerra(amount) + q.Swap.OfferAsset.Info = p.aiFactory.NewFromToken(offerToken) + return offerToken.NewMsgSendExecute(sender, p.Contract, amount, q) +} + +func (p BasePair) NewSwapMessage(sender cosmos.AccAddress, offerToken Token, amount decimal.Decimal, spread string, beliefPrice decimal.Decimal) (cosmos.Msg, error) { + type query struct { + Swap struct { + MaxSpread string `json:"max_spread"` + OfferAsset struct { + Info AssetInfo `json:"info"` + Amount decimal.Decimal `json:"amount"` + } `json:"offer_asset"` + BeliefPrice decimal.Decimal `json:"belief_price"` + } `json:"swap"` + } + + var q query + q.Swap.OfferAsset.Info = p.aiFactory.NewFromToken(offerToken) + q.Swap.OfferAsset.Amount = offerToken.ValueToTerra(amount) + q.Swap.MaxSpread = spread + q.Swap.BeliefPrice = beliefPrice + return offerToken.NewMsgSendExecute(sender, p.Contract, amount, q) +} + +func ComputeConstantProductSwap(offerPool decimal.Decimal, askPool decimal.Decimal, offerAmount decimal.Decimal, commissionRate decimal.Decimal) (decimal.Decimal, decimal.Decimal, decimal.Decimal, decimal.Decimal) { + if offerPool.Equals(decimal.Zero) || askPool.Equals(decimal.Zero) || offerAmount.Equals(decimal.Zero) { + return decimal.Zero, decimal.Zero, decimal.Zero, decimal.Zero + } + cp := offerPool.Mul(askPool) + returnAmount := (askPool.Sub(cp.Div(offerPool.Add(offerAmount)))).Truncate(0) + spread := offerAmount.Mul(askPool).Div(offerPool).Sub(returnAmount).Truncate(0) + commissionAmount := returnAmount.Mul(commissionRate).Truncate(0) + beliefPrice := offerAmount.Div(returnAmount) + returnAmount = returnAmount.Sub(commissionAmount) + return returnAmount, spread, commissionAmount, beliefPrice +} + +func (p BasePair) SimulateSwap(ctx context.Context, offer Token, amount decimal.Decimal) (decimal.Decimal, decimal.Decimal, decimal.Decimal, error) { + type query struct { + Simulation struct { + OfferAsset struct { + Info AssetInfo `json:"info"` + Amount decimal.Decimal `json:"amount"` + } `json:"offer_asset"` + } `json:"simulation"` + } + var q query + q.Simulation.OfferAsset.Info = p.aiFactory.NewFromToken(offer) + q.Simulation.OfferAsset.Amount = offer.ValueToTerra(amount) + type response struct { + ReturnAmount decimal.Decimal `json:"return_amount"` + SpreadAmount decimal.Decimal `json:"spread_amount"` + CommissionAmount decimal.Decimal `json:"commission_amount"` + } + var r response + err := p.QueryStore(ctx, q, &r) + if err != nil { + return decimal.Zero, decimal.Zero, decimal.Zero, errors.Wrap(err, "querying contract store") + } + + return r.ReturnAmount, r.SpreadAmount, r.CommissionAmount, nil + +} + +func (p *BasePair) Equals(pair Pair) bool { + return p.contractAddress.String() == pair.ContractAddressString() +} + +func (p *BasePair) String() string { + t1symbol := "" + if p.token1 != nil { + t1symbol = p.token1.Symbol() + } + t2symbol := "" + if p.token2 != nil { + t2symbol = p.token2.Symbol() + } + return fmt.Sprintf("%s / %s", t1symbol, t2symbol) +} diff --git a/price_service.go b/price_service.go new file mode 100644 index 0000000..79612fb --- /dev/null +++ b/price_service.go @@ -0,0 +1,90 @@ +package terra + +import ( + "context" + "sync" + "time" + + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type PriceService struct { + routers []Router + cache map[string]cachedPrice + cacheMutex *sync.Mutex + cacheTimeout time.Duration + maxRouteLength int +} + +type cachedPrice struct { + price decimal.Decimal + updatedTime time.Time +} + +type PriceServiceOption func(s *PriceService) *PriceService + +func WithCacheTimeout(timeout time.Duration) PriceServiceOption { + return func(s *PriceService) *PriceService { + s.cacheTimeout = timeout + return s + } +} + +func WithMaxRouteLength(maxRouteLenght int) PriceServiceOption { + return func(s *PriceService) *PriceService { + s.maxRouteLength = maxRouteLenght + return s + } +} + +func NewPriceService(options ...PriceServiceOption) *PriceService { + p := &PriceService{ + routers: nil, + cache: make(map[string]cachedPrice), + cacheMutex: &sync.Mutex{}, + cacheTimeout: 30 * time.Second, + maxRouteLength: 2, + } + for _, option := range options { + p = option(p) + } + return p +} + +func (s *PriceService) AddRouter(router Router) { + s.routers = append(s.routers, router) +} + +func (s *PriceService) GetPriceCached(ctx context.Context, token Token) (decimal.Decimal, error) { + s.cacheMutex.Lock() + defer s.cacheMutex.Unlock() + if p, ok := s.cache[token.Id()]; ok && p.updatedTime.Add(s.cacheTimeout).After(time.Now()) { + return p.price, nil + } + p, err := s.getCurrentPrice(ctx, token) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting current price") + } + s.cache[token.Id()] = cachedPrice{ + price: p, + updatedTime: time.Now(), + } + return p, nil +} + +func (s *PriceService) getCurrentPrice(ctx context.Context, token Token) (decimal.Decimal, error) { + var bestprice decimal.Decimal + var bestroute Route + for _, router := range s.routers { + newprice, newroute, err := router.SimulateSwap(ctx, token, UST, decimal.NewFromInt(1), s.maxRouteLength) + if err != nil && err != ErrNoRouteFund { + return decimal.Zero, errors.Wrapf(err, "simulating swap with router %s", router) + } + if newprice.GreaterThan(bestprice) || (newprice.Equals(bestprice) && len(newroute) < len(bestroute)) { + bestprice = newprice + bestroute = newroute + } + } + return bestprice, nil +} diff --git a/protocols/anchor/anchor.go b/protocols/anchor/anchor.go new file mode 100644 index 0000000..b4eae0b --- /dev/null +++ b/protocols/anchor/anchor.go @@ -0,0 +1,65 @@ +package anchor + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Anchor struct { + Market *Market + Overseer *Overseer + PriceOracle *PriceOracle + BLUNACustody *BLUNACustody +} + +func NewAnchor(querier *terra.Querier) (*Anchor, error) { + market, err := NewMarket(querier) + if err != nil { + return nil, errors.Wrap(err, "creating market") + } + overseer, err := NewOverseer(querier) + if err != nil { + return nil, errors.Wrap(err, "creating overseer") + } + priceOracle, err := NewPriceOracle(querier) + if err != nil { + return nil, errors.Wrap(err, "creating price oracle") + } + blunaCustody, err := NewBLUNACustody(querier) + if err != nil { + return nil, errors.Wrap(err, "creating bluna custody") + } + + return &Anchor{ + Market: market, + Overseer: overseer, + PriceOracle: priceOracle, + BLUNACustody: blunaCustody, + }, nil +} + +func (a *Anchor) NewProvideBLUNAMessages(sender cosmos.AccAddress, amount decimal.Decimal) ([]cosmos.Msg, error) { + m1, err := a.BLUNACustody.NewDepositCollateralMessage(sender, amount) + if err != nil { + return nil, errors.Wrap(err, "creating deposit collateral to BLUNA custody message") + } + m2, err := a.Overseer.NewLockCollateralMessage(sender, terra.BLUNA, amount) + if err != nil { + return nil, errors.Wrap(err, "creating lock collateral from overseer message") + } + return []cosmos.Msg{m1, m2}, nil +} + +func (a *Anchor) NewWithdrawBLUNAMessages(sender cosmos.AccAddress, amount decimal.Decimal) ([]cosmos.Msg, error) { + m1, err := a.Overseer.NewUnlockCollateralMessage(sender, terra.BLUNA, amount) + if err != nil { + return nil, errors.Wrap(err, "creating unlock collateral from overseer message") + } + m2, err := a.BLUNACustody.NewWithdrawCollateralMessage(sender, amount) + if err != nil { + return nil, errors.Wrap(err, "creating withdraw collateral from BLUNA custody message") + } + return []cosmos.Msg{m1, m2}, nil +} diff --git a/protocols/anchor/blunacustody.go b/protocols/anchor/blunacustody.go new file mode 100644 index 0000000..bb4197f --- /dev/null +++ b/protocols/anchor/blunacustody.go @@ -0,0 +1,40 @@ +package anchor + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type BLUNACustody struct { + *terra.Contract +} + +func NewBLUNACustody(querier *terra.Querier) (*BLUNACustody, error) { + contract, err := terra.NewContract(querier, "terra1ptjp2vfjrwh0j0faj9r6katm640kgjxnwwq9kn") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &BLUNACustody{ + Contract: contract, + }, nil +} + +func (c *BLUNACustody) NewDepositCollateralMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + DepositCollateral struct { + } `json:"deposit_collateral"` + } + return terra.BLUNA.NewMsgSendExecute(sender, c.Contract, amount, q) +} + +func (c *BLUNACustody) NewWithdrawCollateralMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + WithdrawCollateral struct { + Amount decimal.Decimal + } `json:"withdraw_collateral"` + } + q.WithdrawCollateral.Amount = terra.BLUNA.ValueToTerra(amount) + return c.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/anchor/market.go b/protocols/anchor/market.go new file mode 100644 index 0000000..f6296e1 --- /dev/null +++ b/protocols/anchor/market.go @@ -0,0 +1,98 @@ +package anchor + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Market struct { + *terra.Contract +} + +func NewMarket(querier *terra.Querier) (*Market, error) { + contract, err := terra.NewContract(querier, "terra1sepfj7s0aeg5967uxnfk4thzlerrsktkpelm5s") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &Market{ + contract, + }, nil +} + +type BorrowerInfo struct { + InterestIndex decimal.Decimal + RewardIndex decimal.Decimal + LoanAmount decimal.Decimal + PendingRewards decimal.Decimal +} + +func (m Market) BorrowerInfo(ctx context.Context, borrower cosmos.AccAddress) (BorrowerInfo, error) { + type query struct { + BorrowerInfo struct { + Borrower string `json:"borrower"` + } `json:"borrower_info"` + } + var q query + q.BorrowerInfo.Borrower = borrower.String() + + type response struct { + Borrower string `json:"borrower"` + InterestIndex decimal.Decimal `json:"interest_index"` + RewardIndex decimal.Decimal `json:"reward_index"` + LoanAmount decimal.Decimal `json:"loan_amount"` + PendingRewards decimal.Decimal `json:"pending_rewards"` + } + var r response + err := m.QueryStore(ctx, q, &r) + if err != nil { + return BorrowerInfo{}, errors.Wrap(err, "querying store") + } + return BorrowerInfo{ + InterestIndex: r.InterestIndex, + RewardIndex: r.RewardIndex, + LoanAmount: terra.UST.ValueFromTerra(r.LoanAmount), + PendingRewards: terra.ANC.ValueFromTerra(r.PendingRewards), + }, nil +} + +func (m Market) NewDepositUSTMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + DepositStable struct{} `json:"deposit_stable"` + } + return terra.UST.NewMsgSendExecute(sender, m.Contract, amount, q) +} + +func (m Market) NewRedeemAUSTMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + RedeemStable struct{} `json:"redeem_stable"` + } + return terra.AUST.NewMsgSendExecute(sender, m.Contract, amount, q) +} + +func (m Market) NewClaimRewardsMessage(sender cosmos.AccAddress) (cosmos.Msg, error) { + var q struct { + ClaimRewards struct{} `json:"claim_rewards"` + } + return m.NewMsgExecuteContract(sender, q) +} + +func (m Market) NewBorrowStableMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + BorrowStable struct { + BorrowAmount decimal.Decimal `json:"borrow_amount"` + } `json:"borrow_stable"` + } + q.BorrowStable.BorrowAmount = terra.UST.ValueToTerra(amount) + return m.NewMsgExecuteContract(sender, q) +} + +func (m Market) NewRepayStableMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + RepayStable struct{} `json:"repay_stable"` + } + return terra.UST.NewMsgSendExecute(sender, m.Contract, amount, q) +} diff --git a/protocols/anchor/overseer.go b/protocols/anchor/overseer.go new file mode 100644 index 0000000..e7e8e60 --- /dev/null +++ b/protocols/anchor/overseer.go @@ -0,0 +1,125 @@ +package anchor + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Overseer struct { + *terra.Contract +} + +func NewOverseer(querier *terra.Querier) (*Overseer, error) { + contract, err := terra.NewContract(querier, "terra1tmnqgvg567ypvsvk6rwsga3srp7e3lg6u0elp8") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &Overseer{ + Contract: contract, + }, nil +} + +func (o *Overseer) BorrowLimit(ctx context.Context, borrower cosmos.AccAddress) (decimal.Decimal, error) { + type query struct { + BorrowLimit struct { + Borrower string `json:"borrower"` + } `json:"borrow_limit"` + } + var q query + q.BorrowLimit.Borrower = borrower.String() + + type response struct { + Borrower string `json:"borrower"` + BorrowLimit decimal.Decimal `json:"borrow_limit"` + } + var r response + err := o.QueryStore(ctx, q, &r) + if err != nil { + return decimal.Zero, errors.Wrap(err, "querying store") + } + return terra.UST.ValueFromTerra(r.BorrowLimit), nil +} + +func (o *Overseer) Collaterals(ctx context.Context, borrower cosmos.AccAddress) (map[string]decimal.Decimal, error) { + type query struct { + Collaterals struct { + Borrower string `json:"borrower"` + } `json:"collaterals"` + } + var q query + q.Collaterals.Borrower = borrower.String() + type response struct { + Borrower string `json:"borrower"` + Collaterals [][2]string `json:"collaterals"` + } + var r response + err := o.QueryStore(ctx, q, &r) + if err != nil { + return nil, errors.Wrap(err, "querying store") + } + res := make(map[string]decimal.Decimal) + for _, collateral := range r.Collaterals { + token, err := terra.Cw20TokenFromAddress(ctx, o.Contract.Querier(), collateral[0]) + if err != nil { + continue + } + value, err := decimal.NewFromString(collateral[1]) + if err != nil { + continue + } + res[collateral[0]] = token.ValueFromTerra(value) + } + return res, nil +} + +func (o *Overseer) Collateral(ctx context.Context, borrower cosmos.AccAddress, token terra.Token) (decimal.Decimal, error) { + collaterals, err := o.Collaterals(ctx, borrower) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting collaterals") + } + res := decimal.Zero + found := false + for s, d := range collaterals { + if s == token.Address().String() { + found = true + res = d + break + } + } + if !found { + return decimal.Zero, errors.Errorf("No collateral found for %s", token.Symbol()) + } + return res, nil +} + +func (o *Overseer) NewUnlockCollateralMessage(sender cosmos.AccAddress, token terra.Cw20Token, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + UnlockCollateral struct { + Collaterals [][2]string `json:"collaterals"` + } `json:"unlock_collateral"` + } + var q query + q.UnlockCollateral.Collaterals = append(q.UnlockCollateral.Collaterals, [2]string{ + token.Address().String(), + token.ValueToTerra(amount).String(), + }) + return o.NewMsgExecuteContract(sender, q) +} + +func (o *Overseer) NewLockCollateralMessage(sender cosmos.AccAddress, token terra.Cw20Token, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + LockCollateral struct { + Collaterals [][2]string `json:"collaterals"` + } `json:"lock_collateral"` + } + var q query + q.LockCollateral.Collaterals = append(q.LockCollateral.Collaterals, [2]string{ + token.Address().String(), + token.ValueToTerra(amount).String(), + }) + return o.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/anchor/priceoracle.go b/protocols/anchor/priceoracle.go new file mode 100644 index 0000000..72984ca --- /dev/null +++ b/protocols/anchor/priceoracle.go @@ -0,0 +1,70 @@ +package anchor + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type PriceOracle struct { + *terra.Contract +} + +func NewPriceOracle(querier *terra.Querier) (*PriceOracle, error) { + contract, err := terra.NewContract(querier, "terra1cgg6yef7qcdm070qftghfulaxmllgmvk77nc7t") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &PriceOracle{ + Contract: contract, + }, nil +} + +func (o *PriceOracle) Prices(ctx context.Context) (map[string]decimal.Decimal, error) { + var q struct { + Prices struct { + } `json:"prices"` + } + + type response struct { + Prices []struct { + Asset string `json:"asset"` + Price decimal.Decimal `json:"price"` + LastUpdatedTime int `json:"last_updated_time"` + } `json:"prices"` + } + var r response + err := o.QueryStore(ctx, q, &r) + if err != nil { + return nil, errors.Wrap(err, "querying store") + } + + res := make(map[string]decimal.Decimal) + for _, price := range r.Prices { + res[price.Asset] = price.Price + } + return res, nil +} + +func (o *PriceOracle) Price(ctx context.Context, token terra.Token) (decimal.Decimal, error) { + prices, err := o.Prices(ctx) + if err != nil { + return decimal.Zero, errors.Wrap(err, "getting prices") + } + + res := decimal.Zero + found := false + for s, d := range prices { + if s == token.Address().String() { + found = true + res = d + break + } + } + if !found { + return decimal.Zero, errors.Errorf("price for %s not found in Price Oracle prices", token.Symbol()) + } + return res, nil +} diff --git a/protocols/astroport/bootstrap_auction.go b/protocols/astroport/bootstrap_auction.go new file mode 100644 index 0000000..39c2448 --- /dev/null +++ b/protocols/astroport/bootstrap_auction.go @@ -0,0 +1,123 @@ +package astroport + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type BootstrapAuction struct { + *terra.Contract + astroustpair terra.Pair +} + +func (b *BootstrapAuction) RewardPair() terra.Pair { + return b.astroustpair +} + +func NewBootstrapAuction(ctx context.Context, querier *terra.Querier) (*BootstrapAuction, error) { + contract, err := terra.NewContract(querier, "terra1tvld5k6pus2yh7pcu7xuwyjedn7mjxfkkkjjap") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + b := &BootstrapAuction{ + Contract: contract, + } + cfg, err := b.Config(ctx) + if err != nil { + return nil, errors.Wrap(err, "getting config") + } + p, err := NewXykPair(querier, cfg.AstroUstPoolAddress, terra.ASTRO, terra.UST, terra.ASTRO_ASTROUSTLP) + if err != nil { + return nil, errors.Wrap(err, "getting pool pair object") + } + b.astroustpair = p + return b, nil +} + +type BootstrapAuctionUserInfo struct { + WithdrawableLpShares decimal.Decimal `json:"withdrawable_lp_shares"` +} + +func (b *BootstrapAuction) UserInfo(ctx context.Context, address cosmos.AccAddress) (BootstrapAuctionUserInfo, error) { + type query struct { + UserInfo struct { + Address string `json:"address"` + } `json:"user_info"` + } + var q query + q.UserInfo.Address = address.String() + type response struct { + WithdrawableLpShares decimal.Decimal `json:"withdrawable_lp_shares"` + } + + var r response + err := b.QueryStore(ctx, q, &r) + if err != nil { + return BootstrapAuctionUserInfo{}, errors.Wrap(err, "querying contract store") + } + return BootstrapAuctionUserInfo{ + WithdrawableLpShares: b.astroustpair.LpToken().ValueFromTerra(r.WithdrawableLpShares), + }, nil +} + +type BootstrapAuctionConfig struct { + AstroUstPoolAddress string +} + +func (b *BootstrapAuction) Config(ctx context.Context) (BootstrapAuctionConfig, error) { + var q struct { + Config struct { + } `json:"config"` + } + type response struct { + Owner string `json:"owner"` + AstroTokenAddress string `json:"astro_token_address"` + AirdropContractAddress string `json:"airdrop_contract_address"` + LockdropContractAddress string `json:"lockdrop_contract_address"` + PoolInfo struct { + AstroUstPoolAddress string `json:"astro_ust_pool_address"` + AstroUstLpTokenAddress string `json:"astro_ust_lp_token_address"` + } `json:"pool_info"` + GeneratorContract string `json:"generator_contract"` + AstroIncentiveAmount string `json:"astro_incentive_amount"` + LpTokensVestingDuration int `json:"lp_tokens_vesting_duration"` + InitTimestamp int `json:"init_timestamp"` + DepositWindow int `json:"deposit_window"` + WithdrawalWindow int `json:"withdrawal_window"` + } + + var r response + err := b.QueryStore(ctx, q, &r) + if err != nil { + return BootstrapAuctionConfig{}, errors.Wrap(err, "querying contract store") + } + return BootstrapAuctionConfig{ + AstroUstPoolAddress: r.PoolInfo.AstroUstPoolAddress, + }, nil +} + +func (b *BootstrapAuction) NewClaimAllRewardsMessage(ctx context.Context, sender cosmos.AccAddress) (cosmos.Msg, decimal.Decimal, error) { + r, err := b.UserInfo(ctx, sender) + if err != nil { + return nil, decimal.Zero, errors.Wrap(err, "getting user info") + } + msg, err := b.NewClaimRewardsMessage(sender, r.WithdrawableLpShares) + if err != nil { + return nil, decimal.Zero, errors.Wrap(err, "creating message") + } + return msg, r.WithdrawableLpShares, nil +} + +func (b *BootstrapAuction) NewClaimRewardsMessage(sender cosmos.AccAddress, withdrawLpShares decimal.Decimal) (cosmos.Msg, error) { + var q struct { + ClaimRewards struct { + WithdrawLpShares decimal.Decimal `json:"withdraw_lp_shares"` + } `json:"claim_rewards"` + } + q.ClaimRewards.WithdrawLpShares = b.astroustpair.LpToken().ValueToTerra(withdrawLpShares) + return b.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/astroport/lockdrop.go b/protocols/astroport/lockdrop.go new file mode 100644 index 0000000..2bbf480 --- /dev/null +++ b/protocols/astroport/lockdrop.go @@ -0,0 +1,37 @@ +package astroport + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" +) + +type Lockdrop struct { + *terra.Contract +} + +func NewLockdrop(querier *terra.Querier) (*Lockdrop, error) { + contract, err := terra.NewContract(querier, "terra1627ldjvxatt54ydd3ns6xaxtd68a2vtyu7kakj") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + + return &Lockdrop{ + Contract: contract, + }, nil +} + +func (l *Lockdrop) NewClaimRewardsMessage(sender cosmos.AccAddress, duration int, withdrawLpStake bool, terraswapLpToken string) (cosmos.Msg, error) { + type query struct { + Claim struct { + Duration int `json:"duration"` + WithdrawLpStake bool `json:"withdraw_lp_stake"` + TerraswapLpToken string `json:"terraswap_lp_token"` + } `json:"claim_rewards_and_optionally_unlock"` + } + var q query + q.Claim.Duration = duration + q.Claim.WithdrawLpStake = withdrawLpStake + q.Claim.TerraswapLpToken = terraswapLpToken + return l.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/astroport/pair.go b/protocols/astroport/pair.go new file mode 100644 index 0000000..7b8d4ed --- /dev/null +++ b/protocols/astroport/pair.go @@ -0,0 +1,34 @@ +package astroport + +import ( + "github.com/galacticship/terra" + "github.com/shopspring/decimal" +) + +type XykPair struct { + *terra.BasePair +} + +func NewXykPair(querier *terra.Querier, contractAddress string, token1 terra.Token, token2 terra.Token, lpToken terra.Cw20Token) (*XykPair, error) { + bp, err := terra.NewBasePair(querier, contractAddress, token1, token2, lpToken, decimal.NewFromFloat(0.003), terra.NewAssetInfoFactory()) + if err != nil { + return nil, err + } + return &XykPair{ + bp, + }, nil +} + +type StablePair struct { + *terra.BasePair +} + +func NewStablePair(querier *terra.Querier, contractAddress string, token1 terra.Token, token2 terra.Token, lpToken terra.Cw20Token) (*StablePair, error) { + bp, err := terra.NewBasePair(querier, contractAddress, token1, token2, lpToken, decimal.NewFromFloat(0.0005), terra.NewAssetInfoFactory()) + if err != nil { + return nil, err + } + return &StablePair{ + bp, + }, nil +} diff --git a/protocols/astroport/router.go b/protocols/astroport/router.go new file mode 100644 index 0000000..0d856ed --- /dev/null +++ b/protocols/astroport/router.go @@ -0,0 +1,106 @@ +package astroport + +import ( + "github.com/galacticship/terra" + "github.com/pkg/errors" +) + +type router struct { + *terra.BaseRouter +} + +func NewRouter(querier *terra.Querier) (terra.Router, error) { + r, err := terra.NewBaseRouter(querier, "terra16t7dpwwgx9n3lq6l6te3753lsjqwhxwpday9zx", terra.NewAssetInfoFactory(), newOperation) + if err != nil { + return nil, errors.Wrap(err, "creating base router") + } + + LUNAUST, err := NewXykPair(querier, "terra1m6ywlgn6wrjuagcmmezzz2a029gtldhey5k552", terra.LUNA, terra.UST, terra.ASTRO_LUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LUNAUST pair") + } + BLUNAUST, err := NewXykPair(querier, "terra1wdwg06ksy3dfvkys32yt4yqh9gm6a9f7qmsh37", terra.BLUNA, terra.UST, terra.ASTRO_BLUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init BLUNAUST pair") + } + ANCUST, err := NewXykPair(querier, "terra1qr2k6yjjd5p2kaewqvg93ag74k6gyjr7re37fs", terra.ANC, terra.UST, terra.ASTRO_ANCUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ANCUST pair") + } + MIRUST, err := NewXykPair(querier, "terra143xxfw5xf62d5m32k3t4eu9s82ccw80lcprzl9", terra.MIR, terra.UST, terra.ASTRO_MIRUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MIRUST pair") + } + MINEUST, err := NewXykPair(querier, "terra134m8n2epp0n40qr08qsvvrzycn2zq4zcpmue48", terra.MINE, terra.UST, terra.ASTRO_MINEUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MINEUST pair") + } + SKUJIKUJI, err := NewXykPair(querier, "terra1hlq6ye6km5sq2pcnmrvlf784gs9zygt0akwvsu", terra.SKUJI, terra.KUJI, terra.ASTRO_SKUJIKUJILP) + if err != nil { + return nil, errors.Wrap(err, "init SKUJIKUJI pair") + } + MARSUST, err := NewXykPair(querier, "terra19wauh79y42u5vt62c5adt2g5h4exgh26t3rpds", terra.MARS, terra.UST, terra.ASTRO_MARSUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MARSUST pair") + } + ASTROUST, err := NewXykPair(querier, "terra1l7xu2rl3c7qmtx3r5sd2tz25glf6jh8ul7aag7", terra.ASTRO, terra.UST, terra.ASTRO_ASTROUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ASTROUST pair") + } + ASTROLUNA, err := NewXykPair(querier, "terra1nujm9zqa4hpaz9s8wrhrp86h3m9xwprjt9kmf9", terra.ASTRO, terra.LUNA, terra.ASTRO_ASTROLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init ASTROLUNA pair") + } + + LUNABLUNA, err := NewStablePair(querier, "terra1j66jatn3k50hjtg2xemnjm8s7y8dws9xqa5y8w", terra.LUNA, terra.BLUNA, terra.ASTRO_LUNABLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init LUNABLUNA pair") + } + + r.SetPairs( + LUNAUST, + BLUNAUST, + ANCUST, + MIRUST, + MINEUST, + SKUJIKUJI, + MARSUST, + ASTROUST, + ASTROLUNA, + LUNABLUNA, + //{terra.VKR, terra.UST}, + //{terra.APOLLO, terra.UST}, + //{terra.ORION, terra.UST}, + //{terra.BLUNA, terra.LUNA}, + //{terra.STLUNA, terra.LUNA}, + //{terra.STT, terra.UST}, + //{terra.PSI, terra.UST}, + //{terra.PSI, terra.NLUNA}, + //{terra.WEWSTETH, terra.UST}, + //{terra.PSI, terra.NETH}, + //{terra.XDEFI, terra.UST}, + //{terra.LUART, terra.UST}, + //{terra.ORNE, terra.UST}, + //{terra.HALO, terra.UST}, + ) + + return &router{r}, nil +} + +type operation struct { + Swap struct { + OfferAssetInfo terra.AssetInfo `json:"offer_asset_info"` + AskAssetInfo terra.AssetInfo `json:"ask_asset_info"` + } `json:"astro_swap"` +} + +func newOperation(aiFactory terra.AssetInfoFactory, offer terra.Token, ask terra.Token) interface{} { + var res operation + res.Swap.OfferAssetInfo = aiFactory.NewFromToken(offer) + res.Swap.AskAssetInfo = aiFactory.NewFromToken(ask) + return res +} + +func (r router) String() string { + return "astroport" +} diff --git a/protocols/astroport/staking.go b/protocols/astroport/staking.go new file mode 100644 index 0000000..e12b3e7 --- /dev/null +++ b/protocols/astroport/staking.go @@ -0,0 +1,37 @@ +package astroport + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Staking struct { + *terra.Contract +} + +func NewStaking(querier *terra.Querier) (*Staking, error) { + contract, err := terra.NewContract(querier, "terra1f68wt2ch3cx2g62dxtc8v68mkdh5wchdgdjwz7") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + + return &Staking{ + Contract: contract, + }, nil +} + +func (s *Staking) NewEnterMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + Enter struct{} `json:"enter"` + } + return terra.ASTRO.NewMsgSendExecute(sender, s.Contract, amount, q) +} + +func (s *Staking) NewLeaveMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + Leave struct{} `json:"leave"` + } + return terra.XASTRO.NewMsgSendExecute(sender, s.Contract, amount, q) +} diff --git a/protocols/loop/pair.go b/protocols/loop/pair.go new file mode 100644 index 0000000..a5679db --- /dev/null +++ b/protocols/loop/pair.go @@ -0,0 +1,20 @@ +package loop + +import ( + "github.com/galacticship/terra" + "github.com/shopspring/decimal" +) + +type Pair struct { + *terra.BasePair +} + +func NewPair(querier *terra.Querier, contractAddress string, token1 terra.Token, token2 terra.Token, lpToken terra.Cw20Token) (*Pair, error) { + bp, err := terra.NewBasePair(querier, contractAddress, token1, token2, lpToken, decimal.NewFromFloat(0.003), terra.NewAssetInfoFactory()) + if err != nil { + return nil, err + } + return &Pair{ + bp, + }, nil +} diff --git a/protocols/mars/bootstrap.go b/protocols/mars/bootstrap.go new file mode 100644 index 0000000..21ae380 --- /dev/null +++ b/protocols/mars/bootstrap.go @@ -0,0 +1,116 @@ +package mars + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/galacticship/terra/protocols/astroport" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Bootstrap struct { + *terra.Contract + + marsustpair terra.Pair +} + +func (b *Bootstrap) RewardPair() terra.Pair { + return b.marsustpair +} + +func NewBootstrap(ctx context.Context, querier *terra.Querier) (*Bootstrap, error) { + contract, err := terra.NewContract(querier, "terra1hgyamk2kcy3stqx82wrnsklw9aq7rask5dxfds") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + b := &Bootstrap{ + Contract: contract, + } + cfg, err := b.Config(ctx) + if err != nil { + return nil, errors.Wrap(err, "getting config") + } + p, err := astroport.NewXykPair(querier, cfg.MarsUstPoolAddress, terra.MARS, terra.UST, terra.ASTRO_MARSUSTLP) + if err != nil { + return nil, errors.Wrap(err, "getting pool pair object") + } + b.marsustpair = p + return b, nil +} + +type BootstrapConfig struct { + MarsUstPoolAddress string +} + +func (b *Bootstrap) Config(ctx context.Context) (BootstrapConfig, error) { + var q struct { + Config struct { + } `json:"config"` + } + type response struct { + Owner string `json:"owner"` + MarsTokenAddress string `json:"mars_token_address"` + AstroTokenAddress string `json:"astro_token_address"` + AirdropContractAddress string `json:"airdrop_contract_address"` + LockdropContractAddress string `json:"lockdrop_contract_address"` + AstroportLpPool string `json:"astroport_lp_pool"` + LpTokenAddress string `json:"lp_token_address"` + MarsLpStakingContract string `json:"mars_lp_staking_contract"` + GeneratorContract string `json:"generator_contract"` + MarsRewards string `json:"mars_rewards"` + MarsVestingDuration int `json:"mars_vesting_duration"` + LpTokensVestingDuration int `json:"lp_tokens_vesting_duration"` + InitTimestamp int `json:"init_timestamp"` + MarsDepositWindow int `json:"mars_deposit_window"` + UstDepositWindow int `json:"ust_deposit_window"` + WithdrawalWindow int `json:"withdrawal_window"` + } + + var r response + err := b.QueryStore(ctx, q, &r) + if err != nil { + return BootstrapConfig{}, errors.Wrap(err, "querying contract store") + } + return BootstrapConfig{ + MarsUstPoolAddress: r.AstroportLpPool, + }, nil +} + +type BootstrapUserInfo struct { + WithdrawableLpShares decimal.Decimal `json:"withdrawable_lp_shares"` +} + +func (b *Bootstrap) UserInfo(ctx context.Context, address cosmos.AccAddress) (BootstrapUserInfo, error) { + type query struct { + UserInfo struct { + Address string `json:"address"` + } `json:"user_info"` + } + var q query + q.UserInfo.Address = address.String() + type response struct { + WithdrawableLpShares decimal.Decimal `json:"withdrawable_lp_shares"` + } + + var r response + err := b.QueryStore(ctx, q, &r) + if err != nil { + return BootstrapUserInfo{}, errors.Wrap(err, "querying contract store") + } + return BootstrapUserInfo{ + WithdrawableLpShares: b.marsustpair.LpToken().ValueFromTerra(r.WithdrawableLpShares), + }, nil +} + +func (b *Bootstrap) NewClaimRewardsMessage(sender cosmos.AccAddress, withDrawUnlockedShares bool) (cosmos.Msg, error) { + type query struct { + ClaimRewards struct { + WithdrawUnlockedShares bool `json:"withdraw_unlocked_shares"` + } `json:"claim_rewards"` + } + var q query + q.ClaimRewards.WithdrawUnlockedShares = withDrawUnlockedShares + return b.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/mars/field.go b/protocols/mars/field.go new file mode 100644 index 0000000..19cdbaf --- /dev/null +++ b/protocols/mars/field.go @@ -0,0 +1,65 @@ +package mars + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Field struct { + *terra.Contract +} + +func NewANCUSTField(querier *terra.Querier) (*Field, error) { + return NewField(querier, "terra1vapq79y9cqghqny7zt72g4qukndz282uvqwtz6") +} + +func NewField(querier *terra.Querier, address string) (*Field, error) { + contract, err := terra.NewContract(querier, address) + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &Field{ + contract, + }, nil +} + +type FieldSnapshot struct { + PositionLpValue decimal.Decimal + DebtValue decimal.Decimal + Ltv decimal.Decimal +} + +func (f *Field) Snapshot(ctx context.Context, address string) (FieldSnapshot, error) { + type query struct { + Snapshot struct { + User string `json:"user"` + } `json:"snapshot"` + } + type response struct { + Time int `json:"time"` + Height int `json:"height"` + Position struct { + BondUnits decimal.Decimal `json:"bond_units"` + DebtUnits decimal.Decimal `json:"debt_units"` + } `json:"position"` + Health struct { + BondAmount decimal.Decimal `json:"bond_amount"` + BondValue decimal.Decimal `json:"bond_value"` + DebtAmount decimal.Decimal `json:"debt_amount"` + DebtValue decimal.Decimal `json:"debt_value"` + Ltv decimal.Decimal `json:"ltv"` + } `json:"health"` + } + var q query + q.Snapshot.User = address + var r response + err := f.QueryStore(ctx, q, &r) + if err != nil { + return FieldSnapshot{}, errors.Wrap(err, "querying contract store") + } + res := FieldSnapshot{} + return res, nil +} diff --git a/protocols/mars/governance.go b/protocols/mars/governance.go new file mode 100644 index 0000000..80f5082 --- /dev/null +++ b/protocols/mars/governance.go @@ -0,0 +1,29 @@ +package mars + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Governance struct { + *terra.Contract +} + +func NewGovernance(querier *terra.Querier) (*Governance, error) { + contract, err := terra.NewContract(querier, "terra1y8wwr5q24msk55x9smwn0ptyt24fxpwm4l7tjl") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &Governance{ + Contract: contract, + }, nil +} + +func (g *Governance) NewStakeMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + Stake struct{} `json:"stake"` + } + return terra.MARS.NewMsgSendExecute(sender, g.Contract, amount, q) +} diff --git a/protocols/mars/mars.go b/protocols/mars/mars.go new file mode 100644 index 0000000..e6752ce --- /dev/null +++ b/protocols/mars/mars.go @@ -0,0 +1,35 @@ +package mars + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/pkg/errors" +) + +type Mars struct { + Governance *Governance + Bootstrap *Bootstrap + ANCUSTField *Field +} + +func NewMars(ctx context.Context, querier *terra.Querier) (*Mars, error) { + governance, err := NewGovernance(querier) + if err != nil { + return nil, errors.Wrap(err, "creating governance") + } + bootstrap, err := NewBootstrap(ctx, querier) + if err != nil { + return nil, errors.Wrap(err, "creating bootstrap") + } + ancustfield, err := NewANCUSTField(querier) + if err != nil { + return nil, errors.Wrap(err, "creating ancust field") + } + + return &Mars{ + Governance: governance, + Bootstrap: bootstrap, + ANCUSTField: ancustfield, + }, nil +} diff --git a/protocols/prism/amps.go b/protocols/prism/amps.go new file mode 100644 index 0000000..0fda0a4 --- /dev/null +++ b/protocols/prism/amps.go @@ -0,0 +1,79 @@ +package prism + +import ( + "context" + "time" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Amps struct { + *terra.Contract +} + +func NewAmps(querier *terra.Querier) (*Amps, error) { + contract, err := terra.NewContract(querier, "terra1pa4amk66q8punljptzmmftf6ylq3ezyzx6kl9m") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &Amps{ + Contract: contract, + }, nil +} + +type BoostInfo struct { + AmountBonded decimal.Decimal + Boost decimal.Decimal + LastUpdatedTime time.Time + BoostAccrualStartTime time.Time +} + +func (a *Amps) GetBoost(ctx context.Context, user cosmos.AccAddress) (BoostInfo, error) { + type query struct { + GetBoost struct { + User string `json:"user"` + } `json:"get_boost"` + } + type response struct { + AmtBonded decimal.Decimal `json:"amt_bonded"` + TotalBoost decimal.Decimal `json:"total_boost"` + LastUpdated int64 `json:"last_updated"` + BoostAccrualStartTime int64 `json:"boost_accrual_start_time"` + } + var q query + q.GetBoost.User = user.String() + var r response + err := a.QueryStore(ctx, q, &r) + if err != nil { + return BoostInfo{}, errors.Wrap(err, "querying contract store") + } + return BoostInfo{ + AmountBonded: terra.XPRISM.ValueFromTerra(r.AmtBonded), + Boost: r.TotalBoost.Shift(-6), + LastUpdatedTime: time.Unix(r.LastUpdated, 0), + BoostAccrualStartTime: time.Unix(r.BoostAccrualStartTime, 0), + }, nil +} + +func (a *Amps) NewBondMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + Bond struct { + } `json:"bond"` + } + var q query + return terra.XPRISM.NewMsgSendExecute(sender, a.Contract, amount, q) +} + +func (a *Amps) NewUnbondMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + type query struct { + Unbond struct { + Amount decimal.Decimal `json:"amount"` + } `json:"unbond"` + } + var q query + q.Unbond.Amount = terra.XPRISM.ValueToTerra(amount) + return a.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/prism/asset_info.go b/protocols/prism/asset_info.go new file mode 100644 index 0000000..7f0eb77 --- /dev/null +++ b/protocols/prism/asset_info.go @@ -0,0 +1,54 @@ +package prism + +import ( + "encoding/json" + "errors" + + "github.com/galacticship/terra" +) + +//goland:noinspection GoNameStartsWithPackageName +type PrismAssetInfo struct { + Token string `json:"cw20,omitempty"` + NativeToken string `json:"native,omitempty"` +} + +func (ai PrismAssetInfo) IsNative() bool { + return ai.NativeToken != "" +} + +func (ai PrismAssetInfo) Id() string { + if ai.IsNative() { + return ai.NativeToken + } else if ai.Token != "" { + return ai.Token + } else { + panic(errors.New("invalid asset info")) + } +} + +type assetInfoFactory struct { +} + +func (a assetInfoFactory) NewFromToken(token terra.Token) terra.AssetInfo { + var res PrismAssetInfo + if token.IsNative() { + res.NativeToken = token.Id() + } else { + res.Token = token.Id() + } + return res +} + +func (a assetInfoFactory) DecodeFromJson(raw json.RawMessage) (terra.AssetInfo, error) { + var res PrismAssetInfo + err := json.Unmarshal(raw, &res) + if err != nil { + return nil, err + } + return res, nil +} + +func NewAssetInfoFactory() terra.AssetInfoFactory { + return &assetInfoFactory{} +} diff --git a/protocols/prism/farm.go b/protocols/prism/farm.go new file mode 100644 index 0000000..f52ac4d --- /dev/null +++ b/protocols/prism/farm.go @@ -0,0 +1,63 @@ +package prism + +import ( + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Farm struct { + *terra.Contract +} + +func NewFarm(querier *terra.Querier) (*Farm, error) { + c, err := terra.NewContract(querier, "terra1ns5nsvtdxu53dwdthy3yxs6x3w2hf3fclhzllc") + if err != nil { + return nil, errors.Wrap(err, "init base contract") + } + return &Farm{ + c, + }, nil +} + +func (f *Farm) NewBondMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + Bond struct{} `json:"bond"` + } + return terra.YLUNA.NewMsgSendExecute(sender, f.Contract, amount, q) +} + +func (f *Farm) NewUnBondMessage(sender cosmos.AccAddress, amount decimal.Decimal) (cosmos.Msg, error) { + var q struct { + Unbond struct { + Amount decimal.Decimal + } `json:"unbond"` + } + q.Unbond.Amount = terra.YLUNA.ValueToTerra(amount) + return f.NewMsgExecuteContract(sender, q) +} + +func (f *Farm) NewActivateBoostMessage(sender cosmos.AccAddress) (cosmos.Msg, error) { + var q struct { + ActivateBoost struct{} `json:"activate_boost"` + } + return f.NewMsgExecuteContract(sender, q) +} + +func (f *Farm) newClaimWithdrawnRewardsMessage(sender cosmos.AccAddress, claimType string) (cosmos.Msg, error) { + var q struct { + ClaimWithdrawnRewards struct { + ClaimType string `json:"claim_type"` + } `json:"claim_withdrawn_rewards"` + } + q.ClaimWithdrawnRewards.ClaimType = claimType + return f.NewMsgExecuteContract(sender, q) +} + +func (f *Farm) NewClaimWithdrawnRewardsMessage(sender cosmos.AccAddress) (cosmos.Msg, error) { + return f.newClaimWithdrawnRewardsMessage(sender, "Prism") +} +func (f *Farm) NewClaimAndPledgeWithdrawnRewardsMessage(sender cosmos.AccAddress) (cosmos.Msg, error) { + return f.newClaimWithdrawnRewardsMessage(sender, "Amps") +} diff --git a/protocols/prism/pair.go b/protocols/prism/pair.go new file mode 100644 index 0000000..0789824 --- /dev/null +++ b/protocols/prism/pair.go @@ -0,0 +1,20 @@ +package prism + +import ( + "github.com/galacticship/terra" + "github.com/shopspring/decimal" +) + +type Pair struct { + *terra.BasePair +} + +func NewPair(querier *terra.Querier, contractAddress string, token1 terra.Token, token2 terra.Token, lpToken terra.Cw20Token) (*Pair, error) { + bp, err := terra.NewBasePair(querier, contractAddress, token1, token2, lpToken, decimal.NewFromFloat(0.003), NewAssetInfoFactory()) + if err != nil { + return nil, err + } + return &Pair{ + bp, + }, nil +} diff --git a/protocols/prism/prism.go b/protocols/prism/prism.go new file mode 100644 index 0000000..8d689c7 --- /dev/null +++ b/protocols/prism/prism.go @@ -0,0 +1,33 @@ +package prism + +import ( + "github.com/galacticship/terra" + "github.com/pkg/errors" +) + +type Prism struct { + Amps *Amps + YLUNAStaking *YLUNAStaking + Farm *Farm +} + +func NewPrism(querier *terra.Querier) (*Prism, error) { + amps, err := NewAmps(querier) + if err != nil { + return nil, errors.Wrap(err, "creating amps") + } + ylunastaking, err := NewYLUNAStaking(querier) + if err != nil { + return nil, errors.Wrap(err, "creating yluna staking") + } + farm, err := NewFarm(querier) + if err != nil { + return nil, errors.Wrap(err, "creating farm") + } + + return &Prism{ + Amps: amps, + YLUNAStaking: ylunastaking, + Farm: farm, + }, nil +} diff --git a/protocols/prism/router.go b/protocols/prism/router.go new file mode 100644 index 0000000..8d500e4 --- /dev/null +++ b/protocols/prism/router.go @@ -0,0 +1,73 @@ +package prism + +import ( + "github.com/galacticship/terra" + "github.com/pkg/errors" +) + +type Router struct { + *terra.BaseRouter +} + +func NewRouter(querier *terra.Querier) (terra.Router, error) { + r, err := terra.NewBaseRouter(querier, "terra1yrc0zpwhuqezfnhdgvvh7vs5svqtgyl7pu3n6c", NewAssetInfoFactory(), newOperation) + if err != nil { + return nil, errors.Wrap(err, "creating base router") + } + + PRISMUST, err := NewPair(querier, "terra19d2alknajcngdezrdhq40h6362k92kz23sz62u", terra.PRISM, terra.UST, terra.PRISM_PRISMUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMUST pair") + } + PRISMLUNA, err := NewPair(querier, "terra1r38qlqt69lez4nja5h56qwf4drzjpnu8gz04jd", terra.PRISM, terra.LUNA, terra.PRISM_PRISMLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMLUNA pair") + } + PRISMPLUNA, err := NewPair(querier, "terra1persuahr6f8fm6nyup0xjc7aveaur89nwgs5vs", terra.PRISM, terra.PLUNA, terra.PRISM_PRISMPLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMPLUNA pair") + } + PRISMXPRISM, err := NewPair(querier, "terra1czynvm64nslq2xxavzyrrhau09smvana003nrf", terra.PRISM, terra.XPRISM, terra.PRISM_PRISMXPRISMLP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMXPRISM pair") + } + PRISMCLUNA, err := NewPair(querier, "terra1yxgq5y6mw30xy9mmvz9mllneddy9jaxndrphvk", terra.PRISM, terra.CLUNA, terra.PRISM_PRISMCLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMCLUNA pair") + } + PRISMYLUNA, err := NewPair(querier, "terra1kqc65n5060rtvcgcktsxycdt2a4r67q2zlvhce", terra.PRISM, terra.YLUNA, terra.PRISM_PRISMYLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMYLUNA pair") + } + + r.SetPairs( + PRISMUST, + PRISMLUNA, + PRISMPLUNA, + PRISMXPRISM, + PRISMCLUNA, + PRISMYLUNA, + ) + + return &Router{ + BaseRouter: r, + }, nil +} + +type operation struct { + Swap struct { + OfferAssetInfo terra.AssetInfo `json:"offer_asset_info"` + AskAssetInfo terra.AssetInfo `json:"ask_asset_info"` + } `json:"prism_swap"` +} + +func newOperation(aiFactory terra.AssetInfoFactory, offer terra.Token, ask terra.Token) interface{} { + var res operation + res.Swap.OfferAssetInfo = aiFactory.NewFromToken(offer) + res.Swap.AskAssetInfo = aiFactory.NewFromToken(ask) + return res +} + +func (r Router) String() string { + return "prism" +} diff --git a/protocols/prism/yluna_staking.go b/protocols/prism/yluna_staking.go new file mode 100644 index 0000000..8e19d1b --- /dev/null +++ b/protocols/prism/yluna_staking.go @@ -0,0 +1,78 @@ +package prism + +import ( + "context" + + "github.com/galacticship/terra" + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type YLUNAStaking struct { + *terra.Contract +} + +func NewYLUNAStaking(querier *terra.Querier) (*YLUNAStaking, error) { + contract, err := terra.NewContract(querier, "terra1p7jp8vlt57cf8qwazjg58qngwvarmszsamzaru") + if err != nil { + return nil, errors.Wrap(err, "init contract object") + } + return &YLUNAStaking{ + Contract: contract, + }, nil +} + +type RewardInfo struct { + StakedAmount decimal.Decimal + Rewards map[string]decimal.Decimal +} + +func (y *YLUNAStaking) GetRewardInfo(ctx context.Context, stakerAddress cosmos.AccAddress) (RewardInfo, error) { + type query struct { + RewardInfo struct { + StakerAddr string `json:"staker_addr"` + } `json:"reward_info"` + } + type response struct { + StakerAddr string `json:"staker_addr"` + StakedAmount decimal.Decimal `json:"staked_amount"` + Rewards []struct { + Info struct { + Cw20 string `json:"cw20"` + } `json:"info"` + Amount decimal.Decimal `json:"amount"` + } `json:"rewards"` + } + var q query + q.RewardInfo.StakerAddr = stakerAddress.String() + var r response + err := y.QueryStore(ctx, q, &r) + if err != nil { + return RewardInfo{}, errors.Wrap(err, "querying contract store") + } + res := RewardInfo{ + StakedAmount: terra.YLUNA.ValueFromTerra(r.StakedAmount), + Rewards: make(map[string]decimal.Decimal), + } + for _, reward := range r.Rewards { + token, err := terra.Cw20TokenFromAddress(ctx, y.Contract.Querier(), reward.Info.Cw20) + if err != nil { + return RewardInfo{}, errors.Wrapf(err, "getting token %s", reward.Info.Cw20) + } + res.Rewards[reward.Info.Cw20] = token.ValueFromTerra(reward.Amount) + } + return res, nil +} + +func (y *YLUNAStaking) NewClaimAndConvertRewardMessage(sender cosmos.AccAddress, claimToken terra.Cw20Token) (cosmos.Msg, error) { + var q struct { + ConvertAndClaimRewards struct { + ClaimAsset struct { + Cw20 string `json:"cw20"` + } `json:"claim_asset"` + } `json:"convert_and_claim_rewards"` + } + q.ConvertAndClaimRewards.ClaimAsset.Cw20 = claimToken.Address().String() + return y.NewMsgExecuteContract(sender, q) +} diff --git a/protocols/terraswap/pair.go b/protocols/terraswap/pair.go new file mode 100644 index 0000000..8e3c7cf --- /dev/null +++ b/protocols/terraswap/pair.go @@ -0,0 +1,20 @@ +package terraswap + +import ( + "github.com/galacticship/terra" + "github.com/shopspring/decimal" +) + +type Pair struct { + *terra.BasePair +} + +func NewPair(querier *terra.Querier, contractAddress string, token1 terra.Token, token2 terra.Token, lpToken terra.Cw20Token) (*Pair, error) { + bp, err := terra.NewBasePair(querier, contractAddress, token1, token2, lpToken, decimal.NewFromFloat(0.003), terra.NewAssetInfoFactory()) + if err != nil { + return nil, err + } + return &Pair{ + bp, + }, nil +} diff --git a/protocols/terraswap/router.go b/protocols/terraswap/router.go new file mode 100644 index 0000000..b506fc1 --- /dev/null +++ b/protocols/terraswap/router.go @@ -0,0 +1,252 @@ +package terraswap + +import ( + "github.com/galacticship/terra" + "github.com/pkg/errors" +) + +type Router struct { + *terra.BaseRouter +} + +func NewRouter(querier *terra.Querier) (terra.Router, error) { + r, err := terra.NewBaseRouter(querier, "terra19qx5xe6q9ll4w0890ux7lv2p4mf3csd4qvt3ex", terra.NewAssetInfoFactory(), newOperation) + if err != nil { + return nil, errors.Wrap(err, "creating base router") + } + + LUNAUST, err := NewPair(querier, "terra1tndcaqxkpc5ce9qee5ggqf430mr2z3pefe5wj6", terra.LUNA, terra.UST, terra.TERRASWAP_LUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LUNAUST pair") + } + BLUNALUNA, err := NewPair(querier, "terra1jxazgm67et0ce260kvrpfv50acuushpjsz2y0p", terra.BLUNA, terra.LUNA, terra.TERRASWAP_BLUNALUNALP) + if err != nil { + return nil, errors.Wrap(err, "init BLUNALUNA pair") + } + LUNALUNAX, err := NewPair(querier, "terra1zrzy688j8g6446jzd88vzjzqtywh6xavww92hy", terra.LUNAX, terra.LUNA, terra.TERRASWAP_LUNAXLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init LUNALUNAX pair") + } + LUNAXBLUNA, err := NewPair(querier, "terra1x8h5gan6vey5cz2xfyst74mtqsj7746fqj2hze", terra.LUNAX, terra.BLUNA, terra.TERRASWAP_LUNAXBLUNALP) + if err != nil { + return nil, errors.Wrap(err, "init LUNAXBLUNA pair") + } + LUNAXUST, err := NewPair(querier, "terra1llhpkqd5enjfflt27u3jx0jcp5pdn6s9lfadx3", terra.LUNAX, terra.UST, terra.TERRASWAP_LUNAXUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LUNAXUST pair") + } + BLUNAUST, err := NewPair(querier, "terra1qpd9n7afwf45rkjlpujrrdfh83pldec8rpujgn", terra.BLUNA, terra.UST, terra.TERRASWAP_BLUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init BLUNAUST pair") + } + KUJIUST, err := NewPair(querier, "terra1zkyrfyq7x9v5vqnnrznn3kvj35az4f6jxftrl2", terra.KUJI, terra.UST, terra.TERRASWAP_KUJIUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init KUJIUST pair") + } + PLUNAUST, err := NewPair(querier, "terra1hngzkju6egu78eyzzw2fn8el9dnjk3rr704z2f", terra.PLUNA, terra.UST, terra.TERRASWAP_PLUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init PLUNAUST pair") + } + STLUNAUST, err := NewPair(querier, "terra1de8xa55xm83s3ke0s20fc5pxy7p3cpndmmm7zk", terra.STLUNA, terra.UST, terra.TERRASWAP_STLUNAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init STLUNAUST pair") + } + ANCUST, err := NewPair(querier, "terra1gm5p3ner9x9xpwugn9sp6gvhd0lwrtkyrecdn3", terra.ANC, terra.UST, terra.TERRASWAP_ANCUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ANCUST pair") + } + MIRUST, err := NewPair(querier, "terra1amv303y8kzxuegvurh0gug2xe9wkgj65enq2ux", terra.MIR, terra.UST, terra.TERRASWAP_MIRUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MIRUST pair") + } + LOOPUST, err := NewPair(querier, "terra10k7y9qw63tfwj7e3x4uuzru2u9kvtd4ureajhd", terra.LOOP, terra.UST, terra.TERRASWAP_LOOPUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LOOPUST pair") + } + LOOPRUST, err := NewPair(querier, "terra18raj59xx32kuz66sfg82kqta6q0aslfs3m8s4r", terra.LOOPR, terra.UST, terra.TERRASWAP_LOOPRUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LOOPRUST pair") + } + MINEUST, err := NewPair(querier, "terra178jydtjvj4gw8earkgnqc80c3hrmqj4kw2welz", terra.MINE, terra.UST, terra.TERRASWAP_MINEUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MINEUST pair") + } + SKUJIKUJI, err := NewPair(querier, "terra1g8kjs70d5r68j9507s3gwymzc30yaur5j2ccfr", terra.SKUJI, terra.KUJI, terra.TERRASWAP_SKUJIKUJILP) + if err != nil { + return nil, errors.Wrap(err, "init SKUJIKUJI pair") + } + MARSUST, err := NewPair(querier, "terra15sut89ms4lts4dd5yrcuwcpctlep3hdgeu729f", terra.MARS, terra.UST, terra.TERRASWAP_MARSUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init MARSUST pair") + } + PRISMXPRISM, err := NewPair(querier, "terra1urt608par6rkcancsjzm76472phptfwq397gpm", terra.PRISM, terra.XPRISM, terra.TERRASWAP_PRISMXPRISMLP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMXPRISM pair") + } + PRISMUST, err := NewPair(querier, "terra1ag6fqvxz33nqg78830k5c27n32mmqlcrcgqejl", terra.PRISM, terra.UST, terra.TERRASWAP_PRISMUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init PRISMUST pair") + } + CLUNALUNA, err := NewPair(querier, "terra1ejyqwcemr5kda5pxwz27t2ja784j3d0nj0v6lh", terra.CLUNA, terra.LUNA, terra.TERRASWAP_CLUNALUNALP) + if err != nil { + return nil, errors.Wrap(err, "init CLUNALUNA pair") + } + ASTROUST, err := NewPair(querier, "terra1pufczag48fwqhsmekfullmyu02f93flvfc9a25", terra.ASTRO, terra.UST, terra.TERRASWAP_ASTROUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ASTROUST pair") + } + AUSTUST, err := NewPair(querier, "terra1z50zu7j39s2dls8k9xqyxc89305up0w7f7ec3n", terra.AUST, terra.UST, terra.TERRASWAP_AUSTUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init AUSTUST pair") + } + AUSTVUST, err := NewPair(querier, "terra1gkdudgg2a5wt70cneyx5rtehjls4dvhhcmlptv", terra.AUST, terra.VUST, terra.TERRASWAP_AUSTVUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init AUSTVUST pair") + } + WHALEVUST, err := NewPair(querier, "terra12arl49w7t4xpq7krtv43t3dg6g8kn2xxyaav56", terra.WHALE, terra.VUST, terra.TERRASWAP_WHALEVUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init WHALEVUST pair") + } + BETHUST, err := NewPair(querier, "terra1c0afrdc5253tkp5wt7rxhuj42xwyf2lcre0s7c", terra.BETH, terra.UST, terra.TERRASWAP_BETHUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init BETHUST pair") + } + WHALEUST, err := NewPair(querier, "terra1v4kpj65uq63m4x0mqzntzm27ecpactt42nyp5c", terra.WHALE, terra.UST, terra.TERRASWAP_WHALEUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init WHALEUST pair") + } + SPECUST, err := NewPair(querier, "terra1tn8ejzw8kpuc87nu42f6qeyen4c7qy35tl8t20", terra.SPEC, terra.UST, terra.TERRASWAP_SPECUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init SPECUST pair") + } + STTUST, err := NewPair(querier, "terra19pg6d7rrndg4z4t0jhcd7z9nhl3p5ygqttxjll", terra.STT, terra.UST, terra.TERRASWAP_STTUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init STTUST pair") + } + TWDUST, err := NewPair(querier, "terra1etdkg9p0fkl8zal6ecp98kypd32q8k3ryced9d", terra.TWD, terra.UST, terra.TERRASWAP_TWDUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init TWDUST pair") + } + PSIUST, err := NewPair(querier, "terra163pkeeuwxzr0yhndf8xd2jprm9hrtk59xf7nqf", terra.PSI, terra.UST, terra.TERRASWAP_PSIUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init PSIUST pair") + } + PLYUST, err := NewPair(querier, "terra19fjaurx28dq4wgnf9fv3qg0lwldcln3jqafzm6", terra.PLY, terra.UST, terra.TERRASWAP_PLYUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init PLYUST pair") + } + LOTAUST, err := NewPair(querier, "terra1pn20mcwnmeyxf68vpt3cyel3n57qm9mp289jta", terra.LOTA, terra.UST, terra.TERRASWAP_LOTAUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LOTAUST pair") + } + APOLLOUST, err := NewPair(querier, "terra1xj2w7w8mx6m2nueczgsxy2gnmujwejjeu2xf78", terra.APOLLO, terra.UST, terra.TERRASWAP_APOLLOUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init APOLLOUST pair") + } + VKRUST, err := NewPair(querier, "terra1e59utusv5rspqsu8t37h5w887d9rdykljedxw0", terra.VKR, terra.UST, terra.TERRASWAP_VKRUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init VKRUST pair") + } + ORIONUST, err := NewPair(querier, "terra1z6tp0ruxvynsx5r9mmcc2wcezz9ey9pmrw5r8g", terra.ORION, terra.UST, terra.TERRASWAP_ORIONUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ORIONUST pair") + } + ATLOUST, err := NewPair(querier, "terra1ycp5lnn0qu4sq4wq7k63zax9f05852xt9nu3yc", terra.ATLO, terra.UST, terra.TERRASWAP_ATLOUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ATLOUST pair") + } + GLOWUST, err := NewPair(querier, "terra1p44kn7l233p7gcj0v3mzury8k7cwf4zt6gsxs5", terra.GLOW, terra.UST, terra.TERRASWAP_GLOWUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init GLOWUST pair") + } + TNSUST, err := NewPair(querier, "terra1hqnk9expq3k4la2ruzdnyapgndntec4fztdyln", terra.TNS, terra.UST, terra.TERRASWAP_TNSUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init TNSUST pair") + } + LUVUST, err := NewPair(querier, "terra1hmcd4kwafyydd4mjv2rzhcuuwnfuqc2prkmlhj", terra.LUV, terra.UST, terra.TERRASWAP_LUVUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init LUVUST pair") + } + ROBOUST, err := NewPair(querier, "terra1sprg4sv9dwnk78ahxdw78asslj8upyv9lerjhm", terra.ROBO, terra.UST, terra.TERRASWAP_ROBOUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init ROBOUST pair") + } + XSDWHSD, err := NewPair(querier, "terra1cmehvqwvglg08clmqn66zfuv5cuxgxwrt3jz2u", terra.XSD, terra.WHSD, terra.TERRASWAP_XSDWHSDLP) + if err != nil { + return nil, errors.Wrap(err, "init XSDWHSD pair") + } + WHSDUST, err := NewPair(querier, "terra1upuslwv5twc8l7hrwlka4wju9z97q8ju63a6jt", terra.WHSD, terra.UST, terra.TERRASWAP_WHSDUSTLP) + if err != nil { + return nil, errors.Wrap(err, "init WHSDUST pair") + } + NLUNAPSI, err := NewPair(querier, "terra1zvn8z6y8u2ndwvsjhtpsjsghk6pa6ugwzxp6vx", terra.NLUNA, terra.PSI, terra.TERRASWAP_NLUNAPSILP) + if err != nil { + return nil, errors.Wrap(err, "init NLUNAPSI pair") + } + + r.SetPairs( + LUNAUST, + BLUNALUNA, + LUNALUNAX, + LUNAXBLUNA, + LUNAXUST, + BLUNAUST, + KUJIUST, + PLUNAUST, + STLUNAUST, + ANCUST, + MIRUST, + LOOPUST, + LOOPRUST, + MINEUST, + SKUJIKUJI, + MARSUST, + PRISMXPRISM, + CLUNALUNA, + ASTROUST, + AUSTUST, + AUSTVUST, + WHALEVUST, + BETHUST, + WHALEUST, + SPECUST, + STTUST, + TWDUST, + PSIUST, + PLYUST, + LOTAUST, + APOLLOUST, + VKRUST, + ORIONUST, + ATLOUST, + GLOWUST, + TNSUST, + LUVUST, + ROBOUST, + XSDWHSD, + WHSDUST, + PRISMUST, + NLUNAPSI, + ) + + return &Router{r}, nil +} + +type swap struct { + OfferAssetInfo terra.AssetInfo `json:"offer_asset_info"` + AskAssetInfo terra.AssetInfo `json:"ask_asset_info"` +} +type operation struct { + Swap swap `json:"terra_swap"` +} + +func newOperation(aiFactory terra.AssetInfoFactory, offer terra.Token, ask terra.Token) interface{} { + var res operation + res.Swap.OfferAssetInfo = aiFactory.NewFromToken(offer) + res.Swap.AskAssetInfo = aiFactory.NewFromToken(ask) + return res +} + +func (r Router) String() string { + return "terraswap" +} diff --git a/querier.go b/querier.go new file mode 100644 index 0000000..fce1b8b --- /dev/null +++ b/querier.go @@ -0,0 +1,160 @@ +package terra + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "path" + "time" + + "github.com/gogo/protobuf/proto" + "github.com/pkg/errors" + terraappparams "github.com/terra-money/core/app/params" + "golang.org/x/net/context/ctxhttp" +) + +type Querier struct { + url string + httpClient *http.Client + encodingConfig terraappparams.EncodingConfig + chainId string +} + +type QuerierOption func(q *Querier) *Querier + +func WithChainId(chainId string) QuerierOption { + return func(q *Querier) *Querier { + q.chainId = chainId + return q + } +} + +func NewQuerier(httpClient *http.Client, url string) *Querier { + return &Querier{ + url: url, + httpClient: httpClient, + encodingConfig: terraappparams.MakeEncodingConfig(), + chainId: "columbus-5", + } +} + +func (q Querier) ChainId() string { + return q.chainId +} + +func (q Querier) POST(ctx context.Context, method string, payload interface{}, result interface{}) error { + u, err := url.Parse(q.url) + if err != nil { + return errors.Wrapf(err, "parsing lcd URL %s", q.url) + } + u.Path = path.Join(u.Path, method) + + reqBytes, err := json.Marshal(payload) + if err != nil { + return errors.Wrap(err, "marshalling payload to json") + } + + resp, err := ctxhttp.Post(ctx, q.httpClient, u.String(), "application/json", bytes.NewBuffer(reqBytes)) + if err != nil { + return errors.Wrap(err, "executing http post request") + } + defer resp.Body.Close() + out, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrap(err, "reading response") + } + if resp.StatusCode != 200 { + return fmt.Errorf("non-200 response code %d: %s", resp.StatusCode, string(out)) + } + if result != nil { + err = json.Unmarshal(out, &result) + if err != nil { + return errors.Wrap(err, "unmarshalling response from json") + } + } + return nil +} + +func (q Querier) POSTProto(ctx context.Context, method string, payload proto.Message, result proto.Message) error { + u, err := url.Parse(q.url) + if err != nil { + return errors.Wrapf(err, "parsing lcd URL %s", q.url) + } + u.Path = path.Join(u.Path, method) + + reqBytes, err := q.encodingConfig.Marshaler.MarshalJSON(payload) + if err != nil { + return errors.Wrap(err, "marshalling payload to json") + } + + resp, err := ctxhttp.Post(ctx, q.httpClient, u.String(), "application/json", bytes.NewBuffer(reqBytes)) + if err != nil { + return errors.Wrap(err, "executing http post request") + } + defer resp.Body.Close() + out, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrap(err, "reading response") + } + if resp.StatusCode != 200 { + return fmt.Errorf("non-200 response code %d: %s", resp.StatusCode, string(out)) + } + if result != nil { + err = q.encodingConfig.Marshaler.UnmarshalJSON(out, result) + if err != nil { + return errors.Wrap(err, "unmarshalling response from json") + } + } + return nil +} + +func (q Querier) GET(ctx context.Context, method string, params url.Values, res interface{}) error { + u, err := url.Parse(q.url) + if err != nil { + return errors.Wrapf(err, "parsing lcd URL %s", q.url) + } + u.Path = path.Join(u.Path, method) + if params != nil { + u.RawQuery = params.Encode() + } + resp, err := ctxhttp.Get(ctx, q.httpClient, u.String()) + if err != nil { + return errors.Wrapf(err, "http requesting %s", u.String()) + } + defer resp.Body.Close() + + out, err := ioutil.ReadAll(resp.Body) + if err != nil { + return errors.Wrap(err, "reading response") + } + if resp.StatusCode != 200 { + return fmt.Errorf("non-200 response code %d: %s", resp.StatusCode, string(out)) + } + if res != nil { + err = json.Unmarshal(out, &res) + if err != nil { + return errors.Wrap(err, "unmarshalling response from json") + } + } + return nil +} + +func (q *Querier) LatestBlockInfo(ctx context.Context) (int64, time.Time, error) { + var res struct { + Block struct { + Header struct { + Height int64 `json:"height,string"` + Time time.Time `json:"time"` + } `json:"header"` + } `json:"block"` + } + err := q.GET(ctx, "blocks/latest", nil, &res) + if err != nil { + return 0, time.Time{}, errors.Wrap(err, "executing get request") + } + return res.Block.Header.Height, res.Block.Header.Time, nil +} diff --git a/route.go b/route.go new file mode 100644 index 0000000..e790e42 --- /dev/null +++ b/route.go @@ -0,0 +1,141 @@ +package terra + +import ( + "fmt" + + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type RoutePair struct { + Pair Pair + IsToken1First bool +} + +func NewRoutePair(pair Pair, token1first bool) RoutePair { + return RoutePair{ + Pair: pair, + IsToken1First: token1first, + } +} + +func (p RoutePair) FirstToken() Token { + if p.IsToken1First { + return p.Pair.Token1() + } else { + return p.Pair.Token2() + } +} + +func (p RoutePair) SecondToken() Token { + if p.IsToken1First { + return p.Pair.Token2() + } else { + return p.Pair.Token1() + } +} + +type Route []RoutePair + +func NewRoute(pairs ...RoutePair) Route { + return Route(pairs) +} + +func (r Route) Last() RoutePair { + return r[len(r)-1] +} +func (r Route) First() RoutePair { + return r[0] +} + +func (r Route) Contains(pair Pair) bool { + for _, t := range r { + if t.Pair.Equals(pair) { + return true + } + } + return false +} + +func (r Route) Copy() Route { + res := make(Route, len(r)) + copy(res, r) + return res +} + +func (r Route) String() string { + var res string + for _, pair := range r { + if pair.IsToken1First { + res += fmt.Sprintf("[%s-%s] ", pair.Pair.Token1().Symbol(), pair.Pair.Token2().Symbol()) + } else { + res += fmt.Sprintf("[%s-%s] ", pair.Pair.Token2().Symbol(), pair.Pair.Token1().Symbol()) + } + } + return res +} + +func (r Route) OfferToken() Token { + if r.First().IsToken1First { + return r.First().Pair.Token1() + } else { + return r.First().Pair.Token2() + } +} + +func (r Route) AskToken() Token { + if r.Last().IsToken1First { + return r.Last().Pair.Token2() + } else { + return r.Last().Pair.Token1() + } +} + +func (r Route) CopyAndAdd(pair RoutePair) Route { + return append(r.Copy(), pair) +} + +func (r Route) SimulateSwap(offerAmount decimal.Decimal, pools map[Pair]PoolInfo) decimal.Decimal { + current := r.OfferToken().ValueToTerra(offerAmount) + for _, pair := range r { + pool := pools[pair.Pair] + ra, _, _, _ := ComputeConstantProductSwap(pair.FirstToken().ValueToTerra(pool[pair.FirstToken().Id()]), pair.SecondToken().ValueToTerra(pool[pair.SecondToken().Id()]), current, pair.Pair.CommissionRate()) + current = ra + } + return r.AskToken().ValueFromTerra(current) +} + +func (r Route) GenerateArbitrageMessages(sender cosmos.AccAddress, offerAmount decimal.Decimal, pools map[Pair]PoolInfo) ([]cosmos.Msg, error) { + current := r.OfferToken().ValueToTerra(offerAmount) + var msgs []cosmos.Msg + for _, pair := range r { + pool := pools[pair.Pair] + ra, _, _, bp := ComputeConstantProductSwap(pair.FirstToken().ValueToTerra(pool[pair.FirstToken().Id()]), pair.SecondToken().ValueToTerra(pool[pair.SecondToken().Id()]), current, pair.Pair.CommissionRate()) + newmsg, err := pair.Pair.NewSwapMessage(sender, pair.FirstToken(), current, "0.0", bp) + if err != nil { + return nil, errors.Wrapf(err, "generating message for pair %s", pair.Pair) + } + msgs = append(msgs, newmsg) + current = ra + } + return msgs, nil +} + +func (r Route) Pairs() []Pair { + var res []Pair + for _, pair := range r { + contains := false + for _, re := range res { + if re.Equals(pair.Pair) { + contains = true + break + } + } + if contains { + continue + } + res = append(res, pair.Pair) + } + return res +} diff --git a/route_service.go b/route_service.go new file mode 100644 index 0000000..b6cde50 --- /dev/null +++ b/route_service.go @@ -0,0 +1,75 @@ +package terra + +type RouteService interface { + RegisterPairs(pairs ...Pair) + FindRoutes(offer Token, ask Token, maxDepth int) []Route + FindArbitrages(token Token, maxDepth int) []Route + GetAllArbitrages(maxDepth int) []Route +} + +type routeService struct { + pairs []Pair +} + +func NewRouteService() RouteService { + return &routeService{} +} + +func (s *routeService) RegisterPairs(pairs ...Pair) { + s.pairs = append(s.pairs, pairs...) +} + +func (s *routeService) walkRoute(route Route, ask Token, depth, maxdepth int) []Route { + var res []Route + depth++ + if depth > maxdepth { + return res + } + if route.AskToken().Equals(ask) { + res = append(res, route) + return res + } + for _, pair := range s.pairs { + if route.Contains(pair) { + continue + } + var newroute Route + if route.Last().SecondToken().Equals(pair.Token1()) { + newroute = route.CopyAndAdd(NewRoutePair(pair, true)) + } + if route.Last().SecondToken().Equals(pair.Token2()) { + newroute = route.CopyAndAdd(NewRoutePair(pair, false)) + } + if newroute == nil { + continue + } + res = append(res, s.walkRoute(newroute, ask, depth, maxdepth)...) + } + return res +} + +func (s *routeService) FindRoutes(offer Token, ask Token, maxDepth int) []Route { + var res []Route + for _, pair := range s.pairs { + if pair.Token1().Equals(offer) { + res = append(res, s.walkRoute(NewRoute(NewRoutePair(pair, true)), ask, 0, maxDepth)...) + } + if pair.Token2().Equals(offer) { + res = append(res, s.walkRoute(NewRoute(NewRoutePair(pair, false)), ask, 0, maxDepth)...) + } + } + return res +} + +func (s *routeService) FindArbitrages(token Token, maxDepth int) []Route { + return s.FindRoutes(token, token, maxDepth) +} + +func (s *routeService) GetAllArbitrages(maxDepth int) []Route { + var res []Route + for _, pair := range s.pairs { + res = append(res, s.walkRoute(NewRoute(NewRoutePair(pair, true)), pair.Token1(), 0, maxDepth)...) + res = append(res, s.walkRoute(NewRoute(NewRoutePair(pair, false)), pair.Token2(), 0, maxDepth)...) + } + return res +} diff --git a/router.go b/router.go new file mode 100644 index 0000000..381013f --- /dev/null +++ b/router.go @@ -0,0 +1,138 @@ +package terra + +import ( + "context" + + "github.com/galacticship/terra/cosmos" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type Router interface { + String() string + SimulateSwapWithRoute(ctx context.Context, amount decimal.Decimal, route Route) (decimal.Decimal, error) + SimulateSwap(ctx context.Context, offer Token, ask Token, amount decimal.Decimal, maxRouteLength int) (decimal.Decimal, Route, error) + FindAllRoutes(offer Token, ask Token, maxLength int) []Route + + NewSwapMessageWithRoute(sender cosmos.AccAddress, route Route, offerAmount decimal.Decimal, askExpectedAmount decimal.Decimal, maxSpread float64) (cosmos.Msg, error) + NewSwapMessageWithBestRoute(ctx context.Context, sender cosmos.AccAddress, offer Token, ask Token, offerAmount decimal.Decimal, maxRouteLength int, maxSpread float64) (cosmos.Msg, error) +} + +type BaseRouter struct { + *Contract + routeService RouteService + + operationFactory func(aiFactory AssetInfoFactory, offer Token, ask Token) interface{} + aiFactory AssetInfoFactory +} + +func NewBaseRouter(querier *Querier, contractAddress string, aiFactory AssetInfoFactory, operationFactory func(aiFactory AssetInfoFactory, offer Token, ask Token) interface{}) (*BaseRouter, error) { + contract, err := NewContract(querier, contractAddress) + if err != nil { + return nil, errors.Wrap(err, "creating base contract") + } + return &BaseRouter{ + Contract: contract, + routeService: NewRouteService(), + operationFactory: operationFactory, + aiFactory: aiFactory, + }, nil +} + +func (r BaseRouter) ContractAddress() cosmos.AccAddress { + return r.contractAddress +} + +func (r *BaseRouter) SetPairs(pairs ...Pair) { + r.routeService.RegisterPairs(pairs...) +} + +func (r BaseRouter) FindAllRoutes(offer Token, ask Token, maxLength int) []Route { + return r.routeService.FindRoutes(offer, ask, maxLength) +} + +var ErrNoRouteFund = errors.New("no route found") + +func (r BaseRouter) SimulateSwap(ctx context.Context, offer Token, ask Token, amount decimal.Decimal, maxRouteLength int) (decimal.Decimal, Route, error) { + var resValue decimal.Decimal + var resRoute Route + routes := r.FindAllRoutes(offer, ask, maxRouteLength) + for _, route := range routes { + + tmpValue, err := r.SimulateSwapWithRoute(ctx, amount, route) + if err != nil { + continue + } + if resValue.LessThan(tmpValue) || (resValue.Equals(tmpValue) && len(resRoute) > len(route)) { + resValue = tmpValue + resRoute = route + } + } + if resRoute == nil { + return decimal.Zero, nil, ErrNoRouteFund + } + return resValue, resRoute, nil +} + +func (r BaseRouter) SimulateSwapWithRoute(ctx context.Context, amount decimal.Decimal, route Route) (decimal.Decimal, error) { + + if len(route) < 1 { + return decimal.Zero, errors.Errorf("route length must be greater than 1") + } + type query struct { + SimulateSwapOperations struct { + OfferAmount decimal.Decimal `json:"offer_amount"` + Operations []interface{} `json:"operations"` + } `json:"simulate_swap_operations"` + } + var q query + q.SimulateSwapOperations.OfferAmount = route[0].FirstToken().ValueToTerra(amount) + for _, pair := range route { + q.SimulateSwapOperations.Operations = append(q.SimulateSwapOperations.Operations, + r.operationFactory(r.aiFactory, pair.FirstToken(), pair.SecondToken())) + } + + type response struct { + Amount decimal.Decimal `json:"amount"` + } + var resp response + err := r.QueryStore(ctx, q, &resp) + if err != nil { + return decimal.Zero, errors.Wrap(err, "querying contract store") + } + + return route[len(route)-1].SecondToken().ValueFromTerra(resp.Amount), nil +} + +func (r BaseRouter) NewSwapMessageWithRoute(sender cosmos.AccAddress, route Route, offerAmount decimal.Decimal, askExpectedAmount decimal.Decimal, maxSpread float64) (cosmos.Msg, error) { + askExpectedAmount = route.AskToken().ValueToTerra(askExpectedAmount) + minimumReceived := askExpectedAmount.Sub(askExpectedAmount.Mul(decimal.NewFromFloat(maxSpread).Div(decimal.NewFromInt(100)))).Truncate(0) + + type query struct { + ExecuteSwapOperations struct { + OfferAmount decimal.Decimal `json:"offer_amount"` + MinimumReceive decimal.Decimal `json:"minimum_receive"` + Operations []interface{} `json:"operations"` + } `json:"execute_swap_operations"` + } + var q query + q.ExecuteSwapOperations.OfferAmount = route.OfferToken().ValueToTerra(offerAmount) + q.ExecuteSwapOperations.MinimumReceive = minimumReceived + for _, pair := range route { + q.ExecuteSwapOperations.Operations = append(q.ExecuteSwapOperations.Operations, + r.operationFactory(r.aiFactory, pair.FirstToken(), pair.SecondToken())) + } + res, err := route.OfferToken().NewMsgSendExecute(sender, r.Contract, offerAmount, q) + if err != nil { + return nil, errors.Wrap(err, "generating MsgSendExecute") + } + return res, nil +} + +func (r BaseRouter) NewSwapMessageWithBestRoute(ctx context.Context, sender cosmos.AccAddress, offer Token, ask Token, offerAmount decimal.Decimal, maxRouteLength int, maxSpread float64) (cosmos.Msg, error) { + askExpected, bestRoute, err := r.SimulateSwap(ctx, offer, ask, offerAmount, maxRouteLength) + if err != nil { + return nil, errors.Wrap(err, "simulating swaps to find best route") + } + return r.NewSwapMessageWithRoute(sender, bestRoute, offerAmount, askExpected, maxSpread) +} diff --git a/terra/init.go b/terra/init.go new file mode 100644 index 0000000..0860a38 --- /dev/null +++ b/terra/init.go @@ -0,0 +1,17 @@ +package terra + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + core "github.com/terra-money/core/types" +) + +func init() { + sdkConfig := sdk.GetConfig() + sdkConfig.SetCoinType(core.CoinType) + sdkConfig.SetPurpose(44) + sdkConfig.SetBech32PrefixForAccount(core.Bech32PrefixAccAddr, core.Bech32PrefixAccPub) + sdkConfig.SetBech32PrefixForValidator(core.Bech32PrefixValAddr, core.Bech32PrefixValPub) + sdkConfig.SetBech32PrefixForConsensusNode(core.Bech32PrefixConsAddr, core.Bech32PrefixConsPub) + sdkConfig.SetAddressVerifier(core.AddressVerifier) + sdkConfig.Seal() +} diff --git a/terra/msg.go b/terra/msg.go new file mode 100644 index 0000000..3126cf1 --- /dev/null +++ b/terra/msg.go @@ -0,0 +1,35 @@ +package terra + +import ( + "encoding/json" + + "github.com/galacticship/terra/cosmos" + markettypes "github.com/terra-money/core/x/market/types" + wasmtypes "github.com/terra-money/core/x/wasm/types" +) + +type ( + MsgSwap = markettypes.MsgSwap + MsgSwapSend = markettypes.MsgSwapSend + MsgStoreCode = wasmtypes.MsgStoreCode + MsgMigrateCode = wasmtypes.MsgMigrateCode + MsgInstantiateContract = wasmtypes.MsgInstantiateContract + MsgExecuteContract = wasmtypes.MsgExecuteContract + MsgMigrateContract = wasmtypes.MsgMigrateContract +) + +var ( + NewMsgSwap = markettypes.NewMsgSwap + NewMsgSwapSend = markettypes.NewMsgSwapSend + NewMsgStoreCode = wasmtypes.NewMsgStoreCode + NewMsgMigrateCode = wasmtypes.NewMsgMigrateCode + NewMsgInstantiateContract = wasmtypes.NewMsgInstantiateContract + NewMsgMigrateContract = wasmtypes.NewMsgMigrateContract + NewMsgExecuteContract = func(sender cosmos.AccAddress, contract cosmos.AccAddress, execMsg interface{}, coins cosmos.Coins) (*MsgExecuteContract, error) { + jsonq, err := json.Marshal(execMsg) + if err != nil { + return nil, err + } + return wasmtypes.NewMsgExecuteContract(sender, contract, jsonq, coins), nil + } +) diff --git a/terra/params.go b/terra/params.go new file mode 100644 index 0000000..2785590 --- /dev/null +++ b/terra/params.go @@ -0,0 +1,5 @@ +package terra + +import "github.com/terra-money/core/app/params" + +var EncodingConfig = params.MakeEncodingConfig() diff --git a/terra/tx.go b/terra/tx.go new file mode 100644 index 0000000..ef80108 --- /dev/null +++ b/terra/tx.go @@ -0,0 +1,22 @@ +package terra + +import ( + customauthtx "github.com/terra-money/core/custom/auth/tx" +) + +type ( + ComputeTaxRequest struct { + customauthtx.ComputeTaxRequest + } + ComputeTaxResponse struct { + customauthtx.ComputeTaxResponse + } +) + +func NewComputeTaxRequest(txBytes []byte) *ComputeTaxRequest { + return &ComputeTaxRequest{ + customauthtx.ComputeTaxRequest{ + TxBytes: txBytes, + }, + } +} diff --git a/token.go b/token.go new file mode 100644 index 0000000..275d865 --- /dev/null +++ b/token.go @@ -0,0 +1,264 @@ +package terra + +import ( + "context" + "encoding/json" + "fmt" + "net/url" + + "github.com/galacticship/terra/cosmos" + "github.com/galacticship/terra/terra" + "github.com/pkg/errors" + "github.com/shopspring/decimal" +) + +type tokenInfo struct { + Name string `json:"name"` + Symbol string `json:"symbol"` + Decimals uint8 `json:"decimals"` + TotalSupply decimal.Decimal `json:"total_supply"` +} + +type Token interface { + Id() string + Address() cosmos.AccAddress + Symbol() string + Decimals() uint8 + Balance(context.Context, *Querier, cosmos.AccAddress) (decimal.Decimal, error) + + IsNative() bool + + ValueFromTerra(value decimal.Decimal) decimal.Decimal + ValueToTerra(value decimal.Decimal) decimal.Decimal + + NewMsgSendExecute(sender cosmos.AccAddress, contract *Contract, amount decimal.Decimal, execMsg interface{}) (cosmos.Msg, error) + + Equals(Token) bool + + String() string +} + +type Cw20Token struct { + address cosmos.AccAddress + symbol string + decimals uint8 +} + +func NewCw20Token(contractAddress string, symbol string, decimals uint8) (Cw20Token, error) { + accaddress, err := cosmos.AccAddressFromBech32(contractAddress) + if err != nil { + return Cw20Token{}, errors.Wrap(err, "validating token contract address") + } + return Cw20Token{ + address: accaddress, + symbol: symbol, + decimals: decimals, + }, nil +} + +func Cw20TokenFromAddress(ctx context.Context, querier *Querier, contractAddress string) (Cw20Token, error) { + if t, ok := Cw20TokenMap[contractAddress]; ok { + return t, nil + } + accaddress, err := cosmos.AccAddressFromBech32(contractAddress) + if err != nil { + return Cw20Token{}, errors.Wrap(err, "validating token contract address") + } + t := Cw20Token{ + address: accaddress, + } + ti, err := t.getTokenInfo(ctx, querier) + if err != nil { + return Cw20Token{}, errors.Wrap(err, "getting token info") + } + t.symbol = ti.Symbol + t.decimals = ti.Decimals + + return t, nil +} + +func (t Cw20Token) getTokenInfo(ctx context.Context, querier *Querier) (tokenInfo, error) { + var ti tokenInfo + query := struct { + TokenInfo struct{} `json:"token_info"` + }{} + contract, err := NewContract(querier, t.address.String()) + if err != nil { + return tokenInfo{}, errors.Wrap(err, "creating contract object") + } + err = contract.QueryStore(ctx, query, &ti) + if err != nil { + return tokenInfo{}, errors.Wrap(err, "calling token_info contract method") + } + return ti, nil +} + +func (t Cw20Token) Id() string { + return t.Address().String() +} + +func (t Cw20Token) Decimals() uint8 { + return t.decimals +} + +func (t Cw20Token) DecimalsAsInt32() int32 { + return int32(t.decimals) +} + +func (t Cw20Token) Symbol() string { + return t.symbol +} + +func (t Cw20Token) Address() cosmos.AccAddress { + return t.address +} + +func (t Cw20Token) ValueFromTerra(value decimal.Decimal) decimal.Decimal { + return value.Shift(-t.DecimalsAsInt32()) +} + +func (t Cw20Token) ValueToTerra(value decimal.Decimal) decimal.Decimal { + return value.Shift(t.DecimalsAsInt32()) +} + +func (t Cw20Token) Balance(ctx context.Context, querier *Querier, address cosmos.AccAddress) (decimal.Decimal, error) { + type query struct { + Balance struct { + Address string `json:"address"` + } `json:"balance"` + } + type response struct { + Balance decimal.Decimal `json:"balance"` + } + var q query + q.Balance.Address = address.String() + var r response + contract, err := NewContract(querier, t.address.String()) + if err != nil { + return decimal.Zero, errors.Wrap(err, "creating contract object") + } + err = contract.QueryStore(ctx, q, &r) + if err != nil { + return decimal.Zero, errors.Wrap(err, "querying contract store") + } + return t.ValueFromTerra(r.Balance), nil +} + +func (t Cw20Token) IsNative() bool { + return false +} + +func (t Cw20Token) Equals(token Token) bool { + if !token.IsNative() && t.symbol == token.Symbol() { + return true + } + return false +} + +func (t Cw20Token) String() string { + return t.symbol +} + +func (t Cw20Token) NewMsgSendExecute(sender cosmos.AccAddress, contract *Contract, amount decimal.Decimal, execMsg interface{}) (cosmos.Msg, error) { + jsonexecmsg, err := json.Marshal(execMsg) + if err != nil { + return nil, errors.Wrap(err, "marshalling execMsg") + } + type query struct { + Send struct { + Contract string `json:"contract"` + Amount decimal.Decimal `json:"amount"` + Message interface{} `json:"msg"` + } `json:"send"` + } + var q query + q.Send.Contract = contract.Address().String() + q.Send.Amount = t.ValueToTerra(amount) + q.Send.Message = jsonexecmsg + return terra.NewMsgExecuteContract(sender, t.Address(), q, nil) +} + +type NativeToken struct { + symbol string + denom string +} + +func NewNativeToken(symbol string, denom string) NativeToken { + return NativeToken{ + denom: denom, + symbol: symbol, + } +} + +func NativeTokenFromDenom(denom string) NativeToken { + if t, ok := NativeTokenMap[denom]; ok { + return t + } + return NewNativeToken("", denom) +} + +func (n NativeToken) Id() string { + return n.denom +} + +func (n NativeToken) Address() cosmos.AccAddress { + return cosmos.AccAddress{} +} + +func (n NativeToken) Symbol() string { + return n.symbol +} +func (n NativeToken) Denom() string { + return n.denom +} + +func (n NativeToken) Decimals() uint8 { + return 6 +} + +func (n NativeToken) Balance(ctx context.Context, querier *Querier, address cosmos.AccAddress) (decimal.Decimal, error) { + var response struct { + Balance struct { + Denom string `json:"denom"` + Amount decimal.Decimal `json:"amount"` + } `json:"balance"` + } + params := url.Values{} + params.Set("denom", n.Denom()) + err := querier.GET(ctx, fmt.Sprintf("cosmos/bank/v1beta1/balances/%s/by_denom", address.String()), params, &response) + if err != nil { + return decimal.Zero, errors.Wrap(err, "executing get request") + } + return n.ValueFromTerra(response.Balance.Amount), nil +} + +func (n NativeToken) DecimalsAsInt32() int32 { + return int32(n.Decimals()) +} + +func (n NativeToken) ValueFromTerra(value decimal.Decimal) decimal.Decimal { + return value.Shift(-n.DecimalsAsInt32()) +} + +func (n NativeToken) ValueToTerra(value decimal.Decimal) decimal.Decimal { + return value.Shift(n.DecimalsAsInt32()) +} + +func (n NativeToken) IsNative() bool { + return true +} + +func (n NativeToken) Equals(token Token) bool { + if token.IsNative() && n.symbol == token.Symbol() { + return true + } + return false +} + +func (n NativeToken) String() string { + return n.symbol +} + +func (n NativeToken) NewMsgSendExecute(sender cosmos.AccAddress, contract *Contract, amount decimal.Decimal, execMsg interface{}) (cosmos.Msg, error) { + return terra.NewMsgExecuteContract(sender, contract.contractAddress, execMsg, cosmos.NewCoins(cosmos.NewInt64Coin(n.Id(), n.ValueToTerra(amount).IntPart()))) +} diff --git a/tokens.go b/tokens.go new file mode 100644 index 0000000..0065dbf --- /dev/null +++ b/tokens.go @@ -0,0 +1,170 @@ +package terra + +var ( + LUNA = NewNativeToken("LUNA", "uluna") + UST = NewNativeToken("UST", "uusd") +) + +var ( + SKUJI, _ = NewCw20Token("terra188w26t95tf4dz77raftme8p75rggatxjxfeknw", "sKUJI", 6) + KUJI, _ = NewCw20Token("terra1xfsdgcemqwxp4hhnyk4rle6wr22sseq7j07dnn", "KUJI", 6) + XPRISM, _ = NewCw20Token("terra1042wzrwg2uk6jqxjm34ysqquyr9esdgm5qyswz", "xPRISM", 6) + YLUNA, _ = NewCw20Token("terra17wkadg0tah554r35x6wvff0y5s7ve8npcjfuhz", "yLUNA", 6) + PLUNA, _ = NewCw20Token("terra1tlgelulz9pdkhls6uglfn5lmxarx7f2gxtdzh2", "pLUNA", 6) + PRISM, _ = NewCw20Token("terra1dh9478k2qvqhqeajhn75a2a7dsnf74y5ukregw", "PRISM", 6) + CLUNA, _ = NewCw20Token("terra13zaagrrrxj47qjwczsczujlvnnntde7fdt0mau", "cLUNA", 6) + ASTRO, _ = NewCw20Token("terra1xj49zyqrwpv5k928jwfpfy2ha668nwdgkwlrg3", "ASTRO", 6) + XASTRO, _ = NewCw20Token("terra1f68wt2ch3cx2g62dxtc8v68mkdh5wchdgdjwz7", "xASTRO", 6) + APOLLO, _ = NewCw20Token("terra100yeqvww74h4yaejj6h733thgcafdaukjtw397", "APOLLO", 6) + ANC, _ = NewCw20Token("terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76", "ANC", 6) + BLUNA, _ = NewCw20Token("terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp", "bLUNA", 6) + AUST, _ = NewCw20Token("terra1hzh9vpxhsk8253se0vv5jj6etdvxu3nv8z07zu", "aUST", 6) + BETH, _ = NewCw20Token("terra1dzhzukyezv0etz22ud940z7adyv7xgcjkahuun", "bETH", 6) + MIR, _ = NewCw20Token("terra15gwkyepfc6xgca5t5zefzwy42uts8l2m4g40k6", "MIR", 6) + MINE, _ = NewCw20Token("terra1kcthelkax4j9x8d3ny6sdag0qmxxynl3qtcrpy", "MINE", 6) + STT, _ = NewCw20Token("terra13xujxcrc9dqft4p9a8ls0w3j0xnzm6y2uvve8n", "STT", 6) + PSI, _ = NewCw20Token("terra12897djskt9rge8dtmm86w654g7kzckkd698608", "PSI", 6) + VKR, _ = NewCw20Token("terra1dy9kmlm4anr92e42mrkjwzyvfqwz66un00rwr5", "VKR", 6) + SPEC, _ = NewCw20Token("terra1s5eczhe0h0jutf46re52x5z4r03c8hupacxmdr", "SPEC", 6) + ORION, _ = NewCw20Token("terra1mddcdx0ujx89f38gu7zspk2r2ffdl5enyz2u03", "ORION", 8) + GLOW, _ = NewCw20Token("terra13zx49nk8wjavedjzu8xkk95r3t0ta43c9ptul7", "GLOW", 6) + HALO, _ = NewCw20Token("terra1w8kvd6cqpsthupsk4l0clwnmek4l3zr7c84kwq", "HALO", 6) + LOOP, _ = NewCw20Token("terra1nef5jf6c7js9x6gkntlehgywvjlpytm7pcgkn4", "LOOP", 6) + PLY, _ = NewCw20Token("terra13awdgcx40tz5uygkgm79dytez3x87rpg4uhnvu", "PLY", 6) + WHALE, _ = NewCw20Token("terra1php5m8a6qd68z02t3zpw4jv2pj4vgw4wz0t8mz", "WHALE", 6) + MARS, _ = NewCw20Token("terra12hgwnpupflfpuual532wgrxu2gjp0tcagzgx4n", "MARS", 6) + ATLO, _ = NewCw20Token("terra1cl7whtrqmz5ldr553q69qahck8xvk80fm33qjx", "ATLO", 6) + LOTA, _ = NewCw20Token("terra1ez46kxtulsdv07538fh5ra5xj8l68mu8eg24vr", "LOTA", 6) + TWD, _ = NewCw20Token("terra19djkaepjjswucys4npd5ltaxgsntl7jf0xz7w6", "TWD", 6) + LUNAX, _ = NewCw20Token("terra17y9qkl8dfkeg4py7n0g5407emqnemc3yqk5rup", "LunaX", 6) + VUST, _ = NewCw20Token("terra1w0p5zre38ecdy3ez8efd5h9fvgum5s206xknrg", "vUST", 6) + STLUNA, _ = NewCw20Token("terra1yg3j2s986nyp5z7r2lvt0hx3r0lnd7kwvwwtsc", "stLUNA", 6) + NLUNA, _ = NewCw20Token("terra10f2mt82kjnkxqj2gepgwl637u2w4ue2z5nhz5j", "nLUNA", 6) + WEWSTETH, _ = NewCw20Token("terra133chr09wu8sakfte5v7vd8qzq9vghtkv4tn0ur", "wewstETH", 8) + NETH, _ = NewCw20Token("terra178v546c407pdnx5rer3hu8s2c0fc924k74ymnn", "nETH", 6) + XDEFI, _ = NewCw20Token("terra169edevav3pdrtjcx35j6pvzuv54aevewar4nlh", "XDEFI", 8) + LUART, _ = NewCw20Token("terra1vwz7t30q76s7xx6qgtxdqnu6vpr3ak3vw62ygk", "XDEFI", 6) + ORNE, _ = NewCw20Token("terra1hnezwjqlhzawcrfysczcxs6xqxu2jawn729kkf", "ORNE", 6) + LOOPR, _ = NewCw20Token("terra1jx4lmmke2srcvpjeereetc9hgegp4g5j0p9r2q", "LOOPR", 6) + TNS, _ = NewCw20Token("terra14vz4v8adanzph278xyeggll4tfww7teh0xtw2y", "TNS", 6) + LUV, _ = NewCw20Token("terra15k5r9r8dl8r7xlr29pry8a9w7sghehcnv5mgp6", "LUV", 6) + ROBO, _ = NewCw20Token("terra1f62tqesptvmhtzr8sudru00gsdtdz24srgm7wp", "ROBO", 6) + XSD, _ = NewCw20Token("terra1ln2z938phz0nc2wepxpzfkwp6ezn9yrz9zv9ep", "XSD", 8) + WHSD, _ = NewCw20Token("terra1ustvnmngueq0p4jd7gfnutgvdc6ujpsjhsjd02", "WHSD", 8) +) + +var ( + ASTRO_LUNAUSTLP, _ = NewCw20Token("terra1m24f7k4g66gnh9f7uncp32p722v0kyt3q4l3u5", "uLP", 6) + ASTRO_BLUNAUSTLP, _ = NewCw20Token("terra1aaqmlv4ajsg9043zrhsd44lk8dqnv2hnakjv97", "uLP", 6) + ASTRO_ANCUSTLP, _ = NewCw20Token("terra1wmaty65yt7mjw6fjfymkd9zsm6atsq82d9arcd", "uLP", 6) + ASTRO_MIRUSTLP, _ = NewCw20Token("terra17trxzqjetl0q6xxep0s2w743dhw2cay0x47puc", "uLP", 6) + ASTRO_MINEUSTLP, _ = NewCw20Token("terra16unvjel8vvtanxjpw49ehvga5qjlstn8c826qe", "uLP", 6) + ASTRO_SKUJIKUJILP, _ = NewCw20Token("terra1kp4n4tms5w4tvvypya7589zswssqqahtjxy6da", "uLP", 6) + ASTRO_MARSUSTLP, _ = NewCw20Token("terra1ww6sqvfgmktp0afcmvg78st6z89x5zr3tmvpss", "uLP", 6) + ASTRO_ASTROUSTLP, _ = NewCw20Token("terra17n5sunn88hpy965mzvt3079fqx3rttnplg779g", "uLP", 6) + ASTRO_ASTROLUNALP, _ = NewCw20Token("terra1ryxkslm6p04q0nl046quwz8ctdd5llkjnaccpa", "uLP", 6) + ASTRO_LUNABLUNALP, _ = NewCw20Token("terra1htw7hm40ch0hacm8qpgd24sus4h0tq3hsseatl", "uLP", 6) + + TERRASWAP_LUNAUSTLP, _ = NewCw20Token("terra17dkr9rnmtmu7x4azrpupukvur2crnptyfvsrvr", "uLP", 6) + TERRASWAP_BLUNALUNALP, _ = NewCw20Token("terra1nuy34nwnsh53ygpc4xprlj263cztw7vc99leh2", "uLP", 6) + TERRASWAP_LUNAXLUNALP, _ = NewCw20Token("terra1halhfnaul7c0u9t5aywj430jnlu2hgauftdvdq", "uLP", 6) + TERRASWAP_LUNAXBLUNALP, _ = NewCw20Token("terra1spagsh9rgcpdgl5pj6lfyftmhtz9elugurfl92", "uLP", 6) + TERRASWAP_LUNAXUSTLP, _ = NewCw20Token("terra1ah6vn794y3fjvn5jvcv0pzrzky7gar3tp8zuyu", "uLP", 6) + TERRASWAP_BLUNAUSTLP, _ = NewCw20Token("terra1qmr8j3m9x53dhws0yxhymzsvnkjq886yk8k93m", "uLP", 6) + TERRASWAP_KUJIUSTLP, _ = NewCw20Token("terra1cmqv3sjew8kcm3j907x2026e4n0ejl2jackxlx", "uLP", 6) + TERRASWAP_PLUNAUSTLP, _ = NewCw20Token("terra1t5tg7jrmsk6mj9xs3fk0ey092wfkqqlapuevwr", "uLP", 6) + TERRASWAP_STLUNAUSTLP, _ = NewCw20Token("terra1cksuxx4ryfyhkk2c6lw3mpnn4hahkxlkml82rp", "uLP", 6) + TERRASWAP_ANCUSTLP, _ = NewCw20Token("terra1gecs98vcuktyfkrve9czrpgtg0m3aq586x6gzm", "uLP", 6) + TERRASWAP_MIRUSTLP, _ = NewCw20Token("terra17gjf2zehfvnyjtdgua9p9ygquk6gukxe7ucgwh", "uLP", 6) + TERRASWAP_LOOPUSTLP, _ = NewCw20Token("terra12v03at235nxnmsyfg09akh4tp02mr60ne6flry", "uLP", 6) + TERRASWAP_LOOPRUSTLP, _ = NewCw20Token("terra17mau5a2q453vf4e33ffaa4cvtn0twle5vm0zuf", "uLP", 6) + TERRASWAP_MINEUSTLP, _ = NewCw20Token("terra1rqkyau9hanxtn63mjrdfhpnkpddztv3qav0tq2", "uLP", 6) + TERRASWAP_SKUJIKUJILP, _ = NewCw20Token("terra1qf5xuhns225e6xr3mnjv3z8qwlpzyzf2c8we82", "uLP", 6) + TERRASWAP_MARSUSTLP, _ = NewCw20Token("terra175xghpferetqhnx0hlp3e0um0wyfknxzv8h42q", "uLP", 6) + TERRASWAP_PRISMXPRISMLP, _ = NewCw20Token("terra1pc6fvx7vzk220uj840kmkrnyjhjwxcrneuffnk", "uLP", 6) + TERRASWAP_PRISMUSTLP, _ = NewCw20Token("terra1tragr8vkyx52rzy9f8n42etl6la42zylhcfkwa", "uLP", 6) + TERRASWAP_CLUNALUNALP, _ = NewCw20Token("terra18cul84v9tt4nmxmmyxm2z74vpgjmrj6py73pus", "uLP", 6) + TERRASWAP_ASTROUSTLP, _ = NewCw20Token("terra1xwyhu8geetx2mv8429a3z5dyzr0ajqnmmn4rtr", "uLP", 6) + TERRASWAP_AUSTUSTLP, _ = NewCw20Token("terra1umup8qvslkayek0af8u7x2r3r5ndhk2fwhdxz5", "uLP", 6) + TERRASWAP_AUSTVUSTLP, _ = NewCw20Token("terra14d33ndaanjc802ural7uq8ck3n6smsy2e4r0rt", "uLP", 6) + TERRASWAP_WHALEVUSTLP, _ = NewCw20Token("terra1hg3tr0gx2jfaw38m80s83c7khr4wgfvzyh5uak", "uLP", 6) + TERRASWAP_BETHUSTLP, _ = NewCw20Token("terra1jvewsf7922dm47wr872crumps7ktxd7srwcgte", "uLP", 6) + TERRASWAP_WHALEUSTLP, _ = NewCw20Token("terra17pqpurglgfqnvkhypask28c3llnf69cstaquke", "uLP", 6) + TERRASWAP_SPECUSTLP, _ = NewCw20Token("terra1y9kxxm97vu4ex3uy0rgdr5h2vt7aze5sqx7jyl", "uLP", 6) + TERRASWAP_STTUSTLP, _ = NewCw20Token("terra1uwhf02zuaw7grj6gjs7pxt5vuwm79y87ct5p70", "uLP", 6) + TERRASWAP_TWDUSTLP, _ = NewCw20Token("terra1c9wr85y8p8989tr58flz5gjkqp8q2r6murwpm9", "uLP", 6) + TERRASWAP_PSIUSTLP, _ = NewCw20Token("terra1q6r8hfdl203htfvpsmyh8x689lp2g0m7856fwd", "uLP", 6) + TERRASWAP_PLYUSTLP, _ = NewCw20Token("terra1h69kvcmg8jnq7ph2r45k6md4afkl96ugg73amc", "uLP", 6) + TERRASWAP_LOTAUSTLP, _ = NewCw20Token("terra1t4xype7nzjxrzttuwuyh9sglwaaeszr8l78u6e", "uLP", 6) + TERRASWAP_APOLLOUSTLP, _ = NewCw20Token("terra1n3gt4k3vth0uppk0urche6m3geu9eqcyujt88q", "uLP", 6) + TERRASWAP_VKRUSTLP, _ = NewCw20Token("terra17fysmcl52xjrs8ldswhz7n6mt37r9cmpcguack", "uLP", 6) + TERRASWAP_ORIONUSTLP, _ = NewCw20Token("terra14ffp0waxcck733a9jfd58d86h9rac2chf5xhev", "uLP", 6) + TERRASWAP_ATLOUSTLP, _ = NewCw20Token("terra1l0wqwge0vtfmukx028pluxsr7ee2vk8gl5mlxr", "uLP", 6) + TERRASWAP_GLOWUSTLP, _ = NewCw20Token("terra1khm4az2cjlzl76885x2n7re48l9ygckjuye0mt", "uLP", 6) + TERRASWAP_TNSUSTLP, _ = NewCw20Token("terra1kg9vmu4e43d3pz0dfsdg9vzwgnnuf6uf3z9jwj", "uLP", 6) + TERRASWAP_LUVUSTLP, _ = NewCw20Token("terra1qq6g0kds9zn97lvrukf2qxf6w4sjt0k9jhcdty", "uLP", 6) + TERRASWAP_ROBOUSTLP, _ = NewCw20Token("terra19ryu7a586s75ncw3ddc8julkszjht4ahwd7zja", "uLP", 6) + TERRASWAP_XSDWHSDLP, _ = NewCw20Token("terra1z0vaks4wkehncztu2a3j2z4fj2gjsnyk2ng9xu", "uLP", 6) + TERRASWAP_WHSDUSTLP, _ = NewCw20Token("terra13m7t5z9zvx2phtpa0k6lxht3qtjjhj68u0t0jz", "uLP", 6) + TERRASWAP_NLUNAPSILP, _ = NewCw20Token("terra1tuw46dwfvahpcwf3ulempzsn9a0vhazut87zec", "uLP", 6) + + PRISM_PRISMUSTLP, _ = NewCw20Token("terra1wkv9htanake4yerrrjz8p5n40lyrjg9md28tg3", "uLP", 6) + PRISM_PRISMLUNALP, _ = NewCw20Token("terra1af7hyx4ek8vqr8asmtujsyv7s3z6py3jgtsgh8", "uLP", 6) + PRISM_PRISMPLUNALP, _ = NewCw20Token("terra1rjm3ca2xh2cfm6l6nsnvs6dqzed0lgzdydy7wf", "uLP", 6) + PRISM_PRISMXPRISMLP, _ = NewCw20Token("terra1zuv05w52xvtn3td2lpfl3q9jj807533ew54f0x", "uLP", 6) + PRISM_PRISMCLUNALP, _ = NewCw20Token("terra1vn5c4yf70aasrq50k2xdy3vn2s8vm40wmngljh", "uLP", 6) + PRISM_PRISMYLUNALP, _ = NewCw20Token("terra1argcazqn3ukpyp0vmldxnf9qymnm6vfjaar94g", "uLP", 6) +) + +var ( + Cw20TokenMap = map[string]Cw20Token{ + "terra188w26t95tf4dz77raftme8p75rggatxjxfeknw": SKUJI, + "terra1xfsdgcemqwxp4hhnyk4rle6wr22sseq7j07dnn": KUJI, + "terra1042wzrwg2uk6jqxjm34ysqquyr9esdgm5qyswz": XPRISM, + "terra17wkadg0tah554r35x6wvff0y5s7ve8npcjfuhz": YLUNA, + "terra1tlgelulz9pdkhls6uglfn5lmxarx7f2gxtdzh2": PLUNA, + "terra1dh9478k2qvqhqeajhn75a2a7dsnf74y5ukregw": PRISM, + "terra13zaagrrrxj47qjwczsczujlvnnntde7fdt0mau": CLUNA, + "terra1xj49zyqrwpv5k928jwfpfy2ha668nwdgkwlrg3": ASTRO, + "terra1f68wt2ch3cx2g62dxtc8v68mkdh5wchdgdjwz7": XASTRO, + "terra100yeqvww74h4yaejj6h733thgcafdaukjtw397": APOLLO, + "terra14z56l0fp2lsf86zy3hty2z47ezkhnthtr9yq76": ANC, + "terra1kc87mu460fwkqte29rquh4hc20m54fxwtsx7gp": BLUNA, + "terra1hzh9vpxhsk8253se0vv5jj6etdvxu3nv8z07zu": AUST, + "terra1dzhzukyezv0etz22ud940z7adyv7xgcjkahuun": BETH, + "terra15gwkyepfc6xgca5t5zefzwy42uts8l2m4g40k6": MIR, + "terra1kcthelkax4j9x8d3ny6sdag0qmxxynl3qtcrpy": MINE, + "terra13xujxcrc9dqft4p9a8ls0w3j0xnzm6y2uvve8n": STT, + "terra12897djskt9rge8dtmm86w654g7kzckkd698608": PSI, + "terra1dy9kmlm4anr92e42mrkjwzyvfqwz66un00rwr5": VKR, + "terra1s5eczhe0h0jutf46re52x5z4r03c8hupacxmdr": SPEC, + "terra1mddcdx0ujx89f38gu7zspk2r2ffdl5enyz2u03": ORION, + "terra13zx49nk8wjavedjzu8xkk95r3t0ta43c9ptul7": GLOW, + "terra1w8kvd6cqpsthupsk4l0clwnmek4l3zr7c84kwq": HALO, + "terra1nef5jf6c7js9x6gkntlehgywvjlpytm7pcgkn4": LOOP, + "terra13awdgcx40tz5uygkgm79dytez3x87rpg4uhnvu": PLY, + "terra1php5m8a6qd68z02t3zpw4jv2pj4vgw4wz0t8mz": WHALE, + "terra12hgwnpupflfpuual532wgrxu2gjp0tcagzgx4n": MARS, + "terra1cl7whtrqmz5ldr553q69qahck8xvk80fm33qjx": ATLO, + "terra1ez46kxtulsdv07538fh5ra5xj8l68mu8eg24vr": LOTA, + "terra19djkaepjjswucys4npd5ltaxgsntl7jf0xz7w6": TWD, + "terra17y9qkl8dfkeg4py7n0g5407emqnemc3yqk5rup": LUNAX, + "terra1w0p5zre38ecdy3ez8efd5h9fvgum5s206xknrg": VUST, + "terra1yg3j2s986nyp5z7r2lvt0hx3r0lnd7kwvwwtsc": STLUNA, + "terra133chr09wu8sakfte5v7vd8qzq9vghtkv4tn0ur": WEWSTETH, + "terra178v546c407pdnx5rer3hu8s2c0fc924k74ymnn": NETH, + "terra169edevav3pdrtjcx35j6pvzuv54aevewar4nlh": XDEFI, + "terra1vwz7t30q76s7xx6qgtxdqnu6vpr3ak3vw62ygk": LUART, + "terra1hnezwjqlhzawcrfysczcxs6xqxu2jawn729kkf": ORNE, + "terra1jx4lmmke2srcvpjeereetc9hgegp4g5j0p9r2q": LOOPR, + "terra14vz4v8adanzph278xyeggll4tfww7teh0xtw2y": TNS, + "terra15k5r9r8dl8r7xlr29pry8a9w7sghehcnv5mgp6": LUV, + "terra1f62tqesptvmhtzr8sudru00gsdtdz24srgm7wp": ROBO, + "terra1ln2z938phz0nc2wepxpzfkwp6ezn9yrz9zv9ep": XSD, + "terra1ustvnmngueq0p4jd7gfnutgvdc6ujpsjhsjd02": WHSD, + } + NativeTokenMap = map[string]NativeToken{ + "uusd": UST, + "uluna": LUNA, + } +) diff --git a/transaction.go b/transaction.go new file mode 100644 index 0000000..21108f5 --- /dev/null +++ b/transaction.go @@ -0,0 +1,318 @@ +package terra + +import ( + "context" + "fmt" + "time" + + "github.com/galacticship/terra/cosmos" + "github.com/galacticship/terra/crypto" + "github.com/galacticship/terra/terra" + "github.com/hashicorp/go-multierror" + "github.com/pkg/errors" +) + +type Transaction struct { + builder cosmos.TxBuilder + config cosmos.TxConfig + + q *Querier + errors *multierror.Error + + gasLimit uint64 + feeAmount cosmos.Coins + signMode cosmos.SignMode + accountNumber uint64 + sequence uint64 + messages []cosmos.Msg +} + +func NewTransaction(q *Querier) *Transaction { + return &Transaction{ + builder: terra.EncodingConfig.TxConfig.NewTxBuilder(), + config: terra.EncodingConfig.TxConfig, + q: q, + } +} + +func (t *Transaction) Error() error { + return t.errors +} + +func (t *Transaction) Message(message func() (cosmos.Msg, error)) *Transaction { + m, err := message() + if err != nil { + t.errors = multierror.Append(t.errors, errors.Wrap(err, "generating message")) + } + t.messages = append(t.messages, m) + return t +} + +func (t *Transaction) Memo(memo string) *Transaction { + t.builder.SetMemo(memo) + return t +} + +func (t *Transaction) FeeGranter(feeGranter cosmos.AccAddress) *Transaction { + t.builder.SetFeeGranter(feeGranter) + return t +} + +func (t *Transaction) TimeoutHeight(timeoutHeight uint64) *Transaction { + t.builder.SetTimeoutHeight(timeoutHeight) + return t +} + +func (t *Transaction) GasLimit(gasLimit uint64) *Transaction { + t.gasLimit = gasLimit + return t +} + +func (t *Transaction) FeeAmount(feeAmount cosmos.Coins) *Transaction { + t.feeAmount = feeAmount + return t +} + +func (t *Transaction) SignMode(signMode cosmos.SignMode) *Transaction { + t.signMode = signMode + return t +} + +func (t *Transaction) AccountNumber(accountNumber uint64) *Transaction { + t.accountNumber = accountNumber + return t +} + +func (t *Transaction) Sequence(sequence uint64) *Transaction { + t.sequence = sequence + return t +} + +func (t *Transaction) simulate(ctx context.Context) (*cosmos.SimulateResponse, error) { + sig := cosmos.SignatureV2{ + PubKey: &crypto.PubKey{}, + Data: &cosmos.SingleSignatureData{ + SignMode: t.signMode, + }, + Sequence: t.sequence, + } + if err := t.builder.SetSignatures(sig); err != nil { + return nil, err + } + + txBytes, err := t.GetTxBytes() + if err != nil { + return nil, err + } + + var res cosmos.SimulateResponse + err = t.q.POSTProto(ctx, "cosmos/tx/v1beta1/simulate", cosmos.NewSimulateRequest(txBytes), &res) + + if err != nil { + return nil, errors.Wrap(err, "querying") + } + return &res, nil +} + +func (t *Transaction) computeTax(ctx context.Context) (*terra.ComputeTaxResponse, error) { + txBytes, err := t.GetTxBytes() + if err != nil { + return nil, errors.Wrap(err, "getting transaction bytes") + } + var res terra.ComputeTaxResponse + err = t.q.POSTProto(ctx, "terra/tx/v1beta1/compute_tax", terra.NewComputeTaxRequest(txBytes), &res) + if err != nil { + return nil, errors.Wrap(err, "querying") + } + return &res, nil +} + +func (t *Transaction) validate(ctx context.Context, wallet *Wallet) error { + err := t.builder.SetMsgs(t.messages...) + if err != nil { + t.errors = multierror.Append(t.errors, errors.Wrap(err, "setting messages")) + } + + if t.errors.ErrorOrNil() != nil { + return t.errors.ErrorOrNil() + } + + if t.accountNumber == 0 || t.sequence == 0 { + state, err := wallet.State(ctx) + if err != nil { + return errors.Wrap(err, "getting wallet state") + } + t.accountNumber = state.AccountNumber + t.sequence = state.Sequence + } + + if t.signMode == cosmos.SignModeUnspecified { + t.signMode = cosmos.SignModeDirect + } + + gasLimit := int64(t.gasLimit) + if gasLimit == 0 { + simulateRes, err := t.simulate(ctx) + if err != nil { + return errors.Wrap(err, "simulating transaction for gas limit") + } + gasLimit = wallet.GasAdjustment().MulInt64(int64(simulateRes.GasInfo.GasUsed)).Ceil().RoundInt64() + } + t.builder.SetGasLimit(uint64(gasLimit)) + + feeAmount := t.feeAmount + if feeAmount.IsZero() { + //computeTaxRes, err := t.computeTax(ctx) + //if err != nil { + // return errors.Wrap(err, "computing taxes to determine feeAmount") + //} + gasPrice := wallet.GasPrice() + feeAmount = cosmos.NewCoins(cosmos.NewCoin(gasPrice.Denom, gasPrice.Amount.MulInt64(gasLimit).Ceil().RoundInt())) + } + t.builder.SetFeeAmount(feeAmount) + return nil +} + +func (t *Transaction) broadcast(ctx context.Context) (*cosmos.TxResponse, error) { + txBytes, err := t.GetTxBytes() + if err != nil { + return nil, err + } + + var res cosmos.BroadcastTxResponse + err = t.q.POSTProto(ctx, "cosmos/tx/v1beta1/txs", cosmos.NewBroadcastTxRequest(txBytes, cosmos.BroadcastModeAsync), &res) + if err != nil { + return nil, errors.Wrap(err, "querying") + } + txResponse := res.TxResponse + if txResponse.Code != 0 { + return txResponse, errors.Errorf("tx failed with code %d: %s", txResponse.Code, txResponse.RawLog) + } + return txResponse, nil +} + +func (t *Transaction) ExecuteAndWaitFor(ctx context.Context, wallet *Wallet) error { + wallet.lock() + defer wallet.unlock() + err := t.validate(ctx, wallet) + if err != nil { + return errors.Wrap(err, "validating transaction") + } + err = wallet.SignTransaction(t) + if err != nil { + return errors.Wrap(err, "signing transaction") + } + transresp, err := t.broadcast(ctx) + if err != nil { + return errors.Wrap(err, "broadcasting transaction") + } + tick := time.NewTicker(2 * time.Second) + notfoundmax := 10 + notfoundcount := 0 + for { + select { + case <-ctx.Done(): + return errors.New("context canceled") + case <-tick.C: + var res struct { + TxResponse struct { + Height int64 `json:"height,string"` + Txhash string `json:"txhash"` + Code int `json:"code"` + } `json:"tx_response"` + } + err := t.q.GET(ctx, fmt.Sprintf("cosmos/tx/v1beta1/txs/%s", transresp.TxHash), nil, &res) + if err != nil { + if notfoundcount < notfoundmax { + notfoundcount++ + continue + } + return errors.Wrapf(err, "retrieving transaction state for hash %s", transresp.TxHash) + } + if res.TxResponse.Code != 0 { + return errors.Errorf("transaction %s failed with code %d", transresp.TxHash, res.TxResponse.Code) + } + t.waitForBlock(ctx, res.TxResponse.Height) + return nil + } + } +} + +func (t *Transaction) waitForBlock(ctx context.Context, height int64) { + checkBlock := func(height int64) error { + latestBlockHeight, _, err := t.q.LatestBlockInfo(ctx) + if err != nil { + return errors.Wrap(err, "querying latest block") + } + if latestBlockHeight < height { + return errors.Wrap(err, "latest block height is less than asked height") + } + return nil + } + if err := checkBlock(height); err != nil { + tickHeight := time.NewTicker(5 * time.Second) + for { + select { + case <-ctx.Done(): + return + case <-tickHeight.C: + err = checkBlock(height) + if err != nil { + continue + } + } + } + } +} + +func (t *Transaction) sign( + signMode cosmos.SignMode, signerData cosmos.SignerData, + privKey crypto.PrivKey, overwriteSig bool) error { + + sigData := cosmos.SingleSignatureData{ + SignMode: signMode, + Signature: nil, + } + sig := cosmos.SignatureV2{ + PubKey: privKey.PubKey(), + Data: &sigData, + Sequence: signerData.Sequence, + } + + var err error + var prevSignatures []cosmos.SignatureV2 + if !overwriteSig { + prevSignatures, err = t.builder.GetTx().GetSignaturesV2() + if err != nil { + return err + } + } + + if err := t.builder.SetSignatures(sig); err != nil { + return err + } + + signature, err := cosmos.SignWithPrivKey( + signMode, + signerData, + t.builder, + privKey, + t.config, + signerData.Sequence, + ) + + if err != nil { + return err + } + + if overwriteSig { + return t.builder.SetSignatures(signature) + } + prevSignatures = append(prevSignatures, signature) + return t.builder.SetSignatures(prevSignatures...) +} + +// GetTxBytes return tx bytes for broadcast +func (t Transaction) GetTxBytes() ([]byte, error) { + return t.config.TxEncoder()(t.builder.GetTx()) +} diff --git a/wallet.go b/wallet.go new file mode 100644 index 0000000..0af5d2b --- /dev/null +++ b/wallet.go @@ -0,0 +1,111 @@ +package terra + +import ( + "context" + "fmt" + "sync" + + "github.com/galacticship/terra/cosmos" + "github.com/galacticship/terra/crypto" + "github.com/pkg/errors" +) + +type Wallet struct { + q *Querier + privKey crypto.PrivKey + transactionLock *sync.Mutex + + gasAdjustment cosmos.Dec + gasPrice cosmos.DecCoin +} + +type WalletOption func(w *Wallet) *Wallet + +func WithGasAdjustment(gasAdjustment cosmos.Dec) WalletOption { + return func(w *Wallet) *Wallet { + w.gasAdjustment = gasAdjustment + return w + } +} + +func WithGasPrice(gasPrice cosmos.DecCoin) WalletOption { + return func(w *Wallet) *Wallet { + w.gasPrice = gasPrice + return w + } +} + +func NewWalletFromMnemonic(querier *Querier, mnemonic string, account uint32, index uint32, options ...WalletOption) (*Wallet, error) { + privKeyBz, err := crypto.DerivePrivKeyBz(mnemonic, crypto.CreateHDPath(account, index)) + if err != nil { + return nil, errors.Wrap(err, "deriving private key bytes") + } + privKey, err := crypto.PrivKeyGen(privKeyBz) + if err != nil { + return nil, errors.Wrap(err, "generating private key") + } + + return NewWalletFromPrivateKey(querier, privKey, options...), nil +} + +func NewWalletFromPrivateKey(querier *Querier, privateKey crypto.PrivKey, options ...WalletOption) *Wallet { + w := &Wallet{ + q: querier, + privKey: privateKey, + transactionLock: &sync.Mutex{}, + + gasAdjustment: cosmos.NewDecFromIntWithPrec(cosmos.NewInt(14), 1), + gasPrice: cosmos.NewDecCoinFromDec("uusd", cosmos.NewDecFromIntWithPrec(cosmos.NewInt(15), 2)), + } + for _, option := range options { + w = option(w) + } + return w +} + +func (a Wallet) GasAdjustment() cosmos.Dec { + return a.gasAdjustment +} +func (a Wallet) GasPrice() cosmos.DecCoin { + return a.gasPrice +} + +func (a Wallet) Address() cosmos.AccAddress { + return cosmos.AccAddress(a.privKey.PubKey().Address()) +} + +type WalletState struct { + AccountNumber uint64 `json:"account_number,string"` + Sequence uint64 `json:"sequence,string"` +} + +func (a Wallet) State(ctx context.Context) (WalletState, error) { + var response struct { + AccountInfo WalletState `json:"account"` + } + err := a.q.GET(ctx, fmt.Sprintf("cosmos/auth/v1beta1/accounts/%s", a.Address().String()), nil, &response) + if err != nil { + return WalletState{}, errors.Wrap(err, "querying lcd") + } + return response.AccountInfo, nil +} + +func (a Wallet) SignTransaction(transaction *Transaction) error { + err := transaction.sign(transaction.signMode, cosmos.SignerData{ + AccountNumber: transaction.accountNumber, + ChainID: a.q.ChainId(), + Sequence: transaction.sequence, + }, a.privKey, true) + if err != nil { + return errors.Wrap(err, "signing transaction") + } + return nil +} + +func (a Wallet) lock() { + a.transactionLock.Lock() +} + +func (a Wallet) unlock() { + a.transactionLock.Unlock() +}