Skip to content

Commit

Permalink
add event-query-tx-for cmd to subscribe and wait for transaction
Browse files Browse the repository at this point in the history
  • Loading branch information
mmsqe committed Aug 3, 2023
1 parent 92dffb5 commit e98849e
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
### Features

* (x/bank) [#16795](https://github.com/cosmos/cosmos-sdk/pull/16852) Add `DenomMetadataByQueryString` query in bank module to support metadata query by query string.
* (x/auth) [#17274](https://github.com/cosmos/cosmos-sdk/pull/17274) Add `QueryEventForTxCmd` cmd to subscribe and wait event for transaction by hash.

### Improvements

Expand Down
126 changes: 126 additions & 0 deletions x/auth/client/cli/query.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package cli

import (
"context"
"encoding/hex"
"fmt"
"strings"
"time"

"github.com/spf13/cobra"

rpchttp "github.com/cometbft/cometbft/rpc/client/http"
coretypes "github.com/cometbft/cometbft/rpc/core/types"
tmtypes "github.com/cometbft/cometbft/types"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/flags"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand Down Expand Up @@ -179,6 +185,126 @@ $ %s query tx --%s=%s <sig1_base64>,<sig2_base64...>
return cmd
}

func newTxResponseCheckTx(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
if res == nil {
return nil
}

var txHash string
if res.Hash != nil {
txHash = res.Hash.String()
}

parsedLogs, _ := sdk.ParseABCILogs(res.CheckTx.Log)

return &sdk.TxResponse{
Height: res.Height,
TxHash: txHash,
Codespace: res.CheckTx.Codespace,
Code: res.CheckTx.Code,
Data: strings.ToUpper(hex.EncodeToString(res.CheckTx.Data)),
RawLog: res.CheckTx.Log,
Logs: parsedLogs,
Info: res.CheckTx.Info,
GasWanted: res.CheckTx.GasWanted,
GasUsed: res.CheckTx.GasUsed,
Events: res.CheckTx.Events,
}
}

func newTxResponseDeliverTx(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
if res == nil {
return nil
}

var txHash string
if res.Hash != nil {
txHash = res.Hash.String()
}

parsedLogs, _ := sdk.ParseABCILogs(res.TxResult.Log)

return &sdk.TxResponse{
Height: res.Height,
TxHash: txHash,
Codespace: res.TxResult.Codespace,
Code: res.TxResult.Code,
Data: strings.ToUpper(hex.EncodeToString(res.TxResult.Data)),
RawLog: res.TxResult.Log,
Logs: parsedLogs,
Info: res.TxResult.Info,
GasWanted: res.TxResult.GasWanted,
GasUsed: res.TxResult.GasUsed,
Events: res.TxResult.Events,
}
}

func newResponseFormatBroadcastTxCommit(res *coretypes.ResultBroadcastTxCommit) *sdk.TxResponse {
if res == nil {
return nil
}

if !res.CheckTx.IsOK() {
return newTxResponseCheckTx(res)
}

return newTxResponseDeliverTx(res)
}

// QueryEventForTxCmd returns a CLI command that subscribes to a WebSocket connection and waits for a transaction event with the given hash.
func QueryEventForTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "event-query-tx-for [hash]",
Short: "event-query-tx-for [hash]",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}
c, err := rpchttp.New(clientCtx.NodeURI, "/websocket")
if err != nil {
return err
}
if err := c.Start(); err != nil {
return err
}
defer c.Stop() //nolint:errcheck // ignore stop error

ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
defer cancel()

hash := args[0]
query := fmt.Sprintf("%s='%s' AND %s='%s'", tmtypes.EventTypeKey, tmtypes.EventTx, tmtypes.TxHashKey, hash)
const subscriber = "subscriber"
eventCh, err := c.Subscribe(ctx, subscriber, query)
if err != nil {
return fmt.Errorf("failed to subscribe to tx: %w", err)
}
defer c.UnsubscribeAll(context.Background(), subscriber) //nolint:errcheck // ignore unsubscribe error

select {
case evt := <-eventCh:
if txe, ok := evt.Data.(tmtypes.EventDataTx); ok {
res := &coretypes.ResultBroadcastTxCommit{
TxResult: txe.Result,
Hash: tmtypes.Tx(txe.Tx).Hash(),
Height: txe.Height,
}
return clientCtx.PrintProto(newResponseFormatBroadcastTxCommit(res))
}
case <-ctx.Done():
return errors.ErrLogic.Wrapf("timed out waiting for event")
}
return nil
},
}

flags.AddTxFlagsToCmd(cmd)

return cmd
}

// ParseSigArgs parses comma-separated signatures from the CLI arguments.
func ParseSigArgs(args []string) ([]string, error) {
if len(args) != 1 || args[0] == "" {
Expand Down

0 comments on commit e98849e

Please sign in to comment.