diff --git a/CHANGELOG.md b/CHANGELOG.md index 0aca8de10..560694b99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ FEATURES * [types] Switches internal representation of Int/Uint/Rat to use pointers * [gaiad] unsafe_reset_all now resets addrbook.json * [democoin] add x/oracle, x/assoc +* [gaiacli] added an --async flag to the cli to deliver transactions without waiting for a tendermint response FIXES * [gaia] Added self delegation for validators in the genesis creation diff --git a/client/context/helpers.go b/client/context/helpers.go index fa46c73fd..dfe75e487 100644 --- a/client/context/helpers.go +++ b/client/context/helpers.go @@ -44,6 +44,22 @@ func (ctx CoreContext) BroadcastTx(tx []byte) (*ctypes.ResultBroadcastTxCommit, return res, err } +// Broadcast the transaction bytes to Tendermint +func (ctx CoreContext) BroadcastTxAsync(tx []byte) (*ctypes.ResultBroadcastTx, error) { + + node, err := ctx.GetNode() + if err != nil { + return nil, err + } + + res, err := node.BroadcastTxAsync(tx) + if err != nil { + return res, err + } + + return res, err +} + // Query information about the connected node func (ctx CoreContext) Query(path string) (res []byte, err error) { return ctx.query(path, nil) @@ -160,8 +176,7 @@ func (ctx CoreContext) SignAndBuild(name, passphrase string, msgs []sdk.Msg, cdc } // sign and build the transaction from the msg -func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) { - +func (ctx CoreContext) ensureSignBuild(name string, msgs []sdk.Msg, cdc *wire.Codec) (tyBytes []byte, err error) { ctx, err = EnsureAccountNumber(ctx) if err != nil { return nil, err @@ -182,9 +197,31 @@ func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc return nil, err } + return txBytes, err +} + +// sign and build the transaction from the msg +func (ctx CoreContext) EnsureSignBuildBroadcast(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTxCommit, err error) { + + txBytes, err := ctx.ensureSignBuild(name, msgs, cdc) + if err != nil { + return nil, err + } + return ctx.BroadcastTx(txBytes) } +// sign and build the async transaction from the msg +func (ctx CoreContext) EnsureSignBuildBroadcastAsync(name string, msgs []sdk.Msg, cdc *wire.Codec) (res *ctypes.ResultBroadcastTx, err error) { + + txBytes, err := ctx.ensureSignBuild(name, msgs, cdc) + if err != nil { + return nil, err + } + + return ctx.BroadcastTxAsync(txBytes) +} + // get the next sequence for the account address func (ctx CoreContext) GetAccountNumber(address []byte) (int64, error) { if ctx.Decoder == nil { diff --git a/client/context/viper.go b/client/context/viper.go index d3896fe58..a0c991bbf 100644 --- a/client/context/viper.go +++ b/client/context/viper.go @@ -56,7 +56,7 @@ func defaultChainID() (string, error) { return doc.ChainID, nil } -// EnsureSequence - automatically set sequence number if none provided +// EnsureAccount - automatically set account number if none provided func EnsureAccountNumber(ctx CoreContext) (CoreContext, error) { // Should be viper.IsSet, but this does not work - https://github.com/spf13/viper/pull/331 if viper.GetInt64(client.FlagAccountNumber) != 0 { diff --git a/x/bank/client/cli/sendtx.go b/x/bank/client/cli/sendtx.go index fe2f7fc2a..d3f7377fa 100644 --- a/x/bank/client/cli/sendtx.go +++ b/x/bank/client/cli/sendtx.go @@ -16,6 +16,7 @@ import ( const ( flagTo = "to" flagAmount = "amount" + flagAsync = "async" ) // SendTxCommand will create a send tx and sign it with the given key @@ -47,16 +48,28 @@ func SendTxCmd(cdc *wire.Codec) *cobra.Command { // build and sign the transaction, then broadcast to Tendermint msg := client.BuildMsg(from, to, coins) + + if viper.GetBool(flagAsync) { + res, err := ctx.EnsureSignBuildBroadcastAsync(ctx.FromAddressName, []sdk.Msg{msg}, cdc) + if err != nil { + return err + } + fmt.Println("Async tx sent. tx hash: ", res.Hash.String()) + return nil + } res, err := ctx.EnsureSignBuildBroadcast(ctx.FromAddressName, []sdk.Msg{msg}, cdc) if err != nil { return err } fmt.Printf("Committed at block %d. Hash: %s\n", res.Height, res.Hash.String()) return nil + }, } cmd.Flags().String(flagTo, "", "Address to send coins") cmd.Flags().String(flagAmount, "", "Amount of coins to send") + cmd.Flags().Bool(flagAsync, false, "Pass the async flag to send a tx without waiting for the tx to be included in a block") + return cmd }