-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add event-query-tx-for cmd to subscribe and wait for transaction #17274
Changes from 1 commit
e98849e
6c1c8d4
0d4bcaa
72d8a2b
ffec98a
66aee26
9cf9548
c5bb8b8
e0e1e43
9125d04
2eadad4
041a4c1
20a7372
4ac6bc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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" | ||
|
@@ -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") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is tightly coupled to CometBFT, maybe we should say something about that in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. updated, see if it's ok |
||
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] == "" { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add this command in simapp?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, added