diff --git a/cmd/paratime/show.go b/cmd/paratime/show.go index 8e519220..36e3e1a6 100644 --- a/cmd/paratime/show.go +++ b/cmd/paratime/show.go @@ -18,6 +18,12 @@ import ( runtimeTx "github.com/oasisprotocol/oasis-core/go/runtime/transaction" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/client" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/connection" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/accounts" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/consensusaccounts" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/contracts" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/core" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/evm" + "github.com/oasisprotocol/oasis-sdk/client-sdk/go/modules/rofl" "github.com/oasisprotocol/oasis-sdk/client-sdk/go/types" "github.com/oasisprotocol/cli/cmd/common" @@ -35,15 +41,25 @@ const ( const ( selInvalid propertySelector = iota selParameters + selEvents ) +var eventDecoders = []func(*types.Event) ([]client.DecodedEvent, error){ + accounts.DecodeEvent, + consensusaccounts.DecodeEvent, + contracts.DecodeEvent, + core.DecodeEvent, + evm.DecodeEvent, + rofl.DecodeEvent, +} + var ( outputFormat string selectedRound uint64 showCmd = &cobra.Command{ - Use: "show { [ | ] | parameters }", - Short: "Show information about a ParaTime block, its transactions or other parameters", + Use: "show { [ | ] | parameters | events }", + Short: "Show information about a ParaTime block, its transactions, events or other parameters", Long: "Show ParaTime-specific information about a given block round, (optionally) its transactions or other information. Use \"latest\" to use the last round.", Aliases: []string{"s"}, Args: cobra.RangeArgs(1, 2), @@ -101,13 +117,6 @@ var ( switch v := p.(type) { case uint64: blkNum := v - evDecoders := []client.EventDecoder{ - rt.Accounts, - rt.ConsensusAccounts, - rt.Contracts, - rt.Evm, - rt.ROFL, - } blk, err := rt.GetBlock(ctx, blkNum) cobra.CheckErr(err) @@ -151,7 +160,7 @@ var ( fmt.Println() for evIndex, ev := range blockEvs { - prettyPrintEvent(" ", evIndex, ev, evDecoders) + prettyPrintEvent(" ", evIndex, ev) fmt.Println() } } @@ -261,6 +270,9 @@ var ( case selParameters: showParameters(ctx, npa, selectedRound, rt) return + case selEvents: + showEvents(ctx, selectedRound, rt) + return default: cobra.CheckErr(fmt.Errorf("selector '%s' not found", args[0])) } @@ -294,6 +306,9 @@ func selectorFromString(s string) propertySelector { if strings.ToLower(strings.TrimSpace(s)) == "parameters" { return selParameters } + if strings.ToLower(strings.TrimSpace(s)) == "events" { + return selEvents + } return selInvalid } @@ -414,14 +429,17 @@ func prettyPrintStruct(indent string, kind string, data []byte, body interface{} fmt.Println(indent + output) } -func prettyPrintEvent(indent string, evIndex int, ev *types.Event, decoders []client.EventDecoder) { +func prettyPrintEvent(indent string, evIndex int, ev *types.Event) { fmt.Printf("%s--- Event %d ---\n", indent, evIndex) fmt.Printf("%sModule: %s\n", indent, ev.Module) fmt.Printf("%sCode: %d\n", indent, ev.Code) + if ev.TxHash != nil { + fmt.Printf("%sTx hash: %s\n", indent, ev.TxHash.String()) + } fmt.Printf("%sData:\n", indent) - for _, decoder := range decoders { - decoded, err := decoder.DecodeEvent(ev) + for _, decoder := range eventDecoders { + decoded, err := decoder(ev) if err != nil { continue } @@ -434,6 +452,37 @@ func prettyPrintEvent(indent string, evIndex int, ev *types.Event, decoders []cl prettyPrintCBOR(indent+" ", "event", ev.Value) } +func jsonPrintEvents(evs []*types.Event) { + out := []map[string]interface{}{} + + for _, ev := range evs { + fields := make(map[string]interface{}) + fields["module"] = ev.Module + fields["code"] = ev.Code + if ev.TxHash != nil { + fields["tx_hash"] = ev.TxHash.String() + } + fields["data"] = ev.Value + + for _, decoder := range eventDecoders { + decoded, err := decoder(ev) + if err != nil { + continue + } + if decoded != nil { + fields["parsed"] = decoded + + break + } + } + out = append(out, fields) + } + + str, err := common.PrettyJSONMarshal(out) + cobra.CheckErr(err) + fmt.Printf("%s\n", str) +} + func showParameters(ctx context.Context, npa *common.NPASelection, round uint64, rt connection.RuntimeClient) { checkErr := func(what string, err error) { if err != nil { @@ -465,6 +514,30 @@ func showParameters(ctx context.Context, npa *common.NPASelection, round uint64, } } +func showEvents(ctx context.Context, round uint64, rt connection.RuntimeClient) { + evs, err := rt.GetEventsRaw(ctx, round) + cobra.CheckErr(err) + + if len(evs) == 0 { + if outputFormat == formatJSON { + fmt.Printf("[]\n") + return + } + fmt.Println("No events emitted in this block.") + return + } + + if outputFormat == formatJSON { + jsonPrintEvents(evs) + return + } else { + for evIndex, ev := range evs { + prettyPrintEvent("", evIndex, ev) + fmt.Println() + } + } +} + func init() { formatFlag := flag.NewFlagSet("", flag.ContinueOnError) formatFlag.StringVar(&outputFormat, "format", formatText, "output format ["+strings.Join([]string{formatText, formatJSON}, ",")+"]") diff --git a/docs/network.md b/docs/network.md index 21bcb217..41992974 100644 --- a/docs/network.md +++ b/docs/network.md @@ -397,7 +397,7 @@ The provided ID can be one of the following: ```shell oasis network show 000000000000000000000000000000000000000000000000f80306c9858e7279 | jq '.staking.thresholds."node-compute"' ``` - + ``` "5000000000000000" ``` diff --git a/docs/paratime.md b/docs/paratime.md index 53684348..06da6d19 100644 --- a/docs/paratime.md +++ b/docs/paratime.md @@ -36,7 +36,7 @@ oasis paratime add testnet sapphire2 0000000000000000000000000000000000000000000 ``` ``` -? Description: +? Description: ? Denomination symbol: TEST ? Denomination decimal places: 18 ``` @@ -163,6 +163,18 @@ thresholds. By passing `--format json`, the output is formatted as JSON. +### `events` {#show-events} + +This will return all Paratime events emitted in the block. + +Use `--round ` to specify the round number. + +![code shell](../examples/paratime-show/show-events.in) + +![code](../examples/paratime-show/show-events.out) + +By passing `--format json`, the output is formatted as JSON. + ## Set information about a denomination {#denom-set} To set information about a denomination on the specific network and paratime use diff --git a/examples/paratime-show/show-events.in b/examples/paratime-show/show-events.in new file mode 100644 index 00000000..8ecacc78 --- /dev/null +++ b/examples/paratime-show/show-events.in @@ -0,0 +1 @@ +oasis paratime show events --round 9399871 --format json diff --git a/examples/paratime-show/show-events.out b/examples/paratime-show/show-events.out new file mode 100644 index 00000000..7461366d --- /dev/null +++ b/examples/paratime-show/show-events.out @@ -0,0 +1,80 @@ +[ + { + "code": 1, + "data": "gaNidG9VAGIz3RCYb9ltIk8706by6j2XkXGmZGZyb21VAJZQKbOBY+XnA5YUaDhZkNc3y+nsZmFtb3VudIJHCxBZMMJwAEA=", + "module": "accounts", + "parsed": [ + { + "Transfer": { + "from": "oasis1qzt9q2dns937tecrjc2xswzejrtn0jlfas40j7sz", + "to": "oasis1qp3r8hgsnphajmfzfuaa8fhjag7e0yt35cjxq0u4", + "amount": { + "Amount": "3114200000000000", + "Denomination": "" + } + }, + "Burn": null, + "Mint": null + } + ], + "tx_hash": "c586f05e2103adb953d2287ef22dad0532540bd02481184b5477ba8c38894e62" + }, + { + "code": 1, + "data": "gqNidG9VAIyCi8jiQIOmvod+yJYxN0GhktyEZGZyb21VACg9qHdJLY0x3unzFR/SHF3dLD+oZmFtb3VudIJIAWNFeMTiZV9Ao2J0b1UAYjPdEJhv2W0iTzvTp + "module": "accounts", + "parsed": [ + { + "Transfer": { + "from": "oasis1qq5rm2rhfykc6vw7a8e3287jr3wa6tpl4qv49gzh", + "to": "oasis1qzxg9z7gufqg8f47salv3933xaq6rykusslsq4k7", + "amount": { + "Amount": "100000001733846367", + "Denomination": "" + } + }, + "Burn": null, + "Mint": null + }, + { + "Transfer": { + "from": "oasis1qq5rm2rhfykc6vw7a8e3287jr3wa6tpl4qv49gzh", + "to": "oasis1qp3r8hgsnphajmfzfuaa8fhjag7e0yt35cjxq0u4", + "amount": { + "Amount": "2214300000000000", + "Denomination": "" + } + }, + "Burn": null, + "Mint": null + } + ], + "tx_hash": "de7e52e94f4614ec0b0de47971abc12d5070278e9401c2466ec5664a71bdc57d" + }, + { + "code": 1, + "data": "gaFmYW1vdW50GXmm", + "module": "core", + "parsed": [ + { + "GasUsed": { + "amount": 31142 + } + } + ], + "tx_hash": "c586f05e2103adb953d2287ef22dad0532540bd02481184b5477ba8c38894e62" + }, + { + "code": 1, + "data": "gaFmYW1vdW50GVZ/", + "module": "core", + "parsed": [ + { + "GasUsed": { + "amount": 22143 + } + } + ], + "tx_hash": "de7e52e94f4614ec0b0de47971abc12d5070278e9401c2466ec5664a71bdc57d" + } +]