From 5264bb8df9d7f146ba5447c479b745e91fec5b19 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Thu, 20 Jun 2024 13:11:33 +0200 Subject: [PATCH 1/4] feat: Implement genesis transaction list command. Signed-off-by: Antonio Navarro Perez --- gno.land/cmd/gnoland/genesis_txs.go | 1 + gno.land/cmd/gnoland/genesis_txs_list.go | 63 ++++++++++++++++ gno.land/cmd/gnoland/genesis_txs_list_test.go | 72 +++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 gno.land/cmd/gnoland/genesis_txs_list.go create mode 100644 gno.land/cmd/gnoland/genesis_txs_list_test.go diff --git a/gno.land/cmd/gnoland/genesis_txs.go b/gno.land/cmd/gnoland/genesis_txs.go index 57b4ba93864..46b8d1bd29c 100644 --- a/gno.land/cmd/gnoland/genesis_txs.go +++ b/gno.land/cmd/gnoland/genesis_txs.go @@ -35,6 +35,7 @@ func newTxsCmd(io commands.IO) *commands.Command { newTxsAddCmd(cfg, io), newTxsRemoveCmd(cfg, io), newTxsExportCmd(cfg, io), + newTxsListCmd(cfg, io), ) return cmd diff --git a/gno.land/cmd/gnoland/genesis_txs_list.go b/gno.land/cmd/gnoland/genesis_txs_list.go new file mode 100644 index 00000000000..8cde97e91b3 --- /dev/null +++ b/gno.land/cmd/gnoland/genesis_txs_list.go @@ -0,0 +1,63 @@ +package main + +import ( + "context" + "fmt" + "text/tabwriter" + + "github.com/gnolang/gno/gno.land/pkg/gnoland" + vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" + "github.com/gnolang/gno/tm2/pkg/bft/types" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/sdk/bank" +) + +// newTxsListCmd list all transactions on the specified genesis file +func newTxsListCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { + cmd := commands.NewCommand( + commands.Metadata{ + Name: "list", + ShortUsage: "txs list [flags] [...]", + ShortHelp: "lists transactions existing on genesis.json", + LongHelp: "Lists transactions existing on genesis.json", + }, + commands.NewEmptyConfig(), + func(ctx context.Context, args []string) error { + return execTxsListCmd(io, txsCfg) + }, + ) + + return cmd +} + +func execTxsListCmd(io commands.IO, cfg *txsCfg) error { + genesis, err := types.GenesisDocFromFile(cfg.genesisPath) + if err != nil { + return fmt.Errorf("unable to load genesis, %w", err) + } + + gs, ok := genesis.AppState.(gnoland.GnoGenesisState) + if !ok { + return fmt.Errorf("genesis state is not using the correct Gno Genesis type.") + } + + tw := tabwriter.NewWriter(io.Out(), 0, 8, 2, '\t', 0) + for _, tx := range gs.Txs { + hash, err := getTxHash(tx) + if err != nil { + return fmt.Errorf("unable to generate tx hash, %w", err) + } + for _, msg := range tx.Msgs { + switch m := msg.(type) { + case vmm.MsgAddPackage: + fmt.Fprintf(tw, "tx:%s\ttype:create\tpath:%s\tfiles:%d\tcreator:%s\t\n", hash, m.Package.Path, len(m.Package.Files), m.Creator.String()) + case vmm.MsgCall: + fmt.Fprintf(tw, "tx:%s\ttype:call\tpath:%s\tparams:%d\tcaller:%s\t\n", hash, m.PkgPath, len(m.Args), m.Caller.String()) + case bank.MsgSend: + fmt.Fprintf(tw, "tx:%s\ttype:send\tfrom:%s\tto:%s\tamount:%s\t\n", hash, m.FromAddress.String(), m.ToAddress.String(), m.Amount.String()) + } + } + } + + return tw.Flush() +} diff --git a/gno.land/cmd/gnoland/genesis_txs_list_test.go b/gno.land/cmd/gnoland/genesis_txs_list_test.go new file mode 100644 index 00000000000..bcf0ea1146e --- /dev/null +++ b/gno.land/cmd/gnoland/genesis_txs_list_test.go @@ -0,0 +1,72 @@ +package main + +import ( + "bytes" + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/testutils" +) + +func TestGenesis_List_All(t *testing.T) { + t.Parallel() + + t.Run("invalid genesis path", func(t *testing.T) { + t.Parallel() + + // Create the command + cmd := newRootCmd(commands.NewTestIO()) + args := []string{ + "genesis", + "txs", + "list", + "--genesis-path", + "", + } + + // Run the command + cmdErr := cmd.ParseAndRun(context.Background(), args) + assert.ErrorContains(t, cmdErr, "unable to load genesis") + }) + + t.Run("list all txs", func(t *testing.T) { + t.Parallel() + + tempGenesis, cleanup := testutils.NewTestFile(t) + t.Cleanup(cleanup) + + // Generate dummy txs + txs := generateDummyTxs(t, 10) + + genesis := getDefaultGenesis() + genesis.AppState = gnoland.GnoGenesisState{ + Txs: txs, + } + require.NoError(t, genesis.SaveAs(tempGenesis.Name())) + + cio := commands.NewTestIO() + buf := bytes.NewBuffer(nil) + cio.SetOut(commands.WriteNopCloser(buf)) + + cmd := newRootCmd(cio) + args := []string{ + "genesis", + "txs", + "list", + "--genesis-path", + tempGenesis.Name(), + } + + // Run the command + cmdErr := cmd.ParseAndRun(context.Background(), args) + require.NoError(t, cmdErr) + + require.Len(t, buf.String(), 1830) + + }) +} From 92f6ae52f46e1dcfe1123112d9e0b55dc2610472 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Thu, 20 Jun 2024 13:51:39 +0200 Subject: [PATCH 2/4] linter Signed-off-by: Antonio Navarro Perez --- gno.land/cmd/gnoland/genesis_txs_list.go | 2 +- gno.land/cmd/gnoland/genesis_txs_list_test.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/gno.land/cmd/gnoland/genesis_txs_list.go b/gno.land/cmd/gnoland/genesis_txs_list.go index 8cde97e91b3..de2d9c3eb64 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list.go +++ b/gno.land/cmd/gnoland/genesis_txs_list.go @@ -38,7 +38,7 @@ func execTxsListCmd(io commands.IO, cfg *txsCfg) error { gs, ok := genesis.AppState.(gnoland.GnoGenesisState) if !ok { - return fmt.Errorf("genesis state is not using the correct Gno Genesis type.") + return fmt.Errorf("genesis state is not using the correct Gno Genesis type") } tw := tabwriter.NewWriter(io.Out(), 0, 8, 2, '\t', 0) diff --git a/gno.land/cmd/gnoland/genesis_txs_list_test.go b/gno.land/cmd/gnoland/genesis_txs_list_test.go index bcf0ea1146e..2b3c7235347 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list_test.go +++ b/gno.land/cmd/gnoland/genesis_txs_list_test.go @@ -67,6 +67,5 @@ func TestGenesis_List_All(t *testing.T) { require.NoError(t, cmdErr) require.Len(t, buf.String(), 1830) - }) } From e10e97f435b817887cdf240d94655a1b20f3a9d8 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Tue, 25 Jun 2024 14:25:35 +0200 Subject: [PATCH 3/4] Output to json Signed-off-by: Antonio Navarro Perez --- gno.land/cmd/gnoland/genesis_txs_list.go | 26 ++++--------------- gno.land/cmd/gnoland/genesis_txs_list_test.go | 2 +- 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/gno.land/cmd/gnoland/genesis_txs_list.go b/gno.land/cmd/gnoland/genesis_txs_list.go index de2d9c3eb64..c97171479b1 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list.go +++ b/gno.land/cmd/gnoland/genesis_txs_list.go @@ -2,14 +2,12 @@ package main import ( "context" + "encoding/json" "fmt" - "text/tabwriter" "github.com/gnolang/gno/gno.land/pkg/gnoland" - vmm "github.com/gnolang/gno/gno.land/pkg/sdk/vm" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" - "github.com/gnolang/gno/tm2/pkg/sdk/bank" ) // newTxsListCmd list all transactions on the specified genesis file @@ -41,23 +39,9 @@ func execTxsListCmd(io commands.IO, cfg *txsCfg) error { return fmt.Errorf("genesis state is not using the correct Gno Genesis type") } - tw := tabwriter.NewWriter(io.Out(), 0, 8, 2, '\t', 0) - for _, tx := range gs.Txs { - hash, err := getTxHash(tx) - if err != nil { - return fmt.Errorf("unable to generate tx hash, %w", err) - } - for _, msg := range tx.Msgs { - switch m := msg.(type) { - case vmm.MsgAddPackage: - fmt.Fprintf(tw, "tx:%s\ttype:create\tpath:%s\tfiles:%d\tcreator:%s\t\n", hash, m.Package.Path, len(m.Package.Files), m.Creator.String()) - case vmm.MsgCall: - fmt.Fprintf(tw, "tx:%s\ttype:call\tpath:%s\tparams:%d\tcaller:%s\t\n", hash, m.PkgPath, len(m.Args), m.Caller.String()) - case bank.MsgSend: - fmt.Fprintf(tw, "tx:%s\ttype:send\tfrom:%s\tto:%s\tamount:%s\t\n", hash, m.FromAddress.String(), m.ToAddress.String(), m.Amount.String()) - } - } - } + je := json.NewEncoder(io.Out()) + + je.SetIndent("", " ") - return tw.Flush() + return je.Encode(gs.Txs) } diff --git a/gno.land/cmd/gnoland/genesis_txs_list_test.go b/gno.land/cmd/gnoland/genesis_txs_list_test.go index 2b3c7235347..ee49a5fbf56 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list_test.go +++ b/gno.land/cmd/gnoland/genesis_txs_list_test.go @@ -66,6 +66,6 @@ func TestGenesis_List_All(t *testing.T) { cmdErr := cmd.ParseAndRun(context.Background(), args) require.NoError(t, cmdErr) - require.Len(t, buf.String(), 1830) + require.Len(t, buf.String(), 14743) }) } From 5025d5b6e190ba1dc53b34d78973ce1352925062 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Tue, 2 Jul 2024 11:56:44 +0200 Subject: [PATCH 4/4] Requested changes Signed-off-by: Antonio Navarro Perez --- gno.land/cmd/gnoland/genesis_txs_list.go | 20 +++++++++++++------ gno.land/cmd/gnoland/genesis_txs_list_test.go | 4 ++-- tm2/pkg/amino/amino.go | 5 +++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/gno.land/cmd/gnoland/genesis_txs_list.go b/gno.land/cmd/gnoland/genesis_txs_list.go index c97171479b1..c68fbc30803 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list.go +++ b/gno.land/cmd/gnoland/genesis_txs_list.go @@ -1,15 +1,19 @@ package main import ( + "bytes" "context" - "encoding/json" + "errors" "fmt" "github.com/gnolang/gno/gno.land/pkg/gnoland" + "github.com/gnolang/gno/tm2/pkg/amino" "github.com/gnolang/gno/tm2/pkg/bft/types" "github.com/gnolang/gno/tm2/pkg/commands" ) +var ErrWrongGenesisType = errors.New("genesis state is not using the correct Gno Genesis type") + // newTxsListCmd list all transactions on the specified genesis file func newTxsListCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { cmd := commands.NewCommand( @@ -31,17 +35,21 @@ func newTxsListCmd(txsCfg *txsCfg, io commands.IO) *commands.Command { func execTxsListCmd(io commands.IO, cfg *txsCfg) error { genesis, err := types.GenesisDocFromFile(cfg.genesisPath) if err != nil { - return fmt.Errorf("unable to load genesis, %w", err) + return fmt.Errorf("%w, %w", errUnableToLoadGenesis, err) } gs, ok := genesis.AppState.(gnoland.GnoGenesisState) if !ok { - return fmt.Errorf("genesis state is not using the correct Gno Genesis type") + return ErrWrongGenesisType } - je := json.NewEncoder(io.Out()) + b, err := amino.MarshalJSONIndent(gs.Txs, "", " ") + if err != nil { + return errors.New("error marshalling data to amino JSON") + } - je.SetIndent("", " ") + buf := bytes.NewBuffer(b) + _, err = buf.WriteTo(io.Out()) - return je.Encode(gs.Txs) + return err } diff --git a/gno.land/cmd/gnoland/genesis_txs_list_test.go b/gno.land/cmd/gnoland/genesis_txs_list_test.go index ee49a5fbf56..d18c2f4d641 100644 --- a/gno.land/cmd/gnoland/genesis_txs_list_test.go +++ b/gno.land/cmd/gnoland/genesis_txs_list_test.go @@ -31,7 +31,7 @@ func TestGenesis_List_All(t *testing.T) { // Run the command cmdErr := cmd.ParseAndRun(context.Background(), args) - assert.ErrorContains(t, cmdErr, "unable to load genesis") + assert.ErrorIs(t, cmdErr, errUnableToLoadGenesis) }) t.Run("list all txs", func(t *testing.T) { @@ -66,6 +66,6 @@ func TestGenesis_List_All(t *testing.T) { cmdErr := cmd.ParseAndRun(context.Background(), args) require.NoError(t, cmdErr) - require.Len(t, buf.String(), 14743) + require.Len(t, buf.String(), 4442) }) } diff --git a/tm2/pkg/amino/amino.go b/tm2/pkg/amino/amino.go index 1ca3427b85c..ecff955a582 100644 --- a/tm2/pkg/amino/amino.go +++ b/tm2/pkg/amino/amino.go @@ -11,11 +11,12 @@ import ( "runtime" "time" - "github.com/gnolang/gno/tm2/pkg/amino/pkg" - "github.com/gnolang/gno/tm2/pkg/errors" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/gnolang/gno/tm2/pkg/amino/pkg" + "github.com/gnolang/gno/tm2/pkg/errors" ) // Package "pkg" exists So dependencies can create Packages.