diff --git a/client/context/viper.go b/client/context/viper.go index 4264776df0..9a1cd5d0d4 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -43,5 +43,7 @@ func NewCoreContextFromViper() core.CoreContext { NodeURI: nodeURI, Sequence: viper.GetInt64(client.FlagSequence), Client: rpc, + Decoder: nil, + AccountStore: "main", } } diff --git a/client/core/context.go b/client/core/context.go index 3d7f400a8e..d56af5a816 100644 --- a/client/core/context.go +++ b/client/core/context.go @@ -2,6 +2,8 @@ package core import ( rpcclient "github.com/tendermint/tendermint/rpc/client" + + sdk "github.com/cosmos/cosmos-sdk/types" ) type CoreContext struct { @@ -12,6 +14,8 @@ type CoreContext struct { FromAddressName string Sequence int64 Client rpcclient.Client + Decoder sdk.AccountDecoder + AccountStore string } func (c CoreContext) WithChainID(chainID string) CoreContext { @@ -48,3 +52,13 @@ func (c CoreContext) WithClient(client rpcclient.Client) CoreContext { c.Client = client return c } + +func (c CoreContext) WithDecoder(decoder sdk.AccountDecoder) CoreContext { + c.Decoder = decoder + return c +} + +func (c CoreContext) WithAccountStore(accountStore string) CoreContext { + c.AccountStore = accountStore + return c +} diff --git a/client/core/core.go b/client/core/core.go index a39472c040..e28e6c3928 100644 --- a/client/core/core.go +++ b/client/core/core.go @@ -140,6 +140,24 @@ func (ctx CoreContext) SignBuildBroadcast(name string, msg sdk.Msg, cdc *wire.Co return ctx.BroadcastTx(txBytes) } +func (c CoreContext) NextSequence(address []byte) (int64, error) { + if c.Decoder == nil { + return 0, errors.New("AccountDecoder required but not provided") + } + + res, err := c.Query(address, c.AccountStore) + if err != nil { + return 0, err + } + + account, err := c.Decoder(res) + if err != nil { + panic(err) + } + + return account.GetSequence(), nil +} + // get passphrase from std input func (ctx CoreContext) GetPassphraseFromStdin(name string) (pass string, err error) { buf := client.BufferStdin() diff --git a/x/bank/commands/sendtx.go b/x/bank/commands/sendtx.go index aa0e17a910..17bf268700 100644 --- a/x/bank/commands/sendtx.go +++ b/x/bank/commands/sendtx.go @@ -10,6 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/client/context" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/wire" + authcmd "github.com/cosmos/cosmos-sdk/x/auth/commands" "github.com/cosmos/cosmos-sdk/x/bank" ) @@ -36,7 +37,7 @@ type Commander struct { } func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { - ctx := context.NewCoreContextFromViper() + ctx := context.NewCoreContextFromViper().WithDecoder(authcmd.GetAccountDecoder(c.Cdc)) // get the from address from, err := ctx.GetFromAddress() @@ -62,6 +63,20 @@ func (c Commander) sendTxCmd(cmd *cobra.Command, args []string) error { // build message msg := BuildMsg(from, to, coins) + // default to next sequence number if none provided + if viper.GetInt64(client.FlagSequence) == 0 { + from, err := ctx.GetFromAddress() + if err != nil { + return err + } + seq, err := ctx.NextSequence(from) + if err != nil { + return err + } + fmt.Printf("Defaulting to next sequence number: %d\n", seq) + ctx = ctx.WithSequence(seq) + } + // build and sign the transaction, then broadcast to Tendermint res, err := ctx.SignBuildBroadcast(ctx.FromAddressName, msg, c.Cdc) if err != nil {