feat(client/v2): signing (#17913)
This commit is contained in:
parent
76f8ed1e86
commit
b62301d9d1
@ -49,6 +49,8 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Improvements
|
||||
|
||||
* (keyring) [#17913](https://github.com/cosmos/cosmos-sdk/pull/17913) Add `NewAutoCLIKeyring` for creating an AutoCLI keyring from a SDK keyring.
|
||||
* (codec) [#17913](https://github.com/cosmos/cosmos-sdk/pull/17913) `codectypes.NewAnyWithValue` supports proto v2 messages.
|
||||
* (client) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) Add `client.Context{}.WithAddressCodec`, `WithValidatorAddressCodec`, `WithConsensusAddressCodec` to provide address codecs to the client context. See the [UPGRADING.md](./UPGRADING.md) for more details.
|
||||
* (crypto/keyring) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) Simplify keyring interfaces to use `[]byte` instead of `sdk.Address` for addresses.
|
||||
* (all) [#16537](https://github.com/cosmos/cosmos-sdk/pull/16537) Properly propagated `fmt.Errorf` errors and using `errors.New` where appropriate.
|
||||
@ -65,7 +67,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
* (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The `FundCommunityPool` and `DistributeFromFeePool` keeper methods are now removed from x/distribution.
|
||||
* (x/distribution) [#17657](https://github.com/cosmos/cosmos-sdk/pull/17657) The distribution module keeper now takes a new argument `PoolKeeper` in addition.
|
||||
* (app) [#17838](https://github.com/cosmos/cosmos-sdk/pull/17838) Params module was removed from simapp and all imports of the params module removed throughout the repo.
|
||||
* The Cosmos SDK has migrated aay from using params, if you're app still uses it, then you can leave it plugged into your app
|
||||
* The Cosmos SDK has migrated away from using params, if your app still uses it, then you can leave it plugged into your app
|
||||
* (x/staking) [#17778](https://github.com/cosmos/cosmos-sdk/pull/17778) Use collections for `Params`
|
||||
* remove from `Keeper`: `GetParams`, `SetParams`
|
||||
* (types/simulation) [#17737](https://github.com/cosmos/cosmos-sdk/pull/17737) Remove unused parameter from `RandomFees`
|
||||
|
||||
@ -117,7 +117,9 @@ func AddQueryFlagsToCmd(cmd *cobra.Command) {
|
||||
func AddTxFlagsToCmd(cmd *cobra.Command) {
|
||||
f := cmd.Flags()
|
||||
f.StringP(FlagOutput, "o", OutputFormatJSON, "Output format (text|json)")
|
||||
f.String(FlagFrom, "", "Name or address of private key with which to sign")
|
||||
if cmd.Flag(FlagFrom) == nil { // avoid flag redefinition when it's already been added by AutoCLI
|
||||
f.String(FlagFrom, "", "Name or address of private key with which to sign")
|
||||
}
|
||||
f.Uint64P(FlagAccountNumber, "a", 0, "The account number of the signing account (offline mode only)")
|
||||
f.Uint64P(FlagSequence, "s", 0, "The sequence number of the signing account (offline mode only)")
|
||||
f.String(FlagNote, "", "Note to add a description to the transaction (previously --memo)")
|
||||
|
||||
@ -419,7 +419,12 @@ func (f Factory) BuildSimTx(msgs ...sdk.Msg) ([]byte, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return f.txConfig.TxEncoder()(txb.GetTx())
|
||||
encoder := f.txConfig.TxEncoder()
|
||||
if encoder == nil {
|
||||
return nil, fmt.Errorf("cannot simulate tx: tx encoder is nil")
|
||||
}
|
||||
|
||||
return encoder(txb.GetTx())
|
||||
}
|
||||
|
||||
// getSimPK gets the public key to use for building a simulation tx.
|
||||
|
||||
@ -107,7 +107,7 @@ func BroadcastTx(clientCtx client.Context, txf Factory, msgs ...sdk.Msg) error {
|
||||
|
||||
txBytes, err := encoder(tx.GetTx())
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("failed to encode transaction: %w", err)
|
||||
}
|
||||
|
||||
if err := clientCtx.PrintRaw(json.RawMessage(txBytes)); err != nil {
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
codegen:
|
||||
@(cd internal; buf generate)
|
||||
@(cd internal; buf generate)
|
||||
@ -75,7 +75,7 @@ if err := rootCmd.Execute(); err != nil {
|
||||
|
||||
### Keyring
|
||||
|
||||
`autocli` supports a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the `autocli` generated commands to sign transactions, you must provide a keyring.
|
||||
`autocli` uses a keyring for key name resolving and signing transactions. Providing a keyring is optional, but if you want to use the `autocli` generated commands to sign transactions, you must provide a keyring.
|
||||
|
||||
:::tip
|
||||
This provides a better UX as it allows to resolve key names directly from the keyring in all transactions and commands.
|
||||
@ -87,16 +87,23 @@ This provides a better UX as it allows to resolve key names directly from the ke
|
||||
|
||||
:::
|
||||
|
||||
The keyring to be provided to `client/v2` must match the `client/v2` keyring interface. The Cosmos SDK keyring and Hubl keyring both implement this interface.
|
||||
The keyring to be provided to `client/v2` must match the `client/v2` keyring interface.
|
||||
The keyring should be provided in the `appOptions` struct as follows, and can be gotten from the client context:
|
||||
|
||||
:::tip
|
||||
The Cosmos SDK keyring and Hubl keyring both implement the `client/v2/autocli/keyring` interface, thanks to the following wrapper:
|
||||
|
||||
```go
|
||||
keyring.NewAutoCLIKeyring(kb)
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
:::warning
|
||||
When using AutoCLI the keyring will only be created once and before any command flag parsing.
|
||||
:::
|
||||
|
||||
```go
|
||||
// Get the keyring from the client context
|
||||
keyring := ctx.Keyring
|
||||
// Set the keyring in the appOptions
|
||||
appOptions.Keyring = keyring
|
||||
|
||||
@ -104,6 +111,16 @@ err := autoCliOpts.EnhanceRootCommand(rootCmd)
|
||||
...
|
||||
```
|
||||
|
||||
## Signing
|
||||
|
||||
`autocli` supports signing transactions with the keyring.
|
||||
The [`cosmos.msg.v1.signer` protobuf annotation](https://github.com/cosmos/cosmos-sdk/blob/9dd34510e27376005e7e7ff3628eab9dbc8ad6dc/docs/build/building-modules/05-protobuf-annotations.md#L9) defines the signer field of the message.
|
||||
This field is automatically filled when using the `--from` flag or defining the signer as a positional argument.
|
||||
|
||||
:::warning
|
||||
AutoCLI currently supports only one signer per transaction.
|
||||
:::
|
||||
|
||||
## Module Wiring & Customization
|
||||
|
||||
The `AutoCLIOptions()` method on your module allows to specify custom commands, sub-commands or flags for each service, as it was a `cobra.Command` instance, within the `RpcCommandOptions` struct. Defining such options will customize the behavior of the `autocli` command generation, which by default generates a command for each method in your gRPC service.
|
||||
|
||||
@ -11,10 +11,10 @@ import (
|
||||
"cosmossdk.io/client/v2/autocli/keyring"
|
||||
"cosmossdk.io/core/appmodule"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
sdkflags "github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
)
|
||||
|
||||
// AppOptions are autocli options for an app. These options can be built via depinject based on an app config. Ex:
|
||||
@ -28,9 +28,6 @@ import (
|
||||
type AppOptions struct {
|
||||
depinject.In
|
||||
|
||||
// Logger is the logger to use for client/v2.
|
||||
Logger log.Logger
|
||||
|
||||
// Modules are the AppModule implementations for the modules in the app.
|
||||
Modules map[string]appmodule.AppModule
|
||||
|
||||
@ -40,11 +37,14 @@ type AppOptions struct {
|
||||
// module or need to be improved.
|
||||
ModuleOptions map[string]*autocliv1.ModuleOptions `optional:"true"`
|
||||
|
||||
// ClientCtx contains the necessary information needed to execute the commands.
|
||||
ClientCtx *client.Context
|
||||
|
||||
// Keyring is the keyring to use for client/v2.
|
||||
Keyring keyring.Keyring `optional:"true"`
|
||||
|
||||
// ClientCtx contains the necessary information needed to execute the commands.
|
||||
ClientCtx client.Context
|
||||
|
||||
// TxConfigOptions are the transactions config options.
|
||||
TxConfigOpts tx.ConfigOptions
|
||||
}
|
||||
|
||||
// EnhanceRootCommand enhances the provided root command with autocli AppOptions,
|
||||
@ -64,18 +64,21 @@ type AppOptions struct {
|
||||
// err = autoCliOpts.EnhanceRootCommand(rootCmd)
|
||||
func (appOptions AppOptions) EnhanceRootCommand(rootCmd *cobra.Command) error {
|
||||
builder := &Builder{
|
||||
Logger: appOptions.Logger,
|
||||
Builder: flag.Builder{
|
||||
TypeResolver: protoregistry.GlobalTypes,
|
||||
FileResolver: proto.HybridResolver,
|
||||
ClientCtx: appOptions.ClientCtx,
|
||||
Keyring: appOptions.Keyring,
|
||||
TypeResolver: protoregistry.GlobalTypes,
|
||||
FileResolver: proto.HybridResolver,
|
||||
Keyring: appOptions.Keyring,
|
||||
AddressCodec: appOptions.ClientCtx.AddressCodec,
|
||||
ValidatorAddressCodec: appOptions.ClientCtx.ValidatorAddressCodec,
|
||||
ConsensusAddressCodec: appOptions.ClientCtx.ConsensusAddressCodec,
|
||||
},
|
||||
ClientCtx: appOptions.ClientCtx,
|
||||
TxConfigOpts: appOptions.TxConfigOpts,
|
||||
GetClientConn: func(cmd *cobra.Command) (grpc.ClientConnInterface, error) {
|
||||
return client.GetClientQueryContext(cmd)
|
||||
},
|
||||
AddQueryConnFlags: flags.AddQueryFlagsToCmd,
|
||||
AddTxConnFlags: flags.AddTxFlagsToCmd,
|
||||
AddQueryConnFlags: sdkflags.AddQueryFlagsToCmd,
|
||||
AddTxConnFlags: sdkflags.AddTxFlagsToCmd,
|
||||
}
|
||||
|
||||
return appOptions.EnhanceRootCommandWithBuilder(rootCmd, builder)
|
||||
|
||||
@ -8,7 +8,9 @@ import (
|
||||
|
||||
"cosmossdk.io/client/v2/autocli/flag"
|
||||
"cosmossdk.io/client/v2/autocli/keyring"
|
||||
"cosmossdk.io/log"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
)
|
||||
|
||||
// Builder manages options for building CLI commands.
|
||||
@ -16,13 +18,16 @@ type Builder struct {
|
||||
// flag.Builder embeds the flag builder and its options.
|
||||
flag.Builder
|
||||
|
||||
// Logger is the logger used by the builder.
|
||||
Logger log.Logger
|
||||
|
||||
// GetClientConn specifies how CLI commands will resolve a grpc.ClientConnInterface
|
||||
// from a given context.
|
||||
GetClientConn func(*cobra.Command) (grpc.ClientConnInterface, error)
|
||||
|
||||
// ClientCtx contains the necessary information needed to execute the commands.
|
||||
ClientCtx client.Context
|
||||
|
||||
// TxConfigOptions is required to support sign mode textual
|
||||
TxConfigOpts authtx.ConfigOptions
|
||||
|
||||
// AddQueryConnFlags and AddTxConnFlags are functions that add flags to query and transaction commands
|
||||
AddQueryConnFlags func(*cobra.Command)
|
||||
AddTxConnFlags func(*cobra.Command)
|
||||
@ -33,40 +38,28 @@ type Builder struct {
|
||||
// If the Logger is nil, it will be set to a nop logger.
|
||||
// If the keyring is nil, it will be set to a no keyring.
|
||||
func (b *Builder) ValidateAndComplete() error {
|
||||
if b.Logger == nil {
|
||||
b.Logger = log.NewNopLogger()
|
||||
if b.Builder.AddressCodec == nil {
|
||||
return errors.New("address codec is required in flag builder")
|
||||
}
|
||||
|
||||
if b.ClientCtx == nil {
|
||||
return errors.New("client context is required in builder")
|
||||
if b.Builder.ValidatorAddressCodec == nil {
|
||||
return errors.New("validator address codec is required in flag builder")
|
||||
}
|
||||
|
||||
if b.ClientCtx.AddressCodec == nil {
|
||||
return errors.New("address codec is required in builder")
|
||||
if b.Builder.ConsensusAddressCodec == nil {
|
||||
return errors.New("consensus address codec is required in flag builder")
|
||||
}
|
||||
|
||||
if b.ClientCtx.ValidatorAddressCodec == nil {
|
||||
return errors.New("validator address codec is required in builder")
|
||||
if b.Builder.Keyring == nil {
|
||||
b.Keyring = keyring.NoKeyring{}
|
||||
}
|
||||
|
||||
if b.ClientCtx.ConsensusAddressCodec == nil {
|
||||
return errors.New("consensus address codec is required in builder")
|
||||
if b.Builder.TypeResolver == nil {
|
||||
return errors.New("type resolver is required in flag builder")
|
||||
}
|
||||
|
||||
if b.Keyring == nil {
|
||||
if b.ClientCtx.Keyring != nil {
|
||||
b.Keyring = b.ClientCtx.Keyring
|
||||
} else {
|
||||
b.Keyring = keyring.NoKeyring{}
|
||||
}
|
||||
}
|
||||
|
||||
if b.TypeResolver == nil {
|
||||
return errors.New("type resolver is required in builder")
|
||||
}
|
||||
|
||||
if b.FileResolver == nil {
|
||||
return errors.New("file resolver is required in builder")
|
||||
if b.Builder.FileResolver == nil {
|
||||
return errors.New("file resolver is required in flag builder")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@ -10,9 +10,8 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"cosmossdk.io/client/v2/internal/flags"
|
||||
"cosmossdk.io/client/v2/internal/util"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
)
|
||||
|
||||
type cmdType int
|
||||
@ -67,6 +66,37 @@ func (b *Builder) buildMethodCommandCommon(descriptor protoreflect.MethodDescrip
|
||||
return err
|
||||
}
|
||||
|
||||
// signer related logic, triggers only when there is a signer defined
|
||||
if binder.SignerInfo.FieldName != "" {
|
||||
// mark the signer flag as required if defined
|
||||
// TODO(@julienrbrt): UX improvement by only marking the flag as required when there is more than one key in the keyring;
|
||||
// when there is only one key, use that key by default.
|
||||
if binder.SignerInfo.IsFlag {
|
||||
if err := cmd.MarkFlagRequired(binder.SignerInfo.FieldName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// the client context uses the from flag to determine the signer.
|
||||
// this sets the signer flags to the from flag value if a custom signer flag is set.
|
||||
if binder.SignerInfo.FieldName != flags.FlagFrom {
|
||||
signer, err := cmd.Flags().GetString(binder.SignerInfo.FieldName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get signer flag: %w", err)
|
||||
}
|
||||
|
||||
if err := cmd.Flags().Set(flags.FlagFrom, signer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// if the signer is not a flag, it is a positional argument
|
||||
// we need to get the correct positional arguments
|
||||
if err := cmd.Flags().Set(flags.FlagFrom, args[binder.SignerInfo.PositionalArgIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return exec(cmd, input)
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import (
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
"gotest.tools/v3/assert"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
reflectionv2alpha1 "cosmossdk.io/api/cosmos/base/reflection/v2alpha1"
|
||||
"cosmossdk.io/client/v2/autocli/flag"
|
||||
"cosmossdk.io/client/v2/internal/testpb"
|
||||
@ -19,9 +20,11 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdkkeyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
moduletestutil "github.com/cosmos/cosmos-sdk/types/module/testutil"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
type fixture struct {
|
||||
@ -47,10 +50,16 @@ func initFixture(t *testing.T) *fixture {
|
||||
clientConn, err := grpc.Dial(listener.Addr().String(), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
assert.NilError(t, err)
|
||||
|
||||
appCodec := moduletestutil.MakeTestEncodingConfig().Codec
|
||||
kr, err := keyring.New(sdk.KeyringServiceName(), keyring.BackendMemory, home, nil, appCodec)
|
||||
encodingConfig := moduletestutil.MakeTestEncodingConfig(bank.AppModuleBasic{})
|
||||
kr, err := sdkkeyring.New(sdk.KeyringServiceName(), sdkkeyring.BackendMemory, home, nil, encodingConfig.Codec)
|
||||
assert.NilError(t, err)
|
||||
|
||||
akr, err := sdkkeyring.NewAutoCLIKeyring(kr)
|
||||
assert.NilError(t, err)
|
||||
|
||||
interfaceRegistry := encodingConfig.Codec.InterfaceRegistry()
|
||||
banktypes.RegisterInterfaces(interfaceRegistry)
|
||||
|
||||
var initClientCtx client.Context
|
||||
initClientCtx = initClientCtx.
|
||||
WithAddressCodec(addresscodec.NewBech32Codec("cosmos")).
|
||||
@ -59,21 +68,28 @@ func initFixture(t *testing.T) *fixture {
|
||||
WithKeyring(kr).
|
||||
WithKeyringDir(home).
|
||||
WithHomeDir(home).
|
||||
WithViper("")
|
||||
WithViper("").
|
||||
WithInterfaceRegistry(interfaceRegistry).
|
||||
WithTxConfig(encodingConfig.TxConfig).
|
||||
WithAccountRetriever(client.MockAccountRetriever{}).
|
||||
WithChainID("autocli-test")
|
||||
|
||||
conn := &testClientConn{ClientConn: clientConn}
|
||||
b := &Builder{
|
||||
Builder: flag.Builder{
|
||||
TypeResolver: protoregistry.GlobalTypes,
|
||||
FileResolver: protoregistry.GlobalFiles,
|
||||
ClientCtx: &initClientCtx,
|
||||
Keyring: kr,
|
||||
TypeResolver: protoregistry.GlobalTypes,
|
||||
FileResolver: protoregistry.GlobalFiles,
|
||||
AddressCodec: initClientCtx.AddressCodec,
|
||||
ValidatorAddressCodec: initClientCtx.ValidatorAddressCodec,
|
||||
ConsensusAddressCodec: initClientCtx.ConsensusAddressCodec,
|
||||
Keyring: akr,
|
||||
},
|
||||
GetClientConn: func(*cobra.Command) (grpc.ClientConnInterface, error) {
|
||||
return conn, nil
|
||||
},
|
||||
AddQueryConnFlags: flags.AddQueryFlagsToCmd,
|
||||
AddTxConnFlags: flags.AddTxFlagsToCmd,
|
||||
ClientCtx: initClientCtx,
|
||||
}
|
||||
assert.NilError(t, b.ValidateAndComplete())
|
||||
|
||||
@ -131,3 +147,82 @@ func (t testEchoServer) Echo(_ context.Context, request *testpb.EchoRequest) (*t
|
||||
}
|
||||
|
||||
var _ testpb.QueryServer = testEchoServer{}
|
||||
|
||||
func TestEnhanceCommand(t *testing.T) {
|
||||
b := &Builder{}
|
||||
// Test that the command has a subcommand
|
||||
cmd := &cobra.Command{Use: "test"}
|
||||
cmd.AddCommand(&cobra.Command{Use: "test"})
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
cmdTp := cmdType(i)
|
||||
|
||||
appOptions := AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {},
|
||||
},
|
||||
}
|
||||
|
||||
err := b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
cmd = &cobra.Command{Use: "test"}
|
||||
|
||||
appOptions = AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{},
|
||||
}
|
||||
customCommands := map[string]*cobra.Command{
|
||||
"test2": {Use: "test"},
|
||||
}
|
||||
err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, customCommands)
|
||||
assert.NilError(t, err)
|
||||
|
||||
cmd = &cobra.Command{Use: "test"}
|
||||
appOptions = AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {Tx: nil},
|
||||
},
|
||||
}
|
||||
err = b.enhanceCommandCommon(cmd, cmdTp, appOptions, map[string]*cobra.Command{})
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestErrorBuildCommand(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
b := fixture.b
|
||||
b.AddQueryConnFlags = nil
|
||||
b.AddTxConnFlags = nil
|
||||
|
||||
commandDescriptor := &autocliv1.ServiceCommandDescriptor{
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
||||
{
|
||||
ProtoField: "un-existent-proto-field",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
appOptions := AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {
|
||||
Query: commandDescriptor,
|
||||
Tx: commandDescriptor,
|
||||
},
|
||||
},
|
||||
ClientCtx: b.ClientCtx,
|
||||
}
|
||||
|
||||
_, err := b.BuildMsgCommand(appOptions, nil)
|
||||
assert.ErrorContains(t, err, "can't find field un-existent-proto-field")
|
||||
|
||||
appOptions.ModuleOptions["test"].Tx = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
|
||||
appOptions.ModuleOptions["test"].Query = &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
|
||||
_, err = b.BuildMsgCommand(appOptions, nil)
|
||||
assert.ErrorContains(t, err, "can't find service un-existent-service")
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ import (
|
||||
type addressStringType struct{}
|
||||
|
||||
func (a addressStringType) NewValue(_ context.Context, b *Builder) Value {
|
||||
return &addressValue{addressCodec: b.ClientCtx.AddressCodec, keyring: b.Keyring}
|
||||
return &addressValue{addressCodec: b.AddressCodec, keyring: b.Keyring}
|
||||
}
|
||||
|
||||
func (a addressStringType) DefaultValue() string {
|
||||
@ -29,7 +29,7 @@ func (a addressStringType) DefaultValue() string {
|
||||
type validatorAddressStringType struct{}
|
||||
|
||||
func (a validatorAddressStringType) NewValue(_ context.Context, b *Builder) Value {
|
||||
return &addressValue{addressCodec: b.ClientCtx.ValidatorAddressCodec, keyring: b.Keyring}
|
||||
return &addressValue{addressCodec: b.ValidatorAddressCodec, keyring: b.Keyring}
|
||||
}
|
||||
|
||||
func (a validatorAddressStringType) DefaultValue() string {
|
||||
@ -80,7 +80,12 @@ func (a addressValue) Type() string {
|
||||
type consensusAddressStringType struct{}
|
||||
|
||||
func (a consensusAddressStringType) NewValue(ctx context.Context, b *Builder) Value {
|
||||
return &consensusAddressValue{addressValue: addressValue{addressCodec: b.ClientCtx.ConsensusAddressCodec, keyring: b.Keyring}}
|
||||
return &consensusAddressValue{
|
||||
addressValue: addressValue{
|
||||
addressCodec: b.ConsensusAddressCodec,
|
||||
keyring: b.Keyring,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (a consensusAddressStringType) DefaultValue() string {
|
||||
|
||||
@ -14,10 +14,13 @@ import (
|
||||
"google.golang.org/protobuf/reflect/protoregistry"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
msgv1 "cosmossdk.io/api/cosmos/msg/v1"
|
||||
"cosmossdk.io/client/v2/autocli/keyring"
|
||||
"cosmossdk.io/client/v2/internal/flags"
|
||||
"cosmossdk.io/client/v2/internal/util"
|
||||
"cosmossdk.io/core/address"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
)
|
||||
|
||||
// Builder manages options for building pflag flags for protobuf messages.
|
||||
@ -39,11 +42,13 @@ type Builder struct {
|
||||
messageFlagTypes map[protoreflect.FullName]Type
|
||||
scalarFlagTypes map[string]Type
|
||||
|
||||
// Keyring implementation
|
||||
// Keyring is the keyring to use for client/v2.
|
||||
Keyring keyring.Keyring
|
||||
|
||||
// ClientCtx contains the necessary information needed to execute the commands.
|
||||
ClientCtx *client.Context
|
||||
// Address Codecs are the address codecs to use for client/v2.
|
||||
AddressCodec address.Codec
|
||||
ValidatorAddressCodec runtime.ValidatorAddressCodec
|
||||
ConsensusAddressCodec runtime.ConsensusAddressCodec
|
||||
}
|
||||
|
||||
func (b *Builder) init() {
|
||||
@ -62,35 +67,48 @@ func (b *Builder) init() {
|
||||
}
|
||||
}
|
||||
|
||||
// DefineMessageFlagType allows to extend custom protobuf message type handling for flags (and positional arguments).
|
||||
func (b *Builder) DefineMessageFlagType(messageName protoreflect.FullName, flagType Type) {
|
||||
b.init()
|
||||
b.messageFlagTypes[messageName] = flagType
|
||||
}
|
||||
|
||||
// DefineScalarFlagType allows to extend custom scalar type handling for flags (and positional arguments).
|
||||
func (b *Builder) DefineScalarFlagType(scalarName string, flagType Type) {
|
||||
b.init()
|
||||
b.scalarFlagTypes[scalarName] = flagType
|
||||
}
|
||||
|
||||
// AddMessageFlags adds flags for each field in the message to the flag set.
|
||||
func (b *Builder) AddMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions) (*MessageBinder, error) {
|
||||
return b.addMessageFlags(ctx, flagSet, messageType, commandOptions, namingOptions{})
|
||||
}
|
||||
|
||||
// AddMessageFlags adds flags for each field in the message to the flag set.
|
||||
// addMessageFlags adds flags for each field in the message to the flag set.
|
||||
func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, messageType protoreflect.MessageType, commandOptions *autocliv1.RpcCommandOptions, options namingOptions) (*MessageBinder, error) {
|
||||
fields := messageType.Descriptor().Fields()
|
||||
numFields := fields.Len()
|
||||
handler := &MessageBinder{
|
||||
messageBinder := &MessageBinder{
|
||||
messageType: messageType,
|
||||
// positional args are also parsed using a FlagSet so that we can reuse all the same parsers
|
||||
positionalFlagSet: pflag.NewFlagSet("positional", pflag.ContinueOnError),
|
||||
}
|
||||
|
||||
fields := messageType.Descriptor().Fields()
|
||||
signerFieldName := GetSignerFieldName(messageType.Descriptor())
|
||||
|
||||
isPositional := map[string]bool{}
|
||||
n := len(commandOptions.PositionalArgs)
|
||||
// positional args are also parsed using a FlagSet so that we can reuse all the same parsers
|
||||
handler.positionalFlagSet = pflag.NewFlagSet("positional", pflag.ContinueOnError)
|
||||
|
||||
lengthPositionalArgsOptions := len(commandOptions.PositionalArgs)
|
||||
for i, arg := range commandOptions.PositionalArgs {
|
||||
isPositional[arg.ProtoField] = true
|
||||
|
||||
// verify if a positional field is a signer field
|
||||
if arg.ProtoField == signerFieldName {
|
||||
messageBinder.SignerInfo = SignerInfo{
|
||||
PositionalArgIndex: i,
|
||||
FieldName: arg.ProtoField,
|
||||
}
|
||||
}
|
||||
|
||||
field := fields.ByName(protoreflect.Name(arg.ProtoField))
|
||||
if field == nil {
|
||||
return nil, fmt.Errorf("can't find field %s on %s", arg.ProtoField, messageType.Descriptor().FullName())
|
||||
@ -101,24 +119,24 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m
|
||||
}
|
||||
|
||||
if arg.Varargs {
|
||||
if i != n-1 {
|
||||
if i != lengthPositionalArgsOptions-1 {
|
||||
return nil, fmt.Errorf("varargs positional argument %s must be the last argument", arg.ProtoField)
|
||||
}
|
||||
|
||||
handler.hasVarargs = true
|
||||
messageBinder.hasVarargs = true
|
||||
}
|
||||
|
||||
if arg.Optional {
|
||||
if i != n-1 {
|
||||
if i != lengthPositionalArgsOptions-1 {
|
||||
return nil, fmt.Errorf("optional positional argument %s must be the last argument", arg.ProtoField)
|
||||
}
|
||||
|
||||
handler.hasOptional = true
|
||||
messageBinder.hasOptional = true
|
||||
}
|
||||
|
||||
_, hasValue, err := b.addFieldFlag(
|
||||
ctx,
|
||||
handler.positionalFlagSet,
|
||||
messageBinder.positionalFlagSet,
|
||||
field,
|
||||
&autocliv1.FlagOptions{Name: fmt.Sprintf("%d", i)},
|
||||
namingOptions{},
|
||||
@ -127,21 +145,21 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handler.positionalArgs = append(handler.positionalArgs, fieldBinding{
|
||||
messageBinder.positionalArgs = append(messageBinder.positionalArgs, fieldBinding{
|
||||
field: field,
|
||||
hasValue: hasValue,
|
||||
})
|
||||
}
|
||||
|
||||
if handler.hasVarargs {
|
||||
handler.CobraArgs = cobra.MinimumNArgs(n - 1)
|
||||
handler.MandatoryArgUntil = n - 1
|
||||
} else if handler.hasOptional {
|
||||
handler.CobraArgs = cobra.RangeArgs(n-1, n)
|
||||
handler.MandatoryArgUntil = n - 1
|
||||
if messageBinder.hasVarargs {
|
||||
messageBinder.CobraArgs = cobra.MinimumNArgs(lengthPositionalArgsOptions - 1)
|
||||
messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions - 1
|
||||
} else if messageBinder.hasOptional {
|
||||
messageBinder.CobraArgs = cobra.RangeArgs(lengthPositionalArgsOptions-1, lengthPositionalArgsOptions)
|
||||
messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions - 1
|
||||
} else {
|
||||
handler.CobraArgs = cobra.ExactArgs(n)
|
||||
handler.MandatoryArgUntil = n
|
||||
messageBinder.CobraArgs = cobra.ExactArgs(lengthPositionalArgsOptions)
|
||||
messageBinder.mandatoryArgUntil = lengthPositionalArgsOptions
|
||||
}
|
||||
|
||||
// validate flag options
|
||||
@ -149,12 +167,42 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m
|
||||
if fields.ByName(protoreflect.Name(name)) == nil {
|
||||
return nil, fmt.Errorf("can't find field %s on %s specified as a flag", name, messageType.Descriptor().FullName())
|
||||
}
|
||||
|
||||
// verify if a flag is a signer field
|
||||
if name == signerFieldName {
|
||||
messageBinder.SignerInfo = SignerInfo{
|
||||
FieldName: name,
|
||||
IsFlag: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if signer has not been specified as positional arguments,
|
||||
// add it as `--from` flag (instead of --field-name flags)
|
||||
if signerFieldName != "" && messageBinder.SignerInfo.FieldName == "" {
|
||||
if commandOptions.FlagOptions == nil {
|
||||
commandOptions.FlagOptions = make(map[string]*autocliv1.FlagOptions)
|
||||
}
|
||||
|
||||
commandOptions.FlagOptions[signerFieldName] = &autocliv1.FlagOptions{
|
||||
Name: flags.FlagFrom,
|
||||
Usage: "Name or address with which to sign the message",
|
||||
Shorthand: "f",
|
||||
}
|
||||
|
||||
messageBinder.SignerInfo = SignerInfo{
|
||||
FieldName: flags.FlagFrom,
|
||||
IsFlag: true,
|
||||
}
|
||||
}
|
||||
|
||||
// define all other fields as flags
|
||||
flagOptsByFlagName := map[string]*autocliv1.FlagOptions{}
|
||||
for i := 0; i < numFields; i++ {
|
||||
for i := 0; i < fields.Len(); i++ {
|
||||
field := fields.Get(i)
|
||||
if isPositional[string(field.Name())] {
|
||||
// skips positional args and signer field if already set
|
||||
if isPositional[string(field.Name())] ||
|
||||
(string(field.Name()) == signerFieldName && messageBinder.SignerInfo.FieldName == flags.FlagFrom) {
|
||||
continue
|
||||
}
|
||||
|
||||
@ -165,7 +213,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handler.flagBindings = append(handler.flagBindings, fieldBinding{
|
||||
messageBinder.flagBindings = append(messageBinder.flagBindings, fieldBinding{
|
||||
hasValue: hasValue,
|
||||
field: field,
|
||||
})
|
||||
@ -184,7 +232,7 @@ func (b *Builder) addMessageFlags(ctx context.Context, flagSet *pflag.FlagSet, m
|
||||
}
|
||||
})
|
||||
|
||||
return handler, nil
|
||||
return messageBinder, nil
|
||||
}
|
||||
|
||||
// bindPageRequest create a flag for pagination
|
||||
@ -259,10 +307,11 @@ func (b *Builder) addFieldFlag(ctx context.Context, flagSet *pflag.FlagSet, fiel
|
||||
|
||||
// This is a bit of hacking around the pflag API, but the
|
||||
// defaultValue is set in this way because this is much easier than trying
|
||||
// to parse the string into the types that StringSliceP, Int32P, etc. expect
|
||||
// to parse the string into the types that StringSliceP, Int32P, etc.
|
||||
if defaultValue != "" {
|
||||
err = flagSet.Set(name, defaultValue)
|
||||
}
|
||||
|
||||
return name, val, err
|
||||
}
|
||||
|
||||
@ -363,3 +412,14 @@ func (b *Builder) resolveFlagTypeBasic(field protoreflect.FieldDescriptor) Type
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// GetSignerFieldName gets signer field name of a message.
|
||||
// AutoCLI supports only one signer field per message.
|
||||
func GetSignerFieldName(descriptor protoreflect.MessageDescriptor) string {
|
||||
signersFields := proto.GetExtension(descriptor.Options(), msgv1.E_Signer).([]string)
|
||||
if len(signersFields) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return signersFields[0]
|
||||
}
|
||||
|
||||
@ -8,15 +8,26 @@ import (
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
)
|
||||
|
||||
// SignerInfo contains information about the signer field.
|
||||
// That field is special because it needs to be known for signing.
|
||||
// This struct keeps track of the field name and whether it is a flag.
|
||||
// IsFlag and PositionalArgIndex are mutually exclusive.
|
||||
type SignerInfo struct {
|
||||
PositionalArgIndex int
|
||||
IsFlag bool
|
||||
FieldName string
|
||||
}
|
||||
|
||||
// MessageBinder binds multiple flags in a flag set to a protobuf message.
|
||||
type MessageBinder struct {
|
||||
MandatoryArgUntil int
|
||||
CobraArgs cobra.PositionalArgs
|
||||
CobraArgs cobra.PositionalArgs
|
||||
SignerInfo SignerInfo
|
||||
|
||||
positionalFlagSet *pflag.FlagSet
|
||||
positionalArgs []fieldBinding
|
||||
hasVarargs bool
|
||||
hasOptional bool
|
||||
mandatoryArgUntil int
|
||||
|
||||
flagBindings []fieldBinding
|
||||
messageType protoreflect.MessageType
|
||||
@ -39,15 +50,14 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) e
|
||||
}
|
||||
|
||||
name := fmt.Sprintf("%d", i)
|
||||
if i == m.MandatoryArgUntil && m.hasVarargs {
|
||||
if i == m.mandatoryArgUntil && m.hasVarargs {
|
||||
for _, v := range positionalArgs[i:] {
|
||||
if err := m.positionalFlagSet.Set(name, v); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := m.positionalFlagSet.Set(name, positionalArgs[i])
|
||||
if err != nil {
|
||||
if err := m.positionalFlagSet.Set(name, positionalArgs[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -55,16 +65,14 @@ func (m MessageBinder) Bind(msg protoreflect.Message, positionalArgs []string) e
|
||||
|
||||
// bind positional arg values to the message
|
||||
for _, arg := range m.positionalArgs {
|
||||
err := arg.bind(msg)
|
||||
if err != nil {
|
||||
if err := arg.bind(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// bind flag values to the message
|
||||
for _, binding := range m.flagBindings {
|
||||
err := binding.bind(msg)
|
||||
if err != nil {
|
||||
if err := binding.bind(msg); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
package autocli
|
||||
|
||||
var flagNoIndent = "no-indent"
|
||||
@ -1,6 +1,23 @@
|
||||
package keyring
|
||||
|
||||
import (
|
||||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
// Keyring is an interface used for signing transactions.
|
||||
// It aims to be simplistic and easy to use.
|
||||
type Keyring interface {
|
||||
// List returns the names of all keys stored in the keyring.
|
||||
List() ([]string, error)
|
||||
|
||||
// LookupAddressByKeyName returns the address of the key with the given name.
|
||||
LookupAddressByKeyName(name string) ([]byte, error)
|
||||
|
||||
// GetPubKey returns the public key of the key with the given name.
|
||||
GetPubKey(name string) (cryptotypes.PubKey, error)
|
||||
|
||||
// Sign signs the given bytes with the key with the given name.
|
||||
Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error)
|
||||
}
|
||||
|
||||
@ -1,11 +1,31 @@
|
||||
package keyring
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
|
||||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
var _ Keyring = NoKeyring{}
|
||||
|
||||
var errNoKeyring = errors.New("no keyring configured")
|
||||
|
||||
type NoKeyring struct{}
|
||||
|
||||
func (k NoKeyring) LookupAddressByKeyName(name string) ([]byte, error) {
|
||||
return nil, errors.New("no keyring configured")
|
||||
func (k NoKeyring) List() ([]string, error) {
|
||||
return nil, errNoKeyring
|
||||
}
|
||||
|
||||
func (k NoKeyring) LookupAddressByKeyName(name string) ([]byte, error) {
|
||||
return nil, errNoKeyring
|
||||
}
|
||||
|
||||
func (k NoKeyring) GetPubKey(name string) (cryptotypes.PubKey, error) {
|
||||
return nil, errNoKeyring
|
||||
}
|
||||
|
||||
func (k NoKeyring) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) {
|
||||
return nil, errNoKeyring
|
||||
}
|
||||
|
||||
@ -4,12 +4,21 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
"cosmossdk.io/client/v2/autocli/flag"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
clienttx "github.com/cosmos/cosmos-sdk/client/tx"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx/signing"
|
||||
authtx "github.com/cosmos/cosmos-sdk/x/auth/tx"
|
||||
authtxconfig "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
||||
)
|
||||
|
||||
// BuildMsgCommand builds the msg commands for all the provided modules. If a custom command is provided for a
|
||||
@ -97,46 +106,56 @@ func (b *Builder) AddMsgServiceCommands(cmd *cobra.Command, cmdDescriptor *autoc
|
||||
|
||||
// BuildMsgMethodCommand returns a command that outputs the JSON representation of the message.
|
||||
func (b *Builder) BuildMsgMethodCommand(descriptor protoreflect.MethodDescriptor, options *autocliv1.RpcCommandOptions) (*cobra.Command, error) {
|
||||
jsonMarshalOptions := protojson.MarshalOptions{
|
||||
Indent: " ",
|
||||
UseProtoNames: true,
|
||||
UseEnumNumbers: false,
|
||||
EmitUnpopulated: true,
|
||||
Resolver: b.TypeResolver,
|
||||
}
|
||||
|
||||
cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error {
|
||||
if noIdent, _ := cmd.Flags().GetBool(flagNoIndent); noIdent {
|
||||
jsonMarshalOptions.Indent = ""
|
||||
}
|
||||
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &b.ClientCtx))
|
||||
|
||||
bz, err := jsonMarshalOptions.Marshal(input.Interface())
|
||||
clientCtx, err := client.GetClientTxContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(*b.ClientCtx, cmd.Flags())
|
||||
// enable sign mode textual and config tx options
|
||||
b.TxConfigOpts.EnabledSignModes = append(b.TxConfigOpts.EnabledSignModes, signing.SignMode_SIGN_MODE_TEXTUAL)
|
||||
b.TxConfigOpts.TextualCoinMetadataQueryFn = authtxconfig.NewGRPCCoinMetadataQueryFn(clientCtx)
|
||||
|
||||
txConfigWithTextual, err := authtx.NewTxConfigWithOptions(
|
||||
codec.NewProtoCodec(clientCtx.InterfaceRegistry),
|
||||
b.TxConfigOpts,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clientCtx = clientCtx.WithTxConfig(txConfigWithTextual)
|
||||
clientCtx.Output = cmd.OutOrStdout()
|
||||
|
||||
cmd.SetContext(context.WithValue(context.Background(), client.ClientContextKey, &clientCtx))
|
||||
if err = client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
|
||||
return err
|
||||
// set signer to signer field if empty
|
||||
fd := input.Descriptor().Fields().ByName(protoreflect.Name(flag.GetSignerFieldName(input.Descriptor())))
|
||||
if addr := input.Get(fd).String(); addr == "" {
|
||||
signerFromFlag := clientCtx.GetFromAddress()
|
||||
signer, err := b.ClientCtx.AddressCodec.BytesToString(signerFromFlag.Bytes())
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to set signer on message, got %v: %w", signerFromFlag, err)
|
||||
}
|
||||
|
||||
input.Set(fd, protoreflect.ValueOfString(signer))
|
||||
}
|
||||
|
||||
clientCtx, err = client.GetClientTxContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// AutoCLI uses protov2 messages, while the SDK only supports proto v1 messages.
|
||||
// Here we use dynamicpb, to create a proto v1 compatible message.
|
||||
// The SDK codec will handle protov2 -> protov1 (marshal)
|
||||
msg := dynamicpb.NewMessage(input.Descriptor())
|
||||
proto.Merge(msg, input.Interface())
|
||||
|
||||
return b.outOrStdoutFormat(cmd, bz)
|
||||
return clienttx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
|
||||
})
|
||||
|
||||
if b.AddTxConnFlags != nil {
|
||||
b.AddTxConnFlags(cmd)
|
||||
}
|
||||
|
||||
cmd.Flags().BoolP(flagNoIndent, "", false, "Do not indent JSON output")
|
||||
// silence usage only for inner txs & queries commands
|
||||
if cmd != nil {
|
||||
cmd.SilenceUsage = true
|
||||
}
|
||||
|
||||
return cmd, err
|
||||
|
||||
@ -2,135 +2,97 @@ package autocli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"gotest.tools/v3/assert"
|
||||
"gotest.tools/v3/golden"
|
||||
|
||||
autocliv1 "cosmossdk.io/api/cosmos/autocli/v1"
|
||||
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
|
||||
"cosmossdk.io/client/v2/internal/testpb"
|
||||
)
|
||||
|
||||
var buildModuleMsgCommand = func(moduleName string, b *Builder) (*cobra.Command, error) {
|
||||
cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName))
|
||||
err := b.AddMsgServiceCommands(cmd, testCmdMsgDesc)
|
||||
err := b.AddMsgServiceCommands(cmd, bankAutoCLI)
|
||||
return cmd, err
|
||||
}
|
||||
|
||||
var testCmdMsgDesc = &autocliv1.ServiceCommandDescriptor{
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
func buildCustomModuleMsgCommand(cmdDescriptor *autocliv1.ServiceCommandDescriptor) func(moduleName string, b *Builder) (*cobra.Command, error) {
|
||||
return func(moduleName string, b *Builder) (*cobra.Command, error) {
|
||||
cmd := topLevelCmd(moduleName, fmt.Sprintf("Transactions commands for the %s module", moduleName))
|
||||
err := b.AddMsgServiceCommands(cmd, cmdDescriptor)
|
||||
return cmd, err
|
||||
}
|
||||
}
|
||||
|
||||
var bankAutoCLI = &autocliv1.ServiceCommandDescriptor{
|
||||
Service: bankv1beta1.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
Use: "send [pos1] [pos2] [pos3...]",
|
||||
Version: "1.0",
|
||||
Alias: []string{"s"},
|
||||
SuggestFor: []string{"send"},
|
||||
Example: "send 1 abc {}",
|
||||
Short: "send msg the value provided by the user",
|
||||
Long: "send msg the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
||||
{
|
||||
ProtoField: "positional1",
|
||||
},
|
||||
{
|
||||
ProtoField: "positional2",
|
||||
},
|
||||
{
|
||||
ProtoField: "positional3_varargs",
|
||||
Varargs: true,
|
||||
},
|
||||
},
|
||||
FlagOptions: map[string]*autocliv1.FlagOptions{
|
||||
"u32": {
|
||||
Name: "uint32",
|
||||
Shorthand: "u",
|
||||
Usage: "some random uint32",
|
||||
},
|
||||
"i32": {
|
||||
Usage: "some random int32",
|
||||
DefaultValue: "3",
|
||||
},
|
||||
"u64": {
|
||||
Usage: "some random uint64",
|
||||
DefaultValue: "5",
|
||||
},
|
||||
"deprecated_field": {
|
||||
Deprecated: "don't use this",
|
||||
},
|
||||
"shorthand_deprecated_field": {
|
||||
Shorthand: "d",
|
||||
Deprecated: "bad idea",
|
||||
},
|
||||
"hidden_bool": {
|
||||
Hidden: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SubCommands: map[string]*autocliv1.ServiceCommandDescriptor{
|
||||
// we test the sub-command functionality using the same service with different options
|
||||
"deprecatedmsg": {
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
Deprecated: "dont use this",
|
||||
Short: "deprecated subcommand",
|
||||
},
|
||||
},
|
||||
},
|
||||
"skipmsg": {
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
Skip: true,
|
||||
Short: "skip subcommand",
|
||||
},
|
||||
},
|
||||
RpcMethod: "Send",
|
||||
Use: "send [from_key_or_address] [to_address] [amount] [flags]",
|
||||
Short: "Send coins from one account to another",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "from_address"}, {ProtoField: "to_address"}, {ProtoField: "amount"}},
|
||||
},
|
||||
},
|
||||
EnhanceCustomCommand: true,
|
||||
}
|
||||
|
||||
func TestMsgOptions(t *testing.T) {
|
||||
func TestMsg(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send",
|
||||
"5", "6", "1foo",
|
||||
"--uint32", "7",
|
||||
"--u64", "8",
|
||||
"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo",
|
||||
"--generate-only",
|
||||
"--output", "json",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, out.String(), "msg-output.golden")
|
||||
|
||||
response := out.String()
|
||||
var output testpb.MsgRequest
|
||||
err = protojson.Unmarshal([]byte(response), &output)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, output.GetU32(), uint32(7))
|
||||
assert.Equal(t, output.GetPositional1(), int32(5))
|
||||
assert.Equal(t, output.GetPositional2(), "6")
|
||||
}
|
||||
|
||||
func TestMsgOutputFormat(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "5", "6", "1foo",
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildCustomModuleMsgCommand(&autocliv1.ServiceCommandDescriptor{
|
||||
Service: bankv1beta1.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
Use: "send [from_key_or_address] [to_address] [amount] [flags]",
|
||||
Short: "Send coins from one account to another",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}},
|
||||
// from_address should be automatically added
|
||||
},
|
||||
},
|
||||
EnhanceCustomCommand: true,
|
||||
}), "send",
|
||||
"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo",
|
||||
"--from", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
||||
"--generate-only",
|
||||
"--output", "json",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, strings.Contains(out.String(), "{"))
|
||||
golden.Assert(t, out.String(), "msg-output.golden")
|
||||
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "5", "6", "1foo",
|
||||
"--output", "text",
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildCustomModuleMsgCommand(&autocliv1.ServiceCommandDescriptor{
|
||||
Service: bankv1beta1.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
Use: "send [from_key_or_address] [to_address] [amount] [flags]",
|
||||
Short: "Send coins from one account to another",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{{ProtoField: "to_address"}, {ProtoField: "amount"}},
|
||||
FlagOptions: map[string]*autocliv1.FlagOptions{
|
||||
"from_address": {Name: "sender"}, // use a custom flag for signer
|
||||
},
|
||||
},
|
||||
},
|
||||
EnhanceCustomCommand: true,
|
||||
}), "send",
|
||||
"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk", "1foo",
|
||||
"--sender", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
||||
"--generate-only",
|
||||
"--output", "json",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, strings.Contains(out.String(), "positional1: 5"))
|
||||
golden.Assert(t, out.String(), "msg-output.golden")
|
||||
}
|
||||
|
||||
func TestMsgOptionsError(t *testing.T) {
|
||||
@ -138,92 +100,13 @@ func TestMsgOptionsError(t *testing.T) {
|
||||
|
||||
_, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "5",
|
||||
"--uint32", "7",
|
||||
"--u64", "8",
|
||||
)
|
||||
assert.ErrorContains(t, err, "requires at least 2 arg(s)")
|
||||
assert.ErrorContains(t, err, "accepts 3 arg(s)")
|
||||
|
||||
_, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "5", "6", `{"denom":"foo","amount":"1"}`,
|
||||
"--uint32", "7",
|
||||
"--u64", "abc",
|
||||
"send", "foo", "bar", "invalid",
|
||||
)
|
||||
assert.ErrorContains(t, err, "invalid argument ")
|
||||
}
|
||||
|
||||
func TestDeprecatedMsg(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "1", "abc", "--deprecated-field", "foo",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, strings.Contains(out.String(), "--deprecated-field has been deprecated"))
|
||||
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send", "1", "abc", "5stake", "-d", "foo",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, strings.Contains(out.String(), "--shorthand-deprecated-field has been deprecated"))
|
||||
}
|
||||
|
||||
func TestEverythingMsg(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleMsgCommand,
|
||||
"send",
|
||||
"1",
|
||||
"abc",
|
||||
"1234foo",
|
||||
"4321foo",
|
||||
"--output", "json",
|
||||
"--a-bool",
|
||||
"--an-enum", "two",
|
||||
"--a-message", `{"bar":"abc", "baz":-3}`,
|
||||
"--duration", "4h3s",
|
||||
"--uint32", "27",
|
||||
"--u64", "3267246890",
|
||||
"--i32", "-253",
|
||||
"--i64", "-234602347",
|
||||
"--str", "def",
|
||||
"--timestamp", "2019-01-02T00:01:02Z",
|
||||
"--a-coin", "10000000foo",
|
||||
"--an-address", "cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk",
|
||||
"--bz", "c2RncXdlZndkZ3NkZw==",
|
||||
"--page-count-total",
|
||||
"--page-key", "MTIzNTQ4N3NnaGRhcw==",
|
||||
"--page-limit", "1000",
|
||||
"--page-offset", "10",
|
||||
"--page-reverse",
|
||||
"--bools", "true",
|
||||
"--bools", "false,false,true",
|
||||
"--enums", "one",
|
||||
"--enums", "five",
|
||||
"--enums", "two",
|
||||
"--strings", "abc",
|
||||
"--strings", "xyz",
|
||||
"--strings", "xyz,qrs",
|
||||
"--durations", "3s",
|
||||
"--durations", "5s",
|
||||
"--durations", "10h",
|
||||
"--some-messages", "{}",
|
||||
"--some-messages", `{"bar":"baz"}`,
|
||||
"--some-messages", `{"baz":-1}`,
|
||||
"--uints", "1,2,3",
|
||||
"--uints", "4",
|
||||
)
|
||||
assert.NilError(t, err)
|
||||
|
||||
response := out.String()
|
||||
var output testpb.MsgRequest
|
||||
err = protojson.Unmarshal([]byte(response), &output)
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, output.GetU32(), uint32(27))
|
||||
assert.Equal(t, output.GetU64(), uint64(3267246890))
|
||||
assert.Equal(t, output.GetPositional1(), int32(1))
|
||||
assert.Equal(t, output.GetPositional2(), "abc")
|
||||
assert.Equal(t, output.GetABool(), true)
|
||||
assert.Equal(t, output.GetAnEnum(), testpb.Enum_ENUM_TWO)
|
||||
assert.ErrorContains(t, err, "invalid argument")
|
||||
}
|
||||
|
||||
func TestHelpMsg(t *testing.T) {
|
||||
@ -236,19 +119,18 @@ func TestHelpMsg(t *testing.T) {
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "send", "-h")
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, out.String(), "help-echo-msg.golden")
|
||||
|
||||
out, err = runCmd(fixture.conn, fixture.b, buildModuleMsgCommand, "deprecatedmsg", "send", "-h")
|
||||
assert.NilError(t, err)
|
||||
golden.Assert(t, out.String(), "help-deprecated-msg.golden")
|
||||
}
|
||||
|
||||
func TestBuildMsgCommand(t *testing.T) {
|
||||
func TestBuildCustomMsgCommand(t *testing.T) {
|
||||
b := &Builder{}
|
||||
customCommandCalled := false
|
||||
appOptions := AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {
|
||||
Tx: testCmdMsgDesc,
|
||||
Tx: &autocliv1.ServiceCommandDescriptor{
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -264,44 +146,6 @@ func TestBuildMsgCommand(t *testing.T) {
|
||||
assert.Assert(t, customCommandCalled)
|
||||
}
|
||||
|
||||
func TestErrorBuildMsgCommand(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
b := fixture.b
|
||||
b.AddQueryConnFlags = nil
|
||||
b.AddTxConnFlags = nil
|
||||
|
||||
commandDescriptor := &autocliv1.ServiceCommandDescriptor{
|
||||
Service: testpb.Msg_ServiceDesc.ServiceName,
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "Send",
|
||||
PositionalArgs: []*autocliv1.PositionalArgDescriptor{
|
||||
{
|
||||
ProtoField: "un-existent-proto-field",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
appOptions := AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {
|
||||
Tx: commandDescriptor,
|
||||
},
|
||||
},
|
||||
ClientCtx: b.ClientCtx,
|
||||
}
|
||||
|
||||
_, err := b.BuildMsgCommand(appOptions, nil)
|
||||
assert.ErrorContains(t, err, "can't find field un-existent-proto-field")
|
||||
|
||||
nonExistentService := &autocliv1.ServiceCommandDescriptor{Service: "un-existent-service"}
|
||||
appOptions.ModuleOptions["test"].Tx = nonExistentService
|
||||
_, err = b.BuildMsgCommand(appOptions, nil)
|
||||
assert.ErrorContains(t, err, "can't find service un-existent-service")
|
||||
}
|
||||
|
||||
func TestNotFoundErrorsMsg(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
b := fixture.b
|
||||
@ -353,38 +197,3 @@ func TestNotFoundErrorsMsg(t *testing.T) {
|
||||
})
|
||||
assert.ErrorContains(t, err, "can't find field un-existent-flag")
|
||||
}
|
||||
|
||||
func TestEnhanceMessageCommand(t *testing.T) {
|
||||
b := &Builder{}
|
||||
// Test that the command has a subcommand
|
||||
cmd := &cobra.Command{Use: "test"}
|
||||
cmd.AddCommand(&cobra.Command{Use: "test"})
|
||||
|
||||
appOptions := AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {},
|
||||
},
|
||||
}
|
||||
|
||||
err := b.enhanceCommandCommon(cmd, msgCmdType, appOptions, map[string]*cobra.Command{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
cmd = &cobra.Command{Use: "test"}
|
||||
|
||||
appOptions.ModuleOptions = map[string]*autocliv1.ModuleOptions{}
|
||||
customCommands := map[string]*cobra.Command{
|
||||
"test2": {Use: "test"},
|
||||
}
|
||||
err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands)
|
||||
assert.NilError(t, err)
|
||||
|
||||
cmd = &cobra.Command{Use: "test"}
|
||||
appOptions = AppOptions{
|
||||
ModuleOptions: map[string]*autocliv1.ModuleOptions{
|
||||
"test": {Tx: nil},
|
||||
},
|
||||
}
|
||||
customCommands = map[string]*cobra.Command{}
|
||||
err = b.enhanceCommandCommon(cmd, msgCmdType, appOptions, customCommands)
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
|
||||
"cosmossdk.io/client/v2/internal/flags"
|
||||
"cosmossdk.io/client/v2/internal/util"
|
||||
)
|
||||
|
||||
@ -111,7 +112,7 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript
|
||||
}
|
||||
|
||||
cmd, err := b.buildMethodCommandCommon(descriptor, options, func(cmd *cobra.Command, input protoreflect.Message) error {
|
||||
if noIndent, _ := cmd.Flags().GetBool(flagNoIndent); noIndent {
|
||||
if noIndent, _ := cmd.Flags().GetBool(flags.FlagNoIndent); noIndent {
|
||||
encoderOptions.Indent = ""
|
||||
}
|
||||
|
||||
@ -140,7 +141,12 @@ func (b *Builder) BuildQueryMethodCommand(descriptor protoreflect.MethodDescript
|
||||
if b.AddQueryConnFlags != nil {
|
||||
b.AddQueryConnFlags(cmd)
|
||||
|
||||
cmd.Flags().BoolP(flagNoIndent, "", false, "Do not indent JSON output")
|
||||
cmd.Flags().BoolP(flags.FlagNoIndent, "", false, "Do not indent JSON output")
|
||||
}
|
||||
|
||||
// silence usage only for inner txs & queries commands
|
||||
if cmd != nil {
|
||||
cmd.SilenceUsage = true
|
||||
}
|
||||
|
||||
return cmd, nil
|
||||
|
||||
@ -613,7 +613,7 @@ func TestOutputFormat(t *testing.T) {
|
||||
assert.Assert(t, strings.Contains(out.String(), " positional1: 1"))
|
||||
}
|
||||
|
||||
func TestHelp(t *testing.T) {
|
||||
func TestHelpQuery(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "-h")
|
||||
@ -633,7 +633,7 @@ func TestHelp(t *testing.T) {
|
||||
golden.Assert(t, out.String(), "help-skip.golden")
|
||||
}
|
||||
|
||||
func TestDeprecated(t *testing.T) {
|
||||
func TestDeprecatedQuery(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
|
||||
out, err := runCmd(fixture.conn, fixture.b, buildModuleQueryCommand, "echo",
|
||||
@ -670,7 +670,7 @@ func TestBuildCustomQueryCommand(t *testing.T) {
|
||||
assert.Assert(t, customCommandCalled)
|
||||
}
|
||||
|
||||
func TestNotFoundErrors(t *testing.T) {
|
||||
func TestNotFoundErrorsQuery(t *testing.T) {
|
||||
fixture := initFixture(t)
|
||||
b := fixture.b
|
||||
b.AddQueryConnFlags = nil
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
Command "send" is deprecated, dont use this
|
||||
deprecated subcommand
|
||||
|
||||
Usage:
|
||||
test deprecatedmsg send [flags]
|
||||
|
||||
Flags:
|
||||
--a-bool
|
||||
--a-coin cosmos.base.v1beta1.Coin
|
||||
--a-message testpb.AMessage (json)
|
||||
--a-validator-address account address or key name
|
||||
-a, --account-number uint The account number of the signing account (offline mode only)
|
||||
--an-address account address or key name
|
||||
--an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified)
|
||||
--aux Generate aux signer data instead of sending a tx
|
||||
--bools bools (default [])
|
||||
-b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync")
|
||||
--bz binary
|
||||
--chain-id string The network chain ID
|
||||
--deprecated-field string
|
||||
--dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible)
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--fee-granter string Fee granter grants fees for the transaction
|
||||
--fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer
|
||||
--fees string Fees to pay along with transaction; eg: 10uatom
|
||||
--from string Name or address of private key with which to sign
|
||||
--gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000)
|
||||
--gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1)
|
||||
--gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)
|
||||
--generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name)
|
||||
-h, --help help for send
|
||||
--hidden-bool
|
||||
--i32 int32
|
||||
--i64 int
|
||||
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os")
|
||||
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
|
||||
--ledger Use a connected Ledger device
|
||||
--no-indent Do not indent JSON output
|
||||
--node string <host>:<port> to CometBFT rpc interface for this chain (default "tcp://localhost:26657")
|
||||
--note string Note to add a description to the transaction (previously --memo)
|
||||
--offline Offline mode (does not allow any online functionality)
|
||||
-o, --output string Output format (text|json) (default "json")
|
||||
--page-count-total
|
||||
--page-key binary
|
||||
--page-limit uint
|
||||
--page-offset uint
|
||||
--page-reverse
|
||||
--positional1 int32
|
||||
--positional2 string
|
||||
--positional3-varargs cosmos.base.v1beta1.Coin (repeated)
|
||||
-s, --sequence uint The sequence number of the signing account (offline mode only)
|
||||
--shorthand-deprecated-field string
|
||||
--sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature
|
||||
--some-messages testpb.AMessage (json) (repeated)
|
||||
--str string
|
||||
--strings strings
|
||||
--timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height
|
||||
--timestamp timestamp (RFC 3339)
|
||||
--tip string Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator
|
||||
--u32 uint32
|
||||
--u64 uint
|
||||
--uints uints (default [])
|
||||
-y, --yes Skip tx broadcasting prompt confirmation
|
||||
91
client/v2/autocli/testdata/help-echo-msg.golden
vendored
91
client/v2/autocli/testdata/help-echo-msg.golden
vendored
@ -1,67 +1,32 @@
|
||||
send msg the value provided by the user as a proto JSON object with populated with the provided fields and positional arguments
|
||||
Send coins from one account to another
|
||||
|
||||
Usage:
|
||||
test send [pos1] [pos2] [pos3...] [flags]
|
||||
|
||||
Aliases:
|
||||
send, s
|
||||
|
||||
Examples:
|
||||
send 1 abc {}
|
||||
test send [from_key_or_address] [to_address] [amount] [flags]
|
||||
|
||||
Flags:
|
||||
--a-bool
|
||||
--a-coin cosmos.base.v1beta1.Coin
|
||||
--a-message testpb.AMessage (json)
|
||||
--a-validator-address account address or key name
|
||||
-a, --account-number uint The account number of the signing account (offline mode only)
|
||||
--an-address account address or key name
|
||||
--an-enum Enum (unspecified | one | two | five | neg-three) (default unspecified)
|
||||
--aux Generate aux signer data instead of sending a tx
|
||||
--bools bools (default [])
|
||||
-b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync")
|
||||
--bz binary
|
||||
--chain-id string The network chain ID
|
||||
--deprecated-field string (DEPRECATED: don't use this)
|
||||
--dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible)
|
||||
--duration duration
|
||||
--durations duration (repeated)
|
||||
--enums Enum (unspecified | one | two | five | neg-three) (repeated)
|
||||
--fee-granter string Fee granter grants fees for the transaction
|
||||
--fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer
|
||||
--fees string Fees to pay along with transaction; eg: 10uatom
|
||||
--from string Name or address of private key with which to sign
|
||||
--gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000)
|
||||
--gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1)
|
||||
--gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)
|
||||
--generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name)
|
||||
-h, --help help for send
|
||||
--i32 int32 some random int32
|
||||
--i64 int
|
||||
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os")
|
||||
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
|
||||
--ledger Use a connected Ledger device
|
||||
--no-indent Do not indent JSON output
|
||||
--node string <host>:<port> to CometBFT rpc interface for this chain (default "tcp://localhost:26657")
|
||||
--note string Note to add a description to the transaction (previously --memo)
|
||||
--offline Offline mode (does not allow any online functionality)
|
||||
-o, --output string Output format (text|json) (default "json")
|
||||
--page-count-total
|
||||
--page-key binary
|
||||
--page-limit uint
|
||||
--page-offset uint
|
||||
--page-reverse
|
||||
-s, --sequence uint The sequence number of the signing account (offline mode only)
|
||||
-d, --shorthand-deprecated-field string (DEPRECATED: bad idea)
|
||||
--sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature
|
||||
--some-messages testpb.AMessage (json) (repeated)
|
||||
--str string
|
||||
--strings strings
|
||||
--timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height
|
||||
--timestamp timestamp (RFC 3339)
|
||||
--tip string Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator
|
||||
--u64 uint some random uint64
|
||||
-u, --uint32 uint32 some random uint32
|
||||
--uints uints (default [])
|
||||
-v, --version version for send
|
||||
-y, --yes Skip tx broadcasting prompt confirmation
|
||||
-a, --account-number uint The account number of the signing account (offline mode only)
|
||||
--aux Generate aux signer data instead of sending a tx
|
||||
-b, --broadcast-mode string Transaction broadcasting mode (sync|async) (default "sync")
|
||||
--chain-id string The network chain ID
|
||||
--dry-run ignore the --gas flag and perform a simulation of a transaction, but don't broadcast it (when enabled, the local Keybase is not accessible)
|
||||
--fee-granter string Fee granter grants fees for the transaction
|
||||
--fee-payer string Fee payer pays fees for the transaction instead of deducting from the signer
|
||||
--fees string Fees to pay along with transaction; eg: 10uatom
|
||||
--from string Name or address of private key with which to sign
|
||||
--gas string gas limit to set per-transaction; set to "auto" to calculate sufficient gas automatically. Note: "auto" option doesn't always report accurate results. Set a valid coin value to adjust the result. Can be used instead of "fees". (default 200000)
|
||||
--gas-adjustment float adjustment factor to be multiplied against the estimate returned by the tx simulation; if the gas limit is set manually this flag is ignored (default 1)
|
||||
--gas-prices string Gas prices in decimal format to determine the transaction fee (e.g. 0.1uatom)
|
||||
--generate-only Build an unsigned transaction and write it to STDOUT (when enabled, the local Keybase only accessed when providing a key name)
|
||||
-h, --help help for send
|
||||
--keyring-backend string Select keyring's backend (os|file|kwallet|pass|test|memory) (default "os")
|
||||
--keyring-dir string The client Keyring directory; if omitted, the default 'home' directory will be used
|
||||
--ledger Use a connected Ledger device
|
||||
--node string <host>:<port> to CometBFT rpc interface for this chain (default "tcp://localhost:26657")
|
||||
--note string Note to add a description to the transaction (previously --memo)
|
||||
--offline Offline mode (does not allow any online functionality)
|
||||
-o, --output string Output format (text|json) (default "json")
|
||||
-s, --sequence uint The sequence number of the signing account (offline mode only)
|
||||
--sign-mode string Choose sign mode (direct|amino-json|direct-aux), this is an advanced feature
|
||||
--timeout-height uint Set a block timeout height to prevent the tx from being committed past a certain height
|
||||
--tip string Tip is the amount that is going to be transferred to the fee payer on the target chain. This flag is only valid when used with --aux, and is ignored if the target chain didn't enable the TipDecorator
|
||||
-y, --yes Skip tx broadcasting prompt confirmation
|
||||
|
||||
@ -5,11 +5,13 @@ Usage:
|
||||
test [command]
|
||||
|
||||
Available Commands:
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
deprecatedmsg Tx commands for the testpb.Msg service
|
||||
help Help about any command
|
||||
send send msg the value provided by the user
|
||||
skipmsg Tx commands for the testpb.Msg service
|
||||
burn
|
||||
completion Generate the autocompletion script for the specified shell
|
||||
help Help about any command
|
||||
multi-send
|
||||
send Send coins from one account to another
|
||||
set-send-enabled
|
||||
update-params
|
||||
|
||||
Flags:
|
||||
-h, --help help for test
|
||||
|
||||
1
client/v2/autocli/testdata/msg-output.golden
vendored
Normal file
1
client/v2/autocli/testdata/msg-output.golden
vendored
Normal file
@ -0,0 +1 @@
|
||||
{"body":{"messages":[{"@type":"/cosmos.bank.v1beta1.MsgSend","from_address":"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk","to_address":"cosmos1y74p8wyy4enfhfn342njve6cjmj5c8dtl6emdk","amount":[{"denom":"foo","amount":"1"}]}],"memo":"","timeout_height":"0","extension_options":[],"non_critical_extension_options":[]},"auth_info":{"signer_infos":[],"fee":{"amount":[],"gas_limit":"200000","payer":"","granter":""},"tip":null},"signatures":[]}
|
||||
@ -3,10 +3,9 @@ module cosmossdk.io/client/v2
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
cosmossdk.io/api v0.7.1
|
||||
cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273
|
||||
cosmossdk.io/core v0.12.0
|
||||
cosmossdk.io/depinject v1.0.0-alpha.4
|
||||
cosmossdk.io/log v1.2.1
|
||||
cosmossdk.io/x/tx v0.10.0
|
||||
github.com/cockroachdb/errors v1.11.1
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3
|
||||
@ -23,6 +22,7 @@ require (
|
||||
require (
|
||||
cosmossdk.io/collections v0.4.0 // indirect
|
||||
cosmossdk.io/errors v1.0.0 // indirect
|
||||
cosmossdk.io/log v1.2.1 // indirect
|
||||
cosmossdk.io/math v1.1.3-rc.1 // indirect
|
||||
cosmossdk.io/store v1.0.0-rc.0 // indirect
|
||||
filippo.io/edwards25519 v1.0.0 // indirect
|
||||
@ -69,10 +69,12 @@ require (
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.1.0 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/orderedcode v0.0.1 // indirect
|
||||
github.com/gorilla/handlers v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
@ -95,18 +97,20 @@ require (
|
||||
github.com/klauspost/compress v1.16.7 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/lib/pq v1.10.7 // indirect
|
||||
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
|
||||
github.com/linxGnu/grocksdb v1.8.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mtibben/percent v0.2.1 // indirect
|
||||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/petermattis/goid v0.0.0-20230808133559-b036b712a89b // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
@ -134,11 +138,12 @@ require (
|
||||
golang.org/x/crypto v0.13.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
|
||||
golang.org/x/net v0.15.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/term v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
@ -146,3 +151,5 @@ require (
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/cosmos/cosmos-sdk => ./../../
|
||||
|
||||
@ -35,8 +35,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
||||
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=
|
||||
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
|
||||
cosmossdk.io/api v0.7.1 h1:PNQ1xN8+/0hj/sSD0ANqjkgfXFys+bZ5L8Hg7uzoUTU=
|
||||
cosmossdk.io/api v0.7.1/go.mod h1:ure9edhcROIHsngavM6mBLilMGFnfjhV/AaYhEMUkdo=
|
||||
cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273 h1:rNTYK/OQQ5B8jNY0wGSOv+64Fwm7DG8Yke5eRmdTPqk=
|
||||
cosmossdk.io/api v0.7.2-0.20230927090904-9dd34510e273/go.mod h1:RgzIuGUBiX4E4imKHFyxl+uSKU+qs2v0W2ymVoGoyQQ=
|
||||
cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s=
|
||||
cosmossdk.io/collections v0.4.0/go.mod h1:oa5lUING2dP+gdDquow+QjlF45eL1t4TJDypgGd+tv0=
|
||||
cosmossdk.io/core v0.12.0 h1:aFuvkG6eDv0IQC+UDjx86wxNWVAxdCFk7OABJ1Vh4RU=
|
||||
@ -51,6 +51,8 @@ cosmossdk.io/math v1.1.3-rc.1 h1:NebCNWDqb1MJRNfvxr4YY7d8FSYgkuB3L75K6xvM+Zo=
|
||||
cosmossdk.io/math v1.1.3-rc.1/go.mod h1:l2Gnda87F0su8a/7FEKJfFdJrM0JZRXQaohlgJeyQh0=
|
||||
cosmossdk.io/store v1.0.0-rc.0 h1:9DwOjuUYxDtYxn/REkTxGQAmxlIGfRroB35MQ8TrxF4=
|
||||
cosmossdk.io/store v1.0.0-rc.0/go.mod h1:FtBDOJmwtOZfmKKF65bKZbTYgS3bDNjjo3nP76dAegk=
|
||||
cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190 h1:XQJj9Dv9Gtze0l2TF79BU5lkP6MkUveTUuKICmxoz+o=
|
||||
cosmossdk.io/x/protocolpool v0.0.0-20230925135524-a1bc045b3190/go.mod h1:7WUGupOvmlHJoIMBz1JbObQxeo6/TDiuDBxmtod8HRg=
|
||||
cosmossdk.io/x/tx v0.10.0 h1:LxWF/hksVDbeQmFj4voLM5ZCHyVZ1cCNIqKenfH9plc=
|
||||
cosmossdk.io/x/tx v0.10.0/go.mod h1:MKo9/b5wsoL8dd9y9pvD2yOP1CMvzHIWYxi1l2oLPFo=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
@ -60,18 +62,26 @@ github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMb
|
||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4=
|
||||
github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o=
|
||||
github.com/99designs/keyring v1.2.1/go.mod h1:fc+wB5KTk9wQ9sDx0kFXB3A0MaeGHM9AwRStKOQ5vOA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
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/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
|
||||
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
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/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/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I=
|
||||
github.com/adlio/schema v1.3.3/go.mod h1:1EsRssiv9/Ce2CMzq5DoL7RiMshhuigQxrR4DMV9fHg=
|
||||
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=
|
||||
@ -97,6 +107,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 h1:41iFGWnSlI2gVpmOtVTJZNodLdLQLn/KsJqFvXwnd/s=
|
||||
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bits-and-blooms/bitset v1.9.0 h1:g1YivPG8jOtrN013Fe8OBXubkiTwvm7/vG2vXz03ANU=
|
||||
github.com/bits-and-blooms/bitset v1.9.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
|
||||
@ -106,6 +118,7 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtyd
|
||||
github.com/bufbuild/protocompile v0.6.0 h1:Uu7WiSQ6Yj9DbkdnOe7U4mNKp58y9WDMKDn28/ZlunY=
|
||||
github.com/bufbuild/protocompile v0.6.0/go.mod h1:YNP35qEYoYGme7QMtz5SBCoN4kL4g12jTtjuzRNdjpE=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4=
|
||||
@ -151,6 +164,8 @@ github.com/cometbft/cometbft v0.38.0 h1:ogKnpiPX7gxCvqTEF4ly25/wAxUqf181t30P3vqd
|
||||
github.com/cometbft/cometbft v0.38.0/go.mod h1:5Jz0Z8YsHSf0ZaAqGvi/ifioSdVFPtEGrm8Y9T/993k=
|
||||
github.com/cometbft/cometbft-db v0.8.0 h1:vUMDaH3ApkX8m0KZvOFFy9b5DZHBAjsnEuo9AKVZpjo=
|
||||
github.com/cometbft/cometbft-db v0.8.0/go.mod h1:6ASCP4pfhmrCBpfk01/9E1SI29nD3HfVHrY4PG8x5c0=
|
||||
github.com/containerd/continuity v0.3.0 h1:nisirsYROK15TAMVukJOUyGJjz4BNQJBVsNvAXZJ/eg=
|
||||
github.com/containerd/continuity v0.3.0/go.mod h1:wJEAIwKOm/pBZuBd0JmeTvnLquTB1Ag8espWhkykbPM=
|
||||
github.com/coreos/etcd v3.3.10+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=
|
||||
@ -163,8 +178,6 @@ github.com/cosmos/cosmos-db v1.0.0 h1:EVcQZ+qYag7W6uorBKFPvX6gRjw6Uq2hIh4hCWjuQ0
|
||||
github.com/cosmos/cosmos-db v1.0.0/go.mod h1:iBvi1TtqaedwLdcrZVYRSSCb6eSy61NLj4UNmdIgs0U=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o=
|
||||
github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I=
|
||||
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230915113003-c7e0bd7b54d0 h1:BNa8miwG4Aquqcz7ItXIWCao9e6OM+2HKXAPn96oDO8=
|
||||
github.com/cosmos/cosmos-sdk v0.46.0-beta2.0.20230915113003-c7e0bd7b54d0/go.mod h1:fuDAZLtTNCqYD0tZSJTNkB6DRjqC3t640i4lT6LAWxo=
|
||||
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/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE=
|
||||
@ -203,6 +216,10 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
||||
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/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
@ -461,8 +478,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jhump/protoreflect v1.15.2 h1:7YppbATX94jEt9KLAc5hICx4h6Yt3SaavhQRsIUEHP0=
|
||||
github.com/jhump/protoreflect v1.15.2/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k=
|
||||
github.com/jhump/protoreflect v1.15.3 h1:6SFRuqU45u9hIZPJAoZ8c28T3nK64BNdp9w6jFonzls=
|
||||
github.com/jhump/protoreflect v1.15.3/go.mod h1:4ORHmSBmlCW8fh3xHmJMGyul1zNqZK4Elxc8qKP+p1k=
|
||||
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=
|
||||
@ -594,6 +611,12 @@ github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9
|
||||
github.com/onsi/gomega v1.26.0 h1:03cDLK28U6hWvCAns6NeydX3zIm4SF3ci69ulidS32Q=
|
||||
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w=
|
||||
github.com/opencontainers/runc v1.1.3/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
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=
|
||||
@ -602,14 +625,16 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
||||
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 h1:iLLK6SQwIhcbrG783Dghaaa3WPzGc+4Emza6EbVUUGA=
|
||||
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||
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 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/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o=
|
||||
github.com/petermattis/goid v0.0.0-20230808133559-b036b712a89b h1:vab8deKC4QoIfm9fJM59iuNz1ELGsuLoYYpiF+pHiG8=
|
||||
@ -688,6 +713,8 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx
|
||||
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.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
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/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
@ -758,6 +785,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
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.1 h1:gQe66rtmyZ8VeGFcOpbuH3r7erYtNEAezCAYu8LdkJo=
|
||||
github.com/zondax/hid v0.9.1/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.14.1 h1:Pip65OOl4iJ84WTpA4BKChvOufMhhbxED3BaihoZN4c=
|
||||
@ -837,6 +865,9 @@ 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/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -905,6 +936,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
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/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -916,6 +948,7 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
|
||||
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=
|
||||
@ -1059,6 +1092,9 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/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.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
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=
|
||||
@ -1136,8 +1172,8 @@ google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6D
|
||||
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
|
||||
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA=
|
||||
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
|
||||
19
client/v2/internal/flags/flags.go
Normal file
19
client/v2/internal/flags/flags.go
Normal file
@ -0,0 +1,19 @@
|
||||
package flags
|
||||
|
||||
// This defines flag names that can be used in autocli.
|
||||
const (
|
||||
// FlagFrom is the flag to set the from address with which to sign the transaction.
|
||||
FlagFrom = "from"
|
||||
|
||||
// FlagOutput is the flag to set the output format.
|
||||
FlagOutput = "output"
|
||||
|
||||
// FlagNoIndent is the flag to not indent the output.
|
||||
FlagNoIndent = "no-indent"
|
||||
)
|
||||
|
||||
// List of supported output formats
|
||||
const (
|
||||
OutputFormatJSON = "json"
|
||||
OutputFormatText = "text"
|
||||
)
|
||||
@ -12,16 +12,26 @@ import (
|
||||
codectestutil "github.com/cosmos/cosmos-sdk/codec/testutil"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/testutil/testdata"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
type bankSendWrapper struct {
|
||||
*banktypes.MsgSend
|
||||
}
|
||||
|
||||
func (msg bankSendWrapper) GetSigners() []sdk.AccAddress {
|
||||
fromAddress, _ := sdk.AccAddressFromBech32(msg.FromAddress)
|
||||
return []sdk.AccAddress{fromAddress}
|
||||
}
|
||||
|
||||
func BenchmarkLegacyGetSigners(b *testing.B) {
|
||||
_, _, addr := testdata.KeyTestPubAddr()
|
||||
msg := &banktypes.MsgSend{
|
||||
msg := bankSendWrapper{&banktypes.MsgSend{
|
||||
FromAddress: addr.String(),
|
||||
ToAddress: "",
|
||||
Amount: nil,
|
||||
}
|
||||
}}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
|
||||
@ -4,6 +4,7 @@ import (
|
||||
fmt "fmt"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
|
||||
@ -62,13 +63,21 @@ func NewAnyWithValue(v proto.Message) (*Any, error) {
|
||||
return nil, errorsmod.Wrap(sdkerrors.ErrPackAny, "Expecting non nil value to create a new Any")
|
||||
}
|
||||
|
||||
bz, err := proto.Marshal(v)
|
||||
var (
|
||||
bz []byte
|
||||
err error
|
||||
)
|
||||
if msg, ok := v.(protov2.Message); ok {
|
||||
bz, err = protov2.Marshal(msg)
|
||||
} else {
|
||||
bz, err = proto.Marshal(v)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Any{
|
||||
TypeUrl: "/" + proto.MessageName(v),
|
||||
TypeUrl: MsgTypeURL(v),
|
||||
Value: bz,
|
||||
cachedValue: v,
|
||||
}, nil
|
||||
@ -93,8 +102,17 @@ func UnsafePackAny(x interface{}) *Any {
|
||||
// the packed value so that it can be retrieved from GetCachedValue without
|
||||
// unmarshaling
|
||||
func (any *Any) pack(x proto.Message) error {
|
||||
any.TypeUrl = "/" + proto.MessageName(x)
|
||||
bz, err := proto.Marshal(x)
|
||||
any.TypeUrl = MsgTypeURL(x)
|
||||
|
||||
var (
|
||||
bz []byte
|
||||
err error
|
||||
)
|
||||
if msg, ok := x.(protov2.Message); ok {
|
||||
bz, err = protov2.Marshal(msg)
|
||||
} else {
|
||||
bz, err = proto.Marshal(x)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ func (registry *interfaceRegistry) EnsureRegistered(impl interface{}) error {
|
||||
// same typeURL.
|
||||
func (registry *interfaceRegistry) RegisterImplementations(iface interface{}, impls ...proto.Message) {
|
||||
for _, impl := range impls {
|
||||
typeURL := "/" + proto.MessageName(impl)
|
||||
typeURL := MsgTypeURL(impl)
|
||||
registry.registerImpl(iface, typeURL, impl)
|
||||
}
|
||||
}
|
||||
|
||||
15
codec/types/util.go
Normal file
15
codec/types/util.go
Normal file
@ -0,0 +1,15 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// MsgTypeURL returns the TypeURL of a `sdk.Msg`.
|
||||
func MsgTypeURL(msg proto.Message) string {
|
||||
if m, ok := msg.(protov2.Message); ok {
|
||||
return "/" + string(m.ProtoReflect().Descriptor().FullName())
|
||||
}
|
||||
|
||||
return "/" + proto.MessageName(msg)
|
||||
}
|
||||
86
crypto/keyring/autocli.go
Normal file
86
crypto/keyring/autocli.go
Normal file
@ -0,0 +1,86 @@
|
||||
package keyring
|
||||
|
||||
import (
|
||||
signingv1beta1 "cosmossdk.io/api/cosmos/tx/signing/v1beta1"
|
||||
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing"
|
||||
)
|
||||
|
||||
// autoCLIKeyring represents the keyring interface used by the AutoCLI.
|
||||
// It purposely does not import the AutoCLI package to avoid circular dependencies.
|
||||
type autoCLIKeyring interface {
|
||||
// List returns the names of all keys stored in the keyring.
|
||||
List() ([]string, error)
|
||||
|
||||
// LookupAddressByKeyName returns the address of the key with the given name.
|
||||
LookupAddressByKeyName(name string) ([]byte, error)
|
||||
|
||||
// GetPubKey returns the public key of the key with the given name.
|
||||
GetPubKey(name string) (cryptotypes.PubKey, error)
|
||||
|
||||
// Sign signs the given bytes with the key with the given name.
|
||||
Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error)
|
||||
}
|
||||
|
||||
// NewAutoCLIKeyring wraps the SDK keyring and make it compatible with the AutoCLI keyring interfaces.
|
||||
func NewAutoCLIKeyring(kr Keyring) (autoCLIKeyring, error) {
|
||||
return &autoCLIKeyringAdapter{kr}, nil
|
||||
}
|
||||
|
||||
type autoCLIKeyringAdapter struct {
|
||||
Keyring
|
||||
}
|
||||
|
||||
func (a *autoCLIKeyringAdapter) List() ([]string, error) {
|
||||
list, err := a.Keyring.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
names := make([]string, len(list))
|
||||
for i, key := range list {
|
||||
names[i] = key.Name
|
||||
}
|
||||
|
||||
return names, nil
|
||||
}
|
||||
|
||||
// LookupAddressByKeyName returns the address of a key stored in the keyring
|
||||
func (a *autoCLIKeyringAdapter) LookupAddressByKeyName(name string) ([]byte, error) {
|
||||
record, err := a.Keyring.Key(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (a *autoCLIKeyringAdapter) GetPubKey(name string) (cryptotypes.PubKey, error) {
|
||||
record, err := a.Keyring.Key(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return record.GetPubKey()
|
||||
}
|
||||
|
||||
func (a *autoCLIKeyringAdapter) Sign(name string, msg []byte, signMode signingv1beta1.SignMode) ([]byte, error) {
|
||||
record, err := a.Keyring.Key(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sdkSignMode, err := authsigning.APISignModeToInternal(signMode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
signBytes, _, err := a.Keyring.Sign(record.Name, msg, sdkSignMode)
|
||||
return signBytes, err
|
||||
}
|
||||
@ -102,9 +102,6 @@ type Keyring interface {
|
||||
Exporter
|
||||
|
||||
Migrator
|
||||
|
||||
// Implements client/v2 keyring interface
|
||||
LookupAddressByKeyName(name string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Signer is implemented by key stores that want to provide signing capabilities.
|
||||
@ -622,21 +619,6 @@ func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) {
|
||||
return ks.options.SupportedAlgos, ks.options.SupportedAlgosLedger
|
||||
}
|
||||
|
||||
// LookupAddressByKeyName returns the address of a key stored in the keyring
|
||||
func (ks keystore) LookupAddressByKeyName(name string) ([]byte, error) {
|
||||
record, err := ks.Key(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
addr, err := record.GetAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
// SignWithLedger signs a binary message with the ledger device referenced by an Info object
|
||||
// and returns the signed bytes and the public key. It returns an error if the device could
|
||||
// not be queried or it returned an error.
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
addresscodec "github.com/cosmos/cosmos-sdk/codec/address"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -109,8 +110,8 @@ func NewRootCmd() *cobra.Command {
|
||||
}
|
||||
|
||||
autoCliOpts := tempApp.AutoCliOpts()
|
||||
autoCliOpts.Keyring = initClientCtx.Keyring
|
||||
autoCliOpts.ClientCtx = &initClientCtx
|
||||
autoCliOpts.Keyring, _ = keyring.NewAutoCLIKeyring(initClientCtx.Keyring)
|
||||
autoCliOpts.ClientCtx = initClientCtx
|
||||
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
|
||||
panic(err)
|
||||
|
||||
@ -18,6 +18,7 @@ import (
|
||||
"github.com/cosmos/cosmos-sdk/client/config"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/server"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
@ -34,7 +35,7 @@ func NewRootCmd() *cobra.Command {
|
||||
txConfigOpts tx.ConfigOptions
|
||||
autoCliOpts autocli.AppOptions
|
||||
moduleBasicManager module.BasicManager
|
||||
initClientCtx *client.Context
|
||||
clientCtx client.Context
|
||||
)
|
||||
|
||||
if err := depinject.Inject(
|
||||
@ -51,7 +52,7 @@ func NewRootCmd() *cobra.Command {
|
||||
&txConfigOpts,
|
||||
&autoCliOpts,
|
||||
&moduleBasicManager,
|
||||
&initClientCtx,
|
||||
&clientCtx,
|
||||
); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -65,7 +66,6 @@ func NewRootCmd() *cobra.Command {
|
||||
cmd.SetOut(cmd.OutOrStdout())
|
||||
cmd.SetErr(cmd.ErrOrStderr())
|
||||
|
||||
clientCtx := *initClientCtx
|
||||
clientCtx = clientCtx.WithCmdContext(cmd.Context())
|
||||
clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags())
|
||||
if err != nil {
|
||||
@ -89,7 +89,6 @@ func NewRootCmd() *cobra.Command {
|
||||
return err
|
||||
}
|
||||
clientCtx = clientCtx.WithTxConfig(txConfigWithTextual)
|
||||
|
||||
if err := client.SetCmdClientContextHandler(clientCtx, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -101,7 +100,7 @@ func NewRootCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
initRootCmd(rootCmd, initClientCtx.TxConfig, initClientCtx.InterfaceRegistry, initClientCtx.Codec, moduleBasicManager)
|
||||
initRootCmd(rootCmd, clientCtx.TxConfig, clientCtx.InterfaceRegistry, clientCtx.Codec, moduleBasicManager)
|
||||
|
||||
if err := autoCliOpts.EnhanceRootCommand(rootCmd); err != nil {
|
||||
panic(err)
|
||||
@ -118,7 +117,7 @@ func ProvideClientContext(
|
||||
addressCodec address.Codec,
|
||||
validatorAddressCodec runtime.ValidatorAddressCodec,
|
||||
consensusAddressCodec runtime.ConsensusAddressCodec,
|
||||
) *client.Context {
|
||||
) client.Context {
|
||||
var err error
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
@ -141,14 +140,14 @@ func ProvideClientContext(
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &clientCtx
|
||||
return clientCtx
|
||||
}
|
||||
|
||||
func ProvideKeyring(clientCtx *client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) {
|
||||
kb, err := client.NewKeyringFromBackend(*clientCtx, clientCtx.Keyring.Backend())
|
||||
func ProvideKeyring(clientCtx client.Context, addressCodec address.Codec) (clientv2keyring.Keyring, error) {
|
||||
kb, err := client.NewKeyringFromBackend(clientCtx, clientCtx.Keyring.Backend())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return kb, nil
|
||||
return keyring.NewAutoCLIKeyring(kb)
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
protov2 "google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
|
||||
)
|
||||
|
||||
@ -95,13 +96,7 @@ type TxDecoder func(txBytes []byte) (Tx, error)
|
||||
type TxEncoder func(tx Tx) ([]byte, error)
|
||||
|
||||
// MsgTypeURL returns the TypeURL of a `sdk.Msg`.
|
||||
func MsgTypeURL(msg proto.Message) string {
|
||||
if m, ok := msg.(protov2.Message); ok {
|
||||
return "/" + string(m.ProtoReflect().Descriptor().FullName())
|
||||
}
|
||||
|
||||
return "/" + proto.MessageName(msg)
|
||||
}
|
||||
var MsgTypeURL = codectypes.MsgTypeURL
|
||||
|
||||
// GetMsgFromTypeURL returns a `sdk.Msg` message type from a type URL
|
||||
func GetMsgFromTypeURL(cdc codec.Codec, input string) (Msg, error) {
|
||||
|
||||
@ -16,7 +16,7 @@ type SigVerifiableTx interface {
|
||||
}
|
||||
|
||||
// Tx defines a transaction interface that supports all standard message, signature
|
||||
// fee, memo, tips, and auxiliary interfaces.
|
||||
// fee, memo and auxiliary interfaces.
|
||||
type Tx interface {
|
||||
SigVerifiableTx
|
||||
|
||||
|
||||
@ -15,12 +15,6 @@ func NewMsgSend(fromAddr, toAddr sdk.AccAddress, amount sdk.Coins) *MsgSend {
|
||||
return &MsgSend{FromAddress: fromAddr.String(), ToAddress: toAddr.String(), Amount: amount}
|
||||
}
|
||||
|
||||
// GetSigners Implements Msg.
|
||||
func (msg MsgSend) GetSigners() []sdk.AccAddress {
|
||||
fromAddress, _ := sdk.AccAddressFromBech32(msg.FromAddress)
|
||||
return []sdk.AccAddress{fromAddress}
|
||||
}
|
||||
|
||||
// NewMsgMultiSend - construct arbitrary multi-in, multi-out send msg.
|
||||
func NewMsgMultiSend(in Input, out []Output) *MsgMultiSend {
|
||||
return &MsgMultiSend{Inputs: []Input{in}, Outputs: out}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user