From d58b0c67fdcd95df2f61f6d826d6cbb5ea56434f Mon Sep 17 00:00:00 2001 From: Barrie Byron Date: Mon, 18 Apr 2022 01:58:02 -0400 Subject: [PATCH 01/30] docs(readme.md): fix Discord URL invite (#2376) * fix Discord URL invite in docs * Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 06d9016bc6..d762a5c231 100644 --- a/readme.md +++ b/readme.md @@ -56,7 +56,7 @@ Ignite CLI is a free and open source product maintained by [Ignite](https://igni - [ignite.com website](https://ignite.com) - [@ignite_dev on Twitter](https://twitter.com/ignite_dev) - [ignite.com/blog](https://ignite.com/blog/) -- [Ignite Discord](https://discord.com/ignite) +- [Ignite Discord](https://discord.com/invite/ignite) - [Ignite YouTube](https://www.youtube.com/channel/ignitehq) - [Ignite docs](https://docs.ignite.com/) - [Ignite jobs](https://ignite.com/careers) From ff5215a6957e3c98ef548eefd6eb58b35767f60f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Mon, 18 Apr 2022 18:47:16 +0300 Subject: [PATCH 02/30] cmd: upgade spn endpoints (#2379) --- ignite/cmd/network.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/cmd/network.go b/ignite/cmd/network.go index cbc01c20a8..7438ca25f7 100644 --- a/ignite/cmd/network.go +++ b/ignite/cmd/network.go @@ -31,8 +31,8 @@ const ( flagSPNNodeAddress = "spn-node-address" flagSPNFaucetAddress = "spn-faucet-address" - spnNodeAddressNightly = "https://rpc.nightly.ignite.com:443" - spnFaucetAddressNightly = "https://faucet.nightly.ignite.com" + spnNodeAddressNightly = "https://rpc.nightly.starport.network:443" + spnFaucetAddressNightly = "https://faucet.nightly.starport.network" spnNodeAddressLocal = "http://0.0.0.0:26657" spnFaucetAddressLocal = "http://0.0.0.0:4500" From 35ec162fcb86e1ca675e5830249407539b32d3b6 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 19 Apr 2022 04:19:11 -0300 Subject: [PATCH 03/30] fix(network): fix wrong account address check for the join command (#2386) --- ignite/services/network/join.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ignite/services/network/join.go b/ignite/services/network/join.go index 2ad91043a2..72d69e3074 100644 --- a/ignite/services/network/join.go +++ b/ignite/services/network/join.go @@ -125,10 +125,9 @@ func (n Network) sendAccountRequest( genesisPath string, isCustomGentx bool, launchID uint64, - accountAddress string, + address string, amount sdk.Coins, ) (err error) { - address := n.account.Address(networktypes.SPN) n.ev.Send(events.New(events.StatusOngoing, "Verifying account already exists "+address)) // if is custom gentx path, avoid to check account into genesis from the home folder @@ -154,7 +153,7 @@ func (n Network) sendAccountRequest( msg := launchtypes.NewMsgRequestAddAccount( n.account.Address(networktypes.SPN), launchID, - accountAddress, + address, amount, ) From 170b12058a41d4d852862a38a63cc43257c06d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Tue, 19 Apr 2022 10:40:46 +0200 Subject: [PATCH 04/30] feat(network/publish): add support for source URLs without protocol (#2389) * feat(pkg/xurl): add function to ensure HTTPS scheme * chore(network/publish): change command to ensure the https scheme --- ignite/cmd/network_chain_publish.go | 3 ++- ignite/pkg/xurl/xurl.go | 8 ++++++++ ignite/pkg/xurl/xurl_test.go | 31 +++++++++++++++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index 81f1e32d7c..c3fa9a6099 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -10,6 +10,7 @@ import ( "github.com/tendermint/spn/pkg/chainid" "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" ) @@ -58,7 +59,7 @@ func NewNetworkChainPublish() *cobra.Command { func networkChainPublishHandler(cmd *cobra.Command, args []string) error { var ( - source = args[0] + source = xurl.HTTPS(args[0]) tag, _ = cmd.Flags().GetString(flagTag) branch, _ = cmd.Flags().GetString(flagBranch) hash, _ = cmd.Flags().GetString(flagHash) diff --git a/ignite/pkg/xurl/xurl.go b/ignite/pkg/xurl/xurl.go index 5987a124c2..88137f66e8 100644 --- a/ignite/pkg/xurl/xurl.go +++ b/ignite/pkg/xurl/xurl.go @@ -22,6 +22,14 @@ func HTTP(s string) string { return "http://" + Address(s) } +// HTTPS unsures that s url contains HTTPS protocol identifier. +func HTTPS(s string) string { + if strings.HasPrefix(s, "https") { + return s + } + return "https://" + Address(s) +} + // WS unsures that s url contains WS protocol identifier. func WS(s string) string { if strings.HasPrefix(s, "ws") { diff --git a/ignite/pkg/xurl/xurl_test.go b/ignite/pkg/xurl/xurl_test.go index bfefd3cf2f..7f02df7457 100644 --- a/ignite/pkg/xurl/xurl_test.go +++ b/ignite/pkg/xurl/xurl_test.go @@ -1,14 +1,12 @@ package xurl import ( - "fmt" "testing" "github.com/stretchr/testify/require" ) func TestHTTPEnsurePort(t *testing.T) { - fmt.Println(HTTPEnsurePort("https://26657-crimson-pheasant-2x3fbpak.ws-eu03.gitpod.io/")) cases := []struct { addr string ensured string @@ -24,3 +22,32 @@ func TestHTTPEnsurePort(t *testing.T) { }) } } + +func TestHTTPS(t *testing.T) { + cases := []struct { + name string + addr string + want string + }{ + { + name: "with scheme", + addr: "https://github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "without scheme", + addr: "github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "empty", + addr: "", + want: "https://", + }, + } + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, HTTPS(tt.addr)) + }) + } +} From aa2aa87d6f48d51d75448d7a8f30efe4b9d67bdc Mon Sep 17 00:00:00 2001 From: Petr Ivanov Date: Tue, 19 Apr 2022 23:01:30 +0400 Subject: [PATCH 05/30] test(service/network): introduce unit testing tooling (#2235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * implement unit testing tooling for the network package * implement unit testing tooling for the network package * tests for Publish function * tests for Join function * refactor test accounts * revert accidental testada rename * refactor tests * rename starport to ignite * add tests fo SetReward * add tests fo RevertLaunch * add review fixes * add review fixes * simplify Network constructor Co-authored-by: Petr Ivanov Co-authored-by: İlker G. Öztürk --- go.mod | 17 +- go.sum | 53 +- ignite/cmd/network.go | 12 +- ignite/internal/tools/tools.go | 8 + ignite/pkg/cosmosclient/cosmosclient.go | 25 +- ignite/pkg/relayer/relayer.go | 2 +- ignite/services/network/campaign.go | 7 +- ignite/services/network/join.go | 9 +- ignite/services/network/join_test.go | 542 +++++++++++++ ignite/services/network/launch.go | 8 +- ignite/services/network/launch_test.go | 247 ++++++ ignite/services/network/mocks/account_info.go | 116 +++ .../services/network/mocks/campaign_client.go | 348 ++++++++ ignite/services/network/mocks/chain.go | 252 ++++++ .../services/network/mocks/cosmos_client.go | 142 ++++ .../services/network/mocks/launch_client.go | 348 ++++++++ .../services/network/mocks/profile_client.go | 198 +++++ .../services/network/mocks/reward_client.go | 108 +++ ignite/services/network/network.go | 70 +- ignite/services/network/network_test.go | 14 + ignite/services/network/publish.go | 13 +- ignite/services/network/publish_test.go | 758 ++++++++++++++++++ ignite/services/network/queries.go | 23 +- ignite/services/network/request.go | 7 +- ignite/services/network/reward_test.go | 73 ++ ignite/services/network/testutil/account.go | 21 + ignite/services/network/testutil/chain.go | 17 + ignite/services/network/testutil/genesis.go | 59 ++ ignite/services/network/testutil/gentx.go | 68 ++ ignite/services/network/testutil/mocks.go | 34 + ignite/services/network/testutil/response.go | 35 + ignite/services/network/testutil/suite.go | 42 + integration/faucet/faucet_test.go | 2 +- 33 files changed, 3597 insertions(+), 81 deletions(-) create mode 100644 ignite/internal/tools/tools.go create mode 100644 ignite/services/network/join_test.go create mode 100644 ignite/services/network/launch_test.go create mode 100644 ignite/services/network/mocks/account_info.go create mode 100644 ignite/services/network/mocks/campaign_client.go create mode 100644 ignite/services/network/mocks/chain.go create mode 100644 ignite/services/network/mocks/cosmos_client.go create mode 100644 ignite/services/network/mocks/launch_client.go create mode 100644 ignite/services/network/mocks/profile_client.go create mode 100644 ignite/services/network/mocks/reward_client.go create mode 100644 ignite/services/network/publish_test.go create mode 100644 ignite/services/network/reward_test.go create mode 100644 ignite/services/network/testutil/account.go create mode 100644 ignite/services/network/testutil/chain.go create mode 100644 ignite/services/network/testutil/genesis.go create mode 100644 ignite/services/network/testutil/gentx.go create mode 100644 ignite/services/network/testutil/mocks.go create mode 100644 ignite/services/network/testutil/response.go create mode 100644 ignite/services/network/testutil/suite.go diff --git a/go.mod b/go.mod index ecc4e381fa..6d65d7eb13 100644 --- a/go.mod +++ b/go.mod @@ -49,11 +49,13 @@ require ( github.com/tendermint/tendermint v0.34.19 github.com/tendermint/tm-db v0.6.6 github.com/tendermint/vue v0.3.5 - golang.org/x/mod v0.5.0 + github.com/vektra/mockery/v2 v2.11.0 + golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 golang.org/x/text v0.3.7 google.golang.org/grpc v1.45.0 + google.golang.org/protobuf v1.27.1 ) require ( @@ -193,7 +195,7 @@ require ( github.com/regen-network/cosmos-proto v0.3.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.4.0 // indirect - github.com/rs/zerolog v1.23.0 // indirect + github.com/rs/zerolog v1.26.1 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 // indirect github.com/sahilm/fuzzy v0.1.0 // indirect @@ -204,9 +206,10 @@ require ( github.com/sirupsen/logrus v1.8.1 // indirect github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d // indirect github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e // indirect - github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/afero v1.8.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/viper v1.10.1 // indirect + github.com/stretchr/objx v0.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect @@ -216,18 +219,18 @@ require ( github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce // indirect github.com/xanzy/ssh-agent v0.2.1 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - github.com/yuin/goldmark v1.3.5 // indirect + github.com/yuin/goldmark v1.4.1 // indirect github.com/yuin/goldmark-emoji v1.0.1 // indirect github.com/zondax/hid v0.9.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 // indirect + golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/tools v0.1.10 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect - google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/ini.v1 v1.66.2 // indirect + gopkg.in/ini.v1 v1.66.3 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index 2ca2ac6061..d08d69c71a 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= @@ -16,6 +17,7 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= @@ -26,6 +28,7 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= @@ -46,6 +49,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-beta.2 h1:/BZRNzm8N4K4eWfK28dL4yescorxtO7YG1yun8fy+pI= filippo.io/edwards25519 v1.0.0-beta.2/go.mod h1:X+pm78QAUPtFLi1z9PYIlS/bdDnvbCOGKtZ+ACWEf7o= @@ -755,6 +759,7 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -771,6 +776,7 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -819,6 +825,7 @@ github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIv github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= @@ -1249,6 +1256,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -1338,8 +1346,10 @@ github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.23.0 h1:UskrK+saS9P9Y789yNNulYKdARjPZuS35B8gJF2x60g= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.23.0/go.mod h1:6c7hFfxPOy7TacJc4Fcdi24/J0NKYGzjG8FWRI916Qo= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= @@ -1348,6 +1358,7 @@ github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0= github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM= github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= @@ -1394,8 +1405,9 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/afero v1.8.0 h1:5MmtuhAgYeU6qpa7w7bP0dv6MBYuup0vekhSpSkoq60= +github.com/spf13/afero v1.8.0/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= @@ -1407,6 +1419,7 @@ github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHN github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= @@ -1423,6 +1436,7 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= +github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q= @@ -1504,6 +1518,8 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vektra/mockery/v2 v2.11.0 h1:9NkC3urGvJS9B0ve5aTbFjksbO9f/u5cZFgCTVJ30jg= +github.com/vektra/mockery/v2 v2.11.0/go.mod h1:8vf4KDDUptfkyypzdHLuE7OE2xA7Gdt60WgIS8PgD+U= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1530,8 +1546,10 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1 h1:/vn0k+RBvwlxEmP5E7SZMqNxPhfMVFEJiykr15/0XKM= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= @@ -1616,10 +1634,15 @@ golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 h1:3erb+vDS8lU1sxfDHF4/hhWyaXnhIaO+7RgL4fDZORA= golang.org/x/crypto v0.0.0-20210915214749-c084706c2272/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1662,8 +1685,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1724,10 +1748,13 @@ golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210903162142-ad29c8ab022f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211208012354-db4efeb81f4b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1856,6 +1883,7 @@ golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1864,6 +1892,7 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1873,6 +1902,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210903071746-97244b99971b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1881,6 +1911,7 @@ golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1980,12 +2011,16 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -2029,6 +2064,7 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU= google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= +google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2083,8 +2119,10 @@ google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2109,6 +2147,8 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211223182754-3ac035c7e7cb/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= @@ -2150,8 +2190,9 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.66.3 h1:jRskFVxYaMGAMUbN0UZ7niA9gzL9B49DOqE78vg0k3w= +gopkg.in/ini.v1 v1.66.3/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= diff --git a/ignite/cmd/network.go b/ignite/cmd/network.go index 7438ca25f7..92eb81a6b9 100644 --- a/ignite/cmd/network.go +++ b/ignite/cmd/network.go @@ -3,9 +3,6 @@ package ignitecmd import ( "sync" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" @@ -14,6 +11,8 @@ import ( "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) var ( @@ -112,8 +111,6 @@ func (n NetworkBuilder) Chain(source networkchain.SourceOption, options ...netwo } func (n NetworkBuilder) Network(options ...network.Option) (network.Network, error) { - options = append(options, network.CollectEvents(n.ev)) - var ( err error from = getFrom(n.cmd) @@ -125,7 +122,10 @@ func (n NetworkBuilder) Network(options ...network.Option) (network.Network, err return network.Network{}, errors.Wrap(err, "make sure that this account exists, use 'ignite account -h' to manage accounts") } } - return network.New(*cosmos, account, options...) + + options = append(options, network.CollectEvents(n.ev)) + + return network.New(*cosmos, account, options...), nil } func (n NetworkBuilder) Cleanup() { diff --git a/ignite/internal/tools/tools.go b/ignite/internal/tools/tools.go new file mode 100644 index 0000000000..969f531519 --- /dev/null +++ b/ignite/internal/tools/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package tools + +import ( + _ "github.com/vektra/mockery/v2" +) diff --git a/ignite/pkg/cosmosclient/cosmosclient.go b/ignite/pkg/cosmosclient/cosmosclient.go index ea77b66774..f3fca93b79 100644 --- a/ignite/pkg/cosmosclient/cosmosclient.go +++ b/ignite/pkg/cosmosclient/cosmosclient.go @@ -28,11 +28,10 @@ import ( staking "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/gogo/protobuf/proto" prototypes "github.com/gogo/protobuf/types" - "github.com/pkg/errors" - rpchttp "github.com/tendermint/tendermint/rpc/client/http" - "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosfaucet" + "github.com/pkg/errors" + rpchttp "github.com/tendermint/tendermint/rpc/client/http" ) // FaucetTransferEnsureDuration is the duration that BroadcastTx will wait when a faucet transfer @@ -62,7 +61,7 @@ type Client struct { Factory tx.Factory // context is a Cosmos SDK client context. - Context client.Context + context client.Context // AccountRegistry is the retistry to access accounts. AccountRegistry cosmosaccount.Registry @@ -183,8 +182,8 @@ func New(ctx context.Context, options ...Option) (Client, error) { return Client{}, err } - c.Context = newContext(c.RPC, c.out, c.chainID, c.homePath).WithKeyring(c.AccountRegistry.Keyring) - c.Factory = newFactory(c.Context) + c.context = newContext(c.RPC, c.out, c.chainID, c.homePath).WithKeyring(c.AccountRegistry.Keyring) + c.Factory = newFactory(c.context) return c, nil } @@ -202,9 +201,13 @@ func (c Client) Address(accountName string) (sdktypes.AccAddress, error) { return account.Info.GetAddress(), nil } +func (c Client) Context() client.Context { + return c.context +} + // Response of your broadcasted transaction. type Response struct { - codec codec.Codec + Codec codec.Codec // TxResponse is the underlying tx response. *sdktypes.TxResponse @@ -227,7 +230,7 @@ func (r Response) Decode(message proto.Message) error { } var txMsgData sdktypes.TxMsgData - if err := r.codec.Unmarshal(data, &txMsgData); err != nil { + if err := r.Codec.Unmarshal(data, &txMsgData); err != nil { return err } @@ -270,7 +273,7 @@ func (c Client) BroadcastTxWithProvision(accountName string, msgs ...sdktypes.Ms return 0, nil, err } - ctx := c.Context. + ctx := c.context. WithFromName(accountName). WithFromAddress(accountAddress) @@ -315,7 +318,7 @@ func (c Client) BroadcastTxWithProvision(accountName string, msgs ...sdktypes.Ms } return Response{ - codec: ctx.Codec, + Codec: ctx.Codec, TxResponse: resp, }, handleBroadcastResult(resp, err) }, nil @@ -373,7 +376,7 @@ func (c *Client) makeSureAccountHasTokens(ctx context.Context, address string) e } func (c *Client) checkAccountBalance(ctx context.Context, address string) error { - resp, err := banktypes.NewQueryClient(c.Context).Balance(ctx, &banktypes.QueryBalanceRequest{ + resp, err := banktypes.NewQueryClient(c.context).Balance(ctx, &banktypes.QueryBalanceRequest{ Address: address, Denom: c.faucetDenom, }) diff --git a/ignite/pkg/relayer/relayer.go b/ignite/pkg/relayer/relayer.go index 27bebcac88..3334cbd4a3 100644 --- a/ignite/pkg/relayer/relayer.go +++ b/ignite/pkg/relayer/relayer.go @@ -206,7 +206,7 @@ func (r Relayer) balance(ctx context.Context, rpcAddress, account, addressPrefix addr := acc.Address(addressPrefix) - queryClient := banktypes.NewQueryClient(client.Context) + queryClient := banktypes.NewQueryClient(client.Context()) res, err := queryClient.AllBalances(ctx, &banktypes.QueryAllBalancesRequest{Address: addr}) if err != nil { return nil, err diff --git a/ignite/services/network/campaign.go b/ignite/services/network/campaign.go index 85fdd2c60d..ad4241bb47 100644 --- a/ignite/services/network/campaign.go +++ b/ignite/services/network/campaign.go @@ -5,10 +5,9 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - campaigntypes "github.com/tendermint/spn/x/campaign/types" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + campaigntypes "github.com/tendermint/spn/x/campaign/types" ) type ( @@ -47,7 +46,7 @@ func WithCampaignTotalSupply(totalSupply sdk.Coins) Prop { // Campaign fetches the campaign from Starport Network func (n Network) Campaign(ctx context.Context, campaignID uint64) (networktypes.Campaign, error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching campaign information")) - res, err := campaigntypes.NewQueryClient(n.cosmos.Context).Campaign(ctx, &campaigntypes.QueryGetCampaignRequest{ + res, err := n.campaignQuery.Campaign(ctx, &campaigntypes.QueryGetCampaignRequest{ CampaignID: campaignID, }) if err != nil { @@ -61,7 +60,7 @@ func (n Network) Campaigns(ctx context.Context) ([]networktypes.Campaign, error) var campaigns []networktypes.Campaign n.ev.Send(events.New(events.StatusOngoing, "Fetching campaigns information")) - res, err := campaigntypes.NewQueryClient(n.cosmos.Context). + res, err := n.campaignQuery. CampaignAll(ctx, &campaigntypes.QueryAllCampaignRequest{}) if err != nil { return campaigns, err diff --git a/ignite/services/network/join.go b/ignite/services/network/join.go index 72d69e3074..44137579dc 100644 --- a/ignite/services/network/join.go +++ b/ignite/services/network/join.go @@ -5,14 +5,13 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - launchtypes "github.com/tendermint/spn/x/launch/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network/networkchain" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + launchtypes "github.com/tendermint/spn/x/launch/types" ) type joinOptions struct { @@ -232,7 +231,7 @@ func (n Network) sendValidatorRequest( // hasValidator verify if the validator already exist into the SPN store func (n Network) hasValidator(ctx context.Context, launchID uint64, address string) (bool, error) { - _, err := launchtypes.NewQueryClient(n.cosmos.Context).GenesisValidator(ctx, &launchtypes.QueryGetGenesisValidatorRequest{ + _, err := n.launchQuery.GenesisValidator(ctx, &launchtypes.QueryGetGenesisValidatorRequest{ LaunchID: launchID, Address: address, }) @@ -246,7 +245,7 @@ func (n Network) hasValidator(ctx context.Context, launchID uint64, address stri // hasAccount verify if the account already exist into the SPN store func (n Network) hasAccount(ctx context.Context, launchID uint64, address string) (bool, error) { - _, err := launchtypes.NewQueryClient(n.cosmos.Context).VestingAccount(ctx, &launchtypes.QueryGetVestingAccountRequest{ + _, err := n.launchQuery.VestingAccount(ctx, &launchtypes.QueryGetVestingAccountRequest{ LaunchID: launchID, Address: address, }) @@ -256,7 +255,7 @@ func (n Network) hasAccount(ctx context.Context, launchID uint64, address string return false, err } - _, err = launchtypes.NewQueryClient(n.cosmos.Context).GenesisAccount(ctx, &launchtypes.QueryGetGenesisAccountRequest{ + _, err = n.launchQuery.GenesisAccount(ctx, &launchtypes.QueryGetGenesisAccountRequest{ LaunchID: launchID, Address: address, }) diff --git a/ignite/services/network/join_test.go b/ignite/services/network/join_test.go new file mode 100644 index 0000000000..3421e7d9f9 --- /dev/null +++ b/ignite/services/network/join_test.go @@ -0,0 +1,542 @@ +package network + +import ( + "context" + "errors" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + launchtypes "github.com/tendermint/spn/x/launch/types" +) + +const ( + TestDenom = "stake" + TestAmountString = "95000000" + TestAmountInt = int64(95000000) + TestAccountRequestID = uint64(1) + TestGenesisValidatorRequestID = uint64(2) +) + +func TestJoin(t *testing.T) { + t.Run("successfully send join request", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddValidator{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + ValAddress: account.Address(networktypes.SPN), + GenTx: gentx.JSON(t), + ConsPubKey: []byte{}, + SelfDelegation: sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)), + Peer: launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgRequestAddValidatorResponse{ + RequestID: TestGenesisValidatorRequestID, + AutoApproved: false, + }), nil). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.NoError(t, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("successfully send join request with custom gentx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddValidator{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + ValAddress: account.Address(networktypes.SPN), + GenTx: gentx.JSON(t), + ConsPubKey: []byte{}, + SelfDelegation: sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)), + Peer: launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgRequestAddValidatorResponse{ + RequestID: TestGenesisValidatorRequestID, + AutoApproved: false, + }), nil). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithCustomGentxPath(gentxPath)) + require.NoError(t, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, validator already exists", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, nil). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Errorf(t, joinErr, "validator %s already exist", account.Address(networktypes.SPN)) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to check validator existence", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + expectedError = errors.New("failed to perform request") + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, expectedError). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to broadcast join tx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + expectedError = errors.New("failed to add validator") + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddValidator{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + ValAddress: account.Address(networktypes.SPN), + GenTx: gentx.JSON(t), + ConsPubKey: []byte{}, + SelfDelegation: sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)), + Peer: launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + }, + ). + Return( + testutil.NewResponse(&launchtypes.MsgRequestAddValidatorResponse{}), + expectedError, + ). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("successfully send join request with account request", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.LaunchQueryMock. + On( + "GenesisValidator", + context.Background(), + &launchtypes.QueryGetGenesisValidatorRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }, + ). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.LaunchQueryMock. + On( + "VestingAccount", + context.Background(), + &launchtypes.QueryGetVestingAccountRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddValidator{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + ValAddress: account.Address(networktypes.SPN), + GenTx: gentx.JSON(t), + ConsPubKey: []byte{}, + SelfDelegation: sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)), + Peer: launchtypes.Peer{ + Id: testutil.NodeID, + Connection: &launchtypes.Peer_TcpAddress{ + TcpAddress: testutil.TCPAddress, + }, + }, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgRequestAddValidatorResponse{ + RequestID: TestGenesisValidatorRequestID, + AutoApproved: false, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddAccount{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + Address: account.Address(networktypes.SPN), + Coins: sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt))), + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgRequestAddAccountResponse{ + RequestID: TestAccountRequestID, + AutoApproved: false, + }), nil). + Once() + + joinErr := network.Join( + context.Background(), + suite.ChainMock, + testutil.LaunchID, + WithAccountRequest(sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)))), + WithPublicAddress(testutil.TCPAddress), + ) + require.NoError(t, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request with account request, account exists in genesis", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesis = testutil.NewGenesis(testutil.ChainID).AddAccount(account.Address(networktypes.SPN)) + genesisPath = genesis.SaveTo(t, tmp) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + + joinErr := network.Join( + context.Background(), + suite.ChainMock, + testutil.LaunchID, + WithAccountRequest(sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)))), + WithPublicAddress(testutil.TCPAddress), + ) + require.Errorf(t, joinErr, "account %s already exist", account.Address(networktypes.SPN)) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request with account request, failed to broadcast account tx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + genesisPath = testutil.NewGenesis(testutil.ChainID).SaveTo(t, tmp) + suite, network = newSuite(account) + expectedError = errors.New("failed to create account") + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("GenesisPath").Return(genesisPath, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + + suite.LaunchQueryMock. + On( + "VestingAccount", + context.Background(), + &launchtypes.QueryGetVestingAccountRequest{ + Address: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgRequestAddAccount{ + Creator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + Address: account.Address(networktypes.SPN), + Coins: sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt))), + }, + ). + Return( + testutil.NewResponse(&launchtypes.MsgRequestAddAccountResponse{}), + expectedError, + ). + Once() + + joinErr := network.Join( + context.Background(), + suite.ChainMock, + testutil.LaunchID, + WithAccountRequest(sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt)))), + WithPublicAddress(testutil.TCPAddress), + ) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to read node id", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to get node id") + ) + suite.ChainMock. + On("NodeID", mock.Anything). + Return("", expectedError). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to read default gentx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to get default gentx path") + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock. + On("DefaultGentxPath"). + Return("", expectedError). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to read genesis", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + tmp = t.TempDir() + gentx = testutil.NewGentx( + account.Address(networktypes.SPN), + TestDenom, + TestAmountString, + "", + testutil.PeerAddress, + ) + gentxPath = gentx.SaveTo(t, tmp) + suite, network = newSuite(account) + expectedError = errors.New("failed to get genesis path") + ) + + suite.ChainMock.On("NodeID", context.Background()).Return(testutil.NodeID, nil).Once() + suite.ChainMock.On("DefaultGentxPath").Return(gentxPath, nil).Once() + suite.ChainMock. + On("GenesisPath"). + Return("", expectedError). + Once() + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithPublicAddress(testutil.TCPAddress)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) + + t.Run("failed to send join request, failed to read custom genesis", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + gentxPath = "invalid/path" + suite, network = newSuite(account) + expectedError = errors.New("chain home folder is not initialized yet: invalid/path") + ) + + joinErr := network.Join(context.Background(), suite.ChainMock, testutil.LaunchID, WithCustomGentxPath(gentxPath)) + require.Error(t, joinErr) + require.Equal(t, expectedError, joinErr) + suite.AssertAllMocks(t) + }) +} diff --git a/ignite/services/network/launch.go b/ignite/services/network/launch.go index b54473a770..7af2298348 100644 --- a/ignite/services/network/launch.go +++ b/ignite/services/network/launch.go @@ -5,17 +5,15 @@ import ( "fmt" "time" - launchtypes "github.com/tendermint/spn/x/launch/types" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/pkg/xtime" - "github.com/ignite-hq/cli/ignite/services/network/networkchain" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + launchtypes "github.com/tendermint/spn/x/launch/types" ) // LaunchParams fetches the chain launch module params from SPN func (n Network) LaunchParams(ctx context.Context) (launchtypes.Params, error) { - res, err := launchtypes.NewQueryClient(n.cosmos.Context).Params(ctx, &launchtypes.QueryParamsRequest{}) + res, err := n.launchQuery.Params(ctx, &launchtypes.QueryParamsRequest{}) if err != nil { return launchtypes.Params{}, err } @@ -68,7 +66,7 @@ func (n Network) TriggerLaunch(ctx context.Context, launchID uint64, remainingTi } // RevertLaunch reverts a launched chain as a coordinator -func (n Network) RevertLaunch(launchID uint64, chain *networkchain.Chain) error { +func (n Network) RevertLaunch(launchID uint64, chain Chain) error { n.ev.Send(events.New(events.StatusOngoing, fmt.Sprintf("Reverting launched chain %d", launchID))) address := n.account.Address(networktypes.SPN) diff --git a/ignite/services/network/launch_test.go b/ignite/services/network/launch_test.go new file mode 100644 index 0000000000..117dab7d1b --- /dev/null +++ b/ignite/services/network/launch_test.go @@ -0,0 +1,247 @@ +package network + +import ( + "context" + "errors" + "testing" + "time" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/xtime" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" + "github.com/stretchr/testify/require" + launchtypes "github.com/tendermint/spn/x/launch/types" +) + +const ( + TestMinRemainingTime = 3600 + TestMaxRemainingTime = 86400 + TestRevertDelay = 3600 +) + +func TestTriggerLaunch(t *testing.T) { + t.Run("successfully launch a chain", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, nil). + Once() + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgTriggerLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + RemainingTime: TestMaxRemainingTime, + }). + Return(testutil.NewResponse(&launchtypes.MsgTriggerLaunchResponse{}), nil). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, TestMaxRemainingTime*time.Second) + require.NoError(t, launchError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to launch a chain, remaining time is lower than allowed", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + remainingTimeLowerThanMinimum = (TestMinRemainingTime - 60) * time.Second + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, nil). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, remainingTimeLowerThanMinimum) + require.Errorf( + t, + launchError, + "remaining time %s lower than minimum %s", + xtime.NowAfter(remainingTimeLowerThanMinimum), + xtime.NowAfter(TestMinRemainingTime), + ) + suite.AssertAllMocks(t) + }) + + t.Run("failed to launch a chain, remaining time is greater than allowed", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + remainingTimeGreaterThanMaximum = (TestMaxRemainingTime + 60) * time.Hour + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, nil). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, remainingTimeGreaterThanMaximum) + require.Errorf( + t, + launchError, + "remaining time %s greater than maximum %s", + xtime.NowAfter(remainingTimeGreaterThanMaximum), + xtime.NowAfter(TestMaxRemainingTime), + ) + suite.AssertAllMocks(t) + }) + + t.Run("failed to launch a chain, failed to broadcast the launch tx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("Failed to fetch") + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, nil). + Once() + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgTriggerLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + RemainingTime: TestMaxRemainingTime, + }). + Return(testutil.NewResponse(&launchtypes.MsgTriggerLaunch{}), expectedError). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, TestMaxRemainingTime*time.Second) + require.Error(t, launchError) + require.Equal(t, expectedError, launchError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to launch a chain, invalid response from chain", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to fetch") + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, nil). + Once() + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgTriggerLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + RemainingTime: TestMaxRemainingTime, + }). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{}), expectedError). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, TestMaxRemainingTime*time.Second) + require.Error(t, launchError) + require.Equal(t, expectedError, launchError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to launch a chain, failed to fetch chain params", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to fetch") + ) + + suite.LaunchQueryMock. + On("Params", context.Background(), &launchtypes.QueryParamsRequest{}). + Return(&launchtypes.QueryParamsResponse{ + Params: launchtypes.NewParams(TestMinRemainingTime, TestMaxRemainingTime, TestRevertDelay, sdk.Coins(nil)), + }, expectedError). + Once() + + launchError := network.TriggerLaunch(context.Background(), testutil.LaunchID, (TestMaxRemainingTime+60)*time.Second) + require.Error(t, launchError) + require.Equal(t, expectedError, launchError) + suite.AssertAllMocks(t) + }) +} + +func TestRevertLaunch(t *testing.T) { + t.Run("successfully revert launch", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ChainMock.On("ResetGenesisTime").Return(nil).Once() + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgRevertLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }). + Return(testutil.NewResponse(&launchtypes.MsgRevertLaunchResponse{}), nil). + Once() + + revertError := network.RevertLaunch(testutil.LaunchID, suite.ChainMock) + require.NoError(t, revertError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to revert launch, failed to broadcast revert launch tx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to revert launch") + ) + + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgRevertLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }). + Return( + testutil.NewResponse(&launchtypes.MsgRevertLaunchResponse{}), + expectedError, + ). + Once() + + revertError := network.RevertLaunch(testutil.LaunchID, suite.ChainMock) + require.Error(t, revertError) + require.Equal(t, expectedError, revertError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to revert launch, failed to reset chain genesis time", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to reset genesis time") + ) + + suite.ChainMock. + On("ResetGenesisTime"). + Return(expectedError). + Once() + suite.CosmosClientMock. + On("BroadcastTx", account.Name, &launchtypes.MsgRevertLaunch{ + Coordinator: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + }). + Return(testutil.NewResponse(&launchtypes.MsgRevertLaunchResponse{}), nil). + Once() + + revertError := network.RevertLaunch(testutil.LaunchID, suite.ChainMock) + require.Error(t, revertError) + require.Equal(t, expectedError, revertError) + suite.AssertAllMocks(t) + }) + +} diff --git a/ignite/services/network/mocks/account_info.go b/ignite/services/network/mocks/account_info.go new file mode 100644 index 0000000000..ad803a03c8 --- /dev/null +++ b/ignite/services/network/mocks/account_info.go @@ -0,0 +1,116 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + hd "github.com/cosmos/cosmos-sdk/crypto/hd" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + + keyring "github.com/cosmos/cosmos-sdk/crypto/keyring" + + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// AccountInfo is an autogenerated mock type for the AccountInfo type +type AccountInfo struct { + mock.Mock +} + +// GetAddress provides a mock function with given fields: +func (_m *AccountInfo) GetAddress() types.AccAddress { + ret := _m.Called() + + var r0 types.AccAddress + if rf, ok := ret.Get(0).(func() types.AccAddress); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.AccAddress) + } + } + + return r0 +} + +// GetAlgo provides a mock function with given fields: +func (_m *AccountInfo) GetAlgo() hd.PubKeyType { + ret := _m.Called() + + var r0 hd.PubKeyType + if rf, ok := ret.Get(0).(func() hd.PubKeyType); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(hd.PubKeyType) + } + + return r0 +} + +// GetName provides a mock function with given fields: +func (_m *AccountInfo) GetName() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// GetPath provides a mock function with given fields: +func (_m *AccountInfo) GetPath() (*hd.BIP44Params, error) { + ret := _m.Called() + + var r0 *hd.BIP44Params + if rf, ok := ret.Get(0).(func() *hd.BIP44Params); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*hd.BIP44Params) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPubKey provides a mock function with given fields: +func (_m *AccountInfo) GetPubKey() cryptotypes.PubKey { + ret := _m.Called() + + var r0 cryptotypes.PubKey + if rf, ok := ret.Get(0).(func() cryptotypes.PubKey); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(cryptotypes.PubKey) + } + } + + return r0 +} + +// GetType provides a mock function with given fields: +func (_m *AccountInfo) GetType() keyring.KeyType { + ret := _m.Called() + + var r0 keyring.KeyType + if rf, ok := ret.Get(0).(func() keyring.KeyType); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(keyring.KeyType) + } + + return r0 +} diff --git a/ignite/services/network/mocks/campaign_client.go b/ignite/services/network/mocks/campaign_client.go new file mode 100644 index 0000000000..4bda0a9ff1 --- /dev/null +++ b/ignite/services/network/mocks/campaign_client.go @@ -0,0 +1,348 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/spn/x/campaign/types" +) + +// CampaignClient is an autogenerated mock type for the CampaignClient type +type CampaignClient struct { + mock.Mock +} + +// Campaign provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) Campaign(ctx context.Context, in *types.QueryGetCampaignRequest, opts ...grpc.CallOption) (*types.QueryGetCampaignResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetCampaignResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetCampaignRequest, ...grpc.CallOption) *types.QueryGetCampaignResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetCampaignResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetCampaignRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CampaignAll provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) CampaignAll(ctx context.Context, in *types.QueryAllCampaignRequest, opts ...grpc.CallOption) (*types.QueryAllCampaignResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllCampaignResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllCampaignRequest, ...grpc.CallOption) *types.QueryAllCampaignResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllCampaignResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllCampaignRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CampaignChains provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) CampaignChains(ctx context.Context, in *types.QueryGetCampaignChainsRequest, opts ...grpc.CallOption) (*types.QueryGetCampaignChainsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetCampaignChainsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetCampaignChainsRequest, ...grpc.CallOption) *types.QueryGetCampaignChainsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetCampaignChainsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetCampaignChainsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CampaignSummaries provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) CampaignSummaries(ctx context.Context, in *types.QueryCampaignSummariesRequest, opts ...grpc.CallOption) (*types.QueryCampaignSummariesResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryCampaignSummariesResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCampaignSummariesRequest, ...grpc.CallOption) *types.QueryCampaignSummariesResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryCampaignSummariesResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryCampaignSummariesRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CampaignSummary provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) CampaignSummary(ctx context.Context, in *types.QueryCampaignSummaryRequest, opts ...grpc.CallOption) (*types.QueryCampaignSummaryResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryCampaignSummaryResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryCampaignSummaryRequest, ...grpc.CallOption) *types.QueryCampaignSummaryResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryCampaignSummaryResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryCampaignSummaryRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MainnetAccount provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) MainnetAccount(ctx context.Context, in *types.QueryGetMainnetAccountRequest, opts ...grpc.CallOption) (*types.QueryGetMainnetAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetMainnetAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetMainnetAccountRequest, ...grpc.CallOption) *types.QueryGetMainnetAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetMainnetAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetMainnetAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MainnetAccountAll provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) MainnetAccountAll(ctx context.Context, in *types.QueryAllMainnetAccountRequest, opts ...grpc.CallOption) (*types.QueryAllMainnetAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllMainnetAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllMainnetAccountRequest, ...grpc.CallOption) *types.QueryAllMainnetAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllMainnetAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllMainnetAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MainnetVestingAccount provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) MainnetVestingAccount(ctx context.Context, in *types.QueryGetMainnetVestingAccountRequest, opts ...grpc.CallOption) (*types.QueryGetMainnetVestingAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetMainnetVestingAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetMainnetVestingAccountRequest, ...grpc.CallOption) *types.QueryGetMainnetVestingAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetMainnetVestingAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetMainnetVestingAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MainnetVestingAccountAll provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) MainnetVestingAccountAll(ctx context.Context, in *types.QueryAllMainnetVestingAccountRequest, opts ...grpc.CallOption) (*types.QueryAllMainnetVestingAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllMainnetVestingAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllMainnetVestingAccountRequest, ...grpc.CallOption) *types.QueryAllMainnetVestingAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllMainnetVestingAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllMainnetVestingAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Params provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryParamsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryParamsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TotalShares provides a mock function with given fields: ctx, in, opts +func (_m *CampaignClient) TotalShares(ctx context.Context, in *types.QueryTotalSharesRequest, opts ...grpc.CallOption) (*types.QueryTotalSharesResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryTotalSharesResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryTotalSharesRequest, ...grpc.CallOption) *types.QueryTotalSharesResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryTotalSharesResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryTotalSharesRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/ignite/services/network/mocks/chain.go b/ignite/services/network/mocks/chain.go new file mode 100644 index 0000000000..d7d6e8c0f7 --- /dev/null +++ b/ignite/services/network/mocks/chain.go @@ -0,0 +1,252 @@ +// Code generated by mockery v2.10.6. DO NOT EDIT. + +package mocks + +import ( + context "context" + + mock "github.com/stretchr/testify/mock" +) + +// Chain is an autogenerated mock type for the Chain type +type Chain struct { + mock.Mock +} + +// AppTOMLPath provides a mock function with given fields: +func (_m *Chain) AppTOMLPath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CacheBinary provides a mock function with given fields: launchID +func (_m *Chain) CacheBinary(launchID uint64) error { + ret := _m.Called(launchID) + + var r0 error + if rf, ok := ret.Get(0).(func(uint64) error); ok { + r0 = rf(launchID) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// ChainID provides a mock function with given fields: +func (_m *Chain) ChainID() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConfigTOMLPath provides a mock function with given fields: +func (_m *Chain) ConfigTOMLPath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DefaultGentxPath provides a mock function with given fields: +func (_m *Chain) DefaultGentxPath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GenesisPath provides a mock function with given fields: +func (_m *Chain) GenesisPath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GentxsPath provides a mock function with given fields: +func (_m *Chain) GentxsPath() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ID provides a mock function with given fields: +func (_m *Chain) ID() (string, error) { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Name provides a mock function with given fields: +func (_m *Chain) Name() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// NodeID provides a mock function with given fields: ctx +func (_m *Chain) NodeID(ctx context.Context) (string, error) { + ret := _m.Called(ctx) + + var r0 string + if rf, ok := ret.Get(0).(func(context.Context) string); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(string) + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ResetGenesisTime provides a mock function with given fields: +func (_m *Chain) ResetGenesisTime() error { + ret := _m.Called() + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// SourceHash provides a mock function with given fields: +func (_m *Chain) SourceHash() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + +// SourceURL provides a mock function with given fields: +func (_m *Chain) SourceURL() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} diff --git a/ignite/services/network/mocks/cosmos_client.go b/ignite/services/network/mocks/cosmos_client.go new file mode 100644 index 0000000000..4c1808ee78 --- /dev/null +++ b/ignite/services/network/mocks/cosmos_client.go @@ -0,0 +1,142 @@ +// Code generated by mockery v2.10.6. DO NOT EDIT. + +package mocks + +import ( + client "github.com/cosmos/cosmos-sdk/client" + cosmosaccount "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + + cosmosclient "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" + + mock "github.com/stretchr/testify/mock" + + types "github.com/cosmos/cosmos-sdk/types" +) + +// CosmosClient is an autogenerated mock type for the CosmosClient type +type CosmosClient struct { + mock.Mock +} + +// Account provides a mock function with given fields: accountName +func (_m *CosmosClient) Account(accountName string) (cosmosaccount.Account, error) { + ret := _m.Called(accountName) + + var r0 cosmosaccount.Account + if rf, ok := ret.Get(0).(func(string) cosmosaccount.Account); ok { + r0 = rf(accountName) + } else { + r0 = ret.Get(0).(cosmosaccount.Account) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(accountName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Address provides a mock function with given fields: accountName +func (_m *CosmosClient) Address(accountName string) (types.AccAddress, error) { + ret := _m.Called(accountName) + + var r0 types.AccAddress + if rf, ok := ret.Get(0).(func(string) types.AccAddress); ok { + r0 = rf(accountName) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(types.AccAddress) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(string) error); ok { + r1 = rf(accountName) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastTx provides a mock function with given fields: accountName, msgs +func (_m *CosmosClient) BroadcastTx(accountName string, msgs ...types.Msg) (cosmosclient.Response, error) { + _va := make([]interface{}, len(msgs)) + for _i := range msgs { + _va[_i] = msgs[_i] + } + var _ca []interface{} + _ca = append(_ca, accountName) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 cosmosclient.Response + if rf, ok := ret.Get(0).(func(string, ...types.Msg) cosmosclient.Response); ok { + r0 = rf(accountName, msgs...) + } else { + r0 = ret.Get(0).(cosmosclient.Response) + } + + var r1 error + if rf, ok := ret.Get(1).(func(string, ...types.Msg) error); ok { + r1 = rf(accountName, msgs...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// BroadcastTxWithProvision provides a mock function with given fields: accountName, msgs +func (_m *CosmosClient) BroadcastTxWithProvision(accountName string, msgs ...types.Msg) (uint64, func() (cosmosclient.Response, error), error) { + _va := make([]interface{}, len(msgs)) + for _i := range msgs { + _va[_i] = msgs[_i] + } + var _ca []interface{} + _ca = append(_ca, accountName) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 uint64 + if rf, ok := ret.Get(0).(func(string, ...types.Msg) uint64); ok { + r0 = rf(accountName, msgs...) + } else { + r0 = ret.Get(0).(uint64) + } + + var r1 func() (cosmosclient.Response, error) + if rf, ok := ret.Get(1).(func(string, ...types.Msg) func() (cosmosclient.Response, error)); ok { + r1 = rf(accountName, msgs...) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(func() (cosmosclient.Response, error)) + } + } + + var r2 error + if rf, ok := ret.Get(2).(func(string, ...types.Msg) error); ok { + r2 = rf(accountName, msgs...) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// Context provides a mock function with given fields: +func (_m *CosmosClient) Context() client.Context { + ret := _m.Called() + + var r0 client.Context + if rf, ok := ret.Get(0).(func() client.Context); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(client.Context) + } + + return r0 +} diff --git a/ignite/services/network/mocks/launch_client.go b/ignite/services/network/mocks/launch_client.go new file mode 100644 index 0000000000..83821be397 --- /dev/null +++ b/ignite/services/network/mocks/launch_client.go @@ -0,0 +1,348 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/spn/x/launch/types" +) + +// LaunchClient is an autogenerated mock type for the LaunchClient type +type LaunchClient struct { + mock.Mock +} + +// Chain provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) Chain(ctx context.Context, in *types.QueryGetChainRequest, opts ...grpc.CallOption) (*types.QueryGetChainResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetChainResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetChainRequest, ...grpc.CallOption) *types.QueryGetChainResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetChainResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetChainRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ChainAll provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) ChainAll(ctx context.Context, in *types.QueryAllChainRequest, opts ...grpc.CallOption) (*types.QueryAllChainResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllChainResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllChainRequest, ...grpc.CallOption) *types.QueryAllChainResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllChainResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllChainRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GenesisAccount provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) GenesisAccount(ctx context.Context, in *types.QueryGetGenesisAccountRequest, opts ...grpc.CallOption) (*types.QueryGetGenesisAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetGenesisAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetGenesisAccountRequest, ...grpc.CallOption) *types.QueryGetGenesisAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetGenesisAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetGenesisAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GenesisAccountAll provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) GenesisAccountAll(ctx context.Context, in *types.QueryAllGenesisAccountRequest, opts ...grpc.CallOption) (*types.QueryAllGenesisAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllGenesisAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllGenesisAccountRequest, ...grpc.CallOption) *types.QueryAllGenesisAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllGenesisAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllGenesisAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GenesisValidator provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) GenesisValidator(ctx context.Context, in *types.QueryGetGenesisValidatorRequest, opts ...grpc.CallOption) (*types.QueryGetGenesisValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetGenesisValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetGenesisValidatorRequest, ...grpc.CallOption) *types.QueryGetGenesisValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetGenesisValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetGenesisValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GenesisValidatorAll provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) GenesisValidatorAll(ctx context.Context, in *types.QueryAllGenesisValidatorRequest, opts ...grpc.CallOption) (*types.QueryAllGenesisValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllGenesisValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllGenesisValidatorRequest, ...grpc.CallOption) *types.QueryAllGenesisValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllGenesisValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllGenesisValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Params provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryParamsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryParamsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Request provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) Request(ctx context.Context, in *types.QueryGetRequestRequest, opts ...grpc.CallOption) (*types.QueryGetRequestResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetRequestResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetRequestRequest, ...grpc.CallOption) *types.QueryGetRequestResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetRequestResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetRequestRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RequestAll provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) RequestAll(ctx context.Context, in *types.QueryAllRequestRequest, opts ...grpc.CallOption) (*types.QueryAllRequestResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllRequestResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllRequestRequest, ...grpc.CallOption) *types.QueryAllRequestResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllRequestResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllRequestRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// VestingAccount provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) VestingAccount(ctx context.Context, in *types.QueryGetVestingAccountRequest, opts ...grpc.CallOption) (*types.QueryGetVestingAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetVestingAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetVestingAccountRequest, ...grpc.CallOption) *types.QueryGetVestingAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetVestingAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetVestingAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// VestingAccountAll provides a mock function with given fields: ctx, in, opts +func (_m *LaunchClient) VestingAccountAll(ctx context.Context, in *types.QueryAllVestingAccountRequest, opts ...grpc.CallOption) (*types.QueryAllVestingAccountResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllVestingAccountResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllVestingAccountRequest, ...grpc.CallOption) *types.QueryAllVestingAccountResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllVestingAccountResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllVestingAccountRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/ignite/services/network/mocks/profile_client.go b/ignite/services/network/mocks/profile_client.go new file mode 100644 index 0000000000..68ead6cafb --- /dev/null +++ b/ignite/services/network/mocks/profile_client.go @@ -0,0 +1,198 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/spn/x/profile/types" +) + +// ProfileClient is an autogenerated mock type for the ProfileClient type +type ProfileClient struct { + mock.Mock +} + +// Coordinator provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) Coordinator(ctx context.Context, in *types.QueryGetCoordinatorRequest, opts ...grpc.CallOption) (*types.QueryGetCoordinatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetCoordinatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetCoordinatorRequest, ...grpc.CallOption) *types.QueryGetCoordinatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetCoordinatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetCoordinatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CoordinatorAll provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) CoordinatorAll(ctx context.Context, in *types.QueryAllCoordinatorRequest, opts ...grpc.CallOption) (*types.QueryAllCoordinatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllCoordinatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllCoordinatorRequest, ...grpc.CallOption) *types.QueryAllCoordinatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllCoordinatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllCoordinatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CoordinatorByAddress provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) CoordinatorByAddress(ctx context.Context, in *types.QueryGetCoordinatorByAddressRequest, opts ...grpc.CallOption) (*types.QueryGetCoordinatorByAddressResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetCoordinatorByAddressResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetCoordinatorByAddressRequest, ...grpc.CallOption) *types.QueryGetCoordinatorByAddressResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetCoordinatorByAddressResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetCoordinatorByAddressRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// Validator provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) Validator(ctx context.Context, in *types.QueryGetValidatorRequest, opts ...grpc.CallOption) (*types.QueryGetValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetValidatorRequest, ...grpc.CallOption) *types.QueryGetValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ValidatorAll provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) ValidatorAll(ctx context.Context, in *types.QueryAllValidatorRequest, opts ...grpc.CallOption) (*types.QueryAllValidatorResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllValidatorResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllValidatorRequest, ...grpc.CallOption) *types.QueryAllValidatorResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllValidatorResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllValidatorRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ValidatorByOperatorAddress provides a mock function with given fields: ctx, in, opts +func (_m *ProfileClient) ValidatorByOperatorAddress(ctx context.Context, in *types.QueryGetValidatorByOperatorAddressRequest, opts ...grpc.CallOption) (*types.QueryGetValidatorByOperatorAddressResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetValidatorByOperatorAddressResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetValidatorByOperatorAddressRequest, ...grpc.CallOption) *types.QueryGetValidatorByOperatorAddressResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetValidatorByOperatorAddressResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetValidatorByOperatorAddressRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/ignite/services/network/mocks/reward_client.go b/ignite/services/network/mocks/reward_client.go new file mode 100644 index 0000000000..83810b40de --- /dev/null +++ b/ignite/services/network/mocks/reward_client.go @@ -0,0 +1,108 @@ +// Code generated by mockery v2.10.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + grpc "google.golang.org/grpc" + + mock "github.com/stretchr/testify/mock" + + types "github.com/tendermint/spn/x/reward/types" +) + +// RewardClient is an autogenerated mock type for the RewardClient type +type RewardClient struct { + mock.Mock +} + +// Params provides a mock function with given fields: ctx, in, opts +func (_m *RewardClient) Params(ctx context.Context, in *types.QueryParamsRequest, opts ...grpc.CallOption) (*types.QueryParamsResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryParamsResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) *types.QueryParamsResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryParamsResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryParamsRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RewardPool provides a mock function with given fields: ctx, in, opts +func (_m *RewardClient) RewardPool(ctx context.Context, in *types.QueryGetRewardPoolRequest, opts ...grpc.CallOption) (*types.QueryGetRewardPoolResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryGetRewardPoolResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryGetRewardPoolRequest, ...grpc.CallOption) *types.QueryGetRewardPoolResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryGetRewardPoolResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryGetRewardPoolRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RewardPoolAll provides a mock function with given fields: ctx, in, opts +func (_m *RewardClient) RewardPoolAll(ctx context.Context, in *types.QueryAllRewardPoolRequest, opts ...grpc.CallOption) (*types.QueryAllRewardPoolResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *types.QueryAllRewardPoolResponse + if rf, ok := ret.Get(0).(func(context.Context, *types.QueryAllRewardPoolRequest, ...grpc.CallOption) *types.QueryAllRewardPoolResponse); ok { + r0 = rf(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.QueryAllRewardPoolResponse) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *types.QueryAllRewardPoolRequest, ...grpc.CallOption) error); ok { + r1 = rf(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/ignite/services/network/network.go b/ignite/services/network/network.go index b4810354de..756dbf202d 100644 --- a/ignite/services/network/network.go +++ b/ignite/services/network/network.go @@ -4,20 +4,39 @@ import ( "context" "strconv" - "github.com/pkg/errors" - + "github.com/cosmos/cosmos-sdk/client" + sdktypes "github.com/cosmos/cosmos-sdk/types" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" "github.com/ignite-hq/cli/ignite/pkg/events" + "github.com/pkg/errors" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + profiletypes "github.com/tendermint/spn/x/profile/types" + rewardtypes "github.com/tendermint/spn/x/reward/types" ) +//go:generate mockery --name CosmosClient --case underscore +type CosmosClient interface { + Account(accountName string) (cosmosaccount.Account, error) + Address(accountName string) (sdktypes.AccAddress, error) + Context() client.Context + BroadcastTx(accountName string, msgs ...sdktypes.Msg) (cosmosclient.Response, error) + BroadcastTxWithProvision(accountName string, msgs ...sdktypes.Msg) (gas uint64, broadcast func() (cosmosclient.Response, error), err error) +} + // Network is network builder. type Network struct { - ev events.Bus - cosmos cosmosclient.Client - account cosmosaccount.Account + ev events.Bus + cosmos CosmosClient + account cosmosaccount.Account + campaignQuery campaigntypes.QueryClient + launchQuery launchtypes.QueryClient + profileQuery profiletypes.QueryClient + rewardQuery rewardtypes.QueryClient } +//go:generate mockery --name Chain --case underscore type Chain interface { ID() (string, error) ChainID() (string, error) @@ -31,27 +50,56 @@ type Chain interface { ConfigTOMLPath() (string, error) NodeID(ctx context.Context) (string, error) CacheBinary(launchID uint64) error + ResetGenesisTime() error } type Option func(*Network) +func WithCampaignQueryClient(client campaigntypes.QueryClient) Option { + return func(n *Network) { + n.campaignQuery = client + } +} + +func WithProfileQueryClient(client profiletypes.QueryClient) Option { + return func(n *Network) { + n.profileQuery = client + } +} + +func WithLaunchQueryClient(client launchtypes.QueryClient) Option { + return func(n *Network) { + n.launchQuery = client + } +} + +func WithRewardQueryClient(client rewardtypes.QueryClient) Option { + return func(n *Network) { + n.rewardQuery = client + } +} + // CollectEvents collects events from the network builder. func CollectEvents(ev events.Bus) Option { - return func(b *Network) { - b.ev = ev + return func(n *Network) { + n.ev = ev } } // New creates a Builder. -func New(cosmos cosmosclient.Client, account cosmosaccount.Account, options ...Option) (Network, error) { +func New(cosmos CosmosClient, account cosmosaccount.Account, options ...Option) Network { n := Network{ - cosmos: cosmos, - account: account, + cosmos: cosmos, + account: account, + campaignQuery: campaigntypes.NewQueryClient(cosmos.Context()), + launchQuery: launchtypes.NewQueryClient(cosmos.Context()), + profileQuery: profiletypes.NewQueryClient(cosmos.Context()), + rewardQuery: rewardtypes.NewQueryClient(cosmos.Context()), } for _, opt := range options { opt(&n) } - return n, nil + return n } func ParseID(id string) (uint64, error) { diff --git a/ignite/services/network/network_test.go b/ignite/services/network/network_test.go index 99d079a3d7..2909d02d42 100644 --- a/ignite/services/network/network_test.go +++ b/ignite/services/network/network_test.go @@ -4,9 +4,23 @@ import ( "errors" "testing" + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + "github.com/ignite-hq/cli/ignite/services/network/testutil" "github.com/stretchr/testify/require" ) +func newSuite(account cosmosaccount.Account) (testutil.Suite, Network) { + suite := testutil.NewSuite() + return suite, New( + suite.CosmosClientMock, + account, + WithCampaignQueryClient(suite.CampaignQueryMock), + WithLaunchQueryClient(suite.LaunchQueryMock), + WithProfileQueryClient(suite.ProfileQueryMock), + WithRewardQueryClient(suite.RewardClient), + ) +} + func TestParseID(t *testing.T) { tests := []struct { name string diff --git a/ignite/services/network/publish.go b/ignite/services/network/publish.go index 207da32e0c..82d1f2d739 100644 --- a/ignite/services/network/publish.go +++ b/ignite/services/network/publish.go @@ -4,14 +4,13 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - campaigntypes "github.com/tendermint/spn/x/campaign/types" - launchtypes "github.com/tendermint/spn/x/launch/types" - profiletypes "github.com/tendermint/spn/x/profile/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + profiletypes "github.com/tendermint/spn/x/profile/types" ) // publishOptions holds info about how to create a chain. @@ -120,8 +119,7 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption) n.ev.Send(events.New(events.StatusOngoing, "Publishing the network")) - _, err = profiletypes. - NewQueryClient(n.cosmos.Context). + _, err = n.profileQuery. CoordinatorByAddress(ctx, &profiletypes.QueryGetCoordinatorByAddressRequest{ Address: coordinatorAddress, }) @@ -140,8 +138,7 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption) } if campaignID != 0 { - _, err = campaigntypes. - NewQueryClient(n.cosmos.Context). + _, err = n.campaignQuery. Campaign(ctx, &campaigntypes.QueryGetCampaignRequest{ CampaignID: o.campaignID, }) diff --git a/ignite/services/network/publish_test.go b/ignite/services/network/publish_test.go new file mode 100644 index 0000000000..ea8c361b89 --- /dev/null +++ b/ignite/services/network/publish_test.go @@ -0,0 +1,758 @@ +package network + +import ( + "context" + "encoding/json" + "errors" + "net/http" + "net/http/httptest" + "testing" + + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + profiletypes "github.com/tendermint/spn/x/profile/types" +) + +func startGenesisTestServer(genesis cosmosutil.ChainGenesis) *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + encodedGenesis, _ := json.Marshal(genesis) + w.Write(encodedGenesis) + })) +} + +func startInvalidJSONServer() *httptest.Server { + return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("invalid json")) + })) +} + +func TestPublish(t *testing.T) { + t.Run("publish chain", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + + t.Run("publish chain with pre created campaign", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CampaignQueryMock. + On( + "Campaign", + context.Background(), + &campaigntypes.QueryGetCampaignRequest{ + CampaignID: testutil.CampaignID, + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock, WithCampaign(testutil.CampaignID)) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + + t.Run("publish chain with custom genesis", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + customGenesisChainID = "test-custom-1" + customGenesisHash = "72a80a32e33513cd74423354502cef035e96b0bff59c754646b453b201d12d07" + gts = startGenesisTestServer(cosmosutil.ChainGenesis{ChainID: customGenesisChainID}) + suite, network = newSuite(account) + ) + defer gts.Close() + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: customGenesisChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: gts.URL, + GenesisHash: customGenesisHash, + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock, WithCustomGenesis(gts.URL)) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + + t.Run("publish chain with custom chain id", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock, WithChainID(testutil.ChainID)) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + + t.Run("publish chain with mainnet", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + customGenesisChainID = "test-custom-1" + gts = startGenesisTestServer(cosmosutil.ChainGenesis{ChainID: customGenesisChainID}) + suite, network = newSuite(account) + ) + defer gts.Close() + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgInitializeMainnet{ + Coordinator: account.Address(networktypes.SPN), + CampaignID: testutil.CampaignID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + MainnetChainID: testutil.ChainID, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgInitializeMainnetResponse{ + MainnetID: testutil.MainnetID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Times(2) + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Times(2) + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, mainnetID, publishError := network.Publish(context.Background(), suite.ChainMock, Mainnet()) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + require.Equal(t, testutil.MainnetID, mainnetID) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain with mainnet, failed to initialize mainnet", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to initialize mainnet") + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgInitializeMainnet{ + Coordinator: account.Address(networktypes.SPN), + CampaignID: testutil.CampaignID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + MainnetChainID: testutil.ChainID, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgInitializeMainnetResponse{ + MainnetID: testutil.MainnetID, + }), expectedError). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Times(2) + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Times(2) + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock, Mainnet()) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain with custom genesis, failed to parse custom genesis", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + gts = startInvalidJSONServer() + expectedError = errors.New("cannot unmarshal the chain genesis file: invalid character 'i' looking for beginning of value") + ) + defer gts.Close() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock, WithCustomGenesis(gts.URL)) + require.Error(t, publishError) + require.Equal(t, expectedError.Error(), publishError.Error()) + suite.AssertAllMocks(t) + }) + + t.Run("publish chain with coordinator creation", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ProfileQueryMock. + On("CoordinatorByAddress", mock.Anything, &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &profiletypes.MsgCreateCoordinator{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(testutil.NewResponse(&profiletypes.MsgCreateCoordinatorResponse{}), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to fetch coordinator profile", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to fetch coordinator") + ) + + suite.ProfileQueryMock. + On("CoordinatorByAddress", mock.Anything, &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }). + Return(nil, expectedError). + Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to read chain id", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to get chainID") + ) + + suite.ChainMock. + On("ChainID"). + Return("", expectedError). + Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to fetch existed campaign", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CampaignQueryMock. + On("Campaign", mock.Anything, &campaigntypes.QueryGetCampaignRequest{ + CampaignID: testutil.CampaignID, + }). + Return(nil, cosmoserror.ErrNotFound). + Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock, WithCampaign(testutil.CampaignID)) + require.Error(t, publishError) + require.Equal(t, cosmoserror.ErrNotFound, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to create campaign", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to create") + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), expectedError). + Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to create chain", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to create chain") + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), expectedError). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) + + t.Run("failed to publish chain, failed to cache binary", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + expectedError = errors.New("failed to cache binary") + ) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock. + On("CacheBinary", testutil.LaunchID). + Return(expectedError). + Once() + + _, _, _, publishError := network.Publish(context.Background(), suite.ChainMock) + require.Error(t, publishError) + require.Equal(t, expectedError, publishError) + suite.AssertAllMocks(t) + }) +} diff --git a/ignite/services/network/queries.go b/ignite/services/network/queries.go index 8d971b6792..418800d01b 100644 --- a/ignite/services/network/queries.go +++ b/ignite/services/network/queries.go @@ -5,15 +5,14 @@ import ( "sort" "sync" + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/pkg/events" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" "github.com/pkg/errors" campaigntypes "github.com/tendermint/spn/x/campaign/types" launchtypes "github.com/tendermint/spn/x/launch/types" rewardtypes "github.com/tendermint/spn/x/reward/types" "golang.org/x/sync/errgroup" - - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" - "github.com/ignite-hq/cli/ignite/pkg/events" - "github.com/ignite-hq/cli/ignite/services/network/networktypes" ) var ( @@ -25,7 +24,7 @@ var ( func (n Network) ChainLaunch(ctx context.Context, id uint64) (networktypes.ChainLaunch, error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching chain information")) - res, err := launchtypes.NewQueryClient(n.cosmos.Context). + res, err := n.launchQuery. Chain(ctx, &launchtypes.QueryGetChainRequest{ LaunchID: id, @@ -43,7 +42,7 @@ func (n Network) ChainLaunchesWithReward(ctx context.Context) ([]networktypes.Ch g, ctx := errgroup.WithContext(ctx) n.ev.Send(events.New(events.StatusOngoing, "Fetching chains information")) - res, err := launchtypes.NewQueryClient(n.cosmos.Context). + res, err := n.launchQuery. ChainAll(ctx, &launchtypes.QueryAllChainRequest{}) if err != nil { return nil, err @@ -102,7 +101,7 @@ func (n Network) GenesisInformation(ctx context.Context, launchID uint64) (gi ne // GenesisAccounts returns the list of approved genesis accounts for a launch from SPN func (n Network) GenesisAccounts(ctx context.Context, launchID uint64) (genAccs []networktypes.GenesisAccount, err error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching genesis accounts")) - res, err := launchtypes.NewQueryClient(n.cosmos.Context). + res, err := n.launchQuery. GenesisAccountAll(ctx, &launchtypes.QueryAllGenesisAccountRequest{ LaunchID: launchID, @@ -122,7 +121,7 @@ func (n Network) GenesisAccounts(ctx context.Context, launchID uint64) (genAccs // VestingAccounts returns the list of approved genesis vesting accounts for a launch from SPN func (n Network) VestingAccounts(ctx context.Context, launchID uint64) (vestingAccs []networktypes.VestingAccount, err error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching genesis vesting accounts")) - res, err := launchtypes.NewQueryClient(n.cosmos.Context). + res, err := n.launchQuery. VestingAccountAll(ctx, &launchtypes.QueryAllVestingAccountRequest{ LaunchID: launchID, @@ -147,7 +146,7 @@ func (n Network) VestingAccounts(ctx context.Context, launchID uint64) (vestingA // GenesisValidators returns the list of approved genesis validators for a launch from SPN func (n Network) GenesisValidators(ctx context.Context, launchID uint64) (genVals []networktypes.GenesisValidator, err error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching genesis validators")) - res, err := launchtypes.NewQueryClient(n.cosmos.Context). + res, err := n.launchQuery. GenesisValidatorAll(ctx, &launchtypes.QueryAllGenesisValidatorRequest{ LaunchID: launchID, @@ -167,7 +166,7 @@ func (n Network) GenesisValidators(ctx context.Context, launchID uint64) (genVal // MainnetAccounts returns the list of campaign mainnet accounts for a launch from SPN func (n Network) MainnetAccounts(ctx context.Context, campaignID uint64) (genAccs []networktypes.MainnetAccount, err error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching campaign mainnet accounts")) - res, err := campaigntypes.NewQueryClient(n.cosmos.Context). + res, err := n.campaignQuery. MainnetAccountAll(ctx, &campaigntypes.QueryAllMainnetAccountRequest{ CampaignID: campaignID, @@ -187,7 +186,7 @@ func (n Network) MainnetAccounts(ctx context.Context, campaignID uint64) (genAcc // MainnetVestingAccounts returns the list of campaign mainnet vesting accounts for a launch from SPN func (n Network) MainnetVestingAccounts(ctx context.Context, campaignID uint64) (genAccs []networktypes.MainnetVestingAccount, err error) { n.ev.Send(events.New(events.StatusOngoing, "Fetching campaign mainnet vesting accounts")) - res, err := campaigntypes.NewQueryClient(n.cosmos.Context). + res, err := n.campaignQuery. MainnetVestingAccountAll(ctx, &campaigntypes.QueryAllMainnetVestingAccountRequest{ CampaignID: campaignID, @@ -206,7 +205,7 @@ func (n Network) MainnetVestingAccounts(ctx context.Context, campaignID uint64) // ChainReward fetches the chain reward from SPN by launch id func (n Network) ChainReward(ctx context.Context, launchID uint64) (rewardtypes.RewardPool, error) { - res, err := rewardtypes.NewQueryClient(n.cosmos.Context). + res, err := n.rewardQuery. RewardPool(ctx, &rewardtypes.QueryGetRewardPoolRequest{ LaunchID: launchID, diff --git a/ignite/services/network/request.go b/ignite/services/network/request.go index c64f9b5847..0b394bc2d7 100644 --- a/ignite/services/network/request.go +++ b/ignite/services/network/request.go @@ -4,10 +4,9 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - launchtypes "github.com/tendermint/spn/x/launch/types" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + launchtypes "github.com/tendermint/spn/x/launch/types" ) // Reviewal keeps a request's reviewal. @@ -34,7 +33,7 @@ func RejectRequest(requestID uint64) Reviewal { // Requests fetches all the chain requests from SPN by launch id func (n Network) Requests(ctx context.Context, launchID uint64) ([]launchtypes.Request, error) { - res, err := launchtypes.NewQueryClient(n.cosmos.Context).RequestAll(ctx, &launchtypes.QueryAllRequestRequest{ + res, err := n.launchQuery.RequestAll(ctx, &launchtypes.QueryAllRequestRequest{ LaunchID: launchID, }) if err != nil { @@ -45,7 +44,7 @@ func (n Network) Requests(ctx context.Context, launchID uint64) ([]launchtypes.R // Request fetches the chain request from SPN by launch and request id func (n Network) Request(ctx context.Context, launchID, requestID uint64) (launchtypes.Request, error) { - res, err := launchtypes.NewQueryClient(n.cosmos.Context).Request(ctx, &launchtypes.QueryGetRequestRequest{ + res, err := n.launchQuery.Request(ctx, &launchtypes.QueryGetRequestRequest{ LaunchID: launchID, RequestID: requestID, }) diff --git a/ignite/services/network/reward_test.go b/ignite/services/network/reward_test.go new file mode 100644 index 0000000000..0b5e95b2cb --- /dev/null +++ b/ignite/services/network/reward_test.go @@ -0,0 +1,73 @@ +package network + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/require" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" + rewardtypes "github.com/tendermint/spn/x/reward/types" +) + +func TestSetReward(t *testing.T) { + t.Run("successfully set reward", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + coins = sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt))) + lastRewarHeight = int64(10) + ) + + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &rewardtypes.MsgSetRewards{ + Provider: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + Coins: coins, + LastRewardHeight: lastRewarHeight, + }, + ). + Return(testutil.NewResponse(&rewardtypes.MsgSetRewardsResponse{ + PreviousCoins: nil, + PreviousLastRewardHeight: lastRewarHeight - 1, + NewCoins: coins, + NewLastRewardHeight: lastRewarHeight, + }), nil). + Once() + + setRewardError := network.SetReward(testutil.LaunchID, lastRewarHeight, coins) + require.NoError(t, setRewardError) + suite.AssertAllMocks(t) + }) + t.Run("failed to set reward, failed to broadcast set reward tx", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + coins = sdk.NewCoins(sdk.NewCoin(TestDenom, sdk.NewInt(TestAmountInt))) + lastRewarHeight = int64(10) + expectedErr = errors.New("failed to set reward") + ) + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &rewardtypes.MsgSetRewards{ + Provider: account.Address(networktypes.SPN), + LaunchID: testutil.LaunchID, + Coins: coins, + LastRewardHeight: lastRewarHeight, + }, + ). + Return(testutil.NewResponse(&rewardtypes.MsgSetRewardsResponse{}), expectedErr). + Once() + setRewardError := network.SetReward(testutil.LaunchID, lastRewarHeight, coins) + require.Error(t, setRewardError) + require.Equal(t, expectedErr, setRewardError) + suite.AssertAllMocks(t) + }) +} diff --git a/ignite/services/network/testutil/account.go b/ignite/services/network/testutil/account.go new file mode 100644 index 0000000000..feeaf7d60b --- /dev/null +++ b/ignite/services/network/testutil/account.go @@ -0,0 +1,21 @@ +package testutil + +import ( + "testing" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + "github.com/stretchr/testify/assert" +) + +const ( + TestAccountName = "test" +) + +// NewTestAccount creates an account for test purposes using inmemory keyring backend +func NewTestAccount(t *testing.T, name string) cosmosaccount.Account { + r, err := cosmosaccount.NewInMemory() + assert.NoError(t, err) + account, _, err := r.Create(name) + assert.NoError(t, err) + return account +} diff --git a/ignite/services/network/testutil/chain.go b/ignite/services/network/testutil/chain.go new file mode 100644 index 0000000000..5f3d44ee1b --- /dev/null +++ b/ignite/services/network/testutil/chain.go @@ -0,0 +1,17 @@ +package testutil + +const ( + ChainSourceHash = "testhash" + ChainSourceURL = "http://example.com/test" + ChainName = "test" + ChainID = "test-1" + TCPAddress = "1.2.3.4" + NodeID = "9b1f4adbfb0c0b513040d914bfb717303c0eaa71" + PeerAddress = "9b1f4adbfb0c0b513040d914bfb717303c0eaa71@1.2.3.4" +) + +const ( + LaunchID = uint64(1) + CampaignID = uint64(1) + MainnetID = uint64(1) +) diff --git a/ignite/services/network/testutil/genesis.go b/ignite/services/network/testutil/genesis.go new file mode 100644 index 0000000000..db88820b75 --- /dev/null +++ b/ignite/services/network/testutil/genesis.go @@ -0,0 +1,59 @@ +package testutil + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +type ( + Genesis struct { + ChainID string `json:"chain_id"` + AppState AppState `json:"app_state"` + } + + AppState struct { + Auth Auth `json:"auth"` + Staking Staking `json:"staking"` + } + + Auth struct { + Accounts []GenesisAccount `json:"accounts"` + } + + GenesisAccount struct { + Address string `json:"address"` + } + + Staking struct { + Params StakingParams `json:"params"` + } + + StakingParams struct { + BondDenom string `json:"bond_denom"` + } +) + +// NewGenesis creates easily modifiable genesis object for testing purposes +func NewGenesis(chainID string) *Genesis { + return &Genesis{ChainID: chainID} +} + +// AddAccount adds account to the genesis +func (g *Genesis) AddAccount(address string) *Genesis { + g.AppState.Auth.Accounts = append(g.AppState.Auth.Accounts, GenesisAccount{Address: address}) + return g +} + +// SaveTo saves genesis json representation to the specified directory and returns full path +func (g *Genesis) SaveTo(t *testing.T, dir string) string { + encoded, err := json.Marshal(g) + assert.NoError(t, err) + savePath := filepath.Join(dir, "genesis.json") + err = os.WriteFile(savePath, encoded, 0666) + assert.NoError(t, err) + return savePath +} diff --git a/ignite/services/network/testutil/gentx.go b/ignite/services/network/testutil/gentx.go new file mode 100644 index 0000000000..7b5b139bcd --- /dev/null +++ b/ignite/services/network/testutil/gentx.go @@ -0,0 +1,68 @@ +package testutil + +import ( + "encoding/json" + "os" + "path/filepath" + "testing" + + "github.com/stretchr/testify/assert" +) + +type ( + Gentx struct { + Body Body `json:"body"` + } + + Body struct { + Messages []Message `json:"messages"` + Memo string `json:"memo"` + } + + Message struct { + DelegatorAddress string `json:"delegator_address"` + ValidatorAddress string `json:"validator_address"` + PubKey MessagePubKey `json:"pubkey"` + Value MessageValue `json:"value"` + } + + MessageValue struct { + Denom string `json:"denom"` + Amount string `json:"amount"` + } + + MessagePubKey struct { + Key string `json:"key"` + } +) + +// // NewGenesis creates easily modifiable gentx object for testing purposes +func NewGentx(address, denom, amount, pubkey, memo string) *Gentx { + return &Gentx{Body: Body{ + Memo: memo, + Messages: []Message{ + { + DelegatorAddress: address, + PubKey: MessagePubKey{Key: pubkey}, + Value: MessageValue{Denom: denom, Amount: amount}, + }, + }, + }} +} + +// SaveTo saves gentx json representation to the specified directory and returns full path +func (g *Gentx) SaveTo(t *testing.T, dir string) string { + encoded, err := json.Marshal(g) + assert.NoError(t, err) + savePath := filepath.Join(dir, "gentx0.json") + err = os.WriteFile(savePath, encoded, 0666) + assert.NoError(t, err) + return savePath +} + +// JSON returns json representation of the gentx +func (g *Gentx) JSON(t *testing.T) []byte { + data, err := json.Marshal(g) + assert.NoError(t, err) + return data +} diff --git a/ignite/services/network/testutil/mocks.go b/ignite/services/network/testutil/mocks.go new file mode 100644 index 0000000000..54fd02f8cc --- /dev/null +++ b/ignite/services/network/testutil/mocks.go @@ -0,0 +1,34 @@ +package testutil + +import ( + "github.com/cosmos/cosmos-sdk/crypto/keyring" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + profiletypes "github.com/tendermint/spn/x/profile/types" + rewardtypes "github.com/tendermint/spn/x/reward/types" +) + +//go:generate mockery --name CampaignClient --case underscore --output ../mocks +type CampaignClient interface { + campaigntypes.QueryClient +} + +//go:generate mockery --name ProfileClient --case underscore --output ../mocks +type ProfileClient interface { + profiletypes.QueryClient +} + +//go:generate mockery --name LaunchClient --case underscore --output ../mocks +type LaunchClient interface { + launchtypes.QueryClient +} + +//go:generate mockery --name RewardClient --case underscore --output ../mocks +type RewardClient interface { + rewardtypes.QueryClient +} + +//go:generate mockery --name AccountInfo --case underscore --output ../mocks +type AccountInfo interface { + keyring.Info +} diff --git a/ignite/services/network/testutil/response.go b/ignite/services/network/testutil/response.go new file mode 100644 index 0000000000..1f6eabec3b --- /dev/null +++ b/ignite/services/network/testutil/response.go @@ -0,0 +1,35 @@ +package testutil + +import ( + "encoding/hex" + "strings" + + "github.com/cosmos/cosmos-sdk/codec" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + prototypes "github.com/gogo/protobuf/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" + "google.golang.org/protobuf/runtime/protoiface" +) + +// NewResponse creates cosmosclient.Response object from proto struct +// for using as a return result for a cosmosclient mock +func NewResponse(data protoiface.MessageV1) cosmosclient.Response { + marshaler := codec.NewProtoCodec(codectypes.NewInterfaceRegistry()) + anyEncoded, _ := prototypes.MarshalAny(data) + txData := &sdk.TxMsgData{Data: []*sdk.MsgData{ + { + Data: anyEncoded.Value, + //TODO: Find a better way + MsgType: strings.TrimSuffix(anyEncoded.TypeUrl, "Response"), + }, + }} + encodedTxData, _ := marshaler.Marshal(txData) + resp := cosmosclient.Response{ + Codec: marshaler, + TxResponse: &sdk.TxResponse{ + Data: hex.EncodeToString(encodedTxData), + }, + } + return resp +} diff --git a/ignite/services/network/testutil/suite.go b/ignite/services/network/testutil/suite.go new file mode 100644 index 0000000000..5829373c88 --- /dev/null +++ b/ignite/services/network/testutil/suite.go @@ -0,0 +1,42 @@ +package testutil + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/ignite-hq/cli/ignite/services/network/mocks" +) + +// Suite is a mocks container, used to write less code for tests setup +type Suite struct { + ChainMock *mocks.Chain + CosmosClientMock *mocks.CosmosClient + LaunchQueryMock *mocks.LaunchClient + CampaignQueryMock *mocks.CampaignClient + ProfileQueryMock *mocks.ProfileClient + RewardClient *mocks.RewardClient +} + +// AssertAllMocks asserts all suite mocks expectations +func (s *Suite) AssertAllMocks(t *testing.T) { + s.ChainMock.AssertExpectations(t) + s.ProfileQueryMock.AssertExpectations(t) + s.LaunchQueryMock.AssertExpectations(t) + s.CosmosClientMock.AssertExpectations(t) + s.CampaignQueryMock.AssertExpectations(t) + s.RewardClient.AssertExpectations(t) +} + +// NewSuite creates new suite with mocks +func NewSuite() Suite { + cosmos := new(mocks.CosmosClient) + cosmos.On("Context").Return(client.Context{}) + return Suite{ + ChainMock: new(mocks.Chain), + CosmosClientMock: cosmos, + LaunchQueryMock: new(mocks.LaunchClient), + CampaignQueryMock: new(mocks.CampaignClient), + ProfileQueryMock: new(mocks.ProfileClient), + RewardClient: new(mocks.RewardClient), + } +} diff --git a/integration/faucet/faucet_test.go b/integration/faucet/faucet_test.go index 372b278983..3bb78f45b9 100644 --- a/integration/faucet/faucet_test.go +++ b/integration/faucet/faucet_test.go @@ -101,7 +101,7 @@ func TestRequestCoinsFromFaucet(t *testing.T) { } func checkAccountBalance(t *testing.T, ctx context.Context, c cosmosclient.Client, accAddr string, coins []string) { - resp, err := banktypes.NewQueryClient(c.Context).AllBalances(ctx, &banktypes.QueryAllBalancesRequest{ + resp, err := banktypes.NewQueryClient(c.Context()).AllBalances(ctx, &banktypes.QueryAllBalancesRequest{ Address: accAddr, }) require.NoError(t, err) From bf9fc2b8ad5ab5499d28f71e244cb8b43d8f50fa Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 19 Apr 2022 17:09:51 -0300 Subject: [PATCH 06/30] chore: runs `make format` (#2393) --- ignite/cmd/network.go | 5 +++-- ignite/pkg/cosmosclient/cosmosclient.go | 5 +++-- ignite/services/network/campaign.go | 3 ++- ignite/services/network/join.go | 3 ++- ignite/services/network/join_test.go | 7 ++++--- ignite/services/network/launch.go | 3 ++- ignite/services/network/launch_test.go | 5 +++-- ignite/services/network/mocks/cosmos_client.go | 8 +++----- ignite/services/network/network.go | 7 ++++--- ignite/services/network/network_test.go | 3 ++- ignite/services/network/publish.go | 7 ++++--- ignite/services/network/publish_test.go | 9 +++++---- ignite/services/network/queries.go | 7 ++++--- ignite/services/network/request.go | 3 ++- ignite/services/network/reward_test.go | 3 ++- ignite/services/network/testutil/account.go | 3 ++- ignite/services/network/testutil/response.go | 3 ++- ignite/services/network/testutil/suite.go | 1 + 18 files changed, 50 insertions(+), 35 deletions(-) diff --git a/ignite/cmd/network.go b/ignite/cmd/network.go index 92eb81a6b9..f1554e0e05 100644 --- a/ignite/cmd/network.go +++ b/ignite/cmd/network.go @@ -3,6 +3,9 @@ package ignitecmd import ( "sync" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" @@ -11,8 +14,6 @@ import ( "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/pkg/errors" - "github.com/spf13/cobra" ) var ( diff --git a/ignite/pkg/cosmosclient/cosmosclient.go b/ignite/pkg/cosmosclient/cosmosclient.go index f3fca93b79..0864f0aaa0 100644 --- a/ignite/pkg/cosmosclient/cosmosclient.go +++ b/ignite/pkg/cosmosclient/cosmosclient.go @@ -28,10 +28,11 @@ import ( staking "github.com/cosmos/cosmos-sdk/x/staking/types" "github.com/gogo/protobuf/proto" prototypes "github.com/gogo/protobuf/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - "github.com/ignite-hq/cli/ignite/pkg/cosmosfaucet" "github.com/pkg/errors" rpchttp "github.com/tendermint/tendermint/rpc/client/http" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + "github.com/ignite-hq/cli/ignite/pkg/cosmosfaucet" ) // FaucetTransferEnsureDuration is the duration that BroadcastTx will wait when a faucet transfer diff --git a/ignite/services/network/campaign.go b/ignite/services/network/campaign.go index ad4241bb47..75a73e3ef3 100644 --- a/ignite/services/network/campaign.go +++ b/ignite/services/network/campaign.go @@ -5,9 +5,10 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - campaigntypes "github.com/tendermint/spn/x/campaign/types" ) type ( diff --git a/ignite/services/network/join.go b/ignite/services/network/join.go index 44137579dc..4c094f43da 100644 --- a/ignite/services/network/join.go +++ b/ignite/services/network/join.go @@ -5,13 +5,14 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network/networkchain" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - launchtypes "github.com/tendermint/spn/x/launch/types" ) type joinOptions struct { diff --git a/ignite/services/network/join_test.go b/ignite/services/network/join_test.go index 3421e7d9f9..a868640a6b 100644 --- a/ignite/services/network/join_test.go +++ b/ignite/services/network/join_test.go @@ -6,12 +6,13 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" - "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/ignite-hq/cli/ignite/services/network/testutil" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" launchtypes "github.com/tendermint/spn/x/launch/types" + + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" ) const ( diff --git a/ignite/services/network/launch.go b/ignite/services/network/launch.go index 7af2298348..183d3cae73 100644 --- a/ignite/services/network/launch.go +++ b/ignite/services/network/launch.go @@ -5,10 +5,11 @@ import ( "fmt" "time" + launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/pkg/xtime" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - launchtypes "github.com/tendermint/spn/x/launch/types" ) // LaunchParams fetches the chain launch module params from SPN diff --git a/ignite/services/network/launch_test.go b/ignite/services/network/launch_test.go index 117dab7d1b..bf3228c5ea 100644 --- a/ignite/services/network/launch_test.go +++ b/ignite/services/network/launch_test.go @@ -7,11 +7,12 @@ import ( "time" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/require" + launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/ignite-hq/cli/ignite/pkg/xtime" "github.com/ignite-hq/cli/ignite/services/network/networktypes" "github.com/ignite-hq/cli/ignite/services/network/testutil" - "github.com/stretchr/testify/require" - launchtypes "github.com/tendermint/spn/x/launch/types" ) const ( diff --git a/ignite/services/network/mocks/cosmos_client.go b/ignite/services/network/mocks/cosmos_client.go index 4c1808ee78..7660a3a4e8 100644 --- a/ignite/services/network/mocks/cosmos_client.go +++ b/ignite/services/network/mocks/cosmos_client.go @@ -4,13 +4,11 @@ package mocks import ( client "github.com/cosmos/cosmos-sdk/client" - cosmosaccount "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - - cosmosclient "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" - + types "github.com/cosmos/cosmos-sdk/types" mock "github.com/stretchr/testify/mock" - types "github.com/cosmos/cosmos-sdk/types" + cosmosaccount "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + cosmosclient "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" ) // CosmosClient is an autogenerated mock type for the CosmosClient type diff --git a/ignite/services/network/network.go b/ignite/services/network/network.go index 756dbf202d..2384a49d7b 100644 --- a/ignite/services/network/network.go +++ b/ignite/services/network/network.go @@ -6,14 +6,15 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdktypes "github.com/cosmos/cosmos-sdk/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/pkg/errors" campaigntypes "github.com/tendermint/spn/x/campaign/types" launchtypes "github.com/tendermint/spn/x/launch/types" profiletypes "github.com/tendermint/spn/x/profile/types" rewardtypes "github.com/tendermint/spn/x/reward/types" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" + "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" + "github.com/ignite-hq/cli/ignite/pkg/events" ) //go:generate mockery --name CosmosClient --case underscore diff --git a/ignite/services/network/network_test.go b/ignite/services/network/network_test.go index 2909d02d42..04b03a3108 100644 --- a/ignite/services/network/network_test.go +++ b/ignite/services/network/network_test.go @@ -4,9 +4,10 @@ import ( "errors" "testing" + "github.com/stretchr/testify/require" + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/services/network/testutil" - "github.com/stretchr/testify/require" ) func newSuite(account cosmosaccount.Account) (testutil.Suite, Network) { diff --git a/ignite/services/network/publish.go b/ignite/services/network/publish.go index 82d1f2d739..6bcc228847 100644 --- a/ignite/services/network/publish.go +++ b/ignite/services/network/publish.go @@ -4,13 +4,14 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + profiletypes "github.com/tendermint/spn/x/profile/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - campaigntypes "github.com/tendermint/spn/x/campaign/types" - launchtypes "github.com/tendermint/spn/x/launch/types" - profiletypes "github.com/tendermint/spn/x/profile/types" ) // publishOptions holds info about how to create a chain. diff --git a/ignite/services/network/publish_test.go b/ignite/services/network/publish_test.go index ea8c361b89..50aa2c71b2 100644 --- a/ignite/services/network/publish_test.go +++ b/ignite/services/network/publish_test.go @@ -8,15 +8,16 @@ import ( "net/http/httptest" "testing" - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" - "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" - "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/ignite-hq/cli/ignite/services/network/testutil" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" campaigntypes "github.com/tendermint/spn/x/campaign/types" launchtypes "github.com/tendermint/spn/x/launch/types" profiletypes "github.com/tendermint/spn/x/profile/types" + + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/ignite-hq/cli/ignite/services/network/testutil" ) func startGenesisTestServer(genesis cosmosutil.ChainGenesis) *httptest.Server { diff --git a/ignite/services/network/queries.go b/ignite/services/network/queries.go index 418800d01b..71c9727fcf 100644 --- a/ignite/services/network/queries.go +++ b/ignite/services/network/queries.go @@ -5,14 +5,15 @@ import ( "sort" "sync" - "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" - "github.com/ignite-hq/cli/ignite/pkg/events" - "github.com/ignite-hq/cli/ignite/services/network/networktypes" "github.com/pkg/errors" campaigntypes "github.com/tendermint/spn/x/campaign/types" launchtypes "github.com/tendermint/spn/x/launch/types" rewardtypes "github.com/tendermint/spn/x/reward/types" "golang.org/x/sync/errgroup" + + "github.com/ignite-hq/cli/ignite/pkg/cosmoserror" + "github.com/ignite-hq/cli/ignite/pkg/events" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" ) var ( diff --git a/ignite/services/network/request.go b/ignite/services/network/request.go index 0b394bc2d7..5cd832ec78 100644 --- a/ignite/services/network/request.go +++ b/ignite/services/network/request.go @@ -4,9 +4,10 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" + launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - launchtypes "github.com/tendermint/spn/x/launch/types" ) // Reviewal keeps a request's reviewal. diff --git a/ignite/services/network/reward_test.go b/ignite/services/network/reward_test.go index 0b5e95b2cb..f2e4a4cdd6 100644 --- a/ignite/services/network/reward_test.go +++ b/ignite/services/network/reward_test.go @@ -7,9 +7,10 @@ import ( "github.com/stretchr/testify/require" sdk "github.com/cosmos/cosmos-sdk/types" + rewardtypes "github.com/tendermint/spn/x/reward/types" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" "github.com/ignite-hq/cli/ignite/services/network/testutil" - rewardtypes "github.com/tendermint/spn/x/reward/types" ) func TestSetReward(t *testing.T) { diff --git a/ignite/services/network/testutil/account.go b/ignite/services/network/testutil/account.go index feeaf7d60b..aed2409cea 100644 --- a/ignite/services/network/testutil/account.go +++ b/ignite/services/network/testutil/account.go @@ -3,8 +3,9 @@ package testutil import ( "testing" - "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/stretchr/testify/assert" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" ) const ( diff --git a/ignite/services/network/testutil/response.go b/ignite/services/network/testutil/response.go index 1f6eabec3b..01f1bdf33a 100644 --- a/ignite/services/network/testutil/response.go +++ b/ignite/services/network/testutil/response.go @@ -8,8 +8,9 @@ import ( codectypes "github.com/cosmos/cosmos-sdk/codec/types" sdk "github.com/cosmos/cosmos-sdk/types" prototypes "github.com/gogo/protobuf/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" "google.golang.org/protobuf/runtime/protoiface" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" ) // NewResponse creates cosmosclient.Response object from proto struct diff --git a/ignite/services/network/testutil/suite.go b/ignite/services/network/testutil/suite.go index 5829373c88..8726a71d01 100644 --- a/ignite/services/network/testutil/suite.go +++ b/ignite/services/network/testutil/suite.go @@ -4,6 +4,7 @@ import ( "testing" "github.com/cosmos/cosmos-sdk/client" + "github.com/ignite-hq/cli/ignite/services/network/mocks" ) From e7f5907ead81ba27d1a6d024cb1a8554e74d711f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Wed, 20 Apr 2022 15:11:10 +0300 Subject: [PATCH 07/30] chore(cmd): silence release notifications for nightly (#2396) --- ignite/version/version.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ignite/version/version.go b/ignite/version/version.go index 873bed517e..8ff13d6043 100644 --- a/ignite/version/version.go +++ b/ignite/version/version.go @@ -18,7 +18,11 @@ import ( "github.com/ignite-hq/cli/ignite/pkg/xexec" ) -const versionDev = "development" +const ( + versionDev = "development" + versionNightly = "v0.0.0-nightly" +) + const prefix = "v" var ( @@ -34,7 +38,7 @@ var ( // CheckNext checks whether there is a new version of Starport. func CheckNext(ctx context.Context) (isAvailable bool, version string, err error) { - if Version == versionDev { + if Version == versionDev || Version == versionNightly { return false, "", nil } From bc47ee8c7a1e0ea0653c10b57b52ed58f805da94 Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Thu, 21 Apr 2022 12:14:01 +0400 Subject: [PATCH 08/30] docs: update readme with Ignite (#2398) --- ignite/templates/app/stargate/readme.md.plush | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ignite/templates/app/stargate/readme.md.plush b/ignite/templates/app/stargate/readme.md.plush index 7676842a7f..a243a60ab3 100644 --- a/ignite/templates/app/stargate/readme.md.plush +++ b/ignite/templates/app/stargate/readme.md.plush @@ -1,21 +1,21 @@ # <%= AppName %> -**<%= AppName %>** is a blockchain built using Cosmos SDK and Tendermint and created with [Starport](https://starport.com). +**<%= AppName %>** is a blockchain built using Cosmos SDK and Tendermint and created with [Ignite CLI](https://ignite.com/cli). ## Get started ``` -starport chain serve +ignite chain serve ``` `serve` command installs dependencies, builds, initializes, and starts your blockchain in development. ### Configure -Your blockchain in development can be configured with `config.yml`. To learn more, see the [Starport docs](https://docs.starport.com). +Your blockchain in development can be configured with `config.yml`. To learn more, see the [Ignite CLI docs](https://docs.ignite.com). ### Web Frontend -Starport has scaffolded a Vue.js-based web app in the `vue` directory. Run the following commands to install dependencies and start the app: +Ignite CLI has scaffolded a Vue.js-based web app in the `vue` directory. Run the following commands to install dependencies and start the app: ``` cd vue @@ -23,7 +23,7 @@ npm install npm run serve ``` -The frontend app is built using the `@starport/vue` and `@starport/vuex` packages. For details, see the [monorepo for Starport front-end development](https://github.com/tendermint/vue). +The frontend app is built using the `@starport/vue` and `@starport/vuex` packages. For details, see the [monorepo for Ignite front-end development](https://github.com/ignite-hq/web). ## Release To release a new version of your blockchain, create and push a new tag with `v` prefix. A new draft release with the configured targets will be created. @@ -39,14 +39,14 @@ After a draft release is created, make your final changes from the release page To install the latest version of your blockchain node's binary, execute the following command on your machine: ``` -curl https://get.starport.com/<%= OwnerAndRepoName %>@latest! | sudo bash +curl https://get.ignite.com/<%= OwnerAndRepoName %>@latest! | sudo bash ``` `<%= OwnerAndRepoName %>` should match the `username` and `repo_name` of the Github repository to which the source code was pushed. Learn more about [the install process](https://github.com/allinbits/starport-installer). ## Learn more -- [Starport](https://starport.com) -- [Tutorials](https://docs.starport.com/guide) -- [Starport docs](https://docs.starport.com) +- [Ignite CLI](https://ignite.com/cli) +- [Tutorials](https://docs.ignite.com/guide) +- [Ignite CLI docs](https://docs.ignite.com) - [Cosmos SDK docs](https://docs.cosmos.network) -- [Developer Chat](https://discord.gg/H6wGTY8sxw) +- [Developer Chat](https://discord.gg/ignite) From 5e25e80645bb85b7845e35e491e8393ac719574b Mon Sep 17 00:00:00 2001 From: Chris Valle Date: Tue, 26 Apr 2022 11:14:49 +0200 Subject: [PATCH 09/30] docs(tutorial): Pass in creator as an argument in CRUD txs (#2408) This is a fix to the issue: https://github.com/ignite-hq/cli/issues/2405 We pass in 'creator' as an argument in the Creating blog posts, Processing acknowledgments for sent posts, and Managing post timeouts --- docs/guide/ibc.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guide/ibc.md b/docs/guide/ibc.md index 21a4a36259..caf152ed44 100644 --- a/docs/guide/ibc.md +++ b/docs/guide/ibc.md @@ -82,19 +82,19 @@ These `ignite scaffold list` commands create CRUD code for the following transac - Creating blog posts ```go - ignite scaffold list post title content --no-message --module blog + ignite scaffold list post title content creator --no-message --module blog ``` - Processing acknowledgments for sent posts ```go - ignite scaffold list sentPost postID title chain --no-message --module blog + ignite scaffold list sentPost postID title chain creator --no-message --module blog ``` - Managing post timeouts ```go - ignite scaffold list timedoutPost title chain --no-message --module blog + ignite scaffold list timedoutPost title chain creator --no-message --module blog ``` The scaffolded code includes proto files for defining data structures, messages, messages handlers, keepers for modifying the state, and CLI commands. From c0c81a1e8a8feefa415eae908cd224cb368f1edd Mon Sep 17 00:00:00 2001 From: Denis Fadeev Date: Wed, 27 Apr 2022 12:27:21 +0400 Subject: [PATCH 10/30] docs: build from source URL (#2417) --- docs/guide/install.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/install.md b/docs/guide/install.md index 96ef340049..27bb58e2f7 100644 --- a/docs/guide/install.md +++ b/docs/guide/install.md @@ -94,8 +94,8 @@ For details on version features and changes, see the [changelog.md](https://gith To experiment with the source code, you can build from source: ```bash -git clone https://github.com/ignite-hq/ignite --depth=1 -cd ignite && make install +git clone https://github.com/ignite-hq/cli --depth=1 +cd cli && make install ``` ## Summary From 9dc7c25f0e352ef33b257051f4bb43637e6f3b58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Wed, 27 Apr 2022 12:55:57 +0300 Subject: [PATCH 11/30] feat(network/chain): add --shares to the publish cmd (#2416) * feat(network/chain): add --shares to the publish cmd * add test * force % in coins * fix % placement * fix * fix * fix --- ignite/cmd/network_chain_publish.go | 27 +++++++--- ignite/pkg/cosmosutil/coins.go | 27 ++++++++++ ignite/pkg/cosmosutil/coins_test.go | 55 +++++++++++++++++++ ignite/services/network/publish.go | 25 ++++++++- ignite/services/network/publish_test.go | 71 +++++++++++++++++++++++++ 5 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 ignite/pkg/cosmosutil/coins.go create mode 100644 ignite/pkg/cosmosutil/coins_test.go diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index c3fa9a6099..98be9cf826 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -10,9 +10,11 @@ import ( "github.com/tendermint/spn/pkg/chainid" "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + campaigntypes "github.com/tendermint/spn/x/campaign/types" ) const ( @@ -21,6 +23,7 @@ const ( flagHash = "hash" flagGenesis = "genesis" flagCampaign = "campaign" + flagShares = "shares" flagNoCheck = "no-check" flagChainID = "chain-id" flagMainnet = "mainnet" @@ -46,6 +49,7 @@ func NewNetworkChainPublish() *cobra.Command { c.Flags().Bool(flagNoCheck, false, "Skip verifying chain's integrity") c.Flags().String(flagCampaignMetadata, "", "Add a campaign metadata") c.Flags().String(flagCampaignTotalSupply, "", "Add a total of the mainnet of a campaign") + c.Flags().String(flagShares, "", "Add shares for the campaign") c.Flags().Bool(flagMainnet, false, "Initialize a mainnet campaign") c.Flags().String(flagRewardCoins, "", "Reward coins") c.Flags().Int64(flagRewardHeight, 0, "Last reward height") @@ -69,6 +73,7 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { noCheck, _ = cmd.Flags().GetBool(flagNoCheck) campaignMetadata, _ = cmd.Flags().GetString(flagCampaignMetadata) campaignTotalSupplyStr, _ = cmd.Flags().GetString(flagCampaignTotalSupply) + sharesStr, _ = cmd.Flags().GetString(flagShares) isMainnet, _ = cmd.Flags().GetBool(flagMainnet) rewardCoinsStr, _ = cmd.Flags().GetString(flagRewardCoins) rewardDuration, _ = cmd.Flags().GetInt64(flagRewardHeight) @@ -152,12 +157,7 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { initOptions = append(initOptions, networkchain.WithHome(homeDir)) - // init the chain. - c, err := nb.Chain(sourceOption, initOptions...) - if err != nil { - return err - } - + // prepare publish options publishOptions := []network.PublishOption{network.WithMetadata(campaignMetadata)} if genesisURL != "" { @@ -189,6 +189,21 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { publishOptions = append(publishOptions, network.WithTotalSupply(totalSupply)) } + if sharesStr != "" { + coins, err := cosmosutil.ParseCoinsNormalizedWithPercentageRequired(sharesStr) + if err != nil { + return err + } + + publishOptions = append(publishOptions, network.WithShares(campaigntypes.NewSharesFromCoins(coins))) + } + + // init the chain. + c, err := nb.Chain(sourceOption, initOptions...) + if err != nil { + return err + } + if noCheck { publishOptions = append(publishOptions, network.WithNoCheck()) } else if err := c.Init(cmd.Context()); err != nil { // initialize the chain for checking. diff --git a/ignite/pkg/cosmosutil/coins.go b/ignite/pkg/cosmosutil/coins.go new file mode 100644 index 0000000000..eaa448ec2c --- /dev/null +++ b/ignite/pkg/cosmosutil/coins.go @@ -0,0 +1,27 @@ +package cosmosutil + +import ( + "fmt" + "regexp" + "strings" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var rePercentageRequired = regexp.MustCompile(`^[0-9]+%`) + +// ParseCoinsNormalizedWithPercentageRequired parses coins by requiring percentages. +// format: 20%foo,50%staking +func ParseCoinsNormalizedWithPercentageRequired(coins string) (sdk.Coins, error) { + trimPercentage := func(s string) string { + return strings.ReplaceAll(s, "%", "") + } + + s := strings.Split(coins, ",") + for _, ss := range s { + if len(rePercentageRequired.FindStringIndex(ss)) == 0 { + return nil, fmt.Errorf("amount for %s has to have a %% after the number", trimPercentage(ss)) + } + } + return sdk.ParseCoinsNormalized(trimPercentage(coins)) +} diff --git a/ignite/pkg/cosmosutil/coins_test.go b/ignite/pkg/cosmosutil/coins_test.go new file mode 100644 index 0000000000..c29661cccb --- /dev/null +++ b/ignite/pkg/cosmosutil/coins_test.go @@ -0,0 +1,55 @@ +package cosmosutil_test + +import ( + "errors" + "testing" + + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" + "github.com/stretchr/testify/require" +) + +func TestValidateCoinsStrWithPercentage(t *testing.T) { + tests := []struct { + name string + coins string + parsed sdk.Coins + err error + }{ + { + "format is OK", + "20%foo,50%staking", + sdk.NewCoins(sdk.NewInt64Coin("foo", 20), sdk.NewInt64Coin("staking", 50)), + nil, + }, + { + "wrong format", + "20nova,50baz", + sdk.NewCoins(sdk.NewInt64Coin("nova", 20), sdk.NewInt64Coin("baz", 50)), + errors.New("amount for 20nova has to have a % after the number"), + }, + { + "wrong format with percentage in the beginning", + "%20nova", + sdk.NewCoins(sdk.NewInt64Coin("nova", 20)), + errors.New("amount for 20nova has to have a % after the number"), + }, + { + "wrong format with multiple percentages", + "%20%nova", + sdk.NewCoins(sdk.NewInt64Coin("nova", 20)), + errors.New("amount for 20nova has to have a % after the number"), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + coins, err := cosmosutil.ParseCoinsNormalizedWithPercentageRequired(tt.coins) + if tt.err != nil { + require.EqualError(t, err, tt.err.Error()) + } else { + require.NoError(t, err) + require.Equal(t, tt.parsed, coins) + } + }) + } +} diff --git a/ignite/services/network/publish.go b/ignite/services/network/publish.go index 6bcc228847..926bc56e7f 100644 --- a/ignite/services/network/publish.go +++ b/ignite/services/network/publish.go @@ -22,6 +22,7 @@ type publishOptions struct { noCheck bool metadata string totalSupply sdk.Coins + shares campaigntypes.Shares mainnet bool } @@ -70,6 +71,13 @@ func WithTotalSupply(totalSupply sdk.Coins) PublishOption { } } +// WithShares enables minting vouchers for shares. +func WithShares(shares campaigntypes.Shares) PublishOption { + return func(c *publishOptions) { + c.shares = shares + } +} + // Mainnet initialize a published chain into the mainnet func Mainnet() PublishOption { return func(o *publishOptions) { @@ -164,7 +172,22 @@ func (n Network) Publish(ctx context.Context, c Chain, options ...PublishOption) campaignID, nil, ) - res, err := n.cosmos.BroadcastTx(n.account.Name, msgCreateChain) + + msgs := []sdk.Msg{msgCreateChain} + + if !o.shares.Empty() { + // TODO consider moving to UpdateCampaign, but not sure, may not be relevant. + // It is better to send multiple message in a single tx too. + // consider ways to refactor to accomplish a better API and efficiency. + msgMintVouchers := campaigntypes.NewMsgMintVouchers( + n.account.Address(networktypes.SPN), + campaignID, + o.shares, + ) + msgs = append(msgs, msgMintVouchers) + } + + res, err := n.cosmos.BroadcastTx(n.account.Name, msgs...) if err != nil { return 0, 0, 0, err } diff --git a/ignite/services/network/publish_test.go b/ignite/services/network/publish_test.go index 50aa2c71b2..58bffae1b2 100644 --- a/ignite/services/network/publish_test.go +++ b/ignite/services/network/publish_test.go @@ -96,6 +96,77 @@ func TestPublish(t *testing.T) { suite.AssertAllMocks(t) }) + t.Run("publish chain with shares", func(t *testing.T) { + var ( + account = testutil.NewTestAccount(t, testutil.TestAccountName) + suite, network = newSuite(account) + ) + shares, err := campaigntypes.NewShares("20foo,50staking") + require.NoError(t, err) + + suite.ProfileQueryMock. + On( + "CoordinatorByAddress", + context.Background(), + &profiletypes.QueryGetCoordinatorByAddressRequest{ + Address: account.Address(networktypes.SPN), + }, + ). + Return(nil, nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &launchtypes.MsgCreateChain{ + Coordinator: account.Address(networktypes.SPN), + GenesisChainID: testutil.ChainID, + SourceURL: testutil.ChainSourceURL, + SourceHash: testutil.ChainSourceHash, + GenesisURL: "", + GenesisHash: "", + HasCampaign: true, + CampaignID: testutil.CampaignID, + }, + campaigntypes.NewMsgMintVouchers( + account.Address(networktypes.SPN), + testutil.CampaignID, + shares, + ), + ). + Return(testutil.NewResponse(&launchtypes.MsgCreateChainResponse{ + LaunchID: testutil.LaunchID, + }), nil). + Once() + suite.CosmosClientMock. + On( + "BroadcastTx", + account.Name, + &campaigntypes.MsgCreateCampaign{ + Coordinator: account.Address(networktypes.SPN), + CampaignName: testutil.ChainName, + Metadata: []byte{}, + }, + ). + Return(testutil.NewResponse(&campaigntypes.MsgCreateCampaignResponse{ + CampaignID: testutil.CampaignID, + }), nil). + Once() + suite.ChainMock.On("SourceHash").Return(testutil.ChainSourceHash).Once() + suite.ChainMock.On("SourceURL").Return(testutil.ChainSourceURL).Once() + suite.ChainMock.On("Name").Return(testutil.ChainName).Once() + suite.ChainMock.On("ChainID").Return(testutil.ChainID, nil).Once() + suite.ChainMock.On("CacheBinary", testutil.LaunchID).Return(nil).Once() + + launchID, campaignID, _, publishError := network.Publish(context.Background(), suite.ChainMock, + WithShares(shares), + ) + require.NoError(t, publishError) + require.Equal(t, testutil.LaunchID, launchID) + require.Equal(t, testutil.CampaignID, campaignID) + suite.AssertAllMocks(t) + }) + t.Run("publish chain with pre created campaign", func(t *testing.T) { var ( account = testutil.NewTestAccount(t, testutil.TestAccountName) From 8ba8f628f82f1ff78ef24d1e1f8d824f44d571d9 Mon Sep 17 00:00:00 2001 From: Helder Moreira Date: Wed, 27 Apr 2022 15:37:25 +0100 Subject: [PATCH 12/30] ci(docs): deploy to firebase (#2419) --- .firebaserc | 14 ++++++++ .github/workflows/docs-deploy-preview.yml | 44 +++++++++++++++++++++++ .github/workflows/docs-deploy.yml | 44 +++++++++++++++++++++++ firebase.json | 13 +++++++ 4 files changed, 115 insertions(+) create mode 100644 .firebaserc create mode 100644 .github/workflows/docs-deploy-preview.yml create mode 100644 .github/workflows/docs-deploy.yml create mode 100644 firebase.json diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000000..5acfdb1dde --- /dev/null +++ b/.firebaserc @@ -0,0 +1,14 @@ +{ + "projects": { + "default": "ignite-hq" + }, + "targets": { + "ignite-hq": { + "hosting": { + "docs.ignite.com": [ + "ignite-go-docs" + ] + } + } + } +} \ No newline at end of file diff --git a/.github/workflows/docs-deploy-preview.yml b/.github/workflows/docs-deploy-preview.yml new file mode 100644 index 0000000000..a55bfd2861 --- /dev/null +++ b/.github/workflows/docs-deploy-preview.yml @@ -0,0 +1,44 @@ +name: Docs Deploy Preview + +on: + pull_request: + paths: + - "docs/**" + +jobs: + build_and_deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache node_modules + uses: actions/cache@v2 + with: + path: docs/node_modules + key: node_modules-${{ hashFiles('**/package-lock.json') }} + + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: 16.x + cache: npm + cache-dependency-path: docs/package-lock.json + + - name: Install Dependencies + run: npm install + working-directory: ./docs + + - name: Build + run: npm run build + working-directory: ./docs + + - name: Deploy + uses: FirebaseExtended/action-hosting-deploy@v0 + with: + repoToken: "${{ secrets.GITHUB_TOKEN }}" + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_IGNITE_HQ }}" + expires: 7d + target: docs.ignite.com + projectId: ignite-hq diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml new file mode 100644 index 0000000000..559fa276f9 --- /dev/null +++ b/.github/workflows/docs-deploy.yml @@ -0,0 +1,44 @@ +name: Docs Deploy + +on: + push: + branches: + - develop + +jobs: + build_and_deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Cache node_modules + uses: actions/cache@v2 + with: + path: docs/node_modules + key: node_modules-${{ hashFiles('**/package-lock.json') }} + + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: 16.x + cache: npm + cache-dependency-path: docs/package-lock.json + + - name: Install Dependencies + run: npm install + working-directory: ./docs + + - name: Build + run: npm run build + working-directory: ./docs + + - name: Deploy + uses: FirebaseExtended/action-hosting-deploy@v0 + with: + repoToken: "${{ secrets.GITHUB_TOKEN }}" + firebaseServiceAccount: "${{ secrets.FIREBASE_SERVICE_ACCOUNT_IGNITE_HQ }}" + channelId: live + target: docs.ignite.com + projectId: ignite-hq \ No newline at end of file diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000000..7a3c3b2322 --- /dev/null +++ b/firebase.json @@ -0,0 +1,13 @@ +{ + "emulators": { + "hosting": { + "host": "localhost", + "port": "3000" + } + }, + "hosting": { + "target": "docs.ignite.com", + "public": "docs/.vuepress/dist", + "cleanUrls": true + } +} \ No newline at end of file From fb63741911a61037cbf69199a1b9980e84f929d8 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Thu, 28 Apr 2022 06:01:07 -0300 Subject: [PATCH 13/30] feat(network/request): add status to network request `list` and `show` cmds (#2387) * add status to request list * fix request show command * fix unit tests --- ignite/cmd/network_request_list.go | 15 ++++++---- ignite/pkg/xtime/unix.go | 5 ++++ .../services/network/networkchain/simulate.go | 3 +- .../networktypes/genesisinformation.go | 2 +- .../networktypes/genesisinformation_test.go | 28 +++++++++---------- .../services/network/networktypes/request.go | 28 ++++++++++++++++++- ignite/services/network/request.go | 16 +++++++---- 7 files changed, 67 insertions(+), 30 deletions(-) diff --git a/ignite/cmd/network_request_list.go b/ignite/cmd/network_request_list.go index 379b721cc8..1795f163f8 100644 --- a/ignite/cmd/network_request_list.go +++ b/ignite/cmd/network_request_list.go @@ -10,9 +10,10 @@ import ( "github.com/ignite-hq/cli/ignite/pkg/entrywriter" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" ) -var requestSummaryHeader = []string{"ID", "Type", "Content"} +var requestSummaryHeader = []string{"ID", "Status", "Type", "Content"} // NewNetworkRequestList creates a new request list command to list // requests for a chain @@ -54,13 +55,14 @@ func networkRequestListHandler(cmd *cobra.Command, args []string) error { } // renderRequestSummaries writes into the provided out, the list of summarized requests -func renderRequestSummaries(requests []launchtypes.Request, out io.Writer) error { +func renderRequestSummaries(requests []networktypes.Request, out io.Writer) error { requestEntries := make([][]string, 0) for _, request := range requests { - id := fmt.Sprintf("%d", request.RequestID) - requestType := "Unknown" - content := "" - + var ( + id = fmt.Sprintf("%d", request.RequestID) + requestType = "Unknown" + content = "" + ) switch req := request.Content.Content.(type) { case *launchtypes.RequestContent_GenesisAccount: requestType = "Add Genesis Account" @@ -102,6 +104,7 @@ func renderRequestSummaries(requests []launchtypes.Request, out io.Writer) error requestEntries = append(requestEntries, []string{ id, + request.Status, requestType, content, }) diff --git a/ignite/pkg/xtime/unix.go b/ignite/pkg/xtime/unix.go index b5f063c6f5..3d6ac0321f 100644 --- a/ignite/pkg/xtime/unix.go +++ b/ignite/pkg/xtime/unix.go @@ -19,3 +19,8 @@ func NowAfter(unix time.Duration) string { func FormatUnix(date time.Time) string { return date.Format(time.UnixDate) } + +// FormatUnixInt formats the int timestamp to unix date string +func FormatUnixInt(unix int64) string { + return FormatUnix(time.Unix(unix, 0)) +} diff --git a/ignite/services/network/networkchain/simulate.go b/ignite/services/network/networkchain/simulate.go index bfe36bc566..7df43cb365 100644 --- a/ignite/services/network/networkchain/simulate.go +++ b/ignite/services/network/networkchain/simulate.go @@ -10,7 +10,6 @@ import ( "github.com/cenkalti/backoff" "github.com/pelletier/go-toml" "github.com/pkg/errors" - launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite-hq/cli/ignite/pkg/availableport" "github.com/ignite-hq/cli/ignite/pkg/events" @@ -25,7 +24,7 @@ const ( ) // SimulateRequests simulates the genesis creation and the start of the network from the provided requests -func (c Chain) SimulateRequests(ctx context.Context, gi networktypes.GenesisInformation, reqs []launchtypes.Request) (err error) { +func (c Chain) SimulateRequests(ctx context.Context, gi networktypes.GenesisInformation, reqs []networktypes.Request) (err error) { c.ev.Send(events.New(events.StatusOngoing, "Verifying requests format")) for _, req := range reqs { // static verification of the request diff --git a/ignite/services/network/networktypes/genesisinformation.go b/ignite/services/network/networktypes/genesisinformation.go index 35bbcb7783..8cbffdb3e8 100644 --- a/ignite/services/network/networktypes/genesisinformation.go +++ b/ignite/services/network/networktypes/genesisinformation.go @@ -150,7 +150,7 @@ func (gi *GenesisInformation) RemoveGenesisValidator(address string) { } // ApplyRequest applies to the genesisInformation the changes implied by the approval of a request -func (gi GenesisInformation) ApplyRequest(request launchtypes.Request) (GenesisInformation, error) { +func (gi GenesisInformation) ApplyRequest(request Request) (GenesisInformation, error) { switch requestContent := request.Content.Content.(type) { case *launchtypes.RequestContent_GenesisAccount: // new genesis account in the genesis diff --git a/ignite/services/network/networktypes/genesisinformation_test.go b/ignite/services/network/networktypes/genesisinformation_test.go index ae597f55a6..70a1b4245a 100644 --- a/ignite/services/network/networktypes/genesisinformation_test.go +++ b/ignite/services/network/networktypes/genesisinformation_test.go @@ -150,13 +150,13 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { tests := []struct { name string gi networktypes.GenesisInformation - r launchtypes.Request + r networktypes.Request invalidRequest bool }{ { name: "genesis account request", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewGenesisAccount( 0, "spn1sgphx4vxt63xhvgp9wpewajyxeqt04twfj7gcc", @@ -167,7 +167,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "vesting account request", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewVestingAccount( 0, "spn19klee4szqpeu0laqze5srhdxtp6fuhcztdrh7c", @@ -182,7 +182,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "genesis validator request", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewGenesisValidator( 0, "spn1xnn9w76mf42t249486ss65lvga7gqs02erpw24", @@ -196,7 +196,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "genesis account: existing genesis account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewGenesisAccount( 0, "spn1g50xher44l9hjuatjdfxgv254jh2wgzfs55yu3", @@ -208,7 +208,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "genesis account: existing vesting account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewGenesisAccount( 0, "spn1gkzf4e0x6wr4djfd8h82v6cy507gy5v4spaus3", @@ -220,7 +220,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "vesting account: existing genesis account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewVestingAccount( 0, "spn1g50xher44l9hjuatjdfxgv254jh2wgzfs55yu3", @@ -236,7 +236,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "vesting account: existing vesting account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewVestingAccount( 0, "spn1gkzf4e0x6wr4djfd8h82v6cy507gy5v4spaus3", @@ -252,7 +252,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "existing genesis validator", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewGenesisValidator( 0, "spn1pquxnnpnjyl3ptz3uxs0lrs93s5ljepzq4wyp6", @@ -267,28 +267,28 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "remove genesis account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewAccountRemoval("spn1g50xher44l9hjuatjdfxgv254jh2wgzfs55yu3"), }, }, { name: "remove vesting account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewAccountRemoval("spn1gkzf4e0x6wr4djfd8h82v6cy507gy5v4spaus3"), }, }, { name: "remove genesis validator", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewValidatorRemoval("spn1pquxnnpnjyl3ptz3uxs0lrs93s5ljepzq4wyp6"), }, }, { name: "remove account: non-existent account", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewAccountRemoval("spn1pquxnnpnjyl3ptz3uxs0lrs93s5ljepzq4wyp6"), }, invalidRequest: true, @@ -296,7 +296,7 @@ func TestGenesisInformation_ApplyRequest(t *testing.T) { { name: "remove account: non-existent genesis validator", gi: genesisInformation, - r: launchtypes.Request{ + r: networktypes.Request{ Content: launchtypes.NewValidatorRemoval("spn1g50xher44l9hjuatjdfxgv254jh2wgzfs55yu3"), }, invalidRequest: true, diff --git a/ignite/services/network/networktypes/request.go b/ignite/services/network/networktypes/request.go index b60c0d394c..a95d64f6ea 100644 --- a/ignite/services/network/networktypes/request.go +++ b/ignite/services/network/networktypes/request.go @@ -6,10 +6,36 @@ import ( launchtypes "github.com/tendermint/spn/x/launch/types" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" + "github.com/ignite-hq/cli/ignite/pkg/xtime" ) +type ( + // Request represents the launch Request of a chain on SPN + Request struct { + LaunchID uint64 `json:"LaunchID"` + RequestID uint64 `json:"RequestID"` + Creator string `json:"Creator"` + CreatedAt string `json:"CreatedAt"` + Content launchtypes.RequestContent `json:"Content"` + Status string `json:"Status"` + } +) + +// ToRequest converts a request data from SPN and returns a Request object +func ToRequest(request launchtypes.Request) Request { + + return Request{ + LaunchID: request.LaunchID, + RequestID: request.RequestID, + Creator: request.Creator, + CreatedAt: xtime.FormatUnixInt(request.CreatedAt), + Content: request.Content, + Status: launchtypes.Request_Status_name[int32(request.Status)], + } +} + // VerifyRequest verifies the validity of the request from its content (static check) -func VerifyRequest(request launchtypes.Request) error { +func VerifyRequest(request Request) error { req, ok := request.Content.Content.(*launchtypes.RequestContent_GenesisValidator) if ok { err := VerifyAddValidatorRequest(req) diff --git a/ignite/services/network/request.go b/ignite/services/network/request.go index 5cd832ec78..06d628e8db 100644 --- a/ignite/services/network/request.go +++ b/ignite/services/network/request.go @@ -33,31 +33,35 @@ func RejectRequest(requestID uint64) Reviewal { } // Requests fetches all the chain requests from SPN by launch id -func (n Network) Requests(ctx context.Context, launchID uint64) ([]launchtypes.Request, error) { +func (n Network) Requests(ctx context.Context, launchID uint64) ([]networktypes.Request, error) { res, err := n.launchQuery.RequestAll(ctx, &launchtypes.QueryAllRequestRequest{ LaunchID: launchID, }) if err != nil { return nil, err } - return res.Request, nil + requests := make([]networktypes.Request, len(res.Request)) + for i, req := range res.Request { + requests[i] = networktypes.ToRequest(req) + } + return requests, nil } // Request fetches the chain request from SPN by launch and request id -func (n Network) Request(ctx context.Context, launchID, requestID uint64) (launchtypes.Request, error) { +func (n Network) Request(ctx context.Context, launchID, requestID uint64) (networktypes.Request, error) { res, err := n.launchQuery.Request(ctx, &launchtypes.QueryGetRequestRequest{ LaunchID: launchID, RequestID: requestID, }) if err != nil { - return launchtypes.Request{}, err + return networktypes.Request{}, err } - return res.Request, nil + return networktypes.ToRequest(res.Request), nil } // RequestFromIDs fetches the chain requested from SPN by launch and provided request IDs // TODO: once implemented, use the SPN query from https://github.com/tendermint/spn/issues/420 -func (n Network) RequestFromIDs(ctx context.Context, launchID uint64, requestIDs ...uint64) (reqs []launchtypes.Request, err error) { +func (n Network) RequestFromIDs(ctx context.Context, launchID uint64, requestIDs ...uint64) (reqs []networktypes.Request, err error) { for _, id := range requestIDs { req, err := n.Request(ctx, launchID, id) if err != nil { From 00fd98437b99a5214b8fbf27fdc8aa8224f1d257 Mon Sep 17 00:00:00 2001 From: Petr Ivanov Date: Thu, 28 Apr 2022 16:06:23 +0400 Subject: [PATCH 14/30] fix(cmd): bytes formatting (#2424) Co-authored-by: Petr Ivanov --- ignite/cmd/network_request_show.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ignite/cmd/network_request_show.go b/ignite/cmd/network_request_show.go index d46323efc7..fa1fd4f61a 100644 --- a/ignite/cmd/network_request_show.go +++ b/ignite/cmd/network_request_show.go @@ -56,8 +56,8 @@ func networkRequestShowHandler(cmd *cobra.Command, args []string) error { // convert the request object to YAML to be more readable // and convert the byte array fields to string. requestYaml, err := yaml.Marshal(cmd.Context(), request, - "$.content.content.genesisValidator.genTx", - "$.content.content.genesisValidator.consPubKey", + "$.Content.content.genesisValidator.genTx", + "$.Content.content.genesisValidator.consPubKey", ) if err != nil { return err From 4784cf861b4b9fed6ae8e123a5f88a5a45328a2e Mon Sep 17 00:00:00 2001 From: Aleksander Date: Thu, 28 Apr 2022 14:30:49 +0200 Subject: [PATCH 15/30] feat(cmd/scaffold): confirm when scaffolding over not staged changes (#2409) * Add confirmation when scaffolding over not staged changes Bounty address: cosmos1r9vfrfqypw4zkhkw0pja36tr9yrfqujcf9u3sw * Resolve comments --- ignite/cmd/cmd.go | 2 +- ignite/cmd/generate.go | 8 +-- ignite/cmd/scaffold.go | 55 +++++++++++++++---- ignite/pkg/xgit/xgit.go | 33 +++++++++++ integration/app/cmd_app_test.go | 21 ++++--- integration/app/cmd_ibc_test.go | 47 +++++++++------- integration/app/cmd_serve_test.go | 2 +- integration/cosmosgen/cosmosgen_test.go | 6 ++ integration/list/cmd_list_test.go | 31 ++++++----- integration/map/cmd_map_test.go | 26 +++++---- .../other_components/cmd_message_test.go | 12 ++-- .../other_components/cmd_query_test.go | 15 +++-- integration/readme.md | 4 +- integration/simulation/simapp_test.go | 11 ++-- integration/single/cmd_singleton_test.go | 16 +++--- 15 files changed, 193 insertions(+), 96 deletions(-) create mode 100644 ignite/pkg/xgit/xgit.go diff --git a/ignite/cmd/cmd.go b/ignite/cmd/cmd.go index b3b5aa814c..040244cafa 100644 --- a/ignite/cmd/cmd.go +++ b/ignite/cmd/cmd.go @@ -129,7 +129,7 @@ func getHome(cmd *cobra.Command) (home string) { func flagSetYes() *flag.FlagSet { fs := flag.NewFlagSet("", flag.ContinueOnError) - fs.Bool(flagYes, false, "Answers interactive yes/no questions with yes") + fs.BoolP(flagYes, "y", false, "Answers interactive yes/no questions with yes") return fs } diff --git a/ignite/cmd/generate.go b/ignite/cmd/generate.go index e6d37fde40..a2181e768a 100644 --- a/ignite/cmd/generate.go +++ b/ignite/cmd/generate.go @@ -17,10 +17,10 @@ Produced source code can be regenerated by running a command again and is not me } flagSetPath(c) - c.AddCommand(NewGenerateGo()) - c.AddCommand(NewGenerateVuex()) - c.AddCommand(NewGenerateDart()) - c.AddCommand(NewGenerateOpenAPI()) + c.AddCommand(addGitChangesVerifier(NewGenerateGo())) + c.AddCommand(addGitChangesVerifier(NewGenerateVuex())) + c.AddCommand(addGitChangesVerifier(NewGenerateDart())) + c.AddCommand(addGitChangesVerifier(NewGenerateOpenAPI())) return c } diff --git a/ignite/cmd/scaffold.go b/ignite/cmd/scaffold.go index 323bdfdacc..e13f11919a 100644 --- a/ignite/cmd/scaffold.go +++ b/ignite/cmd/scaffold.go @@ -1,13 +1,16 @@ package ignitecmd import ( + "errors" "fmt" + "github.com/manifoldco/promptui" "github.com/spf13/cobra" flag "github.com/spf13/pflag" "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" + "github.com/ignite-hq/cli/ignite/pkg/xgit" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) @@ -33,17 +36,17 @@ CRUD stands for "create, read, update, delete".`, } c.AddCommand(NewScaffoldChain()) - c.AddCommand(NewScaffoldModule()) - c.AddCommand(NewScaffoldList()) - c.AddCommand(NewScaffoldMap()) - c.AddCommand(NewScaffoldSingle()) - c.AddCommand(NewScaffoldType()) - c.AddCommand(NewScaffoldMessage()) - c.AddCommand(NewScaffoldQuery()) - c.AddCommand(NewScaffoldPacket()) - c.AddCommand(NewScaffoldBandchain()) - c.AddCommand(NewScaffoldVue()) - c.AddCommand(NewScaffoldFlutter()) + c.AddCommand(addGitChangesVerifier(NewScaffoldModule())) + c.AddCommand(addGitChangesVerifier(NewScaffoldList())) + c.AddCommand(addGitChangesVerifier(NewScaffoldMap())) + c.AddCommand(addGitChangesVerifier(NewScaffoldSingle())) + c.AddCommand(addGitChangesVerifier(NewScaffoldType())) + c.AddCommand(addGitChangesVerifier(NewScaffoldMessage())) + c.AddCommand(addGitChangesVerifier(NewScaffoldQuery())) + c.AddCommand(addGitChangesVerifier(NewScaffoldPacket())) + c.AddCommand(addGitChangesVerifier(NewScaffoldBandchain())) + c.AddCommand(addGitChangesVerifier(NewScaffoldVue())) + c.AddCommand(addGitChangesVerifier(NewScaffoldFlutter())) // c.AddCommand(NewScaffoldWasm()) return c @@ -109,6 +112,36 @@ func scaffoldType( return nil } +func addGitChangesVerifier(cmd *cobra.Command) *cobra.Command { + cmd.Flags().AddFlagSet(flagSetYes()) + + preRunFun := cmd.PreRunE + cmd.PreRunE = func(cmd *cobra.Command, args []string) error { + + if preRunFun != nil { + if err := preRunFun(cmd, args); err != nil { + return err + } + } + + appPath := flagGetPath(cmd) + + changesCommitted, _ := xgit.AreChangesCommitted(appPath) + + if !getYes(cmd) && !changesCommitted { + prompt := promptui.Prompt{ + Label: "Your saved project changes have not been committed. To enable reverting to your current state, commit your saved changes. Do you want to proceed with scaffolding without committing your saved changes", + IsConfirm: true, + } + if _, err := prompt.Run(); err != nil { + return errors.New("said no") + } + } + return nil + } + return cmd +} + func flagSetScaffoldType() *flag.FlagSet { f := flag.NewFlagSet("", flag.ContinueOnError) f.String(flagModule, "", "Module to add into. Default is app's main module") diff --git a/ignite/pkg/xgit/xgit.go b/ignite/pkg/xgit/xgit.go new file mode 100644 index 0000000000..b469b63a50 --- /dev/null +++ b/ignite/pkg/xgit/xgit.go @@ -0,0 +1,33 @@ +package xgit + +import ( + "path/filepath" + + "github.com/go-git/go-git/v5" +) + +func AreChangesCommitted(appPath string) (bool, error) { + appPath, err := filepath.Abs(appPath) + if err != nil { + return false, err + } + + repository, err := git.PlainOpen(appPath) + if err != nil { + if err == git.ErrRepositoryNotExists { + return true, nil + } + return false, err + } + + w, err := repository.Worktree() + if err != nil { + return false, err + } + + ws, err := w.Status() + if err != nil { + return false, err + } + return ws.IsClean(), nil +} diff --git a/integration/app/cmd_app_test.go b/integration/app/cmd_app_test.go index 439e75943f..106bed6917 100644 --- a/integration/app/cmd_app_test.go +++ b/integration/app/cmd_app_test.go @@ -70,7 +70,7 @@ func TestGenerateAnAppWithNoDefaultModuleAndCreateAModule(t *testing.T) { env.Must(env.Exec("should scaffold a new module into a chain that never had modules before", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "first_module"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "first_module"), step.Workdir(path), )), )) @@ -86,14 +86,14 @@ func TestGenerateAnAppWithWasm(t *testing.T) { env.Must(env.Exec("add Wasm module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "wasm"), + step.Exec(envtest.IgniteApp, "s", "wasm", "--yes"), step.Workdir(path), )), )) env.Must(env.Exec("should not add Wasm module second time", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "wasm"), + step.Exec(envtest.IgniteApp, "s", "wasm", "--yes"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -110,14 +110,14 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example", "--require-registration"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating an existing module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example", "--require-registration"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -125,7 +125,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { env.Must(env.Exec("should prevent creating a module with an invalid name", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example1", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example1", "--require-registration"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -133,7 +133,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { env.Must(env.Exec("should prevent creating a module with a reserved name", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "tx", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "tx", "--require-registration"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -141,7 +141,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { env.Must(env.Exec("should prevent creating a module with a forbidden prefix", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "ibcfoo", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "ibcfoo", "--require-registration"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -149,7 +149,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { env.Must(env.Exec("should prevent creating a module prefixed with an existing module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "examplefoo", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "examplefoo", "--require-registration"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -161,6 +161,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "with_dep", "--dep", "account,bank,staking,slashing,example", @@ -176,6 +177,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "with_wrong_dep", "--dep", "dup,dup", @@ -192,6 +194,7 @@ func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "with_no_dep", "--dep", "inexistent", diff --git a/integration/app/cmd_ibc_test.go b/integration/app/cmd_ibc_test.go index ed82ecbe09..d1a7c1fef6 100644 --- a/integration/app/cmd_ibc_test.go +++ b/integration/app/cmd_ibc_test.go @@ -20,7 +20,7 @@ func TestCreateModuleWithIBC(t *testing.T) { env.Must(env.Exec("create an IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "foo", "--ibc", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "foo", "--ibc", "--require-registration"), step.Workdir(path), )), )) @@ -30,6 +30,7 @@ func TestCreateModuleWithIBC(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "module", + "--yes", "appPath", "--ibc", "--require-registration", @@ -42,7 +43,7 @@ func TestCreateModuleWithIBC(t *testing.T) { env.Must(env.Exec("create a type in an IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email", "--module", "foo"), step.Workdir(path), )), )) @@ -53,6 +54,7 @@ func TestCreateModuleWithIBC(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "orderedfoo", "--ibc", "--ordering", @@ -69,6 +71,7 @@ func TestCreateModuleWithIBC(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "unorderedfoo", "--ibc", "--ordering", @@ -81,7 +84,7 @@ func TestCreateModuleWithIBC(t *testing.T) { env.Must(env.Exec("create a non IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "non_ibc", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "non_ibc", "--require-registration"), step.Workdir(path), )), )) @@ -92,6 +95,7 @@ func TestCreateModuleWithIBC(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "example_with_dep", "--ibc", "--dep", @@ -114,7 +118,7 @@ func TestCreateIBCOracle(t *testing.T) { env.Must(env.Exec("create an IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "foo", "--ibc", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "foo", "--ibc", "--require-registration"), step.Workdir(path), )), )) @@ -125,6 +129,7 @@ func TestCreateIBCOracle(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", "paramsFoo", "--ibc", "--params", @@ -137,21 +142,21 @@ func TestCreateIBCOracle(t *testing.T) { env.Must(env.Exec("create the first BandChain oracle integration", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "band", "oracleone", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "band", "--yes", "oracleone", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("create the second BandChain oracle integration", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "band", "oracletwo", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "band", "--yes", "oracletwo", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a BandChain oracle with no module specified", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "band", "invalidOracle"), + step.Exec(envtest.IgniteApp, "s", "band", "--yes", "invalidOracle"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -159,7 +164,7 @@ func TestCreateIBCOracle(t *testing.T) { env.Must(env.Exec("should prevent creating a BandChain oracle in a non existent module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "band", "invalidOracle", "--module", "nomodule"), + step.Exec(envtest.IgniteApp, "s", "band", "--yes", "invalidOracle", "--module", "nomodule"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -167,14 +172,14 @@ func TestCreateIBCOracle(t *testing.T) { env.Must(env.Exec("create a non-IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "bar", "--params", "name,minLaunch:uint,maxLaunch:int", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "bar", "--params", "name,minLaunch:uint,maxLaunch:int", "--require-registration"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a BandChain oracle in a non IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "band", "invalidOracle", "--module", "bar"), + step.Exec(envtest.IgniteApp, "s", "band", "--yes", "invalidOracle", "--module", "bar"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -192,7 +197,7 @@ func TestCreateIBCPacket(t *testing.T) { env.Must(env.Exec("create an IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "foo", "--ibc", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "foo", "--ibc", "--require-registration"), step.Workdir(path), )), )) @@ -203,6 +208,7 @@ func TestCreateIBCPacket(t *testing.T) { envtest.IgniteApp, "s", "packet", + "--yes", "bar", "text", "texts:strings", @@ -217,7 +223,7 @@ func TestCreateIBCPacket(t *testing.T) { env.Must(env.Exec("should prevent creating a packet with no module specified", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "bar", "text"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "bar", "text"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -225,7 +231,7 @@ func TestCreateIBCPacket(t *testing.T) { env.Must(env.Exec("should prevent creating a packet in a non existent module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "bar", "text", "--module", "nomodule"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "bar", "text", "--module", "nomodule"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -233,7 +239,7 @@ func TestCreateIBCPacket(t *testing.T) { env.Must(env.Exec("should prevent creating an existing packet", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "bar", "post", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "bar", "post", "--module", "foo"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -244,6 +250,7 @@ func TestCreateIBCPacket(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "packet", + "--yes", "ticket", "numInt:int", "numsInt:array.int", @@ -266,42 +273,42 @@ func TestCreateIBCPacket(t *testing.T) { env.Must(env.Exec("create a custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "type", "custom-type", "customField:uint", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "type", "--yes", "custom-type", "customField:uint", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("create a packet with a custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "foo-baz", "customField:CustomType", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "foo-baz", "customField:CustomType", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("create a packet with no send message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "nomessage", "foo", "--no-message", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "nomessage", "foo", "--no-message", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("create a packet with no field", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "empty", "--module", "foo"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "empty", "--module", "foo"), step.Workdir(path), )), )) env.Must(env.Exec("create a non-IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "bar", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "bar", "--require-registration"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a packet in a non IBC module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "packet", "foo", "text", "--module", "bar"), + step.Exec(envtest.IgniteApp, "s", "packet", "--yes", "foo", "text", "--module", "bar"), step.Workdir(path), )), envtest.ExecShouldError(), diff --git a/integration/app/cmd_serve_test.go b/integration/app/cmd_serve_test.go index de7c6430b6..5349afeb4a 100644 --- a/integration/app/cmd_serve_test.go +++ b/integration/app/cmd_serve_test.go @@ -26,7 +26,7 @@ func TestServeStargateWithWasm(t *testing.T) { env.Must(env.Exec("add Wasm module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "wasm"), + step.Exec(envtest.IgniteApp, "s", "wasm", "--yes"), step.Workdir(apath), )), )) diff --git a/integration/cosmosgen/cosmosgen_test.go b/integration/cosmosgen/cosmosgen_test.go index e1736d622e..3cfe036034 100644 --- a/integration/cosmosgen/cosmosgen_test.go +++ b/integration/cosmosgen/cosmosgen_test.go @@ -30,6 +30,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", withMsgModuleName, ), step.Workdir(path), @@ -42,6 +43,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "s", "message", + "--yes", "mymessage", "myfield1", "myfield2:bool", @@ -58,6 +60,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "s", "module", + "--yes", withoutMsgModuleName, ), step.Workdir(path), @@ -70,6 +73,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "s", "type", + "--yes", "mytype", "mytypefield", "--module", @@ -85,6 +89,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "s", "query", + "--yes", "myQuery", "mytypefield", "--module", @@ -102,6 +107,7 @@ func TestCosmosGen(t *testing.T) { envtest.IgniteApp, "g", "vuex", + "--yes", "--proto-all-modules", ), step.Workdir(path), diff --git a/integration/list/cmd_list_test.go b/integration/list/cmd_list_test.go index 1dda79b278..4480ad9476 100644 --- a/integration/list/cmd_list_test.go +++ b/integration/list/cmd_list_test.go @@ -19,14 +19,14 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("create a list", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email"), step.Workdir(path), )), )) env.Must(env.Exec("create a list with custom path", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "AppPath", "email", "--path", "blog"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "AppPath", "email", "--path", "blog"), step.Workdir(filepath.Dir(path)), )), )) @@ -36,6 +36,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "list", + "--yes", "employee", "numInt:int", "numsInt:array.int", @@ -57,21 +58,21 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("create a list with bool", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "document", "signed:bool"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "document", "signed:bool"), step.Workdir(path), )), )) env.Must(env.Exec("create a list with custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "custom", "document:Document"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "custom", "document:Document"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a list with duplicated fields", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "company", "name", "name"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "company", "name", "name"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -79,7 +80,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("should prevent creating a list with unrecognized field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "employee", "level:itn"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "employee", "level:itn"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -87,7 +88,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("should prevent creating an existing list", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -95,7 +96,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("should prevent creating a list whose name is a reserved word", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "map", "size:int"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "map", "size:int"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -103,7 +104,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("should prevent creating a list containing a field with a reserved word", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "document", "type:int"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "document", "type:int"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -111,7 +112,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { env.Must(env.Exec("create a list with no interaction message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "nomessage", "email", "--no-message"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "nomessage", "email", "--no-message"), step.Workdir(path), )), )) @@ -127,28 +128,28 @@ func TestCreateListInCustomModuleWithStargate(t *testing.T) { env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example", "--require-registration"), step.Workdir(path), )), )) env.Must(env.Exec("create a list", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email", "--module", "example"), step.Workdir(path), )), )) env.Must(env.Exec("create a list in the app's module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a list in a non existent module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email", "--module", "idontexist"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email", "--module", "idontexist"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -156,7 +157,7 @@ func TestCreateListInCustomModuleWithStargate(t *testing.T) { env.Must(env.Exec("should prevent creating an existing list", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email", "--module", "example"), step.Workdir(path), )), envtest.ExecShouldError(), diff --git a/integration/map/cmd_map_test.go b/integration/map/cmd_map_test.go index 4d1c536e9e..77f9c0d3d2 100644 --- a/integration/map/cmd_map_test.go +++ b/integration/map/cmd_map_test.go @@ -19,28 +19,28 @@ func TestCreateMapWithStargate(t *testing.T) { env.Must(env.Exec("create a map", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "user", "user-id", "email"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "user", "user-id", "email"), step.Workdir(path), )), )) env.Must(env.Exec("create a map with custom path", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "appPath", "email", "--path", filepath.Join(path, "app")), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "appPath", "email", "--path", filepath.Join(path, "app")), step.Workdir(filepath.Dir(path)), )), )) env.Must(env.Exec("create a map with no message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "nomessage", "email", "--no-message"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "nomessage", "email", "--no-message"), step.Workdir(path), )), )) env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example", "--require-registration"), step.Workdir(path), )), )) @@ -51,6 +51,7 @@ func TestCreateMapWithStargate(t *testing.T) { envtest.IgniteApp, "s", "list", + "--yes", "user", "email", "--module", @@ -63,7 +64,7 @@ func TestCreateMapWithStargate(t *testing.T) { env.Must(env.Exec("should prevent creating a map with a typename that already exist", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "user", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "user", "email", "--module", "example"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -71,14 +72,14 @@ func TestCreateMapWithStargate(t *testing.T) { env.Must(env.Exec("create a map in a custom module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "mapUser", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "mapUser", "email", "--module", "example"), step.Workdir(path), )), )) env.Must(env.Exec("create a map with a custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "mapDetail", "user:MapUser", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "mapDetail", "user:MapUser", "--module", "example"), step.Workdir(path), )), )) @@ -88,6 +89,7 @@ func TestCreateMapWithStargate(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "map", + "--yes", "salary", "numInt:int", "numsInt:array.int", @@ -114,6 +116,7 @@ func TestCreateMapWithStargate(t *testing.T) { envtest.IgniteApp, "s", "map", + "--yes", "map_with_index", "email", "emailIds:ints", @@ -132,6 +135,7 @@ func TestCreateMapWithStargate(t *testing.T) { envtest.IgniteApp, "s", "map", + "--yes", "map_with_invalid_index", "email", "--index", @@ -146,15 +150,15 @@ func TestCreateMapWithStargate(t *testing.T) { env.Must(env.Exec("create a message and a map with no-message flag to check conflicts", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "message", "create-scavenge", "description"), - step.Exec(envtest.IgniteApp, "s", "map", "scavenge", "description", "--no-message"), + step.Exec(envtest.IgniteApp, "s", "message", "--yes", "create-scavenge", "description"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "scavenge", "description", "--no-message"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating a map with duplicated indexes", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "map_with_duplicated_index", "email", "--index", "foo,foo"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "map_with_duplicated_index", "email", "--index", "foo,foo"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -162,7 +166,7 @@ func TestCreateMapWithStargate(t *testing.T) { env.Must(env.Exec("should prevent creating a map with an index present in fields", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "map", "map_with_invalid_index", "email", "--index", "email"), + step.Exec(envtest.IgniteApp, "s", "map", "--yes", "map_with_invalid_index", "email", "--index", "email"), step.Workdir(path), )), envtest.ExecShouldError(), diff --git a/integration/other_components/cmd_message_test.go b/integration/other_components/cmd_message_test.go index 7fcbbe46d7..53c2daa185 100644 --- a/integration/other_components/cmd_message_test.go +++ b/integration/other_components/cmd_message_test.go @@ -23,6 +23,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { envtest.IgniteApp, "s", "message", + "--yes", "do-foo", "text", "vote:int", @@ -40,6 +41,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { envtest.IgniteApp, "s", "message", + "--yes", "app-path", "text", "vote:int", @@ -56,7 +58,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { env.Must(env.Exec("should prevent creating an existing message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "message", "do-foo", "bar"), + step.Exec(envtest.IgniteApp, "s", "message", "--yes", "do-foo", "bar"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -64,7 +66,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { env.Must(env.Exec("create a message with a custom signer name", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "message", "do-bar", "bar", "--signer", "bar-doer"), + step.Exec(envtest.IgniteApp, "s", "message", "--yes", "do-bar", "bar", "--signer", "bar-doer"), step.Workdir(path), )), )) @@ -74,6 +76,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "type", + "--yes", "custom-type", "numInt:int", "numsInt:array.int", @@ -94,14 +97,14 @@ func TestGenerateAnAppWithMessage(t *testing.T) { env.Must(env.Exec("create a message with the custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "message", "foo-baz", "customField:CustomType"), + step.Exec(envtest.IgniteApp, "s", "message", "--yes", "foo-baz", "customField:CustomType"), step.Workdir(path), )), )) env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "foo", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "foo", "--require-registration"), step.Workdir(path), )), )) @@ -112,6 +115,7 @@ func TestGenerateAnAppWithMessage(t *testing.T) { envtest.IgniteApp, "s", "message", + "--yes", "do-foo", "text", "userIds:array.uint", diff --git a/integration/other_components/cmd_query_test.go b/integration/other_components/cmd_query_test.go index 539b9bd1a7..7451b81daa 100644 --- a/integration/other_components/cmd_query_test.go +++ b/integration/other_components/cmd_query_test.go @@ -23,6 +23,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { envtest.IgniteApp, "s", "query", + "--yes", "foo", "text", "vote:int", @@ -40,6 +41,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { envtest.IgniteApp, "s", "query", + "--yes", "AppPath", "text", "vote:int", @@ -59,6 +61,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { envtest.IgniteApp, "s", "query", + "--yes", "bar", "text", "vote:int", @@ -76,6 +79,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { step.Exec(envtest.IgniteApp, "s", "type", + "--yes", "custom-type", "numInt:int", "numsInt:array.int", @@ -96,14 +100,14 @@ func TestGenerateAnAppWithQuery(t *testing.T) { env.Must(env.Exec("create a query with the custom field type as a response", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "query", "foobaz", "-r", "bar:CustomType"), + step.Exec(envtest.IgniteApp, "s", "query", "--yes", "foobaz", "-r", "bar:CustomType"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent using custom type in request params", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "query", "bur", "bar:CustomType"), + step.Exec(envtest.IgniteApp, "s", "query", "--yes", "bur", "bar:CustomType"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -111,14 +115,14 @@ func TestGenerateAnAppWithQuery(t *testing.T) { env.Must(env.Exec("create an empty query", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "query", "foobar"), + step.Exec(envtest.IgniteApp, "s", "query", "--yes", "foobar"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating an existing query", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "query", "foo", "bar"), + step.Exec(envtest.IgniteApp, "s", "query", "--yes", "foo", "bar"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -126,7 +130,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "foo", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "foo", "--require-registration"), step.Workdir(path), )), )) @@ -137,6 +141,7 @@ func TestGenerateAnAppWithQuery(t *testing.T) { envtest.IgniteApp, "s", "query", + "--yes", "foo", "text", "--module", diff --git a/integration/readme.md b/integration/readme.md index e598b66828..096ae6b883 100644 --- a/integration/readme.md +++ b/integration/readme.md @@ -26,7 +26,7 @@ var ( ```go env.Must(env.Exec("create a list with bool", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "document", "signed:bool"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "document", "signed:bool"), step.Workdir(path), )), )) @@ -37,7 +37,7 @@ env.EnsureAppIsSteady(path) ```go env.Must(env.Exec("should prevent creating a list with duplicated fields", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "company", "name", "name"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "company", "name", "name"), step.Workdir(path), )), envtest.ExecShouldError(), diff --git a/integration/simulation/simapp_test.go b/integration/simulation/simapp_test.go index a4c15b8b4d..630a7d30fc 100644 --- a/integration/simulation/simapp_test.go +++ b/integration/simulation/simapp_test.go @@ -18,35 +18,35 @@ func TestGenerateAnAppAndSimulate(t *testing.T) { env.Must(env.Exec("create a list", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "foo", "foobar"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "foo", "foobar"), step.Workdir(path), )), )) env.Must(env.Exec("create an singleton type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "baz", "foobar"), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "baz", "foobar"), step.Workdir(path), )), )) env.Must(env.Exec("create an singleton type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "noSimapp", "foobar", "--no-simulation"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "noSimapp", "foobar", "--no-simulation"), step.Workdir(path), )), )) env.Must(env.Exec("create a message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "msgFoo", "foobar"), + step.Exec(envtest.IgniteApp, "s", "message", "--yes", "msgFoo", "foobar"), step.Workdir(path), )), )) env.Must(env.Exec("scaffold a new module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "new_module"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "new_module"), step.Workdir(path), )), )) @@ -57,6 +57,7 @@ func TestGenerateAnAppAndSimulate(t *testing.T) { envtest.IgniteApp, "s", "map", + "--yes", "bar", "foobar", "--module", diff --git a/integration/single/cmd_singleton_test.go b/integration/single/cmd_singleton_test.go index 806d56179d..3efce2d4ce 100644 --- a/integration/single/cmd_singleton_test.go +++ b/integration/single/cmd_singleton_test.go @@ -19,49 +19,49 @@ func TestCreateSingletonWithStargate(t *testing.T) { env.Must(env.Exec("create an singleton type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "user", "email"), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "user", "email"), step.Workdir(path), )), )) env.Must(env.Exec("create an singleton type with custom path", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "appPath", "email", "--path", path), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "appPath", "email", "--path", path), step.Workdir(filepath.Dir(path)), )), )) env.Must(env.Exec("create an singleton type with no message", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "no-message", "email", "--no-message"), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "no-message", "email", "--no-message"), step.Workdir(path), )), )) env.Must(env.Exec("create a module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "module", "example", "--require-registration"), + step.Exec(envtest.IgniteApp, "s", "module", "--yes", "example", "--require-registration"), step.Workdir(path), )), )) env.Must(env.Exec("create another type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user", "email", "--module", "example"), step.Workdir(path), )), )) env.Must(env.Exec("create another type with a custom field type", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "list", "user-detail", "user:User", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "list", "--yes", "user-detail", "user:User", "--module", "example"), step.Workdir(path), )), )) env.Must(env.Exec("should prevent creating an singleton type with a typename that already exist", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "user", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "user", "email", "--module", "example"), step.Workdir(path), )), envtest.ExecShouldError(), @@ -69,7 +69,7 @@ func TestCreateSingletonWithStargate(t *testing.T) { env.Must(env.Exec("create an singleton type in a custom module", step.NewSteps(step.New( - step.Exec(envtest.IgniteApp, "s", "single", "singleuser", "email", "--module", "example"), + step.Exec(envtest.IgniteApp, "s", "single", "--yes", "singleuser", "email", "--module", "example"), step.Workdir(path), )), )) From 272673e52f424b1cfde70f01414ddae93237ad63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Thu, 28 Apr 2022 19:17:15 +0200 Subject: [PATCH 16/30] refactor(pkg/xurl): change protocol functions to prevent possible bugs (#2392) * refactor(pkg/xurl): add error support to protocol functions * refactor(pkg/xurl): change existing ensure port test for consistency The "TestHTTPEnsurePort" was slightly changed to be consistent with the existing table driven tests conventions. * refactor: change calls to xurl protocol functions to handle errors * refactor(pkg/xurl): add constants for scheme types * fix: formatting * fix: formatting * fix(pkg/xurl): change ensure protocol function to handle ADDR:HOST The protocol related functions now check for values like for example 0.0.0.0:42 or localhost:42 that can't be parsed by the net package because the scheme is not defined. * chore: review improvements * feat(pkg/xurl): add MightHTTPS function * chore: change network publish command to ensure http/https --- ignite/cmd/network_chain_publish.go | 6 +- ignite/pkg/xurl/xurl.go | 108 +++++-- ignite/pkg/xurl/xurl_test.go | 303 +++++++++++++++++- ignite/services/chain/chain.go | 7 +- ignite/services/chain/faucet.go | 7 +- ignite/services/chain/plugin-stargate.go | 28 +- ignite/services/chain/serve.go | 12 +- .../services/network/networkchain/simulate.go | 37 ++- integration/app/tx_test.go | 14 +- integration/env.go | 12 +- integration/faucet/faucet_test.go | 5 +- 11 files changed, 483 insertions(+), 56 deletions(-) diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index 98be9cf826..fea0285eb7 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -63,7 +63,6 @@ func NewNetworkChainPublish() *cobra.Command { func networkChainPublishHandler(cmd *cobra.Command, args []string) error { var ( - source = xurl.HTTPS(args[0]) tag, _ = cmd.Flags().GetString(flagTag) branch, _ = cmd.Flags().GetString(flagBranch) hash, _ = cmd.Flags().GetString(flagHash) @@ -79,6 +78,11 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { rewardDuration, _ = cmd.Flags().GetInt64(flagRewardHeight) ) + source, err := xurl.MightHTTPS(args[0]) + if err != nil { + return fmt.Errorf("invalid source url format: %w", err) + } + if campaign != 0 && campaignTotalSupplyStr != "" { return fmt.Errorf("%s and %s flags cannot be set together", flagCampaign, flagCampaignTotalSupply) } diff --git a/ignite/pkg/xurl/xurl.go b/ignite/pkg/xurl/xurl.go index 88137f66e8..c428772cd6 100644 --- a/ignite/pkg/xurl/xurl.go +++ b/ignite/pkg/xurl/xurl.go @@ -1,41 +1,76 @@ package xurl import ( + "errors" "fmt" + "net" "net/url" "strings" ) -// TCP unsures that s url contains TCP protocol identifier. -func TCP(s string) string { - if strings.HasPrefix(s, "tcp") { - return s +const ( + schemeTCP = "tcp" + schemeHTTP = "http" + schemeHTTPS = "https" + schemeWS = "ws" +) + +// TCP ensures that a URL contains a TCP scheme. +func TCP(s string) (string, error) { + u, err := parseURL(s) + if err != nil { + return "", err } - return "tcp://" + Address(s) + + u.Scheme = schemeTCP + + return u.String(), nil } -// HTTP unsures that s url contains HTTP protocol identifier. -func HTTP(s string) string { - if strings.HasPrefix(s, "http") { - return s +// HTTP ensures that a URL contains an HTTP scheme. +func HTTP(s string) (string, error) { + u, err := parseURL(s) + if err != nil { + return "", err } - return "http://" + Address(s) + + u.Scheme = schemeHTTP + + return u.String(), nil } -// HTTPS unsures that s url contains HTTPS protocol identifier. -func HTTPS(s string) string { - if strings.HasPrefix(s, "https") { - return s +// HTTPS ensures that a URL contains an HTTPS scheme. +func HTTPS(s string) (string, error) { + u, err := parseURL(s) + if err != nil { + return "", err } - return "https://" + Address(s) + + u.Scheme = schemeHTTPS + + return u.String(), nil } -// WS unsures that s url contains WS protocol identifier. -func WS(s string) string { - if strings.HasPrefix(s, "ws") { - return s +// MightHTTPS ensures that a URL contains an HTTPS scheme when the current scheme is not HTTP. +// When the URL contains an HTTP scheme it is not modified. +func MightHTTPS(s string) (string, error) { + if strings.HasPrefix(strings.ToLower(s), "http://") { + return s, nil + } + + return HTTPS(s) +} + +// WS ensures that a URL contains a WS scheme. +func WS(s string) (string, error) { + u, err := parseURL(s) + if err != nil { + return "", err } - return "ws://" + Address(s) + + u.Scheme = schemeWS + + return u.String(), nil } // HTTPEnsurePort ensures that url has a port number suits with the connection type. @@ -47,7 +82,7 @@ func HTTPEnsurePort(s string) string { port := "80" - if u.Scheme == "https" { + if u.Scheme == schemeHTTPS { port = "443" } @@ -68,7 +103,7 @@ func CleanPath(s string) string { return u.String() } -// Address unsures that address contains localhost as host if non specified. +// Address ensures that address contains localhost as host if non specified. func Address(address string) string { if strings.HasPrefix(address, ":") { return "localhost" + address @@ -93,3 +128,32 @@ func IsLocalPath(address string) bool { func IsHTTP(address string) bool { return strings.HasPrefix(address, "http") } + +func parseURL(s string) (*url.URL, error) { + if s == "" { + return nil, errors.New("url is empty") + } + + // Handle the case where the URI is an IP:PORT or HOST:PORT + // without scheme prefix because that case can't be URL parsed. + // When the URI has not scheme it is parsed as a path by "url.Parse" + // placing the colon within the path, which is invalid. + if isAddressPort(s) { + return &url.URL{Host: s}, nil + } + + return url.Parse(Address(s)) +} + +func isAddressPort(s string) bool { + // Check that the value doesn't contain a URI path + if strings.Index(s, "/") != -1 { + return false + } + + // Use the net split function to support IPv6 addresses + if _, _, err := net.SplitHostPort(s); err != nil { + return false + } + return true +} diff --git a/ignite/pkg/xurl/xurl_test.go b/ignite/pkg/xurl/xurl_test.go index 7f02df7457..a17f851279 100644 --- a/ignite/pkg/xurl/xurl_test.go +++ b/ignite/pkg/xurl/xurl_test.go @@ -8,26 +8,155 @@ import ( func TestHTTPEnsurePort(t *testing.T) { cases := []struct { - addr string - ensured string + name string + addr string + want string }{ - {"http://localhost", "http://localhost:80"}, - {"https://localhost", "https://localhost:443"}, - {"http://localhost:4000", "http://localhost:4000"}, + { + name: "http", + addr: "http://localhost", + want: "http://localhost:80", + }, + { + name: "https", + addr: "https://localhost", + want: "https://localhost:443", + }, + { + name: "custom", + addr: "http://localhost:4000", + want: "http://localhost:4000", + }, } + for _, tt := range cases { - t.Run(tt.addr, func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { addr := HTTPEnsurePort(tt.addr) - require.Equal(t, tt.ensured, addr) + require.Equal(t, tt.want, addr) + }) + } +} + +func TestTCP(t *testing.T) { + cases := []struct { + name string + addr string + want string + error bool + }{ + { + name: "with scheme", + addr: "tcp://github.com/ignite-hq/cli", + want: "tcp://github.com/ignite-hq/cli", + }, + { + name: "without scheme", + addr: "github.com/ignite-hq/cli", + want: "tcp://github.com/ignite-hq/cli", + }, + { + name: "with invalid scheme", + addr: "ftp://github.com/ignite-hq/cli", + want: "tcp://github.com/ignite-hq/cli", + }, + { + name: "with ip and port", + addr: "0.0.0.0:4500", + want: "tcp://0.0.0.0:4500", + }, + { + name: "with localhost and port", + addr: "localhost:4500", + want: "tcp://localhost:4500", + }, + { + name: "with invalid url", + addr: "tcp://github.com:x", + error: true, + }, + { + name: "empty", + addr: "", + error: true, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + addr, err := TCP(tt.addr) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, addr) + } + }) + } +} + +func TestHTTP(t *testing.T) { + cases := []struct { + name string + addr string + want string + error bool + }{ + { + name: "with scheme", + addr: "http://github.com/ignite-hq/cli", + want: "http://github.com/ignite-hq/cli", + }, + { + name: "without scheme", + addr: "github.com/ignite-hq/cli", + want: "http://github.com/ignite-hq/cli", + }, + { + name: "with invalid scheme", + addr: "ftp://github.com/ignite-hq/cli", + want: "http://github.com/ignite-hq/cli", + }, + { + name: "with ip and port", + addr: "0.0.0.0:4500", + want: "http://0.0.0.0:4500", + }, + { + name: "with localhost and port", + addr: "localhost:4500", + want: "http://localhost:4500", + }, + { + name: "with invalid url", + addr: "http://github.com:x", + error: true, + }, + { + name: "empty", + addr: "", + error: true, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + addr, err := HTTP(tt.addr) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, addr) + } }) } } func TestHTTPS(t *testing.T) { cases := []struct { - name string - addr string - want string + name string + addr string + want string + error bool }{ { name: "with scheme", @@ -40,14 +169,160 @@ func TestHTTPS(t *testing.T) { want: "https://github.com/ignite-hq/cli", }, { - name: "empty", - addr: "", - want: "https://", + name: "with invalid scheme", + addr: "ftp://github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "with ip and port", + addr: "0.0.0.0:4500", + want: "https://0.0.0.0:4500", + }, + { + name: "with localhost and port", + addr: "localhost:4500", + want: "https://localhost:4500", + }, + { + name: "with invalid url", + addr: "https://github.com:x", + error: true, + }, + { + name: "empty", + addr: "", + error: true, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + addr, err := HTTPS(tt.addr) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, addr) + } + }) + } +} + +func TestWS(t *testing.T) { + cases := []struct { + name string + addr string + want string + error bool + }{ + { + name: "with scheme", + addr: "ws://github.com/ignite-hq/cli", + want: "ws://github.com/ignite-hq/cli", + }, + { + name: "without scheme", + addr: "github.com/ignite-hq/cli", + want: "ws://github.com/ignite-hq/cli", + }, + { + name: "with invalid scheme", + addr: "ftp://github.com/ignite-hq/cli", + want: "ws://github.com/ignite-hq/cli", + }, + { + name: "with ip and port", + addr: "0.0.0.0:4500", + want: "ws://0.0.0.0:4500", + }, + { + name: "with localhost and port", + addr: "localhost:4500", + want: "ws://localhost:4500", + }, + { + name: "with invalid url", + addr: "ws://github.com:x", + error: true, + }, + { + name: "empty", + addr: "", + error: true, + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + addr, err := WS(tt.addr) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, addr) + } + }) + } +} + +func TestMightHTTPS(t *testing.T) { + cases := []struct { + name string + addr string + want string + error bool + }{ + { + name: "with http scheme", + addr: "http://github.com/ignite-hq/cli", + want: "http://github.com/ignite-hq/cli", + }, + { + name: "with https scheme", + addr: "https://github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "without scheme", + addr: "github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "with invalid scheme", + addr: "ftp://github.com/ignite-hq/cli", + want: "https://github.com/ignite-hq/cli", + }, + { + name: "with ip and port", + addr: "0.0.0.0:4500", + want: "https://0.0.0.0:4500", + }, + { + name: "with localhost and port", + addr: "localhost:4500", + want: "https://localhost:4500", + }, + { + name: "with invalid url", + addr: "https://github.com:x", + error: true, + }, + { + name: "empty", + addr: "", + error: true, }, } + for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, HTTPS(tt.addr)) + addr, err := MightHTTPS(tt.addr) + if tt.error { + require.Error(t, err) + } else { + require.NoError(t, err) + require.Equal(t, tt.want, addr) + } }) } } diff --git a/ignite/services/chain/chain.go b/ignite/services/chain/chain.go index 045a13231e..b5325808dd 100644 --- a/ignite/services/chain/chain.go +++ b/ignite/services/chain/chain.go @@ -442,11 +442,16 @@ func (c *Chain) Commands(ctx context.Context) (chaincmdrunner.Runner, error) { return chaincmdrunner.Runner{}, err } + nodeAddr, err := xurl.TCP(config.Host.RPC) + if err != nil { + return chaincmdrunner.Runner{}, err + } + chainCommandOptions := []chaincmd.Option{ chaincmd.WithChainID(id), chaincmd.WithHome(home), chaincmd.WithVersion(c.Version), - chaincmd.WithNodeAddress(xurl.TCP(config.Host.RPC)), + chaincmd.WithNodeAddress(nodeAddr), chaincmd.WithKeyringBackend(backend), } diff --git a/ignite/services/chain/faucet.go b/ignite/services/chain/faucet.go index 914d9a222b..8a2d0675bf 100644 --- a/ignite/services/chain/faucet.go +++ b/ignite/services/chain/faucet.go @@ -62,10 +62,15 @@ func (c *Chain) Faucet(ctx context.Context) (cosmosfaucet.Faucet, error) { apiAddress = envAPIAddress } + apiAddress, err = xurl.HTTP(apiAddress) + if err != nil { + return cosmosfaucet.Faucet{}, fmt.Errorf("invalid host api address format: %w", err) + } + faucetOptions := []cosmosfaucet.Option{ cosmosfaucet.Account(*conf.Faucet.Name, "", ""), cosmosfaucet.ChainID(id), - cosmosfaucet.OpenAPI(xurl.HTTP(apiAddress)), + cosmosfaucet.OpenAPI(apiAddress), } // parse coins to pass to the faucet as coins. diff --git a/ignite/services/chain/plugin-stargate.go b/ignite/services/chain/plugin-stargate.go index e1c025c7e1..a66d2d73a7 100644 --- a/ignite/services/chain/plugin-stargate.go +++ b/ignite/services/chain/plugin-stargate.go @@ -2,6 +2,7 @@ package chain import ( "context" + "fmt" "os" "path/filepath" @@ -63,17 +64,25 @@ func (p *stargatePlugin) appTOML(homePath string, conf chainconfig.Config) error if err != nil { return err } + + apiAddr, err := xurl.TCP(conf.Host.API) + if err != nil { + return fmt.Errorf("invalid api address format %s: %w", conf.Host.API, err) + } + config.Set("api.enable", true) config.Set("api.enabled-unsafe-cors", true) config.Set("rpc.cors_allowed_origins", []string{"*"}) - config.Set("api.address", xurl.TCP(conf.Host.API)) + config.Set("api.address", apiAddr) config.Set("grpc.address", conf.Host.GRPC) config.Set("grpc-web.address", conf.Host.GRPCWeb) + file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return err } defer file.Close() + _, err = config.WriteTo(file) return err } @@ -85,17 +94,30 @@ func (p *stargatePlugin) configTOML(homePath string, conf chainconfig.Config) er if err != nil { return err } + + rpcAddr, err := xurl.TCP(conf.Host.RPC) + if err != nil { + return fmt.Errorf("invalid rpc address format %s: %w", conf.Host.RPC, err) + } + + p2pAddr, err := xurl.TCP(conf.Host.P2P) + if err != nil { + return fmt.Errorf("invalid p2p address format %s: %w", conf.Host.P2P, err) + } + config.Set("rpc.cors_allowed_origins", []string{"*"}) config.Set("consensus.timeout_commit", "1s") config.Set("consensus.timeout_propose", "1s") - config.Set("rpc.laddr", xurl.TCP(conf.Host.RPC)) - config.Set("p2p.laddr", xurl.TCP(conf.Host.P2P)) + config.Set("rpc.laddr", rpcAddr) + config.Set("p2p.laddr", p2pAddr) config.Set("rpc.pprof_laddr", conf.Host.Prof) + file, err := os.OpenFile(path, os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return err } defer file.Close() + _, err = config.WriteTo(file) return err } diff --git a/ignite/services/chain/serve.go b/ignite/services/chain/serve.go index 9e98efcfc3..99dc4754aa 100644 --- a/ignite/services/chain/serve.go +++ b/ignite/services/chain/serve.go @@ -410,12 +410,18 @@ func (c *Chain) start(ctx context.Context, config chainconfig.Config) error { // set the app as being served c.served = true + // note: address format errors are handled by the + // error group, so they can be safely ignored here + rpcAddr, _ := xurl.HTTP(config.Host.RPC) + apiAddr, _ := xurl.HTTP(config.Host.API) + // print the server addresses. - fmt.Fprintf(c.stdLog().out, "🌍 Tendermint node: %s\n", xurl.HTTP(config.Host.RPC)) - fmt.Fprintf(c.stdLog().out, "🌍 Blockchain API: %s\n", xurl.HTTP(config.Host.API)) + fmt.Fprintf(c.stdLog().out, "🌍 Tendermint node: %s\n", rpcAddr) + fmt.Fprintf(c.stdLog().out, "🌍 Blockchain API: %s\n", apiAddr) if isFaucetEnabled { - fmt.Fprintf(c.stdLog().out, "🌍 Token faucet: %s\n", xurl.HTTP(chainconfig.FaucetHost(config))) + faucetAddr, _ := xurl.HTTP(chainconfig.FaucetHost(config)) + fmt.Fprintf(c.stdLog().out, "🌍 Token faucet: %s\n", faucetAddr) } return g.Wait() diff --git a/ignite/services/network/networkchain/simulate.go b/ignite/services/network/networkchain/simulate.go index 7df43cb365..b9f4b2d932 100644 --- a/ignite/services/network/networkchain/simulate.go +++ b/ignite/services/network/networkchain/simulate.go @@ -113,18 +113,25 @@ func (c Chain) setSimulationConfig() (string, error) { if err != nil { return "", err } + + apiAddr, err := xurl.TCP(genAddr(ports[0])) + if err != nil { + return "", err + } + config.Set("api.enable", true) config.Set("api.enabled-unsafe-cors", true) config.Set("rpc.cors_allowed_origins", []string{"*"}) - config.Set("api.address", xurl.TCP(genAddr(ports[0]))) + config.Set("api.address", apiAddr) config.Set("grpc.address", genAddr(ports[1])) + file, err := os.OpenFile(appPath, os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return "", err } defer file.Close() - _, err = config.WriteTo(file) - if err != nil { + + if _, err := config.WriteTo(file); err != nil { return "", err } @@ -137,17 +144,30 @@ func (c Chain) setSimulationConfig() (string, error) { if err != nil { return "", err } + + rpcAddr, err := xurl.TCP(genAddr(ports[2])) + if err != nil { + return "", err + } + + p2pAddr, err := xurl.TCP(genAddr(ports[3])) + if err != nil { + return "", err + } + config.Set("rpc.cors_allowed_origins", []string{"*"}) config.Set("consensus.timeout_commit", "1s") config.Set("consensus.timeout_propose", "1s") - config.Set("rpc.laddr", xurl.TCP(genAddr(ports[2]))) - config.Set("p2p.laddr", xurl.TCP(genAddr(ports[3]))) + config.Set("rpc.laddr", rpcAddr) + config.Set("p2p.laddr", p2pAddr) config.Set("rpc.pprof_laddr", genAddr(ports[4])) + file, err = os.OpenFile(configPath, os.O_RDWR|os.O_TRUNC, 0644) if err != nil { return "", err } defer file.Close() + _, err = config.WriteTo(file) return genAddr(ports[0]), err @@ -156,7 +176,12 @@ func (c Chain) setSimulationConfig() (string, error) { // isChainListening checks if the chain is listening for API queries on the specified address func isChainListening(ctx context.Context, addressAPI string) error { checkAlive := func() error { - ok, err := httpstatuschecker.Check(ctx, xurl.HTTP(addressAPI)+"/node_info") + addr, err := xurl.HTTP(addressAPI) + if err != nil { + return fmt.Errorf("invalid api address format %s: %w", addressAPI, err) + } + + ok, err := httpstatuschecker.Check(ctx, fmt.Sprintf("%s/node_info", addr)) if err == nil && !ok { err = errors.New("app is not online") } diff --git a/integration/app/tx_test.go b/integration/app/tx_test.go index ab478cee74..a308fb674b 100644 --- a/integration/app/tx_test.go +++ b/integration/app/tx_test.go @@ -92,6 +92,11 @@ func TestGetTxViaGRPCGateway(t *testing.T) { return errors.New("expected alice and bob accounts to be created") } + nodeAddr, err := xurl.TCP(host.RPC) + if err != nil { + return err + } + // send some tokens from alice to bob and confirm the corresponding tx via gRPC gateway // endpoint by asserting denom and amount. return cmdrunner.New().Run(ctx, step.New( @@ -105,7 +110,7 @@ func TestGetTxViaGRPCGateway(t *testing.T) { "10token", "--keyring-backend", "test", "--chain-id", appname, - "--node", xurl.TCP(host.RPC), + "--node", nodeAddr, "--yes", ), step.PreExec(func() error { @@ -124,7 +129,12 @@ func TestGetTxViaGRPCGateway(t *testing.T) { return err } - addr := fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", xurl.HTTP(host.API), tx.Hash) + apiAddr, err := xurl.HTTP(host.API) + if err != nil { + return err + } + + addr := fmt.Sprintf("%s/cosmos/tx/v1beta1/txs/%s", apiAddr, tx.Hash) req, err := http.NewRequestWithContext(ctx, http.MethodGet, addr, nil) if err != nil { return errors.Wrap(err, "call to get tx via gRPC gateway") diff --git a/integration/env.go b/integration/env.go index 776283c2c7..18f10294f2 100644 --- a/integration/env.go +++ b/integration/env.go @@ -251,7 +251,12 @@ func (e Env) EnsureAppIsSteady(appPath string) { // before ctx canceled. func (e Env) IsAppServed(ctx context.Context, host chainconfig.Host) error { checkAlive := func() error { - ok, err := httpstatuschecker.Check(ctx, xurl.HTTP(host.API)+"/node_info") + addr, err := xurl.HTTP(host.API) + if err != nil { + return err + } + + ok, err := httpstatuschecker.Check(ctx, fmt.Sprintf("%s/node_info", addr)) if err == nil && !ok { err = errors.New("app is not online") } @@ -343,7 +348,10 @@ func (e Env) ConfigureFaucet(path string, configFile string, coins, coinsMax []s require.NoError(e.t, err) require.NoError(e.t, yaml.NewEncoder(configyml).Encode(conf)) - return xurl.HTTP(fmt.Sprintf("0.0.0.0:%d", port[0])) + addr, err := xurl.HTTP(fmt.Sprintf("0.0.0.0:%d", port[0])) + require.NoError(e.t, err) + + return addr } // SetRandomHomeConfig sets in the blockchain config files generated temporary directories for home directories diff --git a/integration/faucet/faucet_test.go b/integration/faucet/faucet_test.go index 3bb78f45b9..c9ea7f2f76 100644 --- a/integration/faucet/faucet_test.go +++ b/integration/faucet/faucet_test.go @@ -60,7 +60,10 @@ func TestRequestCoinsFromFaucet(t *testing.T) { // error "account doesn't have any balances" occurs if a sleep is not included time.Sleep(time.Second * 1) - cosmosClient, err := cosmosclient.New(ctx, cosmosclient.WithNodeAddress(xurl.HTTP(servers.RPC))) + nodeAddr, err := xurl.HTTP(servers.RPC) + require.NoError(t, err) + + cosmosClient, err := cosmosclient.New(ctx, cosmosclient.WithNodeAddress(nodeAddr)) require.NoError(t, err) // the faucet sends the default faucet coins value when not specified From 6aaeec906d1bb3f6c66d8ed409356daf642f4bcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Thu, 28 Apr 2022 21:19:10 +0300 Subject: [PATCH 17/30] feat(cmd): handle git status check err (#2427) --- ignite/cmd/scaffold.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ignite/cmd/scaffold.go b/ignite/cmd/scaffold.go index e13f11919a..0d38153b91 100644 --- a/ignite/cmd/scaffold.go +++ b/ignite/cmd/scaffold.go @@ -117,7 +117,6 @@ func addGitChangesVerifier(cmd *cobra.Command) *cobra.Command { preRunFun := cmd.PreRunE cmd.PreRunE = func(cmd *cobra.Command, args []string) error { - if preRunFun != nil { if err := preRunFun(cmd, args); err != nil { return err @@ -126,7 +125,10 @@ func addGitChangesVerifier(cmd *cobra.Command) *cobra.Command { appPath := flagGetPath(cmd) - changesCommitted, _ := xgit.AreChangesCommitted(appPath) + changesCommitted, err := xgit.AreChangesCommitted(appPath) + if err != nil { + return err + } if !getYes(cmd) && !changesCommitted { prompt := promptui.Prompt{ From 9a6756a9298a5336b51b32703f8d50db3b4abc77 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Tue, 3 May 2022 02:05:51 -0300 Subject: [PATCH 18/30] update spn version (#2435) --- go.mod | 6 +++--- go.sum | 14 +++++++------ ignite/cmd/network_chain_publish.go | 2 +- ignite/pkg/cosmosutil/coins_test.go | 3 ++- ignite/services/network/campaign.go | 2 +- ignite/templates/app/stargate/go.mod.plush | 16 +++++++-------- ignite/templates/app/stargate/go.sum | 23 +++++++++++++++++----- 7 files changed, 41 insertions(+), 25 deletions(-) diff --git a/go.mod b/go.mod index 6d65d7eb13..deea792e19 100644 --- a/go.mod +++ b/go.mod @@ -45,9 +45,9 @@ require ( github.com/stretchr/testify v1.7.1 github.com/takuoki/gocase v1.0.0 github.com/tendermint/flutter/v2 v2.0.3 - github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150 + github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 github.com/tendermint/tendermint v0.34.19 - github.com/tendermint/tm-db v0.6.6 + github.com/tendermint/tm-db v0.6.7 github.com/tendermint/vue v0.3.5 github.com/vektra/mockery/v2 v2.11.0 golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 @@ -89,6 +89,7 @@ require ( github.com/containerd/console v1.0.3 // indirect github.com/containerd/containerd v1.6.2 // indirect github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/gorocksdb v1.2.0 // indirect github.com/cosmos/iavl v0.17.3 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.2 // indirect @@ -212,7 +213,6 @@ require ( github.com/stretchr/objx v0.2.0 // indirect github.com/subosito/gotenv v1.2.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca // indirect - github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect diff --git a/go.sum b/go.sum index d08d69c71a..2a67271902 100644 --- a/go.sum +++ b/go.sum @@ -427,6 +427,8 @@ github.com/cosmos/cosmos-sdk v0.45.3/go.mod h1:qYm5JEr0ZlbnmoP/Q3b+dYMOliHf4ddHi github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= github.com/cosmos/ibc-go/v2 v2.0.3 h1:kZ6SAj7hyxoixsLEUBx431bVGiBW22PCHwkWHafWhXs= @@ -524,12 +526,12 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7 github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8plZ0M9VMk4/oM= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -1473,7 +1475,6 @@ github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca/go.mod h1:u2MKk github.com/takuoki/gocase v1.0.0 h1:gPwLJTWVm2T1kUiCsKirg/faaIUGVTI0FA3SYr75a44= github.com/takuoki/gocase v1.0.0/go.mod h1:QgOKJrbuJoDrtoKswBX1/Dw8mJrkOV9tbQZJaxaJ6zc= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= @@ -1484,14 +1485,15 @@ github.com/tendermint/flutter/v2 v2.0.3/go.mod h1:hnaVhWhzv2Od1LqZFWrRKwiOHeMons github.com/tendermint/fundraising v0.2.0 h1:V6N7u/oWXjQZEbXXk34uAfijYnYQFZrZGA39e03UFz8= github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2lyGa2E= github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= -github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150 h1:FJI3e3R0WsSD5rM+z/OUaxk2Qlx0hfyAI9I76F6a7wk= -github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150/go.mod h1:B+KuhkB4Sms4yh0UN1HGsVbbMa3vCypai22QXLudQ3o= +github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 h1:1S5urE/lHktsawx/I4r6iHiV1Ylfhp8mQZ5eQKbY1bA= +github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030/go.mod h1:9wXyogMDn9fK85s+bSADy+wvZ27DjLEByByMM+0O6NU= github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= github.com/tendermint/tendermint v0.34.19 h1:y0P1qI5wSa9IRuhKnTDA6IUcOrLi1hXJuALR+R7HFEk= github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3HDkhpcdum6VeU3R4= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= -github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= +github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= +github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= github.com/tendermint/vue v0.3.5 h1:PTZaW0+7/4lRJyUtuZOxFzMCahNLowTadVoCZns2Wmw= github.com/tendermint/vue v0.3.5/go.mod h1:Sg9MGPF+uY+SJ79sdZgtC2LnH+FDU2qWuiRxoZn5bmw= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index fea0285eb7..1aa7ba52a8 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -8,13 +8,13 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/tendermint/spn/pkg/chainid" + campaigntypes "github.com/tendermint/spn/x/campaign/types" "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - campaigntypes "github.com/tendermint/spn/x/campaign/types" ) const ( diff --git a/ignite/pkg/cosmosutil/coins_test.go b/ignite/pkg/cosmosutil/coins_test.go index c29661cccb..c311702107 100644 --- a/ignite/pkg/cosmosutil/coins_test.go +++ b/ignite/pkg/cosmosutil/coins_test.go @@ -5,8 +5,9 @@ import ( "testing" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/stretchr/testify/require" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" ) func TestValidateCoinsStrWithPercentage(t *testing.T) { diff --git a/ignite/services/network/campaign.go b/ignite/services/network/campaign.go index 75a73e3ef3..8717103d72 100644 --- a/ignite/services/network/campaign.go +++ b/ignite/services/network/campaign.go @@ -146,8 +146,8 @@ func (n Network) UpdateCampaign( if p.name != "" || len(p.metadata) > 0 { msgs = append(msgs, campaigntypes.NewMsgEditCampaign( account, - p.name, id, + p.name, p.metadata, )) } diff --git a/ignite/templates/app/stargate/go.mod.plush b/ignite/templates/app/stargate/go.mod.plush index a04dd757fd..a5ddd11407 100644 --- a/ignite/templates/app/stargate/go.mod.plush +++ b/ignite/templates/app/stargate/go.mod.plush @@ -9,15 +9,15 @@ require ( github.com/golang/protobuf v1.5.2 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/grpc-gateway v1.16.0 - github.com/spf13/cast v1.4.1 - github.com/spf13/cobra v1.3.0 - github.com/stretchr/testify v1.7.0 - github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150 github.com/ignite-hq/cli v0.20.3 - github.com/tendermint/tendermint v0.34.16 - github.com/tendermint/tm-db v0.6.6 - google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e - google.golang.org/grpc v1.45.0 + github.com/spf13/cast v1.4.1 + github.com/spf13/cobra v1.4.0 + github.com/stretchr/testify v1.7.1 + github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 + github.com/tendermint/tendermint v0.34.19 + github.com/tendermint/tm-db v0.6.7 + google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e + google.golang.org/grpc v1.45.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/ignite/templates/app/stargate/go.sum b/ignite/templates/app/stargate/go.sum index 6469fdc1c9..b948920321 100644 --- a/ignite/templates/app/stargate/go.sum +++ b/ignite/templates/app/stargate/go.sum @@ -470,6 +470,8 @@ github.com/cosmos/cosmos-sdk v0.45.3/go.mod h1:qYm5JEr0ZlbnmoP/Q3b+dYMOliHf4ddHi github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= +github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd/go.mod h1:3xOIaNNX19p0QrX0VqWa6voPRoJRGGYtny+DH8NEPvE= github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7uMjgxke/I= github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4= @@ -581,12 +583,14 @@ github.com/ethereum/go-ethereum v1.9.25/go.mod h1:vMkFiYLHI4tgPw4k2j4MHKoovchFE8 github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= -github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 h1:E2s37DuLxFhQDg5gKsWoLBOB0n+ZW8s599zru8FJ2/Y= github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -751,6 +755,7 @@ github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2V github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -918,6 +923,7 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0/go.mod h1:XnLCLFp3tjoZJszVKjfpyAK6J8sYIcQXWQxmqLWF21I= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -991,6 +997,9 @@ github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHL github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ignite-hq/cli v0.20.0/go.mod h1:kOs9GoMwvbIkbgIZP/LWE/qpw1eaqwPchWtNBIUSElY= +github.com/ignite-hq/cli v0.20.3 h1:MFmClpkLyIN+LUR6GEIqyVvILku4aTl/FWOSWSN3Y7Q= +github.com/ignite-hq/cli v0.20.3/go.mod h1:kOs9GoMwvbIkbgIZP/LWE/qpw1eaqwPchWtNBIUSElY= github.com/imdario/mergo v0.3.4/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -1645,7 +1654,6 @@ github.com/takuoki/gocase v1.0.0 h1:gPwLJTWVm2T1kUiCsKirg/faaIUGVTI0FA3SYr75a44= github.com/takuoki/gocase v1.0.0/go.mod h1:QgOKJrbuJoDrtoKswBX1/Dw8mJrkOV9tbQZJaxaJ6zc= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= -github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s= github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U= @@ -1658,8 +1666,10 @@ github.com/tendermint/go-amino v0.16.0 h1:GyhmgQKvqF82e2oZeuMSp9JTN0N09emoSZlb2l github.com/tendermint/go-amino v0.16.0/go.mod h1:TQU0M1i/ImAo+tYpZi73AU3V/dKeCoMC9Sphe2ZwGME= github.com/tendermint/spm v0.1.8/go.mod h1:iHgfQ5YOI6ONc9E7ugGQolVdfSMHpeXfZ/OpXuN/42Q= github.com/tendermint/spn v0.1.1-0.20211210094128-4ca78a240c57/go.mod h1:p4BO8YC6kOKSKqMfySqaLHfwBmuPE/QcLwnnVhh7H9M= -github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150 h1:FJI3e3R0WsSD5rM+z/OUaxk2Qlx0hfyAI9I76F6a7wk= github.com/tendermint/spn v0.1.1-0.20220407154406-5cfd1bf28150/go.mod h1:B+KuhkB4Sms4yh0UN1HGsVbbMa3vCypai22QXLudQ3o= +github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030 h1:1S5urE/lHktsawx/I4r6iHiV1Ylfhp8mQZ5eQKbY1bA= +github.com/tendermint/spn v0.2.1-0.20220427143342-de7398284030/go.mod h1:9wXyogMDn9fK85s+bSADy+wvZ27DjLEByByMM+0O6NU= +github.com/tendermint/starport v0.19.5/go.mod h1:XdbMpJ5R6QzP1+yrfsoCk44fnp9/52raponbkvjIMQA= github.com/tendermint/tendermint v0.34.0-rc4/go.mod h1:yotsojf2C1QBOw4dZrTcxbyxmPUrT4hNuOQWX9XUwB4= github.com/tendermint/tendermint v0.34.0-rc6/go.mod h1:ugzyZO5foutZImv0Iyx/gOFCX6mjJTgbLHTwi17VDVg= github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESxkbA3yo/INM4QwQ= @@ -1671,8 +1681,9 @@ github.com/tendermint/tendermint v0.34.19/go.mod h1:R5+wgIwSxMdKQcmOaeudL0Cjkr3H github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= github.com/tendermint/tm-db v0.6.4/go.mod h1:dptYhIpJ2M5kUuenLr+Yyf3zQOv1SgBZcl8/BmWlMBw= -github.com/tendermint/tm-db v0.6.6 h1:EzhaOfR0bdKyATqcd5PNeyeq8r+V4bRPHBfyFdD9kGM= github.com/tendermint/tm-db v0.6.6/go.mod h1:wP8d49A85B7/erz/r4YbKssKw6ylsO/hKtFk7E1aWZI= +github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu8= +github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= github.com/tendermint/vue v0.3.5/go.mod h1:Sg9MGPF+uY+SJ79sdZgtC2LnH+FDU2qWuiRxoZn5bmw= github.com/tetafro/godot v1.4.9/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/tidwall/gjson v1.6.7/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI= @@ -2001,6 +2012,7 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2565,4 +2577,5 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 42921ac197ca5c4ed27cb97a52cf81cb9d151037 Mon Sep 17 00:00:00 2001 From: Sonia Singla Date: Wed, 4 May 2022 19:46:02 +0530 Subject: [PATCH 19/30] docs: bounty details in the readme file (#2423) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixes #2285 - Update discord link * Add bounty details in the readme file * update discord * Update readme.md Co-authored-by: Barrie Byron * remove the npm preview and use cli * fix primary contributing mentions * update docs contributing to remove npm * update bounty mentions * add link to the bounty page * add link to bounty page * add back in the preview URL * add order and Kyve to list of projects building with * add order and Kyve to list of projects building with * Update docs/bounty/index.md Co-authored-by: Barrie Byron Co-authored-by: barriebyron <> Co-authored-by: İlker G. Öztürk --- contributing.md | 2 +- docs/bounty/index.md | 17 ++++++++++ docs/contributing/index.md | 69 ++++++-------------------------------- docs/readme.md | 7 +++- readme.md | 4 ++- 5 files changed, 38 insertions(+), 61 deletions(-) create mode 100644 docs/bounty/index.md diff --git a/contributing.md b/contributing.md index 47ccd67d6a..af6f3b070e 100644 --- a/contributing.md +++ b/contributing.md @@ -84,6 +84,6 @@ Ignite CLI follows Git Flow for branch strategy shows the issues we are currently working on and what issues we plan to work on. -Contributors, please check the **To Do** column on the project board to find an issue to work on. +Contributors, check the **To Do** column on the project board to find an issue to work on. See the [Ignite CLI bounty program](docs/bounty/index.md) to learn how your participation can earn rewards. We appreciate your contribution! diff --git a/docs/bounty/index.md b/docs/bounty/index.md new file mode 100644 index 0000000000..92d0a43f34 --- /dev/null +++ b/docs/bounty/index.md @@ -0,0 +1,17 @@ +--- +order: 1 +description: Ignite CLI bounty program incentives and rewards. +parent: + order: 7 + title: Bounty program +--- + +# Bounty program + +Our Ignite CLI bounty program provides incentives for your participation and pays rewards. If you know Golang, follow the bounty issues, write code, close issues, and get rewarded. + +Do your bounty hunting in our repo. Track new, in-progress, and completed bounties on the [Bounty board](https://github.com/ignite-hq/cli/projects/5) in GitHub. + +For details on the Ignite CLI bounty program, join the #bounty channel in [Ignite Discord](https://discord.com/invite/ignite). + +New bounties are posted and claimed in Discord on the #bounty announcement channel. diff --git a/docs/contributing/index.md b/docs/contributing/index.md index 58e8bdc44c..00141223fa 100644 --- a/docs/contributing/index.md +++ b/docs/contributing/index.md @@ -1,15 +1,11 @@ +--- +parent: + order: 6 + title: Contributing to Ignite CLI docs +--- + # Contributing to Ignite CLI docs -- [Contributing to Ignite CLI docs](#contributing-to-ignite-cli-docs) - - [Using this repo](#using-this-repo) - - [Reviewing technical content PRs](#reviewing-technical-content-prs) - - [Writing and contributing](#writing-and-contributing) - - [Where can I find the tutorials and docs?](#where-can-i-find-the-tutorials-and-docs) - - [Who works on the tutorials?](#who-works-on-the-tutorials) - - [Viewing tutorial builds](#viewing-tutorial-builds) - - [Preview PRs on a deployed preview](#preview-prs-on-a-deployed-preview) - - [Preview draft PRs on a local web browser](#preview-draft-prs-on-a-local-web-browser) - Thank you for visiting our repository and considering making contributions. We appreciate your interest in helping us to create and maintain awesome tutorials and documentation. To set up your environment for success, follow the [technical setup](technical-setup.md) guidelines. @@ -26,7 +22,7 @@ Review existing [Ignite CLI issues](https://github.com/ignite-hq/cli/issues) to Some of the best content contributions come during the PR review cycles. Follow best practices for technical content PR reviews just like you do for code reviews. -- For in-line suggestions, use the [GitHub suggesting feature](https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request). +- For in-line suggestions, use the [GitHub suggesting feature](https://docs.github.com/en/github/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/commenting-on-a-pull-request). - The PR owner can merge in your suggested commits one at a time or in batch (preferred). - When you are providing a more granular extensive review that results in more than 20 in-line suggestions, go ahead and check out the branch and make the changes yourself. @@ -70,52 +66,9 @@ The Ignite product team developers are focused on building Ignite CLI and improv Meet the [people behind Ignite CLI and our contributors](https://github.com/ignite-hq/cli/graphs/contributors). -## Viewing tutorial builds - -There are two ways to see what your changes will look like in production before the updated pages are published. - -- When a PR is ready for review, you can see a deployed preview on a URL that is unique for that PR. -- While a PR is in draft mode, you can preview a local build. - -### Preview PRs on a deployed preview - -After the PR moves from **Draft** to **Ready for review**, the CI status checks generate a CloudFlare deploy preview. This preview stays up to date as you continue to work and commit new changes to the same branch. - -To view a deployed preview on a **Ready for review** PR, click the CloudFlare Pages **Preview URL** link. - -### Preview draft PRs on a local web browser - -Since the deploy preview doesn't work on Draft PRs, you can rely on using the preview in Markdown or for more complex content updates you can follow these steps to preview a tutorial and docs build on a local web browser. - -1. If you haven't already, clone the tutorials repo to your local machine and change to that directory. For example: - - ```bash - cd ~/github - git clone https://github.com/ignite-hq/cli - cd ignite - cd docs - ``` - -2. Local tutorials require JavaScript. If needed, install [npm](https://docs.npmjs.com/cli/v6/commands/npm-install). - -3. For each branch you work in, install the npm packages for the tutorials: - - ```bash - npm install - ``` - -4. Start the local instance of the tutorial build: - - ```bash - npm run serve - ``` - - A successful client compile looks like: - - ```bash - > VuePress dev server listening at http://localhost:8080/ ✔ Client Compiled successfully in 280.71ms success [12:06:28] Build 03d41f finished in 283 ms! ( http://localhost:8080/ ) - ``` +## Viewing docs builds -5. You can now view the docs build on a local web browser. Isn't this fun? +Use a preview to see what your changes will look like in production before the updated pages are published. - Tip: On a Mac, press the command key and click `http://localhost:8080/` in the terminal window for quick access to the local preview. If you are already using port 8080 on your local machine, the preview increments to the next available port 8081, and so on. +- While a PR is in draft mode, you can rely on using the preview feature in Markdown. +- After the PR moves from **Draft** to **Ready for review**, the CI status checks generate a deploy preview. This preview stays up to date as you continue to work and commit new changes to the same branch. A `Docs Deploy Preview / build_and_deploy (pull_request)` preview on a GitHub actions URL is unique for that PR. diff --git a/docs/readme.md b/docs/readme.md index d0565db8d5..555fc05cee 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -23,13 +23,18 @@ To install the `ignite` binary in `/usr/local/bin` run the following command: curl https://get.ignite.com/cli! | bash ``` +## Bounty program + +Our [Ignite CLI bounty program](bounty/index.md) provides incentives for your participation and pays rewards. + ## Projects using Tendermint and Cosmos SDK -Many projects already showcase the Tendermint BFT consensus engine and the Cosmos SDK. Explore the [Cosmos Network Ecosystem](https://cosmos.network/ecosystem/apps) to discover a wide variety of apps, blockchains, wallets, and explorers that are built in the Cosmos ecosystem. +Many projects already showcase the Tendermint BFT consensus engine and the Cosmos SDK. Explore the [Cosmos ecosystem](https://cosmos.network/ecosystem/apps) to discover a wide variety of apps, blockchains, wallets, and explorers that are built in the Cosmos ecosystem. ## Projects building with Ignite CLI * [Sifchain: omni-chain solution for DEXs](https://github.com/Sifchain/sifnode) +* [Kyve](https://www.kyve.network/) * [crypto.org chain](https://github.com/crypto-org-chain/chain-main) ([initialized with Ignite CLI](https://github.com/crypto-org-chain/chain-main/commit/37b2ecb49a9aae7c581270a4f2dbecfcd8e8a6e9)) * [Cronos](https://github.com/crypto-org-chain/cronos) * [Plugchain](https://github.com/oracleNetworkProtocol/plugchain) diff --git a/readme.md b/readme.md index d762a5c231..f982c6373e 100644 --- a/readme.md +++ b/readme.md @@ -43,7 +43,9 @@ To upgrade your blockchain to the newer version of Cosmos SDK, see the [Migratio ## Contributing -We welcome contributions from everyone. The `develop` branch contains the development version of the code. You can create a branch from `develop` and create a pull request, or maintain your own fork and submit a cross-repository pull request. +We welcome contributions from everyone. The `develop` branch contains the development version of the code. You can create a branch from `develop` and create a pull request, or maintain your own fork and submit a cross-repository pull request. + +Our [Ignite CLI bounty program](docs/bounty/index.md) provides incentives for your participation and pays rewards. Track new, in-progress, and completed bounties on the [Bounty board](https://github.com/ignite-hq/cli/projects/5) in GitHub. **Important** Before you start implementing a new Ignite CLI feature, the first step is to create an issue on Github that describes the proposed changes. From 5f502e12715f1c0aa4364d8541f57688909bd3c6 Mon Sep 17 00:00:00 2001 From: Petr Ivanov Date: Thu, 5 May 2022 15:19:39 +0400 Subject: [PATCH 20/30] refactor: add `cliui` package (#2411) * cliui 1st iteration * cliui refactor network commands * fix lint * configure bus channel size with option * fix events tests * add spinner options * revert import formatting * fix events tests again * fix spinner * do review fixes Co-authored-by: Petr Ivanov --- ignite/cmd/account.go | 4 +- ignite/cmd/account_import.go | 2 +- ignite/cmd/chain_build.go | 9 +- ignite/cmd/chain_init.go | 5 +- ignite/cmd/cmd.go | 29 +- ignite/cmd/generate_dart.go | 2 +- ignite/cmd/generate_go.go | 2 +- ignite/cmd/generate_openapi.go | 2 +- ignite/cmd/generate_vuex.go | 2 +- ignite/cmd/network.go | 52 ++- ignite/cmd/network_campaign_account.go | 59 ++- ignite/cmd/network_campaign_list.go | 24 +- ignite/cmd/network_campaign_publish.go | 19 +- ignite/cmd/network_campaign_show.go | 19 +- ignite/cmd/network_campaign_update.go | 18 +- ignite/cmd/network_chain_init.go | 46 +-- ignite/cmd/network_chain_install.go | 21 +- ignite/cmd/network_chain_join.go | 47 +-- ignite/cmd/network_chain_launch.go | 10 +- ignite/cmd/network_chain_list.go | 30 +- ignite/cmd/network_chain_prepare.go | 20 +- ignite/cmd/network_chain_publish.go | 32 +- ignite/cmd/network_chain_revert_launch.go | 10 +- ignite/cmd/network_chain_show.go | 346 +----------------- ignite/cmd/network_chain_show_accounts.go | 80 ++++ ignite/cmd/network_chain_show_genesis.go | 93 +++++ ignite/cmd/network_chain_show_info.go | 68 ++++ ignite/cmd/network_chain_show_peers.go | 78 ++++ ignite/cmd/network_chain_show_validators.go | 60 +++ ignite/cmd/network_request_approve.go | 25 +- ignite/cmd/network_request_list.go | 24 +- ignite/cmd/network_request_reject.go | 21 +- ignite/cmd/network_request_show.go | 20 +- ignite/cmd/network_request_verify.go | 20 +- ignite/cmd/network_reward_set.go | 10 +- ignite/cmd/relayer_configure.go | 8 +- ignite/cmd/relayer_connect.go | 2 +- ignite/cmd/scaffold.go | 2 +- ignite/cmd/scaffold_band.go | 2 +- ignite/cmd/scaffold_chain.go | 2 +- ignite/cmd/scaffold_flutter.go | 2 +- ignite/cmd/scaffold_message.go | 2 +- ignite/cmd/scaffold_module.go | 2 +- ignite/cmd/scaffold_mwasm.go | 2 +- ignite/cmd/scaffold_package.go | 2 +- ignite/cmd/scaffold_query.go | 2 +- ignite/cmd/scaffold_vue.go | 2 +- ignite/pkg/{ => cliui}/cliquiz/question.go | 0 .../pkg/{ => cliui}/clispinner/clispinner.go | 35 +- ignite/pkg/cliui/cliui.go | 181 +++++++++ ignite/pkg/cliui/colors/colors.go | 5 + .../{ => cliui}/entrywriter/entrywriter.go | 0 .../entrywriter/entrywriter_test.go | 3 +- .../pkg/{clispinner => cliui/icons}/icon.go | 2 +- ignite/pkg/events/events.go | 70 +++- ignite/pkg/events/events_test.go | 90 ++--- ignite/services/network/reward.go | 9 +- 57 files changed, 1004 insertions(+), 730 deletions(-) create mode 100644 ignite/cmd/network_chain_show_accounts.go create mode 100644 ignite/cmd/network_chain_show_genesis.go create mode 100644 ignite/cmd/network_chain_show_info.go create mode 100644 ignite/cmd/network_chain_show_peers.go create mode 100644 ignite/cmd/network_chain_show_validators.go rename ignite/pkg/{ => cliui}/cliquiz/question.go (100%) rename ignite/pkg/{ => cliui}/clispinner/clispinner.go (65%) create mode 100644 ignite/pkg/cliui/cliui.go create mode 100644 ignite/pkg/cliui/colors/colors.go rename ignite/pkg/{ => cliui}/entrywriter/entrywriter.go (100%) rename ignite/pkg/{ => cliui}/entrywriter/entrywriter_test.go (94%) rename ignite/pkg/{clispinner => cliui/icons}/icon.go (95%) diff --git a/ignite/cmd/account.go b/ignite/cmd/account.go index c88366d3e0..065c6e84d9 100644 --- a/ignite/cmd/account.go +++ b/ignite/cmd/account.go @@ -6,9 +6,9 @@ import ( "github.com/spf13/cobra" flag "github.com/spf13/pflag" - "github.com/ignite-hq/cli/ignite/pkg/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" ) const ( diff --git a/ignite/cmd/account_import.go b/ignite/cmd/account_import.go index 7012cd4c98..d990ee2295 100644 --- a/ignite/cmd/account_import.go +++ b/ignite/cmd/account_import.go @@ -8,7 +8,7 @@ import ( "github.com/cosmos/go-bip39" "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" ) diff --git a/ignite/cmd/chain_build.go b/ignite/cmd/chain_build.go index 7a51128839..3a82edec7f 100644 --- a/ignite/cmd/chain_build.go +++ b/ignite/cmd/chain_build.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" "github.com/ignite-hq/cli/ignite/pkg/chaincmd" + "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" "github.com/ignite-hq/cli/ignite/services/chain" ) @@ -49,7 +50,7 @@ Sample usages: return c } -func chainBuildHandler(cmd *cobra.Command, args []string) error { +func chainBuildHandler(cmd *cobra.Command, _ []string) error { var ( isRelease, _ = cmd.Flags().GetBool(flagRelease) releaseTargets, _ = cmd.Flags().GetStringSlice(flagReleaseTargets) @@ -77,7 +78,7 @@ func chainBuildHandler(cmd *cobra.Command, args []string) error { return err } - fmt.Printf("🗃 Release created: %s\n", infoColor(releasePath)) + fmt.Printf("🗃 Release created: %s\n", colors.Info(releasePath)) return nil } @@ -88,10 +89,10 @@ func chainBuildHandler(cmd *cobra.Command, args []string) error { } if output == "" { - fmt.Printf("🗃 Installed. Use with: %s\n", infoColor(binaryName)) + fmt.Printf("🗃 Installed. Use with: %s\n", colors.Info(binaryName)) } else { binaryPath := filepath.Join(output, binaryName) - fmt.Printf("🗃 Binary built at the path: %s\n", infoColor(binaryPath)) + fmt.Printf("🗃 Binary built at the path: %s\n", colors.Info(binaryPath)) } return nil diff --git a/ignite/cmd/chain_init.go b/ignite/cmd/chain_init.go index ec9f699cee..3c887238b8 100644 --- a/ignite/cmd/chain_init.go +++ b/ignite/cmd/chain_init.go @@ -6,6 +6,7 @@ import ( "github.com/spf13/cobra" "github.com/ignite-hq/cli/ignite/pkg/chaincmd" + "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" "github.com/ignite-hq/cli/ignite/services/chain" ) @@ -23,7 +24,7 @@ func NewChainInit() *cobra.Command { return c } -func chainInitHandler(cmd *cobra.Command, args []string) error { +func chainInitHandler(cmd *cobra.Command, _ []string) error { chainOption := []chain.Option{ chain.LogLevel(logLevel(cmd)), chain.KeyringBackend(chaincmd.KeyringBackendTest), @@ -47,7 +48,7 @@ func chainInitHandler(cmd *cobra.Command, args []string) error { return err } - fmt.Printf("🗃 Initialized. Checkout your chain's home (data) directory: %s\n", infoColor(home)) + fmt.Printf("🗃 Initialized. Checkout your chain's home (data) directory: %s\n", colors.Info(home)) return nil } diff --git a/ignite/cmd/cmd.go b/ignite/cmd/cmd.go index 040244cafa..538d4db027 100644 --- a/ignite/cmd/cmd.go +++ b/ignite/cmd/cmd.go @@ -7,23 +7,19 @@ import ( "path/filepath" "sort" "strings" - "sync" "time" "github.com/fatih/color" - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosver" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/pkg/gitpod" "github.com/ignite-hq/cli/ignite/pkg/goenv" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/services/chain" "github.com/ignite-hq/cli/ignite/services/scaffolder" "github.com/ignite-hq/cli/ignite/version" + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" ) const ( @@ -35,8 +31,6 @@ const ( checkVersionTimeout = time.Millisecond * 600 ) -var infoColor = color.New(color.FgYellow).SprintFunc() - // New creates a new root command for `Ignite CLI` with its sub commands. func New(ctx context.Context) *cobra.Command { cobra.EnableCommandSorting = false @@ -82,25 +76,6 @@ func logLevel(cmd *cobra.Command) chain.LogLvl { return chain.LogRegular } -func printEvents(wg *sync.WaitGroup, bus events.Bus, s *clispinner.Spinner) { - defer wg.Done() - - for event := range bus { - switch event.Status { - case events.StatusOngoing: - s.SetText(event.Text()) - s.Start() - case events.StatusDone: - icon := event.Icon - if icon == "" { - icon = clispinner.OK - } - s.Stop() - fmt.Printf("%s %s\n", icon, event.Text()) - } - } -} - func flagSetPath(cmd *cobra.Command) { cmd.PersistentFlags().StringP(flagPath, "p", ".", "path of the app") } diff --git a/ignite/cmd/generate_dart.go b/ignite/cmd/generate_dart.go index 8acf949391..ef9bdd6456 100644 --- a/ignite/cmd/generate_dart.go +++ b/ignite/cmd/generate_dart.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/chain" ) diff --git a/ignite/cmd/generate_go.go b/ignite/cmd/generate_go.go index cf720a6186..5f9d4b0d8d 100644 --- a/ignite/cmd/generate_go.go +++ b/ignite/cmd/generate_go.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/chain" ) diff --git a/ignite/cmd/generate_openapi.go b/ignite/cmd/generate_openapi.go index 6d51cfd8d8..a76ebcb862 100644 --- a/ignite/cmd/generate_openapi.go +++ b/ignite/cmd/generate_openapi.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/chain" ) diff --git a/ignite/cmd/generate_vuex.go b/ignite/cmd/generate_vuex.go index cbf07686e5..43816aa385 100644 --- a/ignite/cmd/generate_vuex.go +++ b/ignite/cmd/generate_vuex.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/chain" ) diff --git a/ignite/cmd/network.go b/ignite/cmd/network.go index f1554e0e05..14c225dee2 100644 --- a/ignite/cmd/network.go +++ b/ignite/cmd/network.go @@ -1,12 +1,9 @@ package ignitecmd import ( - "sync" - "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosclient" "github.com/ignite-hq/cli/ignite/pkg/events" @@ -68,46 +65,49 @@ func NewNetwork() *cobra.Command { var cosmos *cosmosclient.Client -type NetworkBuilder struct { - AccountRegistry cosmosaccount.Registry - Spinner *clispinner.Spinner +type ( + NetworkBuilderOption func(builder *NetworkBuilder) - ev events.Bus - wg *sync.WaitGroup - cmd *cobra.Command - cc cosmosclient.Client -} + NetworkBuilder struct { + AccountRegistry cosmosaccount.Registry -func newNetworkBuilder(cmd *cobra.Command) (NetworkBuilder, error) { - var err error + ev events.Bus + cmd *cobra.Command + cc cosmosclient.Client + } +) - n := NetworkBuilder{ - Spinner: clispinner.New(), - ev: events.NewBus(), - wg: &sync.WaitGroup{}, - cmd: cmd, +func CollectEvents(ev events.Bus) NetworkBuilderOption { + return func(builder *NetworkBuilder) { + builder.ev = ev } +} - n.wg.Add(1) - go printEvents(n.wg, n.ev, n.Spinner) +func newNetworkBuilder(cmd *cobra.Command, options ...NetworkBuilderOption) (NetworkBuilder, error) { + var ( + err error + n = NetworkBuilder{cmd: cmd} + ) if n.cc, err = getNetworkCosmosClient(cmd); err != nil { - n.Cleanup() return NetworkBuilder{}, err } n.AccountRegistry = n.cc.AccountRegistry + for _, apply := range options { + apply(&n) + } return n, nil } func (n NetworkBuilder) Chain(source networkchain.SourceOption, options ...networkchain.Option) (*networkchain.Chain, error) { - options = append(options, networkchain.CollectEvents(n.ev)) - if home := getHome(n.cmd); home != "" { options = append(options, networkchain.WithHome(home)) } + options = append(options, networkchain.CollectEvents(n.ev)) + return networkchain.New(n.cmd.Context(), n.AccountRegistry, source, options...) } @@ -129,12 +129,6 @@ func (n NetworkBuilder) Network(options ...network.Option) (network.Network, err return network.New(*cosmos, account, options...), nil } -func (n NetworkBuilder) Cleanup() { - n.Spinner.Stop() - n.ev.Shutdown() - n.wg.Wait() -} - func getNetworkCosmosClient(cmd *cobra.Command) (cosmosclient.Client, error) { // check preconfigured networks if nightly && local { diff --git a/ignite/cmd/network_campaign_account.go b/ignite/cmd/network_campaign_account.go index 0b0f995175..f645d70ac8 100644 --- a/ignite/cmd/network_campaign_account.go +++ b/ignite/cmd/network_campaign_account.go @@ -1,18 +1,15 @@ package ignitecmd import ( - "bytes" "context" - "fmt" "strconv" - "github.com/spf13/cobra" - "golang.org/x/sync/errgroup" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" ) var ( @@ -44,42 +41,33 @@ func newNetworkCampaignAccountList() *cobra.Command { } func newNetworkCampaignAccountListHandler(cmd *cobra.Command, args []string) error { - nb, campaignID, err := networkChainLaunch(cmd, args) + session := cliui.New() + defer session.Cleanup() + + nb, campaignID, err := networkChainLaunch(cmd, args, session) if err != nil { return err } - defer nb.Cleanup() - n, err := nb.Network() if err != nil { return err } - accountSummary := &bytes.Buffer{} - // get all campaign accounts mainnetAccs, vestingAccs, err := getAccounts(cmd.Context(), n, campaignID) if err != nil { return err } + if len(mainnetAccs)+len(vestingAccs) == 0 { + session.StopSpinner() + return session.Printf("%s %s\n", icons.Info, "no campaign account found") + } + mainnetAccEntries := make([][]string, 0) for _, acc := range mainnetAccs { - mainnetAccEntries = append(mainnetAccEntries, []string{ - acc.Address, - acc.Shares.String(), - }) + mainnetAccEntries = append(mainnetAccEntries, []string{acc.Address, acc.Shares.String()}) } - if len(mainnetAccEntries) > 0 { - if err = entrywriter.MustWrite( - accountSummary, - campaignMainnetsAccSummaryHeader, - mainnetAccEntries..., - ); err != nil { - return err - } - } - mainnetVestingAccEntries := make([][]string, 0) for _, acc := range vestingAccs { mainnetVestingAccEntries = append(mainnetVestingAccEntries, []string{ @@ -89,22 +77,19 @@ func newNetworkCampaignAccountListHandler(cmd *cobra.Command, args []string) err strconv.FormatInt(acc.EndTime, 10), }) } + + session.StopSpinner() + if len(mainnetAccEntries) > 0 { + if err = session.PrintTable(campaignMainnetsAccSummaryHeader, mainnetAccEntries...); err != nil { + return err + } + } if len(mainnetVestingAccEntries) > 0 { - if err = entrywriter.MustWrite( - accountSummary, - campaignVestingAccSummaryHeader, - mainnetVestingAccEntries..., - ); err != nil { + if err = session.PrintTable(campaignVestingAccSummaryHeader, mainnetVestingAccEntries...); err != nil { return err } } - nb.Spinner.Stop() - if accountSummary.Len() > 0 { - fmt.Print(accountSummary.String()) - } else { - fmt.Printf("%s %s\n", clispinner.Info, "no campaign account found") - } return nil } diff --git a/ignite/cmd/network_campaign_list.go b/ignite/cmd/network_campaign_list.go index 20f1a3dee9..a3d65caad9 100644 --- a/ignite/cmd/network_campaign_list.go +++ b/ignite/cmd/network_campaign_list.go @@ -2,13 +2,11 @@ package ignitecmd import ( "fmt" - "io" - "os" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" ) var CampaignSummaryHeader = []string{ @@ -29,8 +27,11 @@ func NewNetworkCampaignList() *cobra.Command { return c } -func networkCampaignListHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) +func networkCampaignListHandler(cmd *cobra.Command, _ []string) error { + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } @@ -44,12 +45,11 @@ func networkCampaignListHandler(cmd *cobra.Command, args []string) error { return err } - nb.Cleanup() - return renderCampaignSummaries(campaigns, os.Stdout) + return renderCampaignSummaries(campaigns, session) } // renderCampaignSummaries writes into the provided out, the list of summarized campaigns -func renderCampaignSummaries(campaigns []networktypes.Campaign, out io.Writer) error { +func renderCampaignSummaries(campaigns []networktypes.Campaign, session cliui.Session) error { var campaignEntries [][]string for _, c := range campaigns { @@ -66,5 +66,7 @@ func renderCampaignSummaries(campaigns []networktypes.Campaign, out io.Writer) e }) } - return entrywriter.MustWrite(out, CampaignSummaryHeader, campaignEntries...) + session.StopSpinner() + + return session.PrintTable(CampaignSummaryHeader, campaignEntries...) } diff --git a/ignite/cmd/network_campaign_publish.go b/ignite/cmd/network_campaign_publish.go index 50df66f11b..2439402aa7 100644 --- a/ignite/cmd/network_campaign_publish.go +++ b/ignite/cmd/network_campaign_publish.go @@ -1,12 +1,10 @@ package ignitecmd import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" ) const ( @@ -29,13 +27,14 @@ func NewNetworkCampaignPublish() *cobra.Command { } func networkCampaignPublishHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() - // parse launch ID totalSupply, err := sdk.ParseCoinsNormalized(args[1]) if err != nil { return err @@ -52,7 +51,7 @@ func networkCampaignPublishHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.Stop() - fmt.Printf("%s Campaign ID: %d \n", clispinner.Bullet, campaignID) - return nil + session.StopSpinner() + + return session.Printf("%s Campaign ID: %d \n", icons.Bullet, campaignID) } diff --git a/ignite/cmd/network_campaign_show.go b/ignite/cmd/network_campaign_show.go index c424547d99..0eea507932 100644 --- a/ignite/cmd/network_campaign_show.go +++ b/ignite/cmd/network_campaign_show.go @@ -1,12 +1,10 @@ package ignitecmd import ( - "fmt" - - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" ) // NewNetworkCampaignShow returns a new command to show published campaign on Ignite @@ -21,22 +19,25 @@ func NewNetworkCampaignShow() *cobra.Command { } func networkCampaignShowHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + // parse campaign ID campaignID, err := network.ParseID(args[0]) if err != nil { return err } - nb, err := newNetworkBuilder(cmd) + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() n, err := nb.Network() if err != nil { return err } + campaign, err := n.Campaign(cmd.Context(), campaignID) if err != nil { return err @@ -47,7 +48,7 @@ func networkCampaignShowHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.Stop() - fmt.Print(info) - return nil + session.StopSpinner() + + return session.Println(info) } diff --git a/ignite/cmd/network_campaign_update.go b/ignite/cmd/network_campaign_update.go index c302ac0f02..ab63364eb6 100644 --- a/ignite/cmd/network_campaign_update.go +++ b/ignite/cmd/network_campaign_update.go @@ -5,10 +5,10 @@ import ( "strings" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" ) const ( @@ -33,6 +33,9 @@ func NewNetworkCampaignUpdate() *cobra.Command { } func networkCampaignUpdateHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + var ( campaignName, _ = cmd.Flags().GetString(flagCampaignName) metadata, _ = cmd.Flags().GetString(flagCampaignMetadata) @@ -43,11 +46,10 @@ func networkCampaignUpdateHandler(cmd *cobra.Command, args []string) error { return err } - nb, err := newNetworkBuilder(cmd) + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse campaign ID campaignID, err := network.ParseID(args[0]) @@ -90,14 +92,14 @@ func networkCampaignUpdateHandler(cmd *cobra.Command, args []string) error { if err != nil { return err } - fmt.Println("") + session.Println() info, err := yaml.Marshal(cmd.Context(), campaign) if err != nil { return err } - nb.Spinner.Stop() - fmt.Print(info) - return nil + session.StopSpinner() + + return session.Print(info) } diff --git a/ignite/cmd/network_chain_init.go b/ignite/cmd/network_chain_init.go index c091f74602..635f731bfc 100644 --- a/ignite/cmd/network_chain_init.go +++ b/ignite/cmd/network_chain_init.go @@ -3,16 +3,15 @@ package ignitecmd import ( "fmt" - "github.com/manifoldco/promptui" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/cliquiz" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/services/chain" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" ) const ( @@ -50,11 +49,13 @@ func NewNetworkChainInit() *cobra.Command { } func networkChainInitHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -76,18 +77,13 @@ func networkChainInitHandler(cmd *cobra.Command, args []string) error { } if !getYes(cmd) && exist { - prompt := promptui.Prompt{ - Label: fmt.Sprintf("The chain has already been initialized under: %s. Would you like to overwrite the home directory", - chainHome, - ), - IsConfirm: true, - } - nb.Spinner.Stop() - if _, err := prompt.Run(); err != nil { - fmt.Println("said no") - return nil + question := fmt.Sprintf( + "The chain has already been initialized under: %s. Would you like to overwrite the home directory", + chainHome, + ) + if err := session.AskConfirm(question); err != nil { + return session.PrintSaidNo() } - nb.Spinner.Start() } n, err := nb.Network() @@ -120,26 +116,24 @@ func networkChainInitHandler(cmd *cobra.Command, args []string) error { } // ask validator information. - v, err := askValidatorInfo(cmd, genesis.StakeDenom) + v, err := askValidatorInfo(cmd, session, genesis.StakeDenom) if err != nil { return err } - nb.Spinner.SetText("Generating your Gentx") - nb.Spinner.Start() + session.StartSpinner("Generating your Gentx") gentxPath, err := c.InitAccount(cmd.Context(), v, validatorAccount) if err != nil { return err } - nb.Spinner.Stop() - fmt.Printf("%s Gentx generated: %s\n", clispinner.Bullet, gentxPath) + session.StopSpinner() - return nil + return session.Printf("%s Gentx generated: %s\n", icons.Bullet, gentxPath) } // askValidatorInfo prompts to the user questions to query validator information -func askValidatorInfo(cmd *cobra.Command, stakeDenom string) (chain.Validator, error) { +func askValidatorInfo(cmd *cobra.Command, session cliui.Session, stakeDenom string) (chain.Validator, error) { var ( account, _ = cmd.Flags().GetString(flagValidatorAccount) website, _ = cmd.Flags().GetString(flagValidatorWebsite) @@ -186,5 +180,5 @@ func askValidatorInfo(cmd *cobra.Command, stakeDenom string) (chain.Validator, e cliquiz.Required(), ), ) - return v, cliquiz.Ask(questions...) + return v, session.Ask(questions...) } diff --git a/ignite/cmd/network_chain_install.go b/ignite/cmd/network_chain_install.go index cc92ed3e40..fba6b94fda 100644 --- a/ignite/cmd/network_chain_install.go +++ b/ignite/cmd/network_chain_install.go @@ -1,15 +1,15 @@ package ignitecmd import ( - "fmt" "path/filepath" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/goenv" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" ) // NewNetworkChainInstall returns a new command to install a chain's binary by the launch id. @@ -25,11 +25,13 @@ func NewNetworkChainInstall() *cobra.Command { } func networkChainInstallHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -58,9 +60,10 @@ func networkChainInstallHandler(cmd *cobra.Command, args []string) error { } binaryPath := filepath.Join(goenv.Bin(), binaryName) - fmt.Printf("%s Binary installed\n", clispinner.OK) - fmt.Printf("%s Binary's name: %s\n", clispinner.Info, infoColor(binaryName)) - fmt.Printf("%s Binary's path: %s\n", clispinner.Info, infoColor(binaryPath)) + session.StopSpinner() + session.Printf("%s Binary installed\n", icons.OK) + session.Printf("%s Binary's name: %s\n", icons.Info, colors.Info(binaryName)) + session.Printf("%s Binary's path: %s\n", icons.Info, colors.Info(binaryPath)) return nil } diff --git a/ignite/cmd/network_chain_join.go b/ignite/cmd/network_chain_join.go index c8cb33566c..8ee562f681 100644 --- a/ignite/cmd/network_chain_join.go +++ b/ignite/cmd/network_chain_join.go @@ -5,17 +5,16 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/manifoldco/promptui" - "github.com/pkg/errors" - "github.com/rdegges/go-ipify" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/cliquiz" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/gitpod" "github.com/ignite-hq/cli/ignite/pkg/xchisel" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/pkg/errors" + "github.com/rdegges/go-ipify" + "github.com/spf13/cobra" ) const ( @@ -42,16 +41,18 @@ func NewNetworkChainJoin() *cobra.Command { } func networkChainJoinHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + var ( gentxPath, _ = cmd.Flags().GetString(flagGentx) amount, _ = cmd.Flags().GetString(flagAmount) ) - nb, err := newNetworkBuilder(cmd) + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID. launchID, err := network.ParseID(args[0]) @@ -66,7 +67,7 @@ func networkChainJoinHandler(cmd *cobra.Command, args []string) error { // if there is no custom gentx, we need to detect the public address. if gentxPath == "" { // get the peer public address for the validator. - publicAddr, err := askPublicAddress(cmd.Context(), nb.Spinner) + publicAddr, err := askPublicAddress(cmd.Context(), session) if err != nil { return err } @@ -97,22 +98,17 @@ func networkChainJoinHandler(cmd *cobra.Command, args []string) error { } joinOptions = append(joinOptions, network.WithAccountRequest(amountCoins)) } else { - nb.Spinner.Stop() - if !getYes(cmd) { - label := fmt.Sprintf("You haven't set the --%s flag and therefore an account request won't be submitted. Do you confirm", flagAmount) - prompt := promptui.Prompt{ - Label: label, - IsConfirm: true, - } - if _, err := prompt.Run(); err != nil { - fmt.Println("said no") - return nil + question := fmt.Sprintf( + "You haven't set the --%s flag and therefore an account request won't be submitted. Do you confirm", + flagAmount, + ) + if err := session.AskConfirm(question); err != nil { + return session.PrintSaidNo() } } - fmt.Printf("%s %s\n", clispinner.Info, "Account request won't be submitted") - nb.Spinner.Start() + session.Printf("%s %s\n", icons.Info, "Account request won't be submitted") } // create the message to add the validator. @@ -121,10 +117,7 @@ func networkChainJoinHandler(cmd *cobra.Command, args []string) error { // askPublicAddress prepare questions to interactively ask for a publicAddress // when peer isn't provided and not running through chisel proxy. -func askPublicAddress(ctx context.Context, s *clispinner.Spinner) (publicAddress string, err error) { - s.Stop() - defer s.Start() - +func askPublicAddress(ctx context.Context, session cliui.Session) (publicAddress string, err error) { options := []cliquiz.Option{ cliquiz.Required(), } @@ -148,5 +141,5 @@ func askPublicAddress(ctx context.Context, s *clispinner.Spinner) (publicAddress &publicAddress, options..., )} - return publicAddress, cliquiz.Ask(questions...) + return publicAddress, session.Ask(questions...) } diff --git a/ignite/cmd/network_chain_launch.go b/ignite/cmd/network_chain_launch.go index d93946c1d0..50f19bb6a0 100644 --- a/ignite/cmd/network_chain_launch.go +++ b/ignite/cmd/network_chain_launch.go @@ -1,9 +1,9 @@ package ignitecmd import ( - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" ) const ( @@ -28,11 +28,13 @@ func NewNetworkChainLaunch() *cobra.Command { } func networkChainLaunchHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) diff --git a/ignite/cmd/network_chain_list.go b/ignite/cmd/network_chain_list.go index e4686f0b3b..ddde4e40af 100644 --- a/ignite/cmd/network_chain_list.go +++ b/ignite/cmd/network_chain_list.go @@ -2,13 +2,12 @@ package ignitecmd import ( "fmt" - "io" - "os" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" + "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" ) var LaunchSummaryHeader = []string{"launch ID", "chain ID", "source", "campaign ID", "network", "reward"} @@ -24,15 +23,15 @@ func NewNetworkChainList() *cobra.Command { return c } -func networkChainListHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) +func networkChainListHandler(cmd *cobra.Command, _ []string) error { + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - - nb.Spinner.Stop() - - n, err := nb.Network() + n, err := nb.Network(network.CollectEvents(session.EventBus())) if err != nil { return err } @@ -41,12 +40,13 @@ func networkChainListHandler(cmd *cobra.Command, args []string) error { return err } - nb.Cleanup() - return renderLaunchSummaries(chainLaunches, os.Stdout) + session.StopSpinner() + + return renderLaunchSummaries(chainLaunches, session) } // renderLaunchSummaries writes into the provided out, the list of summarized launches -func renderLaunchSummaries(chainLaunches []networktypes.ChainLaunch, out io.Writer) error { +func renderLaunchSummaries(chainLaunches []networktypes.ChainLaunch, session cliui.Session) error { var launchEntries [][]string for _, c := range chainLaunches { @@ -70,5 +70,5 @@ func renderLaunchSummaries(chainLaunches []networktypes.ChainLaunch, out io.Writ }) } - return entrywriter.MustWrite(out, LaunchSummaryHeader, launchEntries...) + return session.PrintTable(LaunchSummaryHeader, launchEntries...) } diff --git a/ignite/cmd/network_chain_prepare.go b/ignite/cmd/network_chain_prepare.go index 9c55a4b735..0f3039d0d8 100644 --- a/ignite/cmd/network_chain_prepare.go +++ b/ignite/cmd/network_chain_prepare.go @@ -4,12 +4,13 @@ import ( "fmt" "path/filepath" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/goenv" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" ) const ( @@ -34,13 +35,15 @@ func NewNetworkChainPrepare() *cobra.Command { } func networkChainPrepareHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + force, _ := cmd.Flags().GetBool(flagForce) - nb, err := newNetworkBuilder(cmd) + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -88,10 +91,11 @@ func networkChainPrepareHandler(cmd *cobra.Command, args []string) error { } binaryDir := filepath.Dir(filepath.Join(goenv.Bin(), binaryName)) - fmt.Printf("%s Chain is prepared for launch\n", clispinner.OK) - fmt.Println("\nYou can start your node by running the following command:") + session.StopSpinner() + session.Printf("%s Chain is prepared for launch\n", icons.OK) + session.Println("\nYou can start your node by running the following command:") commandStr := fmt.Sprintf("%s start --home %s", binaryName, chainHome) - fmt.Printf("\t%s/%s\n", binaryDir, infoColor(commandStr)) + session.Printf("\t%s/%s\n", binaryDir, colors.Info(commandStr)) return nil } diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index 1aa7ba52a8..7900d9255d 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -5,16 +5,16 @@ import ( "os" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/tendermint/spn/pkg/chainid" - campaigntypes "github.com/tendermint/spn/x/campaign/types" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/tendermint/spn/pkg/chainid" + campaigntypes "github.com/tendermint/spn/x/campaign/types" ) const ( @@ -62,6 +62,9 @@ func NewNetworkChainPublish() *cobra.Command { } func networkChainPublishHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + var ( tag, _ = cmd.Flags().GetString(flagTag) branch, _ = cmd.Flags().GetString(flagBranch) @@ -125,11 +128,10 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { return fmt.Errorf("%s and %s flags must be provided together", flagRewardCoins, flagRewardHeight) } - nb, err := newNetworkBuilder(cmd) + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // use source from chosen target. var sourceOption networkchain.SourceOption @@ -214,8 +216,7 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.SetText("Publishing...") - nb.Spinner.Start() + session.StartSpinner("Publishing...") n, err := nb.Network() if err != nil { @@ -233,13 +234,12 @@ func networkChainPublishHandler(cmd *cobra.Command, args []string) error { } } - nb.Spinner.Stop() - - fmt.Printf("%s Network published \n", clispinner.OK) - fmt.Printf("%s Launch ID: %d \n", clispinner.Bullet, launchID) - fmt.Printf("%s Campaign ID: %d \n", clispinner.Bullet, campaignID) + session.StopSpinner() + session.Printf("%s Network published \n", icons.OK) + session.Printf("%s Launch ID: %d \n", icons.Bullet, launchID) + session.Printf("%s Campaign ID: %d \n", icons.Bullet, campaignID) if isMainnet { - fmt.Printf("%s Mainnet ID: %d \n", clispinner.Bullet, mainnetID) + session.Printf("%s Mainnet ID: %d \n", icons.Bullet, mainnetID) } return nil diff --git a/ignite/cmd/network_chain_revert_launch.go b/ignite/cmd/network_chain_revert_launch.go index 860c5f9795..2662c95ae8 100644 --- a/ignite/cmd/network_chain_revert_launch.go +++ b/ignite/cmd/network_chain_revert_launch.go @@ -1,10 +1,10 @@ package ignitecmd import ( - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" ) // NewNetworkChainRevertLaunch creates a new chain revert launch command @@ -24,11 +24,13 @@ func NewNetworkChainRevertLaunch() *cobra.Command { } func networkChainRevertLaunchHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) diff --git a/ignite/cmd/network_chain_show.go b/ignite/cmd/network_chain_show.go index bf79d65935..03c572b572 100644 --- a/ignite/cmd/network_chain_show.go +++ b/ignite/cmd/network_chain_show.go @@ -1,32 +1,13 @@ package ignitecmd import ( - "bytes" - "fmt" - "os" - "path/filepath" - "strconv" - "strings" - - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" - "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" - "github.com/ignite-hq/cli/ignite/pkg/yaml" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" ) const flagOut = "out" -var ( - chainGenesisValSummaryHeader = []string{"Genesis Validator", "Self Delegation", "Peer"} - chainGenesisAccSummaryHeader = []string{"Genesis Account", "Coins"} - chainVestingAccSummaryHeader = []string{"Vesting Account", "Total Balance", "Vesting", "EndTime"} -) - // NewNetworkChainShow creates a new chain show // command to show a chain details on SPN. func NewNetworkChainShow() *cobra.Command { @@ -44,8 +25,8 @@ func NewNetworkChainShow() *cobra.Command { return c } -func networkChainLaunch(cmd *cobra.Command, args []string) (NetworkBuilder, uint64, error) { - nb, err := newNetworkBuilder(cmd) +func networkChainLaunch(cmd *cobra.Command, args []string, session cliui.Session) (NetworkBuilder, uint64, error) { + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return nb, 0, err } @@ -56,322 +37,3 @@ func networkChainLaunch(cmd *cobra.Command, args []string) (NetworkBuilder, uint } return nb, launchID, err } - -func newNetworkChainShowInfo() *cobra.Command { - c := &cobra.Command{ - Use: "info [launch-id]", - Short: "Show info details of the chain", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - nb, launchID, err := networkChainLaunch(cmd, args) - if err != nil { - return err - } - defer nb.Cleanup() - n, err := nb.Network() - if err != nil { - return err - } - - chainLaunch, err := n.ChainLaunch(cmd.Context(), launchID) - if err != nil { - return err - } - - reward, err := n.ChainReward(cmd.Context(), launchID) - if err != nil && err != network.ErrObjectNotFound { - return err - } - chainLaunch.Reward = reward.RemainingCoins.String() - - var genesis []byte - if chainLaunch.GenesisURL != "" { - genesis, _, err = cosmosutil.GenesisAndHashFromURL(cmd.Context(), chainLaunch.GenesisURL) - if err != nil { - return err - } - } - chainInfo := struct { - Chain networktypes.ChainLaunch `json:"Chain"` - Genesis []byte `json:"Genesis"` - }{ - Chain: chainLaunch, - Genesis: genesis, - } - info, err := yaml.Marshal(cmd.Context(), chainInfo, "$.Genesis") - if err != nil { - return err - } - nb.Spinner.Stop() - fmt.Print(info) - return nil - }, - } - return c -} - -func newNetworkChainShowGenesis() *cobra.Command { - c := &cobra.Command{ - Use: "genesis [launch-id]", - Short: "Show the chain genesis file", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - out, _ := cmd.Flags().GetString(flagOut) - - nb, launchID, err := networkChainLaunch(cmd, args) - if err != nil { - return err - } - defer nb.Cleanup() - - n, err := nb.Network() - if err != nil { - return err - } - - chainLaunch, err := n.ChainLaunch(cmd.Context(), launchID) - if err != nil { - return err - } - - c, err := nb.Chain(networkchain.SourceLaunch(chainLaunch)) - if err != nil { - return err - } - - genesisPath, err := c.GenesisPath() - if err != nil { - return err - } - - // check if the genesis already exists - if _, err = os.Stat(genesisPath); os.IsNotExist(err) { - // fetch the information to construct genesis - genesisInformation, err := n.GenesisInformation(cmd.Context(), launchID) - if err != nil { - return err - } - - // create the chain into a temp dir - home := filepath.Join(os.TempDir(), "spn/temp", chainLaunch.ChainID) - defer os.RemoveAll(home) - - c.SetHome(home) - - err = c.Prepare(cmd.Context(), genesisInformation) - if err != nil { - return err - } - - // get the new genesis path - genesisPath, err = c.GenesisPath() - if err != nil { - return err - } - } - - if err := os.MkdirAll(filepath.Dir(out), 0744); err != nil { - return err - } - - if err := os.Rename(genesisPath, out); err != nil { - return err - } - fmt.Printf("%s Genesis generated: %s\n", clispinner.Bullet, out) - - return nil - }, - } - - c.Flags().String(flagOut, "./genesis.json", "Path to output Genesis file") - - return c -} - -func newNetworkChainShowAccounts() *cobra.Command { - c := &cobra.Command{ - Use: "accounts [launch-id]", - Short: "Show all vesting and genesis accounts of the chain", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - nb, launchID, err := networkChainLaunch(cmd, args) - if err != nil { - return err - } - defer nb.Cleanup() - n, err := nb.Network() - if err != nil { - return err - } - - accountSummary := &bytes.Buffer{} - - // get all chain genesis accounts - genesisAccs, err := n.GenesisAccounts(cmd.Context(), launchID) - if err != nil { - return err - } - genesisAccEntries := make([][]string, 0) - for _, acc := range genesisAccs { - genesisAccEntries = append(genesisAccEntries, []string{ - acc.Address, - acc.Coins, - }) - } - if len(genesisAccEntries) > 0 { - if err = entrywriter.MustWrite( - accountSummary, - chainGenesisAccSummaryHeader, - genesisAccEntries..., - ); err != nil { - return err - } - } - - // get all chain vesting accounts - vestingAccs, err := n.VestingAccounts(cmd.Context(), launchID) - if err != nil { - return err - } - genesisVestingAccEntries := make([][]string, 0) - for _, acc := range vestingAccs { - genesisVestingAccEntries = append(genesisVestingAccEntries, []string{ - acc.Address, - acc.TotalBalance, - acc.Vesting, - strconv.FormatInt(acc.EndTime, 10), - }) - } - if len(genesisVestingAccEntries) > 0 { - if err = entrywriter.MustWrite( - accountSummary, - chainVestingAccSummaryHeader, - genesisVestingAccEntries..., - ); err != nil { - return err - } - } - nb.Spinner.Stop() - if accountSummary.Len() > 0 { - fmt.Print(accountSummary.String()) - } else { - fmt.Printf("%s %s\n", clispinner.Info, "empty chain account list") - } - return nil - }, - } - return c -} - -func newNetworkChainShowValidators() *cobra.Command { - c := &cobra.Command{ - Use: "validators [launch-id]", - Short: "Show all validators of the chain", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - nb, launchID, err := networkChainLaunch(cmd, args) - if err != nil { - return err - } - defer nb.Cleanup() - n, err := nb.Network() - if err != nil { - return err - } - - validatorSummary := bytes.NewBufferString("") - validators, err := n.GenesisValidators(cmd.Context(), launchID) - if err != nil { - return err - } - validatorEntries := make([][]string, 0) - for _, acc := range validators { - peer, err := network.PeerAddress(acc.Peer) - if err != nil { - return err - } - validatorEntries = append(validatorEntries, []string{ - acc.Address, - acc.SelfDelegation.String(), - peer, - }) - } - nb.Spinner.Stop() - if len(validatorEntries) > 0 { - if err = entrywriter.MustWrite( - validatorSummary, - chainGenesisValSummaryHeader, - validatorEntries..., - ); err != nil { - return err - } - fmt.Print(validatorSummary.String()) - } else { - fmt.Printf("%s %s\n", clispinner.Info, "no account found") - } - return nil - }, - } - return c -} - -func newNetworkChainShowPeers() *cobra.Command { - c := &cobra.Command{ - Use: "peers [launch-id]", - Short: "Show peers list of the chain", - Args: cobra.ExactArgs(1), - RunE: func(cmd *cobra.Command, args []string) error { - out, _ := cmd.Flags().GetString(flagOut) - - nb, launchID, err := networkChainLaunch(cmd, args) - if err != nil { - return err - } - defer nb.Cleanup() - - n, err := nb.Network() - if err != nil { - return err - } - - genVals, err := n.GenesisValidators(cmd.Context(), launchID) - if err != nil { - return err - } - - peers := make([]string, 0) - for _, acc := range genVals { - peer, err := network.PeerAddress(acc.Peer) - if err != nil { - return err - } - peers = append(peers, peer) - } - nb.Spinner.Stop() - - if len(peers) == 0 { - fmt.Printf("%s %s\n", clispinner.Info, "no peers found") - return nil - - } - - if err := os.MkdirAll(filepath.Dir(out), 0744); err != nil { - return err - } - - b := &bytes.Buffer{} - peerList := strings.Join(peers, ",") - fmt.Fprintln(b, peerList) - if err := os.WriteFile(out, b.Bytes(), 0644); err != nil { - return err - } - - fmt.Printf("%s Peer list generated: %s\n", clispinner.Bullet, out) - return nil - }, - } - - c.Flags().String(flagOut, "./peers.txt", "Path to output peers list") - - return c -} diff --git a/ignite/cmd/network_chain_show_accounts.go b/ignite/cmd/network_chain_show_accounts.go new file mode 100644 index 0000000000..332f4cf350 --- /dev/null +++ b/ignite/cmd/network_chain_show_accounts.go @@ -0,0 +1,80 @@ +package ignitecmd + +import ( + "strconv" + + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/spf13/cobra" +) + +var ( + chainGenesisAccSummaryHeader = []string{"Genesis Account", "Coins"} + chainVestingAccSummaryHeader = []string{"Vesting Account", "Total Balance", "Vesting", "EndTime"} +) + +func newNetworkChainShowAccounts() *cobra.Command { + c := &cobra.Command{ + Use: "accounts [launch-id]", + Short: "Show all vesting and genesis accounts of the chain", + Args: cobra.ExactArgs(1), + RunE: networkChainShowAccountsHandler, + } + + return c +} + +func networkChainShowAccountsHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + nb, launchID, err := networkChainLaunch(cmd, args, session) + if err != nil { + return err + } + n, err := nb.Network() + if err != nil { + return err + } + + genesisAccs, err := n.GenesisAccounts(cmd.Context(), launchID) + if err != nil { + return err + } + vestingAccs, err := n.VestingAccounts(cmd.Context(), launchID) + if err != nil { + return err + } + if len(genesisAccs)+len(vestingAccs) == 0 { + session.StopSpinner() + return session.Printf("%s %s\n", icons.Info, "empty chain account list") + } + + genesisAccEntries := make([][]string, 0) + for _, acc := range genesisAccs { + genesisAccEntries = append(genesisAccEntries, []string{acc.Address, acc.Coins}) + } + genesisVestingAccEntries := make([][]string, 0) + for _, acc := range vestingAccs { + genesisVestingAccEntries = append(genesisVestingAccEntries, []string{ + acc.Address, + acc.TotalBalance, + acc.Vesting, + strconv.FormatInt(acc.EndTime, 10), + }) + } + + session.StopSpinner() + if len(genesisAccEntries) > 0 { + if err = session.PrintTable(chainGenesisAccSummaryHeader, genesisAccEntries...); err != nil { + return err + } + } + if len(genesisVestingAccEntries) > 0 { + if err = session.PrintTable(chainVestingAccSummaryHeader, genesisVestingAccEntries...); err != nil { + return err + } + } + + return nil +} diff --git a/ignite/cmd/network_chain_show_genesis.go b/ignite/cmd/network_chain_show_genesis.go new file mode 100644 index 0000000000..db80c13c47 --- /dev/null +++ b/ignite/cmd/network_chain_show_genesis.go @@ -0,0 +1,93 @@ +package ignitecmd + +import ( + "os" + "path/filepath" + + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" +) + +func newNetworkChainShowGenesis() *cobra.Command { + c := &cobra.Command{ + Use: "genesis [launch-id]", + Short: "Show the chain genesis file", + Args: cobra.ExactArgs(1), + RunE: networkChainShowGenesisHandler, + } + + c.Flags().String(flagOut, "./genesis.json", "Path to output Genesis file") + + return c +} + +func networkChainShowGenesisHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + out, _ := cmd.Flags().GetString(flagOut) + + nb, launchID, err := networkChainLaunch(cmd, args, session) + if err != nil { + return err + } + n, err := nb.Network() + if err != nil { + return err + } + + chainLaunch, err := n.ChainLaunch(cmd.Context(), launchID) + if err != nil { + return err + } + + c, err := nb.Chain(networkchain.SourceLaunch(chainLaunch)) + if err != nil { + return err + } + + genesisPath, err := c.GenesisPath() + if err != nil { + return err + } + + // check if the genesis already exists + if _, err = os.Stat(genesisPath); os.IsNotExist(err) { + // fetch the information to construct genesis + genesisInformation, err := n.GenesisInformation(cmd.Context(), launchID) + if err != nil { + return err + } + + // create the chain in a temp dir + home := filepath.Join(os.TempDir(), "spn/temp", chainLaunch.ChainID) + defer os.RemoveAll(home) + + c.SetHome(home) + + err = c.Prepare(cmd.Context(), genesisInformation) + if err != nil { + return err + } + + // get the new genesis path + genesisPath, err = c.GenesisPath() + if err != nil { + return err + } + } + + if err := os.MkdirAll(filepath.Dir(out), 0744); err != nil { + return err + } + + if err := os.Rename(genesisPath, out); err != nil { + return err + } + + session.StopSpinner() + + return session.Printf("%s Genesis generated: %s\n", icons.Bullet, out) +} diff --git a/ignite/cmd/network_chain_show_info.go b/ignite/cmd/network_chain_show_info.go new file mode 100644 index 0000000000..4040759732 --- /dev/null +++ b/ignite/cmd/network_chain_show_info.go @@ -0,0 +1,68 @@ +package ignitecmd + +import ( + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" + "github.com/ignite-hq/cli/ignite/pkg/yaml" + "github.com/ignite-hq/cli/ignite/services/network" + "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" +) + +func newNetworkChainShowInfo() *cobra.Command { + c := &cobra.Command{ + Use: "info [launch-id]", + Short: "Show info details of the chain", + Args: cobra.ExactArgs(1), + RunE: networkChainShowInfoHandler, + } + return c +} + +func networkChainShowInfoHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + nb, launchID, err := networkChainLaunch(cmd, args, session) + if err != nil { + return err + } + n, err := nb.Network() + if err != nil { + return err + } + + chainLaunch, err := n.ChainLaunch(cmd.Context(), launchID) + if err != nil { + return err + } + + reward, err := n.ChainReward(cmd.Context(), launchID) + if err != nil && err != network.ErrObjectNotFound { + return err + } + chainLaunch.Reward = reward.RemainingCoins.String() + + var genesis []byte + if chainLaunch.GenesisURL != "" { + genesis, _, err = cosmosutil.GenesisAndHashFromURL(cmd.Context(), chainLaunch.GenesisURL) + if err != nil { + return err + } + } + chainInfo := struct { + Chain networktypes.ChainLaunch `json:"Chain"` + Genesis []byte `json:"Genesis"` + }{ + Chain: chainLaunch, + Genesis: genesis, + } + info, err := yaml.Marshal(cmd.Context(), chainInfo, "$.Genesis") + if err != nil { + return err + } + + session.StopSpinner() + + return session.Print(info) +} diff --git a/ignite/cmd/network_chain_show_peers.go b/ignite/cmd/network_chain_show_peers.go new file mode 100644 index 0000000000..cea05e2b62 --- /dev/null +++ b/ignite/cmd/network_chain_show_peers.go @@ -0,0 +1,78 @@ +package ignitecmd + +import ( + "bytes" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" +) + +func newNetworkChainShowPeers() *cobra.Command { + c := &cobra.Command{ + Use: "peers [launch-id]", + Short: "Show peers list of the chain", + Args: cobra.ExactArgs(1), + RunE: networkChainShowPeersHandler, + } + + c.Flags().String(flagOut, "./peers.txt", "Path to output peers list") + + return c +} + +func networkChainShowPeersHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + out, _ := cmd.Flags().GetString(flagOut) + + nb, launchID, err := networkChainLaunch(cmd, args, session) + if err != nil { + return err + } + n, err := nb.Network() + if err != nil { + return err + } + + genVals, err := n.GenesisValidators(cmd.Context(), launchID) + if err != nil { + return err + } + + peers := make([]string, 0) + for _, acc := range genVals { + peer, err := network.PeerAddress(acc.Peer) + if err != nil { + return err + } + peers = append(peers, peer) + } + + if len(peers) == 0 { + session.Printf("%s %s\n", icons.Info, "no peers found") + return nil + + } + + if err := os.MkdirAll(filepath.Dir(out), 0744); err != nil { + return err + } + + b := &bytes.Buffer{} + peerList := strings.Join(peers, ",") + fmt.Fprintln(b, peerList) + if err := os.WriteFile(out, b.Bytes(), 0644); err != nil { + return err + } + + session.StopSpinner() + + return session.Printf("%s Peer list generated: %s\n", icons.Bullet, out) +} diff --git a/ignite/cmd/network_chain_show_validators.go b/ignite/cmd/network_chain_show_validators.go new file mode 100644 index 0000000000..73d37af658 --- /dev/null +++ b/ignite/cmd/network_chain_show_validators.go @@ -0,0 +1,60 @@ +package ignitecmd + +import ( + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" +) + +var ( + chainGenesisValSummaryHeader = []string{"Genesis Validator", "Self Delegation", "Peer"} +) + +func newNetworkChainShowValidators() *cobra.Command { + c := &cobra.Command{ + Use: "validators [launch-id]", + Short: "Show all validators of the chain", + Args: cobra.ExactArgs(1), + RunE: networkChainShowValidatorsHandler, + } + return c +} + +func networkChainShowValidatorsHandler(cmd *cobra.Command, args []string) error { + session := cliui.New() + defer session.Cleanup() + + nb, launchID, err := networkChainLaunch(cmd, args, session) + if err != nil { + return err + } + n, err := nb.Network() + if err != nil { + return err + } + + validators, err := n.GenesisValidators(cmd.Context(), launchID) + if err != nil { + return err + } + validatorEntries := make([][]string, 0) + for _, acc := range validators { + peer, err := network.PeerAddress(acc.Peer) + if err != nil { + return err + } + validatorEntries = append(validatorEntries, []string{ + acc.Address, + acc.SelfDelegation.String(), + peer, + }) + } + if len(validatorEntries) == 0 { + return session.Printf("%s %s\n", icons.Info, "no account found") + } + + session.StopSpinner() + + return session.PrintTable(chainGenesisValSummaryHeader, validatorEntries...) +} diff --git a/ignite/cmd/network_request_approve.go b/ignite/cmd/network_request_approve.go index f36ccab584..dae3f2bf9f 100644 --- a/ignite/cmd/network_request_approve.go +++ b/ignite/cmd/network_request_approve.go @@ -1,14 +1,12 @@ package ignitecmd import ( - "fmt" - - "github.com/pkg/errors" - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) const ( @@ -33,12 +31,13 @@ func NewNetworkRequestApprove() *cobra.Command { } func networkRequestApproveHandler(cmd *cobra.Command, args []string) error { - // initialize network common methods - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -68,7 +67,7 @@ func networkRequestApproveHandler(cmd *cobra.Command, args []string) error { if err := verifyRequest(cmd.Context(), nb, launchID, ids...); err != nil { return errors.Wrap(err, "request(s) not valid") } - fmt.Printf("%s Request(s) %s verified\n", clispinner.OK, numbers.List(ids, "#")) + session.Printf("%s Request(s) %s verified\n", icons.OK, numbers.List(ids, "#")) } // Submit the approved requests @@ -80,7 +79,7 @@ func networkRequestApproveHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.Stop() - fmt.Printf("%s Request(s) %s approved\n", clispinner.OK, numbers.List(ids, "#")) - return nil + session.StopSpinner() + + return session.Printf("%s Request(s) %s approved\n", icons.OK, numbers.List(ids, "#")) } diff --git a/ignite/cmd/network_request_list.go b/ignite/cmd/network_request_list.go index 1795f163f8..6875740f24 100644 --- a/ignite/cmd/network_request_list.go +++ b/ignite/cmd/network_request_list.go @@ -2,15 +2,12 @@ package ignitecmd import ( "fmt" - "io" - "os" - "github.com/spf13/cobra" - launchtypes "github.com/tendermint/spn/x/launch/types" - - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" ) var requestSummaryHeader = []string{"ID", "Status", "Type", "Content"} @@ -28,8 +25,10 @@ func NewNetworkRequestList() *cobra.Command { } func networkRequestListHandler(cmd *cobra.Command, args []string) error { - // initialize network common methods - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } @@ -50,12 +49,13 @@ func networkRequestListHandler(cmd *cobra.Command, args []string) error { return err } - nb.Cleanup() - return renderRequestSummaries(requests, os.Stdout) + session.StopSpinner() + + return renderRequestSummaries(requests, session) } // renderRequestSummaries writes into the provided out, the list of summarized requests -func renderRequestSummaries(requests []networktypes.Request, out io.Writer) error { +func renderRequestSummaries(requests []networktypes.Request, session cliui.Session) error { requestEntries := make([][]string, 0) for _, request := range requests { var ( @@ -109,5 +109,5 @@ func renderRequestSummaries(requests []networktypes.Request, out io.Writer) erro content, }) } - return entrywriter.MustWrite(out, requestSummaryHeader, requestEntries...) + return session.PrintTable(requestSummaryHeader, requestEntries...) } diff --git a/ignite/cmd/network_request_reject.go b/ignite/cmd/network_request_reject.go index db9f826d7d..eeb545c129 100644 --- a/ignite/cmd/network_request_reject.go +++ b/ignite/cmd/network_request_reject.go @@ -1,13 +1,11 @@ package ignitecmd import ( - "fmt" - - "github.com/spf13/cobra" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" ) // NewNetworkRequestReject creates a new request reject @@ -27,12 +25,13 @@ func NewNetworkRequestReject() *cobra.Command { } func networkRequestRejectHandler(cmd *cobra.Command, args []string) error { - // initialize network common methods - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -60,7 +59,7 @@ func networkRequestRejectHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.Stop() - fmt.Printf("%s Request(s) %s rejected\n", clispinner.OK, numbers.List(ids, "#")) - return nil + session.StopSpinner() + + return session.Printf("%s Request(s) %s rejected\n", icons.OK, numbers.List(ids, "#")) } diff --git a/ignite/cmd/network_request_show.go b/ignite/cmd/network_request_show.go index fa1fd4f61a..7471a18e36 100644 --- a/ignite/cmd/network_request_show.go +++ b/ignite/cmd/network_request_show.go @@ -1,14 +1,13 @@ package ignitecmd import ( - "fmt" "strconv" - "github.com/pkg/errors" - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/pkg/errors" + "github.com/spf13/cobra" ) // NewNetworkRequestShow creates a new request show command to show @@ -24,12 +23,13 @@ func NewNetworkRequestShow() *cobra.Command { } func networkRequestShowHandler(cmd *cobra.Command, args []string) error { - // initialize network common methods - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -63,7 +63,7 @@ func networkRequestShowHandler(cmd *cobra.Command, args []string) error { return err } - nb.Spinner.Stop() - fmt.Println(requestYaml) - return nil + session.StopSpinner() + + return session.Println(requestYaml) } diff --git a/ignite/cmd/network_request_verify.go b/ignite/cmd/network_request_verify.go index 6dd62e048b..83adc80edd 100644 --- a/ignite/cmd/network_request_verify.go +++ b/ignite/cmd/network_request_verify.go @@ -2,16 +2,15 @@ package ignitecmd import ( "context" - "fmt" "os" - "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/chaincmd" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" + "github.com/spf13/cobra" ) // NewNetworkRequestVerify verify the request and simulate the chain. @@ -29,12 +28,13 @@ func NewNetworkRequestVerify() *cobra.Command { } func networkRequestVerifyHandler(cmd *cobra.Command, args []string) error { - // initialize network common methods - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) @@ -50,13 +50,11 @@ func networkRequestVerifyHandler(cmd *cobra.Command, args []string) error { // verify the requests if err := verifyRequest(cmd.Context(), nb, launchID, ids...); err != nil { - fmt.Printf("%s Request(s) %s not valid\n", clispinner.NotOK, numbers.List(ids, "#")) + session.Printf("%s Request(s) %s not valid\n", icons.NotOK, numbers.List(ids, "#")) return err } - nb.Spinner.Stop() - fmt.Printf("%s Request(s) %s verified\n", clispinner.OK, numbers.List(ids, "#")) - return nil + return session.Printf("%s Request(s) %s verified\n", icons.OK, numbers.List(ids, "#")) } // verifyRequest initialize the chain from the launch ID in a temporary directory diff --git a/ignite/cmd/network_reward_set.go b/ignite/cmd/network_reward_set.go index cefc786091..128ac861f0 100644 --- a/ignite/cmd/network_reward_set.go +++ b/ignite/cmd/network_reward_set.go @@ -5,9 +5,9 @@ import ( "strconv" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/spf13/cobra" - + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" + "github.com/spf13/cobra" ) // NewNetworkRewardSet creates a new chain reward set command to @@ -26,11 +26,13 @@ func NewNetworkRewardSet() *cobra.Command { } func networkChainRewardSetHandler(cmd *cobra.Command, args []string) error { - nb, err := newNetworkBuilder(cmd) + session := cliui.New() + defer session.Cleanup() + + nb, err := newNetworkBuilder(cmd, CollectEvents(session.EventBus())) if err != nil { return err } - defer nb.Cleanup() // parse launch ID launchID, err := network.ParseID(args[0]) diff --git a/ignite/cmd/relayer_configure.go b/ignite/cmd/relayer_configure.go index 8f35b9fabd..3098a6c0d3 100644 --- a/ignite/cmd/relayer_configure.go +++ b/ignite/cmd/relayer_configure.go @@ -8,10 +8,10 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/cliquiz" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" "github.com/ignite-hq/cli/ignite/pkg/relayer" ) @@ -98,7 +98,7 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { return err } - s := clispinner.New().Stop() + s := clispinner.New().Start() defer s.Stop() printSection("Setting up chains") diff --git a/ignite/cmd/relayer_connect.go b/ignite/cmd/relayer_connect.go index 1e85cffc39..b6c9372bcf 100644 --- a/ignite/cmd/relayer_connect.go +++ b/ignite/cmd/relayer_connect.go @@ -7,7 +7,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/relayer" ) diff --git a/ignite/cmd/scaffold.go b/ignite/cmd/scaffold.go index 0d38153b91..9df999cc43 100644 --- a/ignite/cmd/scaffold.go +++ b/ignite/cmd/scaffold.go @@ -8,7 +8,7 @@ import ( "github.com/spf13/cobra" flag "github.com/spf13/pflag" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgit" "github.com/ignite-hq/cli/ignite/services/scaffolder" diff --git a/ignite/cmd/scaffold_band.go b/ignite/cmd/scaffold_band.go index eb1ec7f2d9..6b9c0d732c 100644 --- a/ignite/cmd/scaffold_band.go +++ b/ignite/cmd/scaffold_band.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/cmd/scaffold_chain.go b/ignite/cmd/scaffold_chain.go index 7cc961ba05..14838075ab 100644 --- a/ignite/cmd/scaffold_chain.go +++ b/ignite/cmd/scaffold_chain.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/cmd/scaffold_flutter.go b/ignite/cmd/scaffold_flutter.go index 99bbcafabb..6dd9b4dba8 100644 --- a/ignite/cmd/scaffold_flutter.go +++ b/ignite/cmd/scaffold_flutter.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/cmd/scaffold_message.go b/ignite/cmd/scaffold_message.go index 5457af0b76..9bbc2d4ad7 100644 --- a/ignite/cmd/scaffold_message.go +++ b/ignite/cmd/scaffold_message.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/cmd/scaffold_module.go b/ignite/cmd/scaffold_module.go index 9d9080393c..0be64e7942 100644 --- a/ignite/cmd/scaffold_module.go +++ b/ignite/cmd/scaffold_module.go @@ -9,7 +9,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/validation" "github.com/ignite-hq/cli/ignite/services/scaffolder" diff --git a/ignite/cmd/scaffold_mwasm.go b/ignite/cmd/scaffold_mwasm.go index 7942fe9b9b..7ecec30ea7 100644 --- a/ignite/cmd/scaffold_mwasm.go +++ b/ignite/cmd/scaffold_mwasm.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" ) diff --git a/ignite/cmd/scaffold_package.go b/ignite/cmd/scaffold_package.go index 01f97169d9..1d94f3c208 100644 --- a/ignite/cmd/scaffold_package.go +++ b/ignite/cmd/scaffold_package.go @@ -6,7 +6,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/cmd/scaffold_query.go b/ignite/cmd/scaffold_query.go index d34518370d..09e81684bb 100644 --- a/ignite/cmd/scaffold_query.go +++ b/ignite/cmd/scaffold_query.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" ) diff --git a/ignite/cmd/scaffold_vue.go b/ignite/cmd/scaffold_vue.go index 76424b9d91..3ab71232e7 100644 --- a/ignite/cmd/scaffold_vue.go +++ b/ignite/cmd/scaffold_vue.go @@ -5,7 +5,7 @@ import ( "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/services/scaffolder" ) diff --git a/ignite/pkg/cliquiz/question.go b/ignite/pkg/cliui/cliquiz/question.go similarity index 100% rename from ignite/pkg/cliquiz/question.go rename to ignite/pkg/cliui/cliquiz/question.go diff --git a/ignite/pkg/clispinner/clispinner.go b/ignite/pkg/cliui/clispinner/clispinner.go similarity index 65% rename from ignite/pkg/clispinner/clispinner.go rename to ignite/pkg/cliui/clispinner/clispinner.go index b28065265d..aa1e6967a9 100644 --- a/ignite/pkg/clispinner/clispinner.go +++ b/ignite/pkg/cliui/clispinner/clispinner.go @@ -1,6 +1,7 @@ package clispinner import ( + "io" "time" "github.com/briandowns/spinner" @@ -16,9 +17,35 @@ type Spinner struct { sp *spinner.Spinner } +type ( + Option func(*Options) + + Options struct { + writer io.Writer + } +) + +// WithWriter configures an output for a spinner +func WithWriter(w io.Writer) Option { + return func(options *Options) { + options.writer = w + } +} + // New creates a new spinner. -func New() *Spinner { - sp := spinner.New(charset, refreshRate) +func New(options ...Option) *Spinner { + o := Options{} + for _, apply := range options { + apply(&o) + } + + underlyingSpinnerOptions := []spinner.Option{} + if o.writer != nil { + underlyingSpinnerOptions = append(underlyingSpinnerOptions, spinner.WithWriter(o.writer)) + } + + sp := spinner.New(charset, refreshRate, underlyingSpinnerOptions...) + sp.Color(spinnerColor) s := &Spinner{ sp: sp, @@ -69,3 +96,7 @@ func (s *Spinner) Stop() *Spinner { s.sp.Stop() return s } + +func (s *Spinner) IsActive() bool { + return s.sp.Active() +} diff --git a/ignite/pkg/cliui/cliui.go b/ignite/pkg/cliui/cliui.go new file mode 100644 index 0000000000..fefcb9bf8b --- /dev/null +++ b/ignite/pkg/cliui/cliui.go @@ -0,0 +1,181 @@ +package cliui + +import ( + "fmt" + "io" + "os" + "sync" + + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" + "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" + "github.com/ignite-hq/cli/ignite/pkg/events" + "github.com/manifoldco/promptui" +) + +// Session controls command line interaction with users. +type Session struct { + ev events.Bus + eventsWg *sync.WaitGroup + + spinner *clispinner.Spinner + + in io.Reader + out io.Writer + printLoopWg *sync.WaitGroup +} + +type Option func(s *Session) + +// WithOutput sets output stream for a session. +func WithOutput(output io.Writer) Option { + return func(s *Session) { + s.out = output + } +} + +// WithInput sets input stream for a session. +func WithInput(input io.Reader) Option { + return func(s *Session) { + s.in = input + } +} + +// New creates new Session. +func New(options ...Option) Session { + wg := &sync.WaitGroup{} + session := Session{ + ev: events.NewBus(events.WithWaitGroup(wg)), + in: os.Stdin, + out: os.Stdout, + eventsWg: wg, + printLoopWg: &sync.WaitGroup{}, + } + for _, apply := range options { + apply(&session) + } + session.spinner = clispinner.New(clispinner.WithWriter(session.out)) + session.printLoopWg.Add(1) + go session.printLoop() + return session +} + +// StopSpinner returns session's event bus. +func (s Session) EventBus() events.Bus { + return s.ev +} + +// StartSpinner starts spinner. +func (s Session) StartSpinner(text string) { + s.spinner.SetText(text).Start() +} + +// StopSpinner stops spinner. +func (s Session) StopSpinner() { + s.spinner.Stop() +} + +// PauseSpinner pauses spinner, returns resume function to start paused spinner again. +func (s Session) PauseSpinner() (mightResume func()) { + isActive := s.spinner.IsActive() + f := func() { + if isActive { + s.spinner.Start() + } + } + s.spinner.Stop() + return f +} + +// Printf prints formatted arbitrary message. +func (s Session) Printf(format string, a ...interface{}) error { + s.Wait() + defer s.PauseSpinner()() + _, err := fmt.Fprintf(s.out, format, a...) + return err +} + +// Println prints arbitrary message with line break. +func (s Session) Println(messages ...interface{}) error { + s.Wait() + defer s.PauseSpinner()() + _, err := fmt.Fprintln(s.out, messages...) + return err +} + +// PrintSaidNo prints message informing negative was given in a confirmation prompt +func (s Session) PrintSaidNo() error { + return s.Println("said no") +} + +// Println prints arbitrary message +func (s Session) Print(messages ...interface{}) error { + s.Wait() + defer s.PauseSpinner()() + _, err := fmt.Fprint(s.out, messages...) + return err +} + +// Ask asks questions in the terminal and collect answers. +func (s Session) Ask(questions ...cliquiz.Question) error { + s.Wait() + defer s.PauseSpinner()() + return cliquiz.Ask(questions...) +} + +// AskConfirm asks yes/no question in the terminal. +func (s Session) AskConfirm(message string) error { + s.Wait() + defer s.PauseSpinner()() + prompt := promptui.Prompt{ + Label: message, + IsConfirm: true, + } + _, err := prompt.Run() + return err +} + +// PrintTable prints table data. +func (s Session) PrintTable(header []string, entries ...[]string) error { + s.Wait() + defer s.PauseSpinner()() + return entrywriter.MustWrite(s.out, header, entries...) +} + +// Wait blocks until all queued events are handled. +func (s Session) Wait() { + s.eventsWg.Wait() +} + +// Cleanup ensure spinner is stopped and printLoop exited correctly. +func (s Session) Cleanup() { + s.StopSpinner() + s.ev.Shutdown() + s.printLoopWg.Wait() +} + +// printLoop handles events. +func (s Session) printLoop() { + for event := range s.ev.Events() { + switch event.Status { + case events.StatusOngoing: + s.StartSpinner(event.Text()) + + case events.StatusDone: + if event.Icon == "" { + event.Icon = icons.OK + } + s.StopSpinner() + fmt.Fprintf(s.out, "%s %s\n", event.Icon, event.Text()) + + case events.StatusNeutral: + resume := s.PauseSpinner() + fmt.Fprintf(s.out, event.Text()) + resume() + } + + s.eventsWg.Done() + } + s.printLoopWg.Done() +} diff --git a/ignite/pkg/cliui/colors/colors.go b/ignite/pkg/cliui/colors/colors.go new file mode 100644 index 0000000000..e7e1c9a1e0 --- /dev/null +++ b/ignite/pkg/cliui/colors/colors.go @@ -0,0 +1,5 @@ +package colors + +import "github.com/fatih/color" + +var Info = color.New(color.FgYellow).SprintFunc() diff --git a/ignite/pkg/entrywriter/entrywriter.go b/ignite/pkg/cliui/entrywriter/entrywriter.go similarity index 100% rename from ignite/pkg/entrywriter/entrywriter.go rename to ignite/pkg/cliui/entrywriter/entrywriter.go diff --git a/ignite/pkg/entrywriter/entrywriter_test.go b/ignite/pkg/cliui/entrywriter/entrywriter_test.go similarity index 94% rename from ignite/pkg/entrywriter/entrywriter_test.go rename to ignite/pkg/cliui/entrywriter/entrywriter_test.go index 078430601a..69fb0c0c45 100644 --- a/ignite/pkg/entrywriter/entrywriter_test.go +++ b/ignite/pkg/cliui/entrywriter/entrywriter_test.go @@ -2,12 +2,11 @@ package entrywriter_test import ( "errors" + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "io" "testing" "github.com/stretchr/testify/require" - - "github.com/ignite-hq/cli/ignite/pkg/entrywriter" ) type WriterWithError struct{} diff --git a/ignite/pkg/clispinner/icon.go b/ignite/pkg/cliui/icons/icon.go similarity index 95% rename from ignite/pkg/clispinner/icon.go rename to ignite/pkg/cliui/icons/icon.go index af0807fa8a..78ca3740b1 100644 --- a/ignite/pkg/clispinner/icon.go +++ b/ignite/pkg/cliui/icons/icon.go @@ -1,4 +1,4 @@ -package clispinner +package icons import "github.com/fatih/color" diff --git a/ignite/pkg/events/events.go b/ignite/pkg/events/events.go index 2a76fd6cfa..86ad5cae52 100644 --- a/ignite/pkg/events/events.go +++ b/ignite/pkg/events/events.go @@ -4,6 +4,7 @@ package events import ( "fmt" + "sync" "github.com/gookit/color" ) @@ -34,6 +35,7 @@ type ( const ( StatusOngoing Status = iota StatusDone + StatusNeutral ) // TextColor sets the text color @@ -43,7 +45,7 @@ func TextColor(c color.Color) Option { } } -// Icon sets the text icon prefix +// Icon sets the text icon prefix. func Icon(icon string) Option { return func(e *Event) { e.Icon = icon @@ -59,6 +61,21 @@ func New(status Status, description string, options ...Option) Event { return ev } +// NewOngoing creates a new StatusOngoing event. +func NewOngoing(description string) Event { + return New(StatusOngoing, description) +} + +// NewNeutral creates a new StatusNeutral event. +func NewNeutral(description string) Event { + return New(StatusNeutral, description) +} + +// NewDone creates a new StatusDone event. +func NewDone(description, icon string) Event { + return New(StatusDone, description, Icon(icon)) +} + // IsOngoing checks if state change that triggered this event is still ongoing. func (e Event) IsOngoing() bool { return e.Status == StatusOngoing @@ -74,25 +91,62 @@ func (e Event) Text() string { } // Bus is a send/receive event bus. -type Bus chan Event +type ( + Bus struct { + evchan chan Event + buswg *sync.WaitGroup + } + + BusOption func(*Bus) +) + +// WithWaitGroup sets wait group which is blocked if events bus is not empty. +func WithWaitGroup(wg *sync.WaitGroup) BusOption { + return func(bus *Bus) { + bus.buswg = wg + } +} + +// WithCustomBufferSize configures buffer size of underlying bus channel +func WithCustomBufferSize(size int) BusOption { + return func(bus *Bus) { + bus.evchan = make(chan Event, size) + } +} // NewBus creates a new event bus to send/receive events. -func NewBus() Bus { - return make(Bus) +func NewBus(options ...BusOption) Bus { + bus := Bus{ + evchan: make(chan Event), + } + + for _, apply := range options { + apply(&bus) + } + + return bus } // Send sends a new event to bus. func (b Bus) Send(e Event) { - if b == nil { + if b.evchan == nil { return } - b <- e + if b.buswg != nil { + b.buswg.Add(1) + } + b.evchan <- e +} + +// Events returns go channel with Event accessible only for read. +func (b *Bus) Events() <-chan Event { + return b.evchan } // Shutdown shutdowns event bus. func (b Bus) Shutdown() { - if b == nil { + if b.evchan == nil { return } - close(b) + close(b.evchan) } diff --git a/ignite/pkg/events/events_test.go b/ignite/pkg/events/events_test.go index c8e18cde9f..3a8a82541a 100644 --- a/ignite/pkg/events/events_test.go +++ b/ignite/pkg/events/events_test.go @@ -1,48 +1,56 @@ -package events +package events_test import ( "testing" "github.com/gookit/color" + "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/stretchr/testify/require" ) func TestBusSend(t *testing.T) { tests := []struct { name string - bus Bus - event Event + bus events.Bus + event events.Event }{ { name: "send status ongoing event", - bus: make(Bus), - event: Event{ - Status: StatusOngoing, + bus: events.NewBus(), + event: events.Event{ + Status: events.StatusOngoing, Description: "description", }, }, { name: "send status done event", - bus: make(Bus), - event: Event{ - Status: StatusDone, + bus: events.NewBus(), + event: events.Event{ + Status: events.StatusDone, Description: "description", }, }, { - name: "send event on nil bus", - bus: nil, - event: Event{ - Status: StatusDone, + name: "send status neutral event", + bus: events.NewBus(), + event: events.Event{ + Status: events.StatusNeutral, Description: "description", }, }, + { + name: "send event on nil bus", + bus: events.Bus{}, + event: events.Event{ + Status: events.StatusDone, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { go tt.bus.Send(tt.event) - if tt.bus != nil { - require.Equal(t, tt.event, <-tt.bus) + if tt.bus.Events() != nil { + require.Equal(t, tt.event, <-tt.bus.Events()) } tt.bus.Shutdown() }) @@ -52,19 +60,19 @@ func TestBusSend(t *testing.T) { func TestBusShutdown(t *testing.T) { tests := []struct { name string - bus Bus + bus events.Bus }{ { name: "shutdown nil bus", - bus: nil, + bus: events.Bus{}, }, { name: "shutdown bus correctly", - bus: make(Bus), + bus: events.NewBus(), }, { name: "shutdown bus with size correctly", - bus: make(Bus, 1), + bus: events.NewBus(events.WithCustomBufferSize(1)), }, } for _, tt := range tests { @@ -76,7 +84,7 @@ func TestBusShutdown(t *testing.T) { func TestEventIsOngoing(t *testing.T) { type fields struct { - status Status + status events.Status description string } tests := []struct { @@ -84,12 +92,12 @@ func TestEventIsOngoing(t *testing.T) { fields fields want bool }{ - {"status ongoing", fields{StatusOngoing, "description"}, true}, - {"status done", fields{StatusDone, "description"}, false}, + {"status ongoing", fields{events.StatusOngoing, "description"}, true}, + {"status done", fields{events.StatusDone, "description"}, false}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - e := Event{ + e := events.Event{ Status: tt.fields.status, Description: tt.fields.description, } @@ -100,7 +108,7 @@ func TestEventIsOngoing(t *testing.T) { func TestEventText(t *testing.T) { type fields struct { - status Status + status events.Status description string textColor color.Color } @@ -112,7 +120,7 @@ func TestEventText(t *testing.T) { { name: "status done", fields: fields{ - status: StatusDone, + status: events.StatusDone, description: "description", textColor: color.Red, }, @@ -121,7 +129,7 @@ func TestEventText(t *testing.T) { { name: "status ongoing", fields: fields{ - status: StatusOngoing, + status: events.StatusOngoing, description: "description", textColor: color.Red, }, @@ -130,7 +138,7 @@ func TestEventText(t *testing.T) { { name: "status ongoing with empty description", fields: fields{ - status: StatusOngoing, + status: events.StatusOngoing, description: "", textColor: color.Red, }, @@ -139,7 +147,7 @@ func TestEventText(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - e := Event{ + e := events.Event{ Status: tt.fields.status, Description: tt.fields.description, TextColor: tt.fields.textColor, @@ -151,22 +159,22 @@ func TestEventText(t *testing.T) { func TestNew(t *testing.T) { type args struct { - status Status + status events.Status description string } tests := []struct { name string args args - want Event + want events.Event }{ - {"zero value args", args{}, Event{}}, - {"large value args", args{status: 99999, description: "description"}, Event{Status: 99999, Description: "description"}}, - {"status ongoing", args{status: StatusOngoing, description: "description"}, Event{Status: 0, Description: "description"}}, - {"status done", args{status: StatusDone, description: "description"}, Event{Status: 1, Description: "description"}}, + {"zero value args", args{}, events.Event{}}, + {"large value args", args{status: 99999, description: "description"}, events.Event{Status: 99999, Description: "description"}}, + {"status ongoing", args{status: events.StatusOngoing, description: "description"}, events.Event{Status: 0, Description: "description"}}, + {"status done", args{status: events.StatusDone, description: "description"}, events.Event{Status: 1, Description: "description"}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - require.Equal(t, tt.want, New(tt.args.status, tt.args.description)) + require.Equal(t, tt.want, events.New(tt.args.status, tt.args.description)) }) } } @@ -174,19 +182,19 @@ func TestNew(t *testing.T) { func TestNewBus(t *testing.T) { tests := []struct { name string - event Event + event events.Event }{ - {"new bus with status done event", Event{Status: StatusDone, Description: "description"}}, - {"new bus with status ongoing event", Event{Status: StatusOngoing, Description: "description"}}, - {"new bus with zero value event", Event{}}, + {"new bus with status done event", events.Event{Status: events.StatusDone, Description: "description"}}, + {"new bus with status ongoing event", events.Event{Status: events.StatusOngoing, Description: "description"}}, + {"new bus with zero value event", events.Event{}}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - bus := NewBus() + bus := events.NewBus() defer bus.Shutdown() for i := 0; i < 10; i++ { go bus.Send(tt.event) - require.Equal(t, tt.event, <-bus) + require.Equal(t, tt.event, <-bus.Events()) } }) } diff --git a/ignite/services/network/reward.go b/ignite/services/network/reward.go index af0bc4f973..9e96cf4086 100644 --- a/ignite/services/network/reward.go +++ b/ignite/services/network/reward.go @@ -4,11 +4,10 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" - rewardtypes "github.com/tendermint/spn/x/reward/types" - - "github.com/ignite-hq/cli/ignite/pkg/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" + rewardtypes "github.com/tendermint/spn/x/reward/types" ) // SetReward set a chain reward @@ -42,7 +41,7 @@ func (n Network) SetReward(launchID uint64, lastRewardHeight int64, coins sdk.Co n.ev.Send(events.New( events.StatusDone, "The reward pool was empty", - events.Icon(clispinner.Info), + events.Icon(icons.Info), )) } else { n.ev.Send(events.New(events.StatusDone, @@ -51,7 +50,7 @@ func (n Network) SetReward(launchID uint64, lastRewardHeight int64, coins sdk.Co coins.String(), lastRewardHeight, ), - events.Icon(clispinner.Info), + events.Icon(icons.Info), )) } From e2a1fafea29b1872dc170ac86b6bbef2085a6d19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Thu, 5 May 2022 13:48:16 +0200 Subject: [PATCH 21/30] chore: add @jeronimoalbi to CODEOWNERS (#2442) --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index e81ceaf974..4d71364266 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,4 +4,4 @@ *.md @fadeev @ilgooz @barriebyron @ignite-hq/growth-ecodev # Primary repo maintainers -* @fadeev @ilgooz @lubtd @Pantani @ivanovpetr +* @fadeev @ilgooz @lubtd @Pantani @ivanovpetr @jeronimoalbi From 8631f30f176938c20ab581917ef17acb966a23d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jer=C3=B3nimo=20Albi?= Date: Fri, 6 May 2022 10:06:14 +0200 Subject: [PATCH 22/30] feat: support non-Git URL app names (#2353) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(pkg/gomodulepath): change parse to support single name paths * feat(pkg/gomodulepath): add function to extract user and repo names * fix(pkg/giturl): changed to handle URL with scheme The previous implementation was tested using an URL with scheme but CLI is using URIs that comes from Go module names that don't have a scheme as prefix. This implementation allows for both cases. * refactor: improve gomodulepath pkg and tests * feat: add support for non git module names to scaffolder service * feat: add support for non git module names to cosmosgen pkg * test: add integration test to scaffold a chain using a name * test: add integration test to serve a chain scaffolded using a name * feat(pkg/protopath): add function to format protocol buffer package names * refactor: fix proto package names for scaffold chain & module commands * refactor: fix proto package names for scaffolded types commands * refactor: fix proto package names for scaffold band command * refactor: add missing formatPackageName context definitions * chore: remove unused formatOwnerName definition from app template * chore: fix documentation rebranding typo * refactor: remove redundant app name from proto file templates This change results in proto file package names like "owner.repo" instead of "owner.repo.repo" when a URI is used as app name during the initial chain scaffolding. Or for example "owner.module" instead of "owner.repo.module" when a module is created. * refactor(pkg/gomodulepath): changed user and repo name extraction func The function was renamed to be shorter and the extraction functionality changed to use the last two path elements as user and repository names, with the exception of short paths where the names are the same. * refactor(pkg/protopath): change proto package name formatting arguments Using the arguments is more intuitive and works better with the data extracted from the Go module path used to scaffold the chain. * chore: fix formatting * refactor: change proto templates to use the updated pkg name formatter * refactor: remove unused formatOwnerName references * chore(pkg/gomodulepath): rename private function for clarity * refactor: change base API URL to match new module paths * fix: fix invalid vuex store module paths * chore: review fixes * chore: change integration scaffolder func to use appname as is * test: change integration tests to explicitly use GitHub URIs * test: change name based scaffolding integration tests to use Env.Scaffold * chore: change existing app integration test to call Env.Scaffold * refactor: removed the unused giturl package * chore: fix broken cosmosanalysis test * fix: change Env.Scaffold to only use the app name for directory paths * refactor: rewrite gomodulepath ExtractUserRepoNames to ExtractAppPath * refactor(pkg/cosmosgen): change pkg to use gomodulepath.ExtractAppPath * refactor: remove FormatPackageName from protopath pkg The function is now located in the module package within the `ignite/templates/` path and it was renamed to ProtoPackageName. * refactor: replace owner name references with app module paths The owner name shouldn't be used anymore because the Go module paths might be defined as a single name or a URI with a single path element that only describes the app name, so in those cases there is no owner definition. App module paths are used instead of the owner name. App module paths are extracted from the Go module path, e.g.: - github.com/username/reponame => "username/reponame" - domain.com/reponame => "reponame" - reponame => "reponame" - namespace/reponame => "namespace/reponame" - a/b/c/namespace/reponame => "namespace/reponame" * chore: remove unused test file * chore: fix broken Vuex store module path test Co-authored-by: İlker G. Öztürk --- ignite/pkg/cosmosanalysis/module/module.go | 8 +- .../pkg/cosmosanalysis/module/module_test.go | 3 +- ignite/pkg/cosmosgen/cosmosgen.go | 20 +++- ignite/pkg/cosmosgen/cosmosgen_test.go | 58 +++++++++ ignite/pkg/cosmosgen/generate_javascript.go | 15 +-- .../templates/vuex/root/package.json.tpl | 4 +- ignite/pkg/giturl/giturl.go | 43 ------- ignite/pkg/giturl/giturl_test.go | 16 --- ignite/pkg/gomodulepath/gomodulepath.go | 61 +++++++++- ignite/pkg/gomodulepath/gomodulepath_test.go | 111 ++++++++++++++++++ ignite/pkg/xstrings/xstrings.go | 2 +- ignite/services/chain/generate.go | 6 +- ignite/services/scaffolder/init.go | 14 +-- ignite/services/scaffolder/message.go | 2 - ignite/services/scaffolder/module.go | 1 - ignite/services/scaffolder/oracle.go | 1 - ignite/services/scaffolder/packet.go | 1 - ignite/services/scaffolder/query.go | 1 - ignite/services/scaffolder/scaffolder.go | 12 +- ignite/services/scaffolder/type.go | 2 - ignite/templates/app/app.go | 7 +- ignite/templates/app/options.go | 3 +- ignite/templates/app/stargate/readme.md.plush | 4 +- ignite/templates/ibc/oracle.go | 11 +- .../{{moduleName}}/{{queryName}}.proto.plush | 2 +- ignite/templates/ibc/packet.go | 2 - ignite/templates/message/message.go | 1 - ignite/templates/message/options.go | 1 - ignite/templates/module/create/ibc.go | 9 +- .../proto/{{moduleName}}/packet.proto.plush | 4 +- ignite/templates/module/create/msgserver.go | 10 +- .../proto/{{moduleName}}/tx.proto.plush | 4 +- ignite/templates/module/create/options.go | 2 - ignite/templates/module/create/stargate.go | 10 +- .../proto/{{moduleName}}/genesis.proto.plush | 2 +- .../proto/{{moduleName}}/params.proto.plush | 4 +- .../proto/{{moduleName}}/query.proto.plush | 4 +- ignite/templates/module/module.go | 20 ++++ ignite/templates/module/module_test.go | 53 +++++++++ ignite/templates/query/options.go | 1 - ignite/templates/query/query.go | 1 - ignite/templates/query/stargate.go | 7 +- .../{{moduleName}}/{{typeName}}.proto.plush | 2 +- ignite/templates/typed/list/stargate.go | 15 +-- .../{{moduleName}}/{{typeName}}.proto.plush | 4 +- ignite/templates/typed/map/stargate.go | 9 +- .../{{moduleName}}/{{typeName}}.proto.plush | 2 +- ignite/templates/typed/options.go | 1 - ignite/templates/typed/singleton/stargate.go | 7 +- .../{{moduleName}}/{{typeName}}.proto.plush | 2 +- ignite/templates/typed/typed.go | 11 +- integration/app/cmd_app_test.go | 43 +++---- integration/app/cmd_ibc_test.go | 6 +- integration/app/cmd_serve_test.go | 33 +++++- integration/app/config_test.go | 3 +- integration/app/tx_test.go | 2 +- integration/cosmosgen/cosmosgen_test.go | 2 +- integration/env.go | 11 +- integration/faucet/faucet_test.go | 2 +- integration/list/cmd_list_test.go | 4 +- integration/map/cmd_map_test.go | 2 +- .../other_components/cmd_message_test.go | 2 +- .../other_components/cmd_query_test.go | 2 +- integration/readme.md | 4 +- integration/simulation/simapp_test.go | 2 +- integration/single/cmd_singleton_test.go | 2 +- 66 files changed, 478 insertions(+), 238 deletions(-) create mode 100644 ignite/pkg/cosmosgen/cosmosgen_test.go delete mode 100644 ignite/pkg/giturl/giturl.go delete mode 100644 ignite/pkg/giturl/giturl_test.go create mode 100644 ignite/templates/module/module.go create mode 100644 ignite/templates/module/module_test.go diff --git a/ignite/pkg/cosmosanalysis/module/module.go b/ignite/pkg/cosmosanalysis/module/module.go index 86aec5c1d9..e121954e03 100644 --- a/ignite/pkg/cosmosanalysis/module/module.go +++ b/ignite/pkg/cosmosanalysis/module/module.go @@ -20,6 +20,9 @@ type Module struct { // Name of the module. Name string + // GoModulePath of the app where the module is defined. + GoModulePath string + // Pkg holds the proto package info. Pkg protoanalysis.Package @@ -163,8 +166,9 @@ func (d *moduleDiscoverer) discover(pkg protoanalysis.Package) (Module, error) { namesplit := strings.Split(pkg.Name, ".") m := Module{ - Name: namesplit[len(namesplit)-1], - Pkg: pkg, + Name: namesplit[len(namesplit)-1], + GoModulePath: d.basegopath, + Pkg: pkg, } // fill sdk Msgs. diff --git a/ignite/pkg/cosmosanalysis/module/module_test.go b/ignite/pkg/cosmosanalysis/module/module_test.go index 02f7da33ef..b62294445c 100644 --- a/ignite/pkg/cosmosanalysis/module/module_test.go +++ b/ignite/pkg/cosmosanalysis/module/module_test.go @@ -10,7 +10,8 @@ import ( ) var testModule = Module{ - Name: "planet", + Name: "planet", + GoModulePath: "github.com/tendermint/planet", Pkg: protoanalysis.Package{ Name: "tendermint.planet.planet", Path: "testdata/planet/proto/planet", diff --git a/ignite/pkg/cosmosgen/cosmosgen.go b/ignite/pkg/cosmosgen/cosmosgen.go index ad0ccd68cc..3abbf6188d 100644 --- a/ignite/pkg/cosmosgen/cosmosgen.go +++ b/ignite/pkg/cosmosgen/cosmosgen.go @@ -2,10 +2,12 @@ package cosmosgen import ( "context" + "path/filepath" gomodmodule "golang.org/x/mod/module" "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" ) // generateOptions used to configure code generation. @@ -26,6 +28,9 @@ type generateOptions struct { // TODO add WithInstall. +// ModulePathFunc defines a function type that returns a path based on a Cosmos SDK module. +type ModulePathFunc func(module.Module) string + // Option configures code generation. type Option func(*generateOptions) @@ -33,7 +38,7 @@ type Option func(*generateOptions) // retrieve the path that should be used to place generated js code inside for a given module. // if includeThirdPartyModules set to true, code generation will be made for the 3rd party modules // used by the app -including the SDK- as well. -func WithJSGeneration(includeThirdPartyModules bool, out func(module.Module) (path string)) Option { +func WithJSGeneration(includeThirdPartyModules bool, out ModulePathFunc) Option { return func(o *generateOptions) { o.jsOut = out o.jsIncludeThirdParty = includeThirdPartyModules @@ -43,7 +48,7 @@ func WithJSGeneration(includeThirdPartyModules bool, out func(module.Module) (pa // WithVuexGeneration adds Vuex code generation. storeRootPath is used to determine the root path of generated // Vuex stores. includeThirdPartyModules and out configures the underlying JS lib generation which is // documented in WithJSGeneration. -func WithVuexGeneration(includeThirdPartyModules bool, out func(module.Module) (path string), storeRootPath string) Option { +func WithVuexGeneration(includeThirdPartyModules bool, out ModulePathFunc, storeRootPath string) Option { return func(o *generateOptions) { o.jsOut = out o.jsIncludeThirdParty = includeThirdPartyModules @@ -51,7 +56,7 @@ func WithVuexGeneration(includeThirdPartyModules bool, out func(module.Module) ( } } -func WithDartGeneration(includeThirdPartyModules bool, out func(module.Module) (path string), rootPath string) Option { +func WithDartGeneration(includeThirdPartyModules bool, out ModulePathFunc, rootPath string) Option { return func(o *generateOptions) { o.dartOut = out o.dartIncludeThirdParty = includeThirdPartyModules @@ -142,3 +147,12 @@ func Generate(ctx context.Context, appPath, protoDir string, options ...Option) return nil } + +// VuexStoreModulePath generates Vuex store module paths for Cosmos SDK modules. +// The root path is used as prefix for the generated paths. +func VuexStoreModulePath(rootPath string) ModulePathFunc { + return func(m module.Module) string { + appModulePath := gomodulepath.ExtractAppPath(m.GoModulePath) + return filepath.Join(rootPath, appModulePath, m.Pkg.Name, "module") + } +} diff --git a/ignite/pkg/cosmosgen/cosmosgen_test.go b/ignite/pkg/cosmosgen/cosmosgen_test.go new file mode 100644 index 0000000000..412f2e260d --- /dev/null +++ b/ignite/pkg/cosmosgen/cosmosgen_test.go @@ -0,0 +1,58 @@ +package cosmosgen + +import ( + "testing" + + "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" + "github.com/ignite-hq/cli/ignite/pkg/protoanalysis" + "github.com/stretchr/testify/require" +) + +func TestVuexStoreModulePath(t *testing.T) { + modulePath := VuexStoreModulePath("prefix") + + cases := []struct { + name string + goModulePath string + protoPkgName string + want string + }{ + { + name: "github uri", + goModulePath: "github.com/owner/app", + protoPkgName: "owner.app.module", + want: "prefix/owner/app/owner.app.module/module", + }, + { + name: "short uri", + goModulePath: "domain.com/app", + protoPkgName: "app.module", + want: "prefix/app/app.module/module", + }, + { + name: "path", + goModulePath: "owner/app", + protoPkgName: "owner.app.module", + want: "prefix/owner/app/owner.app.module/module", + }, + { + name: "name", + goModulePath: "app", + protoPkgName: "app.module", + want: "prefix/app/app.module/module", + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + m := module.Module{ + GoModulePath: tt.goModulePath, + Pkg: protoanalysis.Package{ + Name: tt.protoPkgName, + }, + } + + require.Equal(t, tt.want, modulePath(m)) + }) + } +} diff --git a/ignite/pkg/cosmosgen/generate_javascript.go b/ignite/pkg/cosmosgen/generate_javascript.go index 92574e279a..4cb7fbf851 100644 --- a/ignite/pkg/cosmosgen/generate_javascript.go +++ b/ignite/pkg/cosmosgen/generate_javascript.go @@ -2,6 +2,7 @@ package cosmosgen import ( "context" + "fmt" "os" "path/filepath" "strings" @@ -10,7 +11,6 @@ import ( "golang.org/x/sync/errgroup" "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" - "github.com/ignite-hq/cli/ignite/pkg/giturl" "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/localfs" "github.com/ignite-hq/cli/ignite/pkg/nodetime/programs/sta" @@ -164,10 +164,7 @@ func (g *jsGenerator) generateVuexModuleLoader() error { return err } - chainURL, err := giturl.Parse(chainPath.RawPath) - if err != nil { - return err - } + appModulePath := gomodulepath.ExtractAppPath(chainPath.RawPath) type module struct { Name string @@ -177,12 +174,10 @@ func (g *jsGenerator) generateVuexModuleLoader() error { } data := struct { - Modules []module - User string - Repo string + Modules []module + PackageName string }{ - User: chainURL.User, - Repo: chainURL.Repo, + PackageName: fmt.Sprintf("%s-js", strings.ReplaceAll(appModulePath, "/", "-")), } for _, path := range modulePaths { diff --git a/ignite/pkg/cosmosgen/templates/vuex/root/package.json.tpl b/ignite/pkg/cosmosgen/templates/vuex/root/package.json.tpl index 6bf8567176..9f3b392396 100644 --- a/ignite/pkg/cosmosgen/templates/vuex/root/package.json.tpl +++ b/ignite/pkg/cosmosgen/templates/vuex/root/package.json.tpl @@ -1,5 +1,5 @@ { - "name": "{{ .User }}-{{ .Repo }}-js", + "name": "{{ .PackageName }}", "version": "0.1.0", "description": "Autogenerated cosmos modules vuex store", "author": "Starport Codegen ", @@ -14,4 +14,4 @@ "publishConfig": { "access": "public" } -} \ No newline at end of file +} diff --git a/ignite/pkg/giturl/giturl.go b/ignite/pkg/giturl/giturl.go deleted file mode 100644 index 6de4d71782..0000000000 --- a/ignite/pkg/giturl/giturl.go +++ /dev/null @@ -1,43 +0,0 @@ -package giturl - -import ( - "errors" - "net/url" - "strings" -) - -// GitURL represents a Git url. -type GitURL struct { - // Host is a Git host. - Host string - - // User is a user or an org. - User string - - // Repo is a repo name. - Repo string -} - -// UserAndRepo returns the combined string representation of user and repo. -func (g GitURL) UserAndRepo() string { - return strings.Join([]string{g.User, g.Repo}, "/") -} - -// Parse parses a Git url u. -func Parse(u string) (GitURL, error) { - ur, err := url.Parse(u) - if err != nil { - return GitURL{}, err - } - - sp := strings.Split(ur.Path, "/") - if len(sp) < 3 { - return GitURL{}, errors.New("invalid url") - } - - return GitURL{ - Host: ur.Host, - User: sp[1], - Repo: sp[2], - }, nil -} diff --git a/ignite/pkg/giturl/giturl_test.go b/ignite/pkg/giturl/giturl_test.go deleted file mode 100644 index fbd608c0dd..0000000000 --- a/ignite/pkg/giturl/giturl_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package giturl - -import ( - "testing" - - "github.com/stretchr/testify/require" -) - -func TestParse(t *testing.T) { - parsed, err := Parse("http://github.com/ignite-hq/cli/a/b") - require.NoError(t, err) - require.Equal(t, "github.com", parsed.Host) - require.Equal(t, "ignite-hq", parsed.User) - require.Equal(t, "cli", parsed.Repo) - require.Equal(t, "ignite-hq/cli", parsed.UserAndRepo()) -} diff --git a/ignite/pkg/gomodulepath/gomodulepath.go b/ignite/pkg/gomodulepath/gomodulepath.go index 522815d587..6f17b2a4c8 100644 --- a/ignite/pkg/gomodulepath/gomodulepath.go +++ b/ignite/pkg/gomodulepath/gomodulepath.go @@ -1,3 +1,7 @@ +// Package gomodulepath implements functions for the manipulation of Go module paths. +// Paths are typically defined as a domain name and a path containing the user and +// repository names, e.g. "github.com/username/reponame", but Go also allows other module +// names like "domain.com/name", "name", "namespace/name", or similar variants. package gomodulepath import ( @@ -22,18 +26,18 @@ type Path struct { RawPath string // Root is the root directory name of Go module. - // e.g.: starport for github.com/ignite-hq/cli. + // e.g.: cli for github.com/ignite-hq/cli. Root string // Package is the default package name for the Go module that can be used // to host main functionality of the module. - // e.g.: starport for github.com/ignite-hq/cli. + // e.g.: cli for github.com/ignite-hq/cli. Package string } // Parse parses rawpath into a module Path. func Parse(rawpath string) (Path, error) { - if err := validateModulePath(rawpath); err != nil { + if err := validateRawPath(rawpath); err != nil { return Path{}, err } rootName := root(rawpath) @@ -48,6 +52,7 @@ func Parse(rawpath string) (Path, error) { Root: rootName, Package: packageName, } + return p, nil } @@ -73,13 +78,61 @@ func Find(path string) (parsed Path, appPath string, err error) { return Path{}, "", errors.Wrap(gomodule.ErrGoModNotFound, "could not locate your app's root dir") } -func validateModulePath(path string) error { +// ExtractAppPath extracts the app module path from a Go module path. +func ExtractAppPath(path string) string { + if path == "" { + return "" + } + + items := strings.Split(path, "/") + + // Remove the first path item if it is assumed to be a domain name + if len(items) > 1 && strings.Contains(items[0], ".") { + items = items[1:] + } + + count := len(items) + if count == 1 { + // The Go module path is a single name + return items[0] + } + + // The last two items in the path define the namespace and app name + return strings.Join(items[count-2:], "/") +} + +func hasDomainNamePrefix(path string) bool { + if path == "" { + return false + } + + // TODO: should we use a regexp instead of the simplistic check ? + name, _, _ := strings.Cut(path, "/") + return strings.Contains(name, ".") +} + +func validateRawPath(path string) error { + // A raw path should be either a URI, a single name or a path + if hasDomainNamePrefix(path) { + return validateURIPath(path) + } + return validateNamePath(path) +} + +func validateURIPath(path string) error { if err := module.CheckPath(path); err != nil { return fmt.Errorf("app name is an invalid go module name: %w", err) } return nil } +func validateNamePath(path string) error { + if err := module.CheckImportPath(path); err != nil { + return fmt.Errorf("app name is an invalid go module name: %w", err) + } + return nil +} + func validatePackageName(name string) error { fset := token.NewFileSet() src := fmt.Sprintf("package %s", name) diff --git a/ignite/pkg/gomodulepath/gomodulepath_test.go b/ignite/pkg/gomodulepath/gomodulepath_test.go index 79269c5f5a..bedd924586 100644 --- a/ignite/pkg/gomodulepath/gomodulepath_test.go +++ b/ignite/pkg/gomodulepath/gomodulepath_test.go @@ -26,6 +26,21 @@ func TestParse(t *testing.T) { rawpath: "github.com/a/b-c", path: Path{RawPath: "github.com/a/b-c", Root: "b-c", Package: "bc"}, }, + { + name: "short", + rawpath: "github.com/a", + path: Path{RawPath: "github.com/a", Root: "a", Package: "a"}, + }, + { + name: "short with dash", + rawpath: "github.com/a-c", + path: Path{RawPath: "github.com/a-c", Root: "a-c", Package: "ac"}, + }, + { + name: "short with version", + rawpath: "github.com/a/v2", + path: Path{RawPath: "github.com/a/v2", Root: "a", Package: "a"}, + }, { name: "long", rawpath: "github.com/a/b/c", @@ -60,6 +75,36 @@ func TestParse(t *testing.T) { rawpath: "github.com/a/bC", path: Path{RawPath: "github.com/a/bC", Root: "bC", Package: "bc"}, }, + { + name: "with a name", + rawpath: "a", + path: Path{RawPath: "a", Root: "a", Package: "a"}, + }, + { + name: "with a name containing underscore", + rawpath: "a_b", + path: Path{RawPath: "a_b", Root: "a_b", Package: "ab"}, + }, + { + name: "with a name containing dash", + rawpath: "a-b", + path: Path{RawPath: "a-b", Root: "a-b", Package: "ab"}, + }, + { + name: "with a path", + rawpath: "a/b/c", + path: Path{RawPath: "a/b/c", Root: "c", Package: "c"}, + }, + { + name: "with a path containing underscore", + rawpath: "a/b_c", + path: Path{RawPath: "a/b_c", Root: "b_c", Package: "bc"}, + }, + { + name: "with a path containing dash", + rawpath: "a/b-c", + path: Path{RawPath: "a/b-c", Root: "b-c", Package: "bc"}, + }, } for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { @@ -74,3 +119,69 @@ func TestParse(t *testing.T) { }) } } + +func TestExtractAppPath(t *testing.T) { + cases := []struct { + name string + path string + want string + }{ + { + name: "github uri", + path: "github.com/ignite-hq/cli", + want: "ignite-hq/cli", + }, + { + name: "short uri", + path: "domain.com/ignite-hq", + want: "ignite-hq", + }, + { + name: "long uri", + path: "domain.com/a/b/c/ignite-hq/cli", + want: "ignite-hq/cli", + }, + { + name: "name", + path: "cli", + want: "cli", + }, + { + name: "path", + path: "ignite-hq/cli", + want: "ignite-hq/cli", + }, + { + name: "long path", + path: "a/b/c/ignite-hq/cli", + want: "ignite-hq/cli", + }, + { + name: "empty", + path: "", + want: "", + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, ExtractAppPath(tt.path)) + }) + } +} + +func TestValidateURIPath(t *testing.T) { + require.NoError(t, validateURIPath("github.com/ignite-hq/cli")) +} + +func TestValidateURIPathWithInvalidPath(t *testing.T) { + require.Error(t, validateURIPath("github/ignite-hq/cli")) +} + +func TestValidateNamePath(t *testing.T) { + require.NoError(t, validateNamePath("cli")) +} + +func TestValidateNamePathWithInvalidPath(t *testing.T) { + require.Error(t, validateNamePath("cli@")) +} diff --git a/ignite/pkg/xstrings/xstrings.go b/ignite/pkg/xstrings/xstrings.go index a60729912e..91116e2f49 100644 --- a/ignite/pkg/xstrings/xstrings.go +++ b/ignite/pkg/xstrings/xstrings.go @@ -61,7 +61,7 @@ func NoDash(s string) string { } // NoNumberPrefix adds a underscore at the beginning of the string if it stars with a number -// this is used for package of proto files template because the package name can't start with a string +// this is used for package of proto files template because the package name can't start with a number. func NoNumberPrefix(s string) string { // Check if it starts with a digit if unicode.IsDigit(rune(s[0])) { diff --git a/ignite/services/chain/generate.go b/ignite/services/chain/generate.go index 6e68bcf8eb..7514674046 100644 --- a/ignite/services/chain/generate.go +++ b/ignite/services/chain/generate.go @@ -8,7 +8,6 @@ import ( "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" "github.com/ignite-hq/cli/ignite/pkg/cosmosgen" - "github.com/ignite-hq/cli/ignite/pkg/giturl" ) const ( @@ -126,10 +125,7 @@ func (c *Chain) Generate( options = append(options, cosmosgen.WithVuexGeneration( enableThirdPartyModuleCodegen, - func(m module.Module) string { - parsedGitURL, _ := giturl.Parse(m.Pkg.GoImportName) - return filepath.Join(storeRootPath, parsedGitURL.UserAndRepo(), m.Pkg.Name, "module") - }, + cosmosgen.VuexStoreModulePath(storeRootPath), storeRootPath, ), ) diff --git a/ignite/services/scaffolder/init.go b/ignite/services/scaffolder/init.go index 27e0ca4451..91d477b3d2 100644 --- a/ignite/services/scaffolder/init.go +++ b/ignite/services/scaffolder/init.go @@ -2,7 +2,9 @@ package scaffolder import ( "context" + "fmt" "path/filepath" + "strings" "time" "github.com/go-git/go-git/v5" @@ -11,7 +13,6 @@ import ( "github.com/tendermint/flutter/v2" "github.com/tendermint/vue" - "github.com/ignite-hq/cli/ignite/pkg/giturl" "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/localfs" "github.com/ignite-hq/cli/ignite/pkg/placeholder" @@ -66,9 +67,10 @@ func generate( absRoot string, noDefaultModule bool, ) error { - gu, err := giturl.Parse(pathInfo.RawPath) - if err != nil { - return err + githubPath := gomodulepath.ExtractAppPath(pathInfo.RawPath) + if !strings.Contains(githubPath, "/") { + // A username must be added when the app module path has a single element + githubPath = fmt.Sprintf("username/%s", githubPath) } g, err := app.New(&app.Options{ @@ -76,8 +78,7 @@ func generate( ModulePath: pathInfo.RawPath, AppName: pathInfo.Package, AppPath: absRoot, - OwnerName: owner(pathInfo.RawPath), - OwnerAndRepoName: gu.UserAndRepo(), + GitHubPath: githubPath, BinaryNamePrefix: pathInfo.Root, AddressPrefix: addressPrefix, }) @@ -101,7 +102,6 @@ func generate( ModulePath: pathInfo.RawPath, AppName: pathInfo.Package, AppPath: absRoot, - OwnerName: owner(pathInfo.RawPath), IsIBC: false, } g, err = modulecreate.NewStargate(opts) diff --git a/ignite/services/scaffolder/message.go b/ignite/services/scaffolder/message.go index ca85b91289..b717bcfa4f 100644 --- a/ignite/services/scaffolder/message.go +++ b/ignite/services/scaffolder/message.go @@ -119,7 +119,6 @@ func (s Scaffolder) AddMessage( AppPath: s.path, ModulePath: s.modpath.RawPath, ModuleName: moduleName, - OwnerName: owner(s.modpath.RawPath), MsgName: name, Fields: parsedMsgFields, ResFields: parsedResFields, @@ -140,7 +139,6 @@ func (s Scaffolder) AddMessage( ModulePath: opts.ModulePath, AppName: opts.AppName, AppPath: opts.AppPath, - OwnerName: opts.OwnerName, }, ) if err != nil { diff --git a/ignite/services/scaffolder/module.go b/ignite/services/scaffolder/module.go index 00cabaeda0..b47f8f9ea6 100644 --- a/ignite/services/scaffolder/module.go +++ b/ignite/services/scaffolder/module.go @@ -191,7 +191,6 @@ func (s Scaffolder) CreateModule( Params: params, AppName: s.modpath.Package, AppPath: s.path, - OwnerName: owner(s.modpath.RawPath), IsIBC: creationOpts.ibc, IBCOrdering: creationOpts.ibcChannelOrdering, Dependencies: creationOpts.dependencies, diff --git a/ignite/services/scaffolder/oracle.go b/ignite/services/scaffolder/oracle.go index 098bc26111..ee8d4b7fa2 100644 --- a/ignite/services/scaffolder/oracle.go +++ b/ignite/services/scaffolder/oracle.go @@ -94,7 +94,6 @@ func (s *Scaffolder) AddOracle( AppPath: s.path, ModulePath: s.modpath.RawPath, ModuleName: moduleName, - OwnerName: owner(s.modpath.RawPath), QueryName: name, MsgSigner: mfSigner, } diff --git a/ignite/services/scaffolder/packet.go b/ignite/services/scaffolder/packet.go index 5de23101a8..34212f5e6a 100644 --- a/ignite/services/scaffolder/packet.go +++ b/ignite/services/scaffolder/packet.go @@ -126,7 +126,6 @@ func (s Scaffolder) AddPacket( AppPath: s.path, ModulePath: s.modpath.RawPath, ModuleName: moduleName, - OwnerName: owner(s.modpath.RawPath), PacketName: name, Fields: parsedPacketFields, AckFields: parsedAcksFields, diff --git a/ignite/services/scaffolder/query.go b/ignite/services/scaffolder/query.go index 197a334384..8bd604b208 100644 --- a/ignite/services/scaffolder/query.go +++ b/ignite/services/scaffolder/query.go @@ -68,7 +68,6 @@ func (s Scaffolder) AddQuery( AppPath: s.path, ModulePath: s.modpath.RawPath, ModuleName: moduleName, - OwnerName: owner(s.modpath.RawPath), QueryName: name, ReqFields: parsedReqFields, ResFields: parsedResFields, diff --git a/ignite/services/scaffolder/scaffolder.go b/ignite/services/scaffolder/scaffolder.go index 2076d4d822..473040e599 100644 --- a/ignite/services/scaffolder/scaffolder.go +++ b/ignite/services/scaffolder/scaffolder.go @@ -6,17 +6,14 @@ import ( "context" "os" "path/filepath" - "strings" "github.com/ignite-hq/cli/ignite/chainconfig" sperrors "github.com/ignite-hq/cli/ignite/errors" "github.com/ignite-hq/cli/ignite/pkg/cmdrunner" "github.com/ignite-hq/cli/ignite/pkg/cmdrunner/step" "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis" - "github.com/ignite-hq/cli/ignite/pkg/cosmosanalysis/module" "github.com/ignite-hq/cli/ignite/pkg/cosmosgen" "github.com/ignite-hq/cli/ignite/pkg/cosmosver" - "github.com/ignite-hq/cli/ignite/pkg/giturl" "github.com/ignite-hq/cli/ignite/pkg/gocmd" "github.com/ignite-hq/cli/ignite/pkg/gomodule" "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" @@ -71,10 +68,6 @@ func App(path string) (Scaffolder, error) { return s, nil } -func owner(modulePath string) string { - return strings.Split(modulePath, "/")[1] -} - func finish(path, gomodPath string) error { if err := protoc(path, gomodPath); err != nil { return err @@ -111,10 +104,7 @@ func protoc(projectPath, gomodPath string) error { options = append(options, cosmosgen.WithVuexGeneration( false, - func(m module.Module) string { - parsedGitURL, _ := giturl.Parse(m.Pkg.GoImportName) - return filepath.Join(storeRootPath, parsedGitURL.UserAndRepo(), m.Pkg.Name, "module") - }, + cosmosgen.VuexStoreModulePath(storeRootPath), storeRootPath, ), ) diff --git a/ignite/services/scaffolder/type.go b/ignite/services/scaffolder/type.go index 497b4b963a..c2d613467a 100644 --- a/ignite/services/scaffolder/type.go +++ b/ignite/services/scaffolder/type.go @@ -175,7 +175,6 @@ func (s Scaffolder) AddType( AppPath: s.path, ModulePath: s.modpath.RawPath, ModuleName: moduleName, - OwnerName: owner(s.modpath.RawPath), TypeName: name, Fields: tFields, NoMessage: o.withoutMessage, @@ -195,7 +194,6 @@ func (s Scaffolder) AddType( ModulePath: opts.ModulePath, AppName: opts.AppName, AppPath: opts.AppPath, - OwnerName: opts.OwnerName, }, ) if err != nil { diff --git a/ignite/templates/app/app.go b/ignite/templates/app/app.go index b85f2bd112..3b0f181877 100644 --- a/ignite/templates/app/app.go +++ b/ignite/templates/app/app.go @@ -8,7 +8,6 @@ import ( "github.com/gobuffalo/plushgen" "github.com/ignite-hq/cli/ignite/pkg/xgenny" - "github.com/ignite-hq/cli/ignite/pkg/xstrings" "github.com/ignite-hq/cli/ignite/templates/field/plushhelpers" "github.com/ignite-hq/cli/ignite/templates/testutil" ) @@ -30,14 +29,10 @@ func New(opts *Options) (*genny.Generator, error) { ctx := plush.NewContext() ctx.Set("ModulePath", opts.ModulePath) ctx.Set("AppName", opts.AppName) - ctx.Set("OwnerAndRepoName", opts.OwnerAndRepoName) - ctx.Set("OwnerName", opts.OwnerName) + ctx.Set("GitHubPath", opts.GitHubPath) ctx.Set("BinaryNamePrefix", opts.BinaryNamePrefix) ctx.Set("AddressPrefix", opts.AddressPrefix) - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) - plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) g.Transformer(genny.Replace("{{appName}}", opts.AppName)) diff --git a/ignite/templates/app/options.go b/ignite/templates/app/options.go index 0b99d09d64..b682ff3f63 100644 --- a/ignite/templates/app/options.go +++ b/ignite/templates/app/options.go @@ -4,8 +4,7 @@ package app type Options struct { AppName string AppPath string - OwnerName string - OwnerAndRepoName string + GitHubPath string BinaryNamePrefix string ModulePath string AddressPrefix string diff --git a/ignite/templates/app/stargate/readme.md.plush b/ignite/templates/app/stargate/readme.md.plush index a243a60ab3..16bddb321f 100644 --- a/ignite/templates/app/stargate/readme.md.plush +++ b/ignite/templates/app/stargate/readme.md.plush @@ -39,9 +39,9 @@ After a draft release is created, make your final changes from the release page To install the latest version of your blockchain node's binary, execute the following command on your machine: ``` -curl https://get.ignite.com/<%= OwnerAndRepoName %>@latest! | sudo bash +curl https://get.ignite.com/<%= GitHubPath %>@latest! | sudo bash ``` -`<%= OwnerAndRepoName %>` should match the `username` and `repo_name` of the Github repository to which the source code was pushed. Learn more about [the install process](https://github.com/allinbits/starport-installer). +`<%= GitHubPath %>` should match the `username` and `repo_name` of the Github repository to which the source code was pushed. Learn more about [the install process](https://github.com/allinbits/starport-installer). ## Learn more diff --git a/ignite/templates/ibc/oracle.go b/ignite/templates/ibc/oracle.go index 2d4a1e5b50..d876c4276a 100644 --- a/ignite/templates/ibc/oracle.go +++ b/ignite/templates/ibc/oracle.go @@ -10,11 +10,12 @@ import ( "github.com/gobuffalo/plush" "github.com/gobuffalo/plushgen" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/multiformatname" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" - "github.com/ignite-hq/cli/ignite/pkg/xstrings" "github.com/ignite-hq/cli/ignite/templates/field/plushhelpers" + "github.com/ignite-hq/cli/ignite/templates/module" "github.com/ignite-hq/cli/ignite/templates/testutil" ) @@ -29,7 +30,6 @@ type OracleOptions struct { AppPath string ModuleName string ModulePath string - OwnerName string QueryName multiformatname.Name MsgSigner multiformatname.Name } @@ -48,16 +48,15 @@ func NewOracle(replacer placeholder.Replacer, opts *OracleOptions) (*genny.Gener g.RunFn(clientCliTxOracleModify(replacer, opts)) g.RunFn(codecOracleModify(replacer, opts)) + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) + ctx := plush.NewContext() ctx.Set("moduleName", opts.ModuleName) ctx.Set("ModulePath", opts.ModulePath) ctx.Set("appName", opts.AppName) - ctx.Set("ownerName", opts.OwnerName) ctx.Set("queryName", opts.QueryName) ctx.Set("MsgSigner", opts.MsgSigner) - - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) + ctx.Set("protoPkgName", module.ProtoPackageName(appModulePath, opts.ModuleName)) plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) diff --git a/ignite/templates/ibc/oracle/proto/{{moduleName}}/{{queryName}}.proto.plush b/ignite/templates/ibc/oracle/proto/{{moduleName}}/{{queryName}}.proto.plush index 0fbefdcfcb..2ef679f28a 100644 --- a/ignite/templates/ibc/oracle/proto/{{moduleName}}/{{queryName}}.proto.plush +++ b/ignite/templates/ibc/oracle/proto/{{moduleName}}/{{queryName}}.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; option go_package = "<%= ModulePath %>/x/<%= moduleName %>/types"; diff --git a/ignite/templates/ibc/packet.go b/ignite/templates/ibc/packet.go index b69a61edae..3c86d07cfc 100644 --- a/ignite/templates/ibc/packet.go +++ b/ignite/templates/ibc/packet.go @@ -34,7 +34,6 @@ type PacketOptions struct { AppPath string ModuleName string ModulePath string - OwnerName string PacketName multiformatname.Name MsgSigner multiformatname.Name Fields field.Fields @@ -84,7 +83,6 @@ func NewPacket(replacer placeholder.Replacer, opts *PacketOptions) (*genny.Gener ctx.Set("appName", opts.AppName) ctx.Set("packetName", opts.PacketName) ctx.Set("MsgSigner", opts.MsgSigner) - ctx.Set("ownerName", opts.OwnerName) ctx.Set("fields", opts.Fields) ctx.Set("ackFields", opts.AckFields) diff --git a/ignite/templates/message/message.go b/ignite/templates/message/message.go index fc677e02da..8e958027f4 100644 --- a/ignite/templates/message/message.go +++ b/ignite/templates/message/message.go @@ -30,7 +30,6 @@ func Box(box packd.Walker, opts *Options, g *genny.Generator) error { ctx.Set("MsgName", opts.MsgName) ctx.Set("MsgDesc", opts.MsgDesc) ctx.Set("MsgSigner", opts.MsgSigner) - ctx.Set("OwnerName", opts.OwnerName) ctx.Set("ModulePath", opts.ModulePath) ctx.Set("Fields", opts.Fields) ctx.Set("ResFields", opts.ResFields) diff --git a/ignite/templates/message/options.go b/ignite/templates/message/options.go index ac72e0bb4b..969a019620 100644 --- a/ignite/templates/message/options.go +++ b/ignite/templates/message/options.go @@ -11,7 +11,6 @@ type Options struct { AppPath string ModuleName string ModulePath string - OwnerName string MsgName multiformatname.Name MsgSigner multiformatname.Name MsgDesc string diff --git a/ignite/templates/module/create/ibc.go b/ignite/templates/module/create/ibc.go index d2c9645560..8efbb01026 100644 --- a/ignite/templates/module/create/ibc.go +++ b/ignite/templates/module/create/ibc.go @@ -8,6 +8,7 @@ import ( "github.com/gobuffalo/plush" "github.com/gobuffalo/plushgen" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/pkg/xstrings" @@ -31,16 +32,16 @@ func NewIBC(replacer placeholder.Replacer, opts *CreateOptions) (*genny.Generato if err := g.Box(template); err != nil { return g, err } + + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) + ctx := plush.NewContext() ctx.Set("moduleName", opts.ModuleName) ctx.Set("modulePath", opts.ModulePath) ctx.Set("appName", opts.AppName) - ctx.Set("ownerName", opts.OwnerName) ctx.Set("ibcOrdering", opts.IBCOrdering) ctx.Set("dependencies", opts.Dependencies) - - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) + ctx.Set("protoPkgName", module.ProtoPackageName(appModulePath, opts.ModuleName)) plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) diff --git a/ignite/templates/module/create/ibc/proto/{{moduleName}}/packet.proto.plush b/ignite/templates/module/create/ibc/proto/{{moduleName}}/packet.proto.plush index 99d27ff926..c263816dfe 100644 --- a/ignite/templates/module/create/ibc/proto/{{moduleName}}/packet.proto.plush +++ b/ignite/templates/module/create/ibc/proto/{{moduleName}}/packet.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; // this line is used by starport scaffolding # proto/packet/import @@ -15,4 +15,4 @@ message <%= title(moduleName) %>PacketData { message NoData { } -// this line is used by starport scaffolding # ibc/packet/proto/message \ No newline at end of file +// this line is used by starport scaffolding # ibc/packet/proto/message diff --git a/ignite/templates/module/create/msgserver.go b/ignite/templates/module/create/msgserver.go index ac5f8ecf34..a917b59195 100644 --- a/ignite/templates/module/create/msgserver.go +++ b/ignite/templates/module/create/msgserver.go @@ -8,9 +8,9 @@ import ( "github.com/gobuffalo/plush" "github.com/gobuffalo/plushgen" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" - "github.com/ignite-hq/cli/ignite/pkg/xstrings" "github.com/ignite-hq/cli/ignite/templates/field/plushhelpers" "github.com/ignite-hq/cli/ignite/templates/module" "github.com/ignite-hq/cli/ignite/templates/typed" @@ -32,14 +32,14 @@ func AddMsgServerConventionToLegacyModule(replacer placeholder.Replacer, opts *M if err := g.Box(template); err != nil { return g, err } + + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) + ctx := plush.NewContext() ctx.Set("moduleName", opts.ModuleName) ctx.Set("modulePath", opts.ModulePath) ctx.Set("appName", opts.AppName) - ctx.Set("ownerName", opts.OwnerName) - - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) + ctx.Set("protoPkgName", module.ProtoPackageName(appModulePath, opts.ModuleName)) plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) diff --git a/ignite/templates/module/create/msgserver/proto/{{moduleName}}/tx.proto.plush b/ignite/templates/module/create/msgserver/proto/{{moduleName}}/tx.proto.plush index 501b59f74c..ab7e8cfe26 100644 --- a/ignite/templates/module/create/msgserver/proto/{{moduleName}}/tx.proto.plush +++ b/ignite/templates/module/create/msgserver/proto/{{moduleName}}/tx.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; // this line is used by starport scaffolding # proto/tx/import @@ -10,4 +10,4 @@ service Msg { // this line is used by starport scaffolding # proto/tx/rpc } -// this line is used by starport scaffolding # proto/tx/message \ No newline at end of file +// this line is used by starport scaffolding # proto/tx/message diff --git a/ignite/templates/module/create/options.go b/ignite/templates/module/create/options.go index f64537d985..889b29a231 100644 --- a/ignite/templates/module/create/options.go +++ b/ignite/templates/module/create/options.go @@ -13,7 +13,6 @@ type CreateOptions struct { ModulePath string AppName string AppPath string - OwnerName string Params field.Fields // True if the module should implement the IBC module interface @@ -32,7 +31,6 @@ type MsgServerOptions struct { ModulePath string AppName string AppPath string - OwnerName string } // Validate that options are usable diff --git a/ignite/templates/module/create/stargate.go b/ignite/templates/module/create/stargate.go index c412d13511..692003dceb 100644 --- a/ignite/templates/module/create/stargate.go +++ b/ignite/templates/module/create/stargate.go @@ -8,6 +8,7 @@ import ( "github.com/gobuffalo/plush" "github.com/gobuffalo/plushgen" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/pkg/xstrings" @@ -46,17 +47,18 @@ func NewStargate(opts *CreateOptions) (*genny.Generator, error) { if err := g.Box(stargateTemplate); err != nil { return g, err } + + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) + ctx := plush.NewContext() ctx.Set("moduleName", opts.ModuleName) ctx.Set("modulePath", opts.ModulePath) ctx.Set("appName", opts.AppName) - ctx.Set("ownerName", opts.OwnerName) ctx.Set("dependencies", opts.Dependencies) ctx.Set("params", opts.Params) ctx.Set("isIBC", opts.IsIBC) - - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) + ctx.Set("apiPath", fmt.Sprintf("/%s/%s", appModulePath, opts.ModuleName)) + ctx.Set("protoPkgName", module.ProtoPackageName(appModulePath, opts.ModuleName)) plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) diff --git a/ignite/templates/module/create/stargate/proto/{{moduleName}}/genesis.proto.plush b/ignite/templates/module/create/stargate/proto/{{moduleName}}/genesis.proto.plush index 3f7e69e177..603735f055 100644 --- a/ignite/templates/module/create/stargate/proto/{{moduleName}}/genesis.proto.plush +++ b/ignite/templates/module/create/stargate/proto/{{moduleName}}/genesis.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; import "gogoproto/gogo.proto"; import "<%= moduleName %>/params.proto"; diff --git a/ignite/templates/module/create/stargate/proto/{{moduleName}}/params.proto.plush b/ignite/templates/module/create/stargate/proto/{{moduleName}}/params.proto.plush index bf3f025f15..2487dade89 100644 --- a/ignite/templates/module/create/stargate/proto/{{moduleName}}/params.proto.plush +++ b/ignite/templates/module/create/stargate/proto/{{moduleName}}/params.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; import "gogoproto/gogo.proto"; @@ -10,4 +10,4 @@ message Params { option (gogoproto.goproto_stringer) = false; <%= for (i, param) in params { %> <%= param.ProtoType(i+1) %> [(gogoproto.moretags) = "yaml:\"<%= param.Name.Snake %>\""];<% } %> -} \ No newline at end of file +} diff --git a/ignite/templates/module/create/stargate/proto/{{moduleName}}/query.proto.plush b/ignite/templates/module/create/stargate/proto/{{moduleName}}/query.proto.plush index 83e8d6b3c2..a5d5dab226 100644 --- a/ignite/templates/module/create/stargate/proto/{{moduleName}}/query.proto.plush +++ b/ignite/templates/module/create/stargate/proto/{{moduleName}}/query.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(ownerName) %>.<%= appName %>.<%= moduleName %>; +package <%= protoPkgName %>; import "gogoproto/gogo.proto"; import "google/api/annotations.proto"; @@ -13,7 +13,7 @@ option go_package = "<%= modulePath %>/x/<%= moduleName %>/types"; service Query { // Parameters queries the parameters of the module. rpc Params(QueryParamsRequest) returns (QueryParamsResponse) { - option (google.api.http).get = "/<%= formatOwnerName(ownerName) %>/<%= appName %>/<%= moduleName %>/params"; + option (google.api.http).get = "<%= apiPath %>/params"; } // this line is used by starport scaffolding # 2 } diff --git a/ignite/templates/module/module.go b/ignite/templates/module/module.go new file mode 100644 index 0000000000..6f34467088 --- /dev/null +++ b/ignite/templates/module/module.go @@ -0,0 +1,20 @@ +package module + +import ( + "strings" + + "github.com/ignite-hq/cli/ignite/pkg/xstrings" +) + +// ProtoPackageName creates a protocol buffer package name for an app module. +func ProtoPackageName(appModulePath, moduleName string) string { + path := strings.Split(appModulePath, "/") + path = append(path, moduleName) + + // Make sure that the first path element can be used as proto package name. + // This is required for app module names like "github.com/username/repo" where + // "username" might be not be compatible with proto buffer package names. + path[0] = xstrings.FormatUsername(path[0]) + + return strings.Join(path, ".") +} diff --git a/ignite/templates/module/module_test.go b/ignite/templates/module/module_test.go new file mode 100644 index 0000000000..2289cc0aed --- /dev/null +++ b/ignite/templates/module/module_test.go @@ -0,0 +1,53 @@ +package module + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestProtoPackageName(t *testing.T) { + cases := []struct { + name string + app string + module string + want string + }{ + { + name: "name", + app: "ignite", + module: "test", + want: "ignite.test", + }, + { + name: "path", + app: "ignite/cli", + module: "test", + want: "ignite.cli.test", + }, + { + name: "path with dash", + app: "ignite-hq/cli", + module: "test", + want: "ignitehq.cli.test", + }, + { + name: "path with number prefix", + app: "0ignite/cli", + module: "test", + want: "_0ignite.cli.test", + }, + { + name: "path with number prefix and dash", + app: "0ignite-hq/cli", + module: "test", + want: "_0ignitehq.cli.test", + }, + } + + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, ProtoPackageName(tt.app, tt.module)) + }) + } +} diff --git a/ignite/templates/query/options.go b/ignite/templates/query/options.go index 5e9469ed4a..0ae2f1c878 100644 --- a/ignite/templates/query/options.go +++ b/ignite/templates/query/options.go @@ -11,7 +11,6 @@ type Options struct { AppPath string ModuleName string ModulePath string - OwnerName string QueryName multiformatname.Name Description string ResFields field.Fields diff --git a/ignite/templates/query/query.go b/ignite/templates/query/query.go index ef1de8d36f..518adf0480 100644 --- a/ignite/templates/query/query.go +++ b/ignite/templates/query/query.go @@ -25,7 +25,6 @@ func Box(box packd.Walker, opts *Options, g *genny.Generator) error { ctx.Set("AppName", opts.AppName) ctx.Set("QueryName", opts.QueryName) ctx.Set("Description", opts.Description) - ctx.Set("OwnerName", opts.OwnerName) ctx.Set("ModulePath", opts.ModulePath) ctx.Set("ReqFields", opts.ReqFields) ctx.Set("ResFields", opts.ResFields) diff --git a/ignite/templates/query/stargate.go b/ignite/templates/query/stargate.go index 62c24e0da3..bde916f6d4 100644 --- a/ignite/templates/query/stargate.go +++ b/ignite/templates/query/stargate.go @@ -7,6 +7,7 @@ import ( "github.com/gobuffalo/genny" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" ) @@ -46,16 +47,16 @@ func protoQueryModify(replacer placeholder.Replacer, opts *Options) genny.RunFn // RPC service templateRPC := `// Queries a list of %[2]v items. rpc %[2]v(Query%[2]vRequest) returns (Query%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v%[7]v"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v%[6]v"; } %[1]v` + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) replacementRPC := fmt.Sprintf( templateRPC, Placeholder2, opts.QueryName.UpperCamel, - opts.OwnerName, - opts.AppName, + appModulePath, opts.ModuleName, opts.QueryName.Snake, reqPath, diff --git a/ignite/templates/typed/dry/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush b/ignite/templates/typed/dry/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush index c59cc818fa..9dfb7c5f53 100644 --- a/ignite/templates/typed/dry/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush +++ b/ignite/templates/typed/dry/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(OwnerName) %>.<%= AppName %>.<%= ModuleName %>; +package <%= protoPkgName %>; option go_package = "<%= ModulePath %>/x/<%= ModuleName %>/types";<%= for (importName) in mergeCustomImports(Fields) { %> import "<%= ModuleName %>/<%= importName %>.proto"; <% } %><%= for (importName) in mergeProtoImports(Fields) { %> diff --git a/ignite/templates/typed/list/stargate.go b/ignite/templates/typed/list/stargate.go index 062a5635f6..49a2470496 100644 --- a/ignite/templates/typed/list/stargate.go +++ b/ignite/templates/typed/list/stargate.go @@ -9,6 +9,7 @@ import ( "github.com/gobuffalo/genny" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/templates/typed" @@ -230,19 +231,19 @@ func protoQueryModify(replacer placeholder.Replacer, opts *typed.Options) genny. // RPC service templateRPC := `// Queries a %[2]v by id. rpc %[2]v(QueryGet%[2]vRequest) returns (QueryGet%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v/{id}"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/{id}"; } // Queries a list of %[2]v items. rpc %[2]vAll(QueryAll%[2]vRequest) returns (QueryAll%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v"; } %[1]v` + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) replacementRPC := fmt.Sprintf(templateRPC, typed.Placeholder2, opts.TypeName.UpperCamel, - opts.OwnerName, - opts.AppName, + appModulePath, opts.ModuleName, opts.TypeName.Snake, ) @@ -395,11 +396,11 @@ func frontendSrcStoreAppModify(replacer placeholder.Replacer, opts *typed.Option if err != nil { return err } + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) replacement := fmt.Sprintf(`%[1]v - `, + `, typed.Placeholder4, - opts.OwnerName, - opts.AppName, + strings.ReplaceAll(appModulePath, "/", "."), opts.ModuleName, opts.TypeName.UpperCamel, ) diff --git a/ignite/templates/typed/list/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush b/ignite/templates/typed/list/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush index 92ebe08e0d..f37c3ed5e9 100644 --- a/ignite/templates/typed/list/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush +++ b/ignite/templates/typed/list/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(OwnerName) %>.<%= AppName %>.<%= ModuleName %>; +package <%= protoPkgName %>; option go_package = "<%= ModulePath %>/x/<%= ModuleName %>/types";<%= for (importName) in mergeCustomImports(Fields) { %> import "<%= ModuleName %>/<%= importName %>.proto"; <% } %><%= for (importName) in mergeProtoImports(Fields) { %> @@ -9,4 +9,4 @@ message <%= TypeName.UpperCamel %> { uint64 id = 1;<%= for (i, field) in Fields { %> <%= field.ProtoType(i+2) %>; <% } %> <%= if (!NoMessage) { %>string <%= MsgSigner.LowerCamel %> = <%= len(Fields)+2 %>;<% } %> -} \ No newline at end of file +} diff --git a/ignite/templates/typed/map/stargate.go b/ignite/templates/typed/map/stargate.go index a2de498f7f..255679c791 100644 --- a/ignite/templates/typed/map/stargate.go +++ b/ignite/templates/typed/map/stargate.go @@ -8,6 +8,7 @@ import ( "github.com/gobuffalo/genny" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/templates/field/datatype" @@ -145,20 +146,20 @@ func protoRPCModify(replacer placeholder.Replacer, opts *typed.Options) genny.Ru // Add the service templateService := `// Queries a %[2]v by index. rpc %[2]v(QueryGet%[2]vRequest) returns (QueryGet%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v/%[7]v"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v"; } // Queries a list of %[2]v items. rpc %[2]vAll(QueryAll%[2]vRequest) returns (QueryAll%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v"; } %[1]v` + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) replacementService := fmt.Sprintf(templateService, typed.Placeholder2, opts.TypeName.UpperCamel, - opts.OwnerName, - opts.AppName, + appModulePath, opts.ModuleName, opts.TypeName.Snake, indexPath, diff --git a/ignite/templates/typed/map/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush b/ignite/templates/typed/map/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush index 8e34e7e04a..efec0ead9c 100644 --- a/ignite/templates/typed/map/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush +++ b/ignite/templates/typed/map/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(OwnerName) %>.<%= AppName %>.<%= ModuleName %>; +package <%= protoPkgName %>; option go_package = "<%= ModulePath %>/x/<%= ModuleName %>/types";<%= for (importName) in mergeCustomImports(Fields, Indexes) { %> import "<%= ModuleName %>/<%= importName %>.proto"; <% } %><%= for (importName) in mergeProtoImports(Fields, Indexes) { %> diff --git a/ignite/templates/typed/options.go b/ignite/templates/typed/options.go index 038fa727c5..4003fb482c 100644 --- a/ignite/templates/typed/options.go +++ b/ignite/templates/typed/options.go @@ -11,7 +11,6 @@ type Options struct { AppPath string ModuleName string ModulePath string - OwnerName string TypeName multiformatname.Name MsgSigner multiformatname.Name Fields field.Fields diff --git a/ignite/templates/typed/singleton/stargate.go b/ignite/templates/typed/singleton/stargate.go index f19c1a0985..53c74b1688 100644 --- a/ignite/templates/typed/singleton/stargate.go +++ b/ignite/templates/typed/singleton/stargate.go @@ -9,6 +9,7 @@ import ( "github.com/gobuffalo/genny" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgenny" "github.com/ignite-hq/cli/ignite/templates/module" @@ -122,13 +123,13 @@ func protoRPCModify(replacer placeholder.Replacer, opts *typed.Options) genny.Ru // Add the service templateService := `// Queries a %[2]v by index. rpc %[2]v(QueryGet%[2]vRequest) returns (QueryGet%[2]vResponse) { - option (google.api.http).get = "/%[3]v/%[4]v/%[5]v/%[6]v"; + option (google.api.http).get = "/%[3]v/%[4]v/%[5]v"; } %[1]v` + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) replacementService := fmt.Sprintf(templateService, typed.Placeholder2, opts.TypeName.UpperCamel, - opts.OwnerName, - opts.AppName, + appModulePath, opts.ModuleName, opts.TypeName.Snake, ) diff --git a/ignite/templates/typed/singleton/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush b/ignite/templates/typed/singleton/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush index 9cc9b70b83..10157cf1f6 100644 --- a/ignite/templates/typed/singleton/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush +++ b/ignite/templates/typed/singleton/stargate/component/proto/{{moduleName}}/{{typeName}}.proto.plush @@ -1,5 +1,5 @@ syntax = "proto3"; -package <%= formatOwnerName(OwnerName) %>.<%= AppName %>.<%= ModuleName %>; +package <%= protoPkgName %>; option go_package = "<%= ModulePath %>/x/<%= ModuleName %>/types";<%= for (importName) in mergeCustomImports(Fields) { %> import "<%= ModuleName %>/<%= importName %>.proto"; <% } %><%= for (importName) in mergeProtoImports(Fields) { %> diff --git a/ignite/templates/typed/typed.go b/ignite/templates/typed/typed.go index 13ca8a6218..7983562efe 100644 --- a/ignite/templates/typed/typed.go +++ b/ignite/templates/typed/typed.go @@ -6,8 +6,9 @@ import ( "github.com/gobuffalo/plush" "github.com/gobuffalo/plushgen" - "github.com/ignite-hq/cli/ignite/pkg/xstrings" + "github.com/ignite-hq/cli/ignite/pkg/gomodulepath" "github.com/ignite-hq/cli/ignite/templates/field/plushhelpers" + "github.com/ignite-hq/cli/ignite/templates/module" "github.com/ignite-hq/cli/ignite/templates/testutil" ) @@ -15,16 +16,19 @@ func Box(box packd.Walker, opts *Options, g *genny.Generator) error { if err := g.Box(box); err != nil { return err } + + appModulePath := gomodulepath.ExtractAppPath(opts.ModulePath) + ctx := plush.NewContext() ctx.Set("ModuleName", opts.ModuleName) ctx.Set("AppName", opts.AppName) ctx.Set("TypeName", opts.TypeName) - ctx.Set("OwnerName", opts.OwnerName) ctx.Set("ModulePath", opts.ModulePath) ctx.Set("MsgSigner", opts.MsgSigner) ctx.Set("Fields", opts.Fields) ctx.Set("Indexes", opts.Indexes) ctx.Set("NoMessage", opts.NoMessage) + ctx.Set("protoPkgName", module.ProtoPackageName(appModulePath, opts.ModuleName)) ctx.Set("strconv", func() bool { strconv := false for _, field := range opts.Fields { @@ -35,9 +39,6 @@ func Box(box packd.Walker, opts *Options, g *genny.Generator) error { return strconv }) - // Used for proto package name - ctx.Set("formatOwnerName", xstrings.FormatUsername) - plushhelpers.ExtendPlushContext(ctx) g.Transformer(plushgen.Transformer(ctx)) g.Transformer(genny.Replace("{{moduleName}}", opts.ModuleName)) diff --git a/integration/app/cmd_app_test.go b/integration/app/cmd_app_test.go index 106bed6917..a9c180db24 100644 --- a/integration/app/cmd_app_test.go +++ b/integration/app/cmd_app_test.go @@ -4,7 +4,6 @@ package app_test import ( - "fmt" "os" "path/filepath" "testing" @@ -18,7 +17,7 @@ import ( func TestGenerateAnApp(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) _, statErr := os.Stat(filepath.Join(path, "x", "blog")) @@ -27,32 +26,24 @@ func TestGenerateAnApp(t *testing.T) { env.EnsureAppIsSteady(path) } -func TestGenerateAnAppWithNoDefaultModule(t *testing.T) { +// TestGenerateAnAppWithName tests scaffolding a new chain using a local name instead of a GitHub URI. +func TestGenerateAnAppWithName(t *testing.T) { var ( - env = envtest.New(t) - appName = "blog" + env = envtest.New(t) + path = env.Scaffold("blog") ) - root := env.TmpDir() - env.Exec("scaffold an app", - step.NewSteps(step.New( - step.Exec( - envtest.IgniteApp, - "scaffold", - "chain", - fmt.Sprintf("github.com/test/%s", appName), - "--no-module", - ), - step.Workdir(root), - )), - ) + _, statErr := os.Stat(filepath.Join(path, "x", "blog")) + require.False(t, os.IsNotExist(statErr), "the default module should be scaffolded") - // Cleanup the home directory of the app - env.SetCleanup(func() { - os.RemoveAll(filepath.Join(env.Home(), fmt.Sprintf(".%s", appName))) - }) + env.EnsureAppIsSteady(path) +} - path := filepath.Join(root, appName) +func TestGenerateAnAppWithNoDefaultModule(t *testing.T) { + var ( + env = envtest.New(t) + path = env.Scaffold("github.com/test/blog", "--no-module") + ) _, statErr := os.Stat(filepath.Join(path, "x", "blog")) require.True(t, os.IsNotExist(statErr), "the default module should not be scaffolded") @@ -63,7 +54,7 @@ func TestGenerateAnAppWithNoDefaultModule(t *testing.T) { func TestGenerateAnAppWithNoDefaultModuleAndCreateAModule(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog", "--no-module") + path = env.Scaffold("github.com/test/blog", "--no-module") ) defer env.EnsureAppIsSteady(path) @@ -81,7 +72,7 @@ func TestGenerateAnAppWithWasm(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("add Wasm module", @@ -105,7 +96,7 @@ func TestGenerateAnAppWithWasm(t *testing.T) { func TestGenerateAStargateAppWithEmptyModule(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a module", diff --git a/integration/app/cmd_ibc_test.go b/integration/app/cmd_ibc_test.go index d1a7c1fef6..8be41ebf73 100644 --- a/integration/app/cmd_ibc_test.go +++ b/integration/app/cmd_ibc_test.go @@ -15,7 +15,7 @@ func TestCreateModuleWithIBC(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blogibc") + path = env.Scaffold("github.com/test/blogibc") ) env.Must(env.Exec("create an IBC module", @@ -113,7 +113,7 @@ func TestCreateIBCOracle(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("ibcoracle") + path = env.Scaffold("github.com/test/ibcoracle") ) env.Must(env.Exec("create an IBC module", @@ -192,7 +192,7 @@ func TestCreateIBCPacket(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blogibc2") + path = env.Scaffold("github.com/test/blogibc2") ) env.Must(env.Exec("create an IBC module", diff --git a/integration/app/cmd_serve_test.go b/integration/app/cmd_serve_test.go index 5349afeb4a..2b2523253b 100644 --- a/integration/app/cmd_serve_test.go +++ b/integration/app/cmd_serve_test.go @@ -20,7 +20,7 @@ func TestServeStargateWithWasm(t *testing.T) { var ( env = envtest.New(t) - apath = env.Scaffold("sgblog") + apath = env.Scaffold("github.com/test/sgblog") servers = env.RandomizeServerPorts(apath, "") ) @@ -47,7 +47,7 @@ func TestServeStargateWithWasm(t *testing.T) { func TestServeStargateWithCustomHome(t *testing.T) { var ( env = envtest.New(t) - apath = env.Scaffold("sgblog2") + apath = env.Scaffold("github.com/test/sgblog2") servers = env.RandomizeServerPorts(apath, "") ) @@ -67,7 +67,7 @@ func TestServeStargateWithCustomHome(t *testing.T) { func TestServeStargateWithConfigHome(t *testing.T) { var ( env = envtest.New(t) - apath = env.Scaffold("sgblog3") + apath = env.Scaffold("github.com/test/sgblog3") servers = env.RandomizeServerPorts(apath, "") ) @@ -92,7 +92,7 @@ func TestServeStargateWithCustomConfigFile(t *testing.T) { var ( env = envtest.New(t) - apath = env.Scaffold("sgblog4") + apath = env.Scaffold("github.com/test/sgblog4") ) // Move config newConfig := "new_config.yml" @@ -117,3 +117,28 @@ func TestServeStargateWithCustomConfigFile(t *testing.T) { require.NoError(t, isBackendAliveErr, "app cannot get online in time") } + +// TestServeStargateWithName tests serving a new chain scaffolded using a local name instead of a GitHub URI. +func TestServeStargateWithName(t *testing.T) { + var ( + env = envtest.New(t) + apath = env.Scaffold("sgblog5") + servers = env.RandomizeServerPorts(apath, "") + ) + + env.SetRandomHomeConfig(apath, "") + + ctx, cancel := context.WithTimeout(env.Ctx(), envtest.ServeTimeout) + + var isBackendAliveErr error + + go func() { + defer cancel() + + isBackendAliveErr = env.IsAppServed(ctx, servers) + }() + + env.Must(env.Serve("should serve with Stargate version", apath, "", "", envtest.ExecCtx(ctx))) + + require.NoError(t, isBackendAliveErr, "app cannot get online in time") +} diff --git a/integration/app/config_test.go b/integration/app/config_test.go index 16a25c1aa7..ba68578402 100644 --- a/integration/app/config_test.go +++ b/integration/app/config_test.go @@ -5,6 +5,7 @@ package app_test import ( "context" + "fmt" "path/filepath" "testing" @@ -20,7 +21,7 @@ func TestOverwriteSDKConfigsAndChainID(t *testing.T) { var ( env = envtest.New(t) appname = randstr.Runes(10) - path = env.Scaffold(appname) + path = env.Scaffold(fmt.Sprintf("github.com/test/%s", appname)) servers = env.RandomizeServerPorts(path, "") ctx, cancel = context.WithCancel(env.Ctx()) isBackendAliveErr error diff --git a/integration/app/tx_test.go b/integration/app/tx_test.go index a308fb674b..9efa335476 100644 --- a/integration/app/tx_test.go +++ b/integration/app/tx_test.go @@ -25,7 +25,7 @@ func TestGetTxViaGRPCGateway(t *testing.T) { var ( env = envtest.New(t) appname = randstr.Runes(10) - path = env.Scaffold(appname) + path = env.Scaffold(fmt.Sprintf("github.com/test/%s", appname)) host = env.RandomizeServerPorts(path, "") ctx, cancel = context.WithCancel(env.Ctx()) ) diff --git a/integration/cosmosgen/cosmosgen_test.go b/integration/cosmosgen/cosmosgen_test.go index 3cfe036034..2ce286ace4 100644 --- a/integration/cosmosgen/cosmosgen_test.go +++ b/integration/cosmosgen/cosmosgen_test.go @@ -15,7 +15,7 @@ import ( func TestCosmosGen(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") dirGenerated = filepath.Join(path, "vue/src/store/generated") ) diff --git a/integration/env.go b/integration/env.go index 18f10294f2..5e3183a103 100644 --- a/integration/env.go +++ b/integration/env.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "os" + "path" "path/filepath" "strconv" "testing" @@ -165,7 +166,7 @@ const ( ) // Scaffold scaffolds an app to a unique appPath and returns it. -func (e Env) Scaffold(appName string, flags ...string) (appPath string) { +func (e Env) Scaffold(name string, flags ...string) (appPath string) { root := e.TmpDir() e.Exec("scaffold an app", step.NewSteps(step.New( @@ -174,19 +175,21 @@ func (e Env) Scaffold(appName string, flags ...string) (appPath string) { append([]string{ "scaffold", "chain", - fmt.Sprintf("github.com/test/%s", appName), + name, }, flags...)..., ), step.Workdir(root), )), ) + appDir := path.Base(name) + // Cleanup the home directory of the app e.t.Cleanup(func() { - os.RemoveAll(filepath.Join(e.Home(), fmt.Sprintf(".%s", appName))) + os.RemoveAll(filepath.Join(e.Home(), fmt.Sprintf(".%s", appDir))) }) - return filepath.Join(root, appName) + return filepath.Join(root, appDir) } // Serve serves an application lives under path with options where msg describes the diff --git a/integration/faucet/faucet_test.go b/integration/faucet/faucet_test.go index c9ea7f2f76..40b615e869 100644 --- a/integration/faucet/faucet_test.go +++ b/integration/faucet/faucet_test.go @@ -32,7 +32,7 @@ var ( func TestRequestCoinsFromFaucet(t *testing.T) { var ( env = envtest.New(t) - apath = env.Scaffold("faucet") + apath = env.Scaffold("github.com/test/faucet") servers = env.RandomizeServerPorts(apath, "") faucetURL = env.ConfigureFaucet(apath, "", defaultCoins, maxCoins) ctx, cancel = context.WithTimeout(env.Ctx(), envtest.ServeTimeout) diff --git a/integration/list/cmd_list_test.go b/integration/list/cmd_list_test.go index 4480ad9476..8a2385c97a 100644 --- a/integration/list/cmd_list_test.go +++ b/integration/list/cmd_list_test.go @@ -14,7 +14,7 @@ import ( func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a list", @@ -123,7 +123,7 @@ func TestGenerateAnAppWithStargateWithListAndVerify(t *testing.T) { func TestCreateListInCustomModuleWithStargate(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a module", diff --git a/integration/map/cmd_map_test.go b/integration/map/cmd_map_test.go index 77f9c0d3d2..73e013bc37 100644 --- a/integration/map/cmd_map_test.go +++ b/integration/map/cmd_map_test.go @@ -14,7 +14,7 @@ import ( func TestCreateMapWithStargate(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a map", diff --git a/integration/other_components/cmd_message_test.go b/integration/other_components/cmd_message_test.go index 53c2daa185..a49de5d26f 100644 --- a/integration/other_components/cmd_message_test.go +++ b/integration/other_components/cmd_message_test.go @@ -14,7 +14,7 @@ import ( func TestGenerateAnAppWithMessage(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a message", diff --git a/integration/other_components/cmd_query_test.go b/integration/other_components/cmd_query_test.go index 7451b81daa..d752a6c243 100644 --- a/integration/other_components/cmd_query_test.go +++ b/integration/other_components/cmd_query_test.go @@ -14,7 +14,7 @@ import ( func TestGenerateAnAppWithQuery(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a query", diff --git a/integration/readme.md b/integration/readme.md index 096ae6b883..2dcafbfe23 100644 --- a/integration/readme.md +++ b/integration/readme.md @@ -18,7 +18,7 @@ go test -v -timeout 120m ./integration/list ```go var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) ``` @@ -43,4 +43,4 @@ env.Must(env.Exec("should prevent creating a list with duplicated fields", envtest.ExecShouldError(), )) env.EnsureAppIsSteady(path) -``` \ No newline at end of file +``` diff --git a/integration/simulation/simapp_test.go b/integration/simulation/simapp_test.go index 630a7d30fc..da08510728 100644 --- a/integration/simulation/simapp_test.go +++ b/integration/simulation/simapp_test.go @@ -13,7 +13,7 @@ import ( func TestGenerateAnAppAndSimulate(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create a list", diff --git a/integration/single/cmd_singleton_test.go b/integration/single/cmd_singleton_test.go index 3efce2d4ce..00a5d4d797 100644 --- a/integration/single/cmd_singleton_test.go +++ b/integration/single/cmd_singleton_test.go @@ -14,7 +14,7 @@ import ( func TestCreateSingletonWithStargate(t *testing.T) { var ( env = envtest.New(t) - path = env.Scaffold("blog") + path = env.Scaffold("github.com/test/blog") ) env.Must(env.Exec("create an singleton type", From 33791939799ac81a6a636694de3933b5cbd50f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Fri, 6 May 2022 11:27:08 +0300 Subject: [PATCH 23/30] chore(gitpod): upgrade Go version to v1.18.1 (#2452) --- .gitpod.Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitpod.Dockerfile b/.gitpod.Dockerfile index fb9b397241..ea8c8f486b 100644 --- a/.gitpod.Dockerfile +++ b/.gitpod.Dockerfile @@ -1,5 +1,14 @@ FROM gitpod/workspace-full +# Go +ENV GO_VERSION=1.18.1 +ENV GOPATH=$HOME/go-packages +ENV GOROOT=$HOME/go +ENV PATH=$GOROOT/bin:$GOPATH/bin:$PATH +RUN curl -fsSL https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz | tar xzs && printf '%s\n' 'export GOPATH=/workspace/go' 'export PATH=$GOPATH/bin:$PATH' > $HOME/.bashrc.d/300-go + +# GH CLI RUN brew install gh +# NPM RUN npm install -g npm@7.10.0 From 22f1254f1af548fbc50f213aac1f93cc351c4cc7 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Fri, 6 May 2022 05:33:21 -0300 Subject: [PATCH 24/30] fix(relayer): CLI UI package is stuck in the relayer commands (#2449) * fix realyer cliui * add empty line for clean logs --- ignite/cmd/cmd.go | 11 ++-- ignite/cmd/network_campaign_account.go | 5 +- ignite/cmd/network_campaign_list.go | 3 +- ignite/cmd/network_campaign_publish.go | 3 +- ignite/cmd/network_campaign_show.go | 3 +- ignite/cmd/network_campaign_update.go | 3 +- ignite/cmd/network_chain_init.go | 3 +- ignite/cmd/network_chain_install.go | 3 +- ignite/cmd/network_chain_join.go | 7 ++- ignite/cmd/network_chain_launch.go | 3 +- ignite/cmd/network_chain_list.go | 3 +- ignite/cmd/network_chain_prepare.go | 3 +- ignite/cmd/network_chain_publish.go | 9 +-- ignite/cmd/network_chain_revert_launch.go | 3 +- ignite/cmd/network_chain_show.go | 3 +- ignite/cmd/network_chain_show_accounts.go | 3 +- ignite/cmd/network_chain_show_genesis.go | 3 +- ignite/cmd/network_chain_show_info.go | 3 +- ignite/cmd/network_chain_show_peers.go | 3 +- ignite/cmd/network_chain_show_validators.go | 3 +- ignite/cmd/network_request_approve.go | 5 +- ignite/cmd/network_request_list.go | 5 +- ignite/cmd/network_request_reject.go | 3 +- ignite/cmd/network_request_show.go | 5 +- ignite/cmd/network_request_verify.go | 3 +- ignite/cmd/network_reward_set.go | 3 +- ignite/cmd/relayer_configure.go | 62 +++++++++---------- ignite/cmd/relayer_connect.go | 45 ++++++++------ ignite/pkg/cliui/cliui.go | 3 +- .../pkg/cliui/entrywriter/entrywriter_test.go | 3 +- ignite/pkg/events/events_test.go | 3 +- ignite/services/network/reward.go | 3 +- 32 files changed, 127 insertions(+), 96 deletions(-) diff --git a/ignite/cmd/cmd.go b/ignite/cmd/cmd.go index 538d4db027..4069367659 100644 --- a/ignite/cmd/cmd.go +++ b/ignite/cmd/cmd.go @@ -9,7 +9,12 @@ import ( "strings" "time" + "github.com/ignite-hq/cli/ignite/pkg/cliui" + "github.com/fatih/color" + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" + "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/cosmosver" "github.com/ignite-hq/cli/ignite/pkg/gitpod" @@ -18,8 +23,6 @@ import ( "github.com/ignite-hq/cli/ignite/services/chain" "github.com/ignite-hq/cli/ignite/services/scaffolder" "github.com/ignite-hq/cli/ignite/version" - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" ) const ( @@ -259,6 +262,6 @@ https://docs.ignite.com/migration`, sc.Version.String(), return sc, nil } -func printSection(title string) { - fmt.Printf("------\n%s\n------\n\n", title) +func printSection(session cliui.Session, title string) error { + return session.Printf("------\n%s\n------\n\n", title) } diff --git a/ignite/cmd/network_campaign_account.go b/ignite/cmd/network_campaign_account.go index f645d70ac8..912edd9091 100644 --- a/ignite/cmd/network_campaign_account.go +++ b/ignite/cmd/network_campaign_account.go @@ -4,12 +4,13 @@ import ( "context" "strconv" + "github.com/spf13/cobra" + "golang.org/x/sync/errgroup" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/spf13/cobra" - "golang.org/x/sync/errgroup" ) var ( diff --git a/ignite/cmd/network_campaign_list.go b/ignite/cmd/network_campaign_list.go index a3d65caad9..00a43f4891 100644 --- a/ignite/cmd/network_campaign_list.go +++ b/ignite/cmd/network_campaign_list.go @@ -3,10 +3,11 @@ package ignitecmd import ( "fmt" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/spf13/cobra" ) var CampaignSummaryHeader = []string{ diff --git a/ignite/cmd/network_campaign_publish.go b/ignite/cmd/network_campaign_publish.go index 2439402aa7..6ac279d47f 100644 --- a/ignite/cmd/network_campaign_publish.go +++ b/ignite/cmd/network_campaign_publish.go @@ -2,9 +2,10 @@ package ignitecmd import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_campaign_show.go b/ignite/cmd/network_campaign_show.go index 0eea507932..b725be7d1e 100644 --- a/ignite/cmd/network_campaign_show.go +++ b/ignite/cmd/network_campaign_show.go @@ -1,10 +1,11 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) // NewNetworkCampaignShow returns a new command to show published campaign on Ignite diff --git a/ignite/cmd/network_campaign_update.go b/ignite/cmd/network_campaign_update.go index ab63364eb6..3d238725a7 100644 --- a/ignite/cmd/network_campaign_update.go +++ b/ignite/cmd/network_campaign_update.go @@ -5,10 +5,11 @@ import ( "strings" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_chain_init.go b/ignite/cmd/network_chain_init.go index 635f731bfc..6053cf1626 100644 --- a/ignite/cmd/network_chain_init.go +++ b/ignite/cmd/network_chain_init.go @@ -3,6 +3,8 @@ package ignitecmd import ( "fmt" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" @@ -11,7 +13,6 @@ import ( "github.com/ignite-hq/cli/ignite/services/chain" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_chain_install.go b/ignite/cmd/network_chain_install.go index fba6b94fda..c57285cc84 100644 --- a/ignite/cmd/network_chain_install.go +++ b/ignite/cmd/network_chain_install.go @@ -3,13 +3,14 @@ package ignitecmd import ( "path/filepath" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/goenv" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) // NewNetworkChainInstall returns a new command to install a chain's binary by the launch id. diff --git a/ignite/cmd/network_chain_join.go b/ignite/cmd/network_chain_join.go index 8ee562f681..83271c2ba0 100644 --- a/ignite/cmd/network_chain_join.go +++ b/ignite/cmd/network_chain_join.go @@ -5,6 +5,10 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" + "github.com/rdegges/go-ipify" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" @@ -12,9 +16,6 @@ import ( "github.com/ignite-hq/cli/ignite/pkg/xchisel" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/pkg/errors" - "github.com/rdegges/go-ipify" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_chain_launch.go b/ignite/cmd/network_chain_launch.go index 50f19bb6a0..038728b09a 100644 --- a/ignite/cmd/network_chain_launch.go +++ b/ignite/cmd/network_chain_launch.go @@ -1,9 +1,10 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_chain_list.go b/ignite/cmd/network_chain_list.go index ddde4e40af..d99c644dbd 100644 --- a/ignite/cmd/network_chain_list.go +++ b/ignite/cmd/network_chain_list.go @@ -3,11 +3,12 @@ package ignitecmd import ( "fmt" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/spf13/cobra" ) var LaunchSummaryHeader = []string{"launch ID", "chain ID", "source", "campaign ID", "network", "reward"} diff --git a/ignite/cmd/network_chain_prepare.go b/ignite/cmd/network_chain_prepare.go index 0f3039d0d8..31907f3382 100644 --- a/ignite/cmd/network_chain_prepare.go +++ b/ignite/cmd/network_chain_prepare.go @@ -4,13 +4,14 @@ import ( "fmt" "path/filepath" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/colors" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/goenv" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_chain_publish.go b/ignite/cmd/network_chain_publish.go index 7900d9255d..02c3147263 100644 --- a/ignite/cmd/network_chain_publish.go +++ b/ignite/cmd/network_chain_publish.go @@ -5,16 +5,17 @@ import ( "os" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/tendermint/spn/pkg/chainid" + campaigntypes "github.com/tendermint/spn/x/campaign/types" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/xurl" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/pkg/errors" - "github.com/spf13/cobra" - "github.com/tendermint/spn/pkg/chainid" - campaigntypes "github.com/tendermint/spn/x/campaign/types" ) const ( diff --git a/ignite/cmd/network_chain_revert_launch.go b/ignite/cmd/network_chain_revert_launch.go index 2662c95ae8..1d83e304a0 100644 --- a/ignite/cmd/network_chain_revert_launch.go +++ b/ignite/cmd/network_chain_revert_launch.go @@ -1,10 +1,11 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) // NewNetworkChainRevertLaunch creates a new chain revert launch command diff --git a/ignite/cmd/network_chain_show.go b/ignite/cmd/network_chain_show.go index 03c572b572..a8248203ba 100644 --- a/ignite/cmd/network_chain_show.go +++ b/ignite/cmd/network_chain_show.go @@ -1,9 +1,10 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) const flagOut = "out" diff --git a/ignite/cmd/network_chain_show_accounts.go b/ignite/cmd/network_chain_show_accounts.go index 332f4cf350..0024c0e20b 100644 --- a/ignite/cmd/network_chain_show_accounts.go +++ b/ignite/cmd/network_chain_show_accounts.go @@ -3,9 +3,10 @@ package ignitecmd import ( "strconv" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" - "github.com/spf13/cobra" ) var ( diff --git a/ignite/cmd/network_chain_show_genesis.go b/ignite/cmd/network_chain_show_genesis.go index db80c13c47..2ff7ccbefb 100644 --- a/ignite/cmd/network_chain_show_genesis.go +++ b/ignite/cmd/network_chain_show_genesis.go @@ -4,10 +4,11 @@ import ( "os" "path/filepath" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) func newNetworkChainShowGenesis() *cobra.Command { diff --git a/ignite/cmd/network_chain_show_info.go b/ignite/cmd/network_chain_show_info.go index 4040759732..6826a40cc8 100644 --- a/ignite/cmd/network_chain_show_info.go +++ b/ignite/cmd/network_chain_show_info.go @@ -1,12 +1,13 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cosmosutil" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/spf13/cobra" ) func newNetworkChainShowInfo() *cobra.Command { diff --git a/ignite/cmd/network_chain_show_peers.go b/ignite/cmd/network_chain_show_peers.go index cea05e2b62..cd99378e31 100644 --- a/ignite/cmd/network_chain_show_peers.go +++ b/ignite/cmd/network_chain_show_peers.go @@ -7,10 +7,11 @@ import ( "path/filepath" "strings" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) func newNetworkChainShowPeers() *cobra.Command { diff --git a/ignite/cmd/network_chain_show_validators.go b/ignite/cmd/network_chain_show_validators.go index 73d37af658..7256930c86 100644 --- a/ignite/cmd/network_chain_show_validators.go +++ b/ignite/cmd/network_chain_show_validators.go @@ -1,10 +1,11 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) var ( diff --git a/ignite/cmd/network_request_approve.go b/ignite/cmd/network_request_approve.go index dae3f2bf9f..76a4894650 100644 --- a/ignite/cmd/network_request_approve.go +++ b/ignite/cmd/network_request_approve.go @@ -1,12 +1,13 @@ package ignitecmd import ( + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/pkg/errors" - "github.com/spf13/cobra" ) const ( diff --git a/ignite/cmd/network_request_list.go b/ignite/cmd/network_request_list.go index 6875740f24..ffed6c1ad0 100644 --- a/ignite/cmd/network_request_list.go +++ b/ignite/cmd/network_request_list.go @@ -3,11 +3,12 @@ package ignitecmd import ( "fmt" + "github.com/spf13/cobra" + launchtypes "github.com/tendermint/spn/x/launch/types" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - "github.com/spf13/cobra" - launchtypes "github.com/tendermint/spn/x/launch/types" ) var requestSummaryHeader = []string{"ID", "Status", "Type", "Content"} diff --git a/ignite/cmd/network_request_reject.go b/ignite/cmd/network_request_reject.go index eeb545c129..d996df643f 100644 --- a/ignite/cmd/network_request_reject.go +++ b/ignite/cmd/network_request_reject.go @@ -1,11 +1,12 @@ package ignitecmd import ( + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) // NewNetworkRequestReject creates a new request reject diff --git a/ignite/cmd/network_request_show.go b/ignite/cmd/network_request_show.go index 7471a18e36..caed83daff 100644 --- a/ignite/cmd/network_request_show.go +++ b/ignite/cmd/network_request_show.go @@ -3,11 +3,12 @@ package ignitecmd import ( "strconv" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/yaml" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/pkg/errors" - "github.com/spf13/cobra" ) // NewNetworkRequestShow creates a new request show command to show diff --git a/ignite/cmd/network_request_verify.go b/ignite/cmd/network_request_verify.go index 83adc80edd..5c804b0b53 100644 --- a/ignite/cmd/network_request_verify.go +++ b/ignite/cmd/network_request_verify.go @@ -4,13 +4,14 @@ import ( "context" "os" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/chaincmd" "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/numbers" "github.com/ignite-hq/cli/ignite/services/network" "github.com/ignite-hq/cli/ignite/services/network/networkchain" - "github.com/spf13/cobra" ) // NewNetworkRequestVerify verify the request and simulate the chain. diff --git a/ignite/cmd/network_reward_set.go b/ignite/cmd/network_reward_set.go index 128ac861f0..01cf4ef009 100644 --- a/ignite/cmd/network_reward_set.go +++ b/ignite/cmd/network_reward_set.go @@ -5,9 +5,10 @@ import ( "strconv" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/services/network" - "github.com/spf13/cobra" ) // NewNetworkRewardSet creates a new chain reward set command to diff --git a/ignite/cmd/relayer_configure.go b/ignite/cmd/relayer_configure.go index 3098a6c0d3..845af0eedc 100644 --- a/ignite/cmd/relayer_configure.go +++ b/ignite/cmd/relayer_configure.go @@ -1,15 +1,12 @@ package ignitecmd import ( - "fmt" - - "github.com/briandowns/spinner" "github.com/gookit/color" "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" - "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/relayer" @@ -87,6 +84,9 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { err = handleRelayerAccountErr(err) }() + session := cliui.New() + defer session.Cleanup() + ca, err := cosmosaccount.New( cosmosaccount.WithKeyringBackend(getKeyringBackend(cmd)), ) @@ -98,10 +98,9 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { return err } - s := clispinner.New().Start() - defer s.Stop() - - printSection("Setting up chains") + if err := printSection(session, "Setting up chains"); err != nil { + return err + } // basic configuration var ( @@ -352,22 +351,23 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { } } + session.PauseSpinner() if len(questions) > 0 { - if err := cliquiz.Ask(questions...); err != nil { + if err := session.Ask(questions...); err != nil { return err } } - r := relayer.New(ca) + session.StartSpinner("Fetching chain info...") - fmt.Println() - s.SetText("Fetching chain info...") + session.Println() + r := relayer.New(ca) // initialize the chains sourceChain, err := initChain( cmd, r, - s, + session, relayerSource, sourceAccount, sourceRPCAddress, @@ -383,7 +383,7 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { targetChain, err := initChain( cmd, r, - s, + session, relayerTarget, targetAccount, targetRPCAddress, @@ -396,7 +396,7 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { return err } - s.SetText("Configuring...").Start() + session.StartSpinner("Configuring...") // sets advanced channel options var channelOptions []relayer.ChannelOption @@ -419,9 +419,8 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { return err } - s.Stop() - - fmt.Printf("⛓ Configured chains: %s\n\n", color.Green.Sprint(id)) + session.StopSpinner() + session.Printf("⛓ Configured chains: %s\n\n", color.Green.Sprint(id)) return nil } @@ -430,7 +429,7 @@ func relayerConfigureHandler(cmd *cobra.Command, args []string) (err error) { func initChain( cmd *cobra.Command, r relayer.Relayer, - s *clispinner.Spinner, + session cliui.Session, name, accountName, rpcAddr, @@ -439,8 +438,8 @@ func initChain( gasLimit int64, addressPrefix string, ) (*relayer.Chain, error) { - defer s.Stop() - s.SetText("Initializing chain...").Start() + defer session.StopSpinner() + session.StartSpinner("Initializing chain...") c, account, err := r.NewChain( cmd.Context(), @@ -455,33 +454,28 @@ func initChain( return nil, errors.Wrapf(err, "cannot resolve %s", name) } - s.Stop() + session.StopSpinner() accountAddr := account.Address(addressPrefix) - fmt.Printf("🔐 Account on %q is %s(%s)\n \n", name, accountName, accountAddr) - s. - SetCharset(spinner.CharSets[9]). - SetColor("white"). - SetPrefix(" |·"). - SetText(color.Yellow.Sprintf("trying to receive tokens from a faucet...")). - Start() + session.Printf("🔐 Account on %q is %s(%s)\n \n", name, accountName, accountAddr) + session.StartSpinner(color.Yellow.Sprintf("trying to receive tokens from a faucet...")) coins, err := c.TryRetrieve(cmd.Context()) - s.Stop() + session.StopSpinner() - fmt.Print(" |· ") + session.Print(" |· ") if err != nil { - fmt.Println(color.Yellow.Sprintf(err.Error())) + session.Println(color.Yellow.Sprintf(err.Error())) } else { - fmt.Println(color.Green.Sprintf("received coins from a faucet")) + session.Println(color.Green.Sprintf("received coins from a faucet")) } balance := coins.String() if balance == "" { balance = entrywriter.None } - fmt.Printf(" |· (balance: %s)\n\n", balance) + session.Printf(" |· (balance: %s)\n\n", balance) return c, nil } diff --git a/ignite/cmd/relayer_connect.go b/ignite/cmd/relayer_connect.go index b6c9372bcf..d13f15a236 100644 --- a/ignite/cmd/relayer_connect.go +++ b/ignite/cmd/relayer_connect.go @@ -1,13 +1,13 @@ package ignitecmd import ( + "bytes" "fmt" - "os" "text/tabwriter" "github.com/spf13/cobra" - "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" + "github.com/ignite-hq/cli/ignite/pkg/cliui" "github.com/ignite-hq/cli/ignite/pkg/cosmosaccount" "github.com/ignite-hq/cli/ignite/pkg/relayer" ) @@ -32,6 +32,9 @@ func relayerConnectHandler(cmd *cobra.Command, args []string) (err error) { err = handleRelayerAccountErr(err) }() + session := cliui.New() + defer session.Cleanup() + ca, err := cosmosaccount.New( cosmosaccount.WithKeyringBackend(getKeyringBackend(cmd)), ) @@ -43,14 +46,11 @@ func relayerConnectHandler(cmd *cobra.Command, args []string) (err error) { return err } - ids := args - - s := clispinner.New() - defer s.Stop() - - var use []string - - r := relayer.New(ca) + var ( + use []string + ids = args + r = relayer.New(ca) + ) all, err := r.ListPaths(cmd.Context()) if err != nil { @@ -77,41 +77,46 @@ func relayerConnectHandler(cmd *cobra.Command, args []string) (err error) { } if len(use) == 0 { - s.Stop() - - fmt.Println("No chains found to connect.") + session.StopSpinner() + session.Println("No chains found to connect.") return nil } - s.SetText("Creating links between chains...") + session.StartSpinner("Creating links between chains...") if err := r.Link(cmd.Context(), use...); err != nil { return err } - s.Stop() + session.StopSpinner() - printSection("Paths") + if err := printSection(session, "Paths"); err != nil { + return err + } for _, id := range use { - s.SetText("Loading...").Start() + session.StartSpinner("Loading...") path, err := r.GetPath(cmd.Context(), id) if err != nil { return err } - s.Stop() + session.StopSpinner() - w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent) + var buf bytes.Buffer + w := tabwriter.NewWriter(&buf, 0, 0, 1, ' ', tabwriter.TabIndent) fmt.Fprintf(w, "%s:\n", path.ID) fmt.Fprintf(w, " \t%s\t>\t(port: %s)\t(channel: %s)\n", path.Src.ChainID, path.Src.PortID, path.Src.ChannelID) fmt.Fprintf(w, " \t%s\t>\t(port: %s)\t(channel: %s)\n", path.Dst.ChainID, path.Dst.PortID, path.Dst.ChannelID) fmt.Fprintln(w) w.Flush() + session.Print(buf.String()) } - printSection("Listening and relaying packets between chains...") + if err := printSection(session, "Listening and relaying packets between chains..."); err != nil { + return err + } return r.Start(cmd.Context(), use...) } diff --git a/ignite/pkg/cliui/cliui.go b/ignite/pkg/cliui/cliui.go index fefcb9bf8b..39862b6e49 100644 --- a/ignite/pkg/cliui/cliui.go +++ b/ignite/pkg/cliui/cliui.go @@ -6,12 +6,13 @@ import ( "os" "sync" + "github.com/manifoldco/promptui" + "github.com/ignite-hq/cli/ignite/pkg/cliui/cliquiz" "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/events" - "github.com/manifoldco/promptui" ) // Session controls command line interaction with users. diff --git a/ignite/pkg/cliui/entrywriter/entrywriter_test.go b/ignite/pkg/cliui/entrywriter/entrywriter_test.go index 69fb0c0c45..b4f55df756 100644 --- a/ignite/pkg/cliui/entrywriter/entrywriter_test.go +++ b/ignite/pkg/cliui/entrywriter/entrywriter_test.go @@ -2,11 +2,12 @@ package entrywriter_test import ( "errors" - "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" "io" "testing" "github.com/stretchr/testify/require" + + "github.com/ignite-hq/cli/ignite/pkg/cliui/entrywriter" ) type WriterWithError struct{} diff --git a/ignite/pkg/events/events_test.go b/ignite/pkg/events/events_test.go index 3a8a82541a..e7dddf3e45 100644 --- a/ignite/pkg/events/events_test.go +++ b/ignite/pkg/events/events_test.go @@ -4,8 +4,9 @@ import ( "testing" "github.com/gookit/color" - "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/stretchr/testify/require" + + "github.com/ignite-hq/cli/ignite/pkg/events" ) func TestBusSend(t *testing.T) { diff --git a/ignite/services/network/reward.go b/ignite/services/network/reward.go index 9e96cf4086..e4b99c59d8 100644 --- a/ignite/services/network/reward.go +++ b/ignite/services/network/reward.go @@ -4,10 +4,11 @@ import ( "fmt" sdk "github.com/cosmos/cosmos-sdk/types" + rewardtypes "github.com/tendermint/spn/x/reward/types" + "github.com/ignite-hq/cli/ignite/pkg/cliui/icons" "github.com/ignite-hq/cli/ignite/pkg/events" "github.com/ignite-hq/cli/ignite/services/network/networktypes" - rewardtypes "github.com/tendermint/spn/x/reward/types" ) // SetReward set a chain reward From 1eeeaf772e00f416bd94d7e99a91e2dd3daf2d88 Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Fri, 6 May 2022 06:00:51 -0300 Subject: [PATCH 25/30] fix(serve): fix custom p2p port from the `config.yml` (#2447) * update cosmos-sdk version and fix port without host from the config.yml * remove unused xurl methods --- go.mod | 2 +- go.sum | 2 + ignite/pkg/xurl/xurl.go | 47 ++++++-------------- ignite/pkg/xurl/xurl_test.go | 50 ++++++++++++++++++++++ ignite/templates/app/stargate/go.mod.plush | 2 +- ignite/templates/app/stargate/go.sum | 3 +- 6 files changed, 69 insertions(+), 37 deletions(-) diff --git a/go.mod b/go.mod index deea792e19..3936177a68 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/briandowns/spinner v1.11.1 github.com/cenkalti/backoff v2.2.1+incompatible github.com/charmbracelet/glow v1.4.0 - github.com/cosmos/cosmos-sdk v0.45.3 + github.com/cosmos/cosmos-sdk v0.45.4 github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/ibc-go/v2 v2.0.3 github.com/docker/docker v20.10.7+incompatible diff --git a/go.sum b/go.sum index 2a67271902..28f69da601 100644 --- a/go.sum +++ b/go.sum @@ -424,6 +424,8 @@ github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/Tv github.com/cosmos/cosmos-sdk v0.44.5/go.mod h1:maUA6m2TBxOJZkbwl0eRtEBgTX37kcaiOWU5t1HEGaY= github.com/cosmos/cosmos-sdk v0.45.3 h1:PiVSU3IkNEDPhoxOZHk2lPnhwBBJgEYAtAR0jGXRN4g= github.com/cosmos/cosmos-sdk v0.45.3/go.mod h1:qYm5JEr0ZlbnmoP/Q3b+dYMOliHf4ddHirpILiwZzqg= +github.com/cosmos/cosmos-sdk v0.45.4 h1:eStDAhJdMY8n5arbBRe+OwpNeBSunxSBHp1g55ulfdA= +github.com/cosmos/cosmos-sdk v0.45.4/go.mod h1:WOqtDxN3eCCmnYLVla10xG7lEXkFjpTaqm2a2WasgCc= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= diff --git a/ignite/pkg/xurl/xurl.go b/ignite/pkg/xurl/xurl.go index c428772cd6..6cbe8ac100 100644 --- a/ignite/pkg/xurl/xurl.go +++ b/ignite/pkg/xurl/xurl.go @@ -91,18 +91,6 @@ func HTTPEnsurePort(s string) string { return u.String() } -// CleanPath cleans path from the url. -func CleanPath(s string) string { - u, err := url.Parse(s) - if err != nil { - return s - } - - u.Path = "" - - return u.String() -} - // Address ensures that address contains localhost as host if non specified. func Address(address string) string { if strings.HasPrefix(address, ":") { @@ -111,20 +99,6 @@ func Address(address string) string { return address } -// IsLocalPath checks if given address is a local fs path or a URL. -func IsLocalPath(address string) bool { - for _, pattern := range []string{ - "http://", - "https://", - "git@", - } { - if strings.HasPrefix(address, pattern) { - return false - } - } - return true -} - func IsHTTP(address string) bool { return strings.HasPrefix(address, "http") } @@ -138,22 +112,27 @@ func parseURL(s string) (*url.URL, error) { // without scheme prefix because that case can't be URL parsed. // When the URI has not scheme it is parsed as a path by "url.Parse" // placing the colon within the path, which is invalid. - if isAddressPort(s) { - return &url.URL{Host: s}, nil + if host, isAddrPort := addressPort(s); isAddrPort { + return &url.URL{Host: host}, nil } - return url.Parse(Address(s)) + p, err := url.Parse(Address(s)) + return p, err } -func isAddressPort(s string) bool { +func addressPort(s string) (string, bool) { // Check that the value doesn't contain a URI path if strings.Index(s, "/") != -1 { - return false + return "", false } // Use the net split function to support IPv6 addresses - if _, _, err := net.SplitHostPort(s); err != nil { - return false + host, port, err := net.SplitHostPort(s) + if err != nil { + return "", false + } + if host == "" { + host = "0.0.0.0" } - return true + return net.JoinHostPort(host, port), true } diff --git a/ignite/pkg/xurl/xurl_test.go b/ignite/pkg/xurl/xurl_test.go index a17f851279..1cfb20e193 100644 --- a/ignite/pkg/xurl/xurl_test.go +++ b/ignite/pkg/xurl/xurl_test.go @@ -326,3 +326,53 @@ func TestMightHTTPS(t *testing.T) { }) } } + +func Test_addressPort(t *testing.T) { + tests := []struct { + name string + arg string + wantHost string + want bool + }{ + { + name: "URI path", + arg: "/test/false", + want: false, + }, + { + name: "invalid address", + arg: "aeihf3/aef/f..//", + want: false, + }, + { + name: "host and port", + arg: "102.33.3.43:10000", + wantHost: "102.33.3.43:10000", + want: true, + }, + { + name: "local port", + arg: "0.0.0.0:10000", + wantHost: "0.0.0.0:10000", + want: true, + }, + { + name: "only port", + arg: ":10000", + wantHost: "0.0.0.0:10000", + want: true, + }, + { + name: "only host", + arg: "102.33.3.43", + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotHost, got := addressPort(tt.arg) + require.Equal(t, tt.want, got) + require.Equal(t, tt.wantHost, gotHost) + }) + } +} diff --git a/ignite/templates/app/stargate/go.mod.plush b/ignite/templates/app/stargate/go.mod.plush index a5ddd11407..a9adcea440 100644 --- a/ignite/templates/app/stargate/go.mod.plush +++ b/ignite/templates/app/stargate/go.mod.plush @@ -3,7 +3,7 @@ module <%= ModulePath %> go 1.16 require ( - github.com/cosmos/cosmos-sdk v0.45.3 + github.com/cosmos/cosmos-sdk v0.45.4 github.com/cosmos/ibc-go/v2 v2.0.3 github.com/gogo/protobuf v1.3.3 github.com/golang/protobuf v1.5.2 diff --git a/ignite/templates/app/stargate/go.sum b/ignite/templates/app/stargate/go.sum index b948920321..cf549d4cc6 100644 --- a/ignite/templates/app/stargate/go.sum +++ b/ignite/templates/app/stargate/go.sum @@ -465,8 +465,9 @@ github.com/cosmos/cosmos-sdk v0.44.4/go.mod h1:0QTCOkE8IWu5LZyfnbbjFjxYRIcV4pBOr github.com/cosmos/cosmos-sdk v0.44.5/go.mod h1:maUA6m2TBxOJZkbwl0eRtEBgTX37kcaiOWU5t1HEGaY= github.com/cosmos/cosmos-sdk v0.45.1/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ= github.com/cosmos/cosmos-sdk v0.45.2/go.mod h1:DhSVBqJkhjB694w99FudptzPhU0XHd/qcyiNCLOjkds= -github.com/cosmos/cosmos-sdk v0.45.3 h1:PiVSU3IkNEDPhoxOZHk2lPnhwBBJgEYAtAR0jGXRN4g= github.com/cosmos/cosmos-sdk v0.45.3/go.mod h1:qYm5JEr0ZlbnmoP/Q3b+dYMOliHf4ddHirpILiwZzqg= +github.com/cosmos/cosmos-sdk v0.45.4 h1:eStDAhJdMY8n5arbBRe+OwpNeBSunxSBHp1g55ulfdA= +github.com/cosmos/cosmos-sdk v0.45.4/go.mod h1:WOqtDxN3eCCmnYLVla10xG7lEXkFjpTaqm2a2WasgCc= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= From 6475ecc1a64f8809350c0d58ab6f5be8a250ac3d Mon Sep 17 00:00:00 2001 From: Danilo Pantani Date: Fri, 6 May 2022 09:46:59 -0300 Subject: [PATCH 26/30] chore: run make format (#2444) From 7c32dc49c545466b8ff3f47a38b4d8c40bf0bbd5 Mon Sep 17 00:00:00 2001 From: Petr Ivanov Date: Sun, 8 May 2022 20:57:28 +0400 Subject: [PATCH 27/30] refactor: use os.MkdirTemp instead of os.TempDir (#2441) Co-authored-by: Petr Ivanov --- ignite/cmd/network_chain_show_genesis.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ignite/cmd/network_chain_show_genesis.go b/ignite/cmd/network_chain_show_genesis.go index 2ff7ccbefb..3dcf03bfd5 100644 --- a/ignite/cmd/network_chain_show_genesis.go +++ b/ignite/cmd/network_chain_show_genesis.go @@ -63,10 +63,13 @@ func networkChainShowGenesisHandler(cmd *cobra.Command, args []string) error { } // create the chain in a temp dir - home := filepath.Join(os.TempDir(), "spn/temp", chainLaunch.ChainID) - defer os.RemoveAll(home) + tmpHome, err := os.MkdirTemp("", "*-spn") + if err != nil { + return err + } + defer os.RemoveAll(tmpHome) - c.SetHome(home) + c.SetHome(tmpHome) err = c.Prepare(cmd.Context(), genesisInformation) if err != nil { From d1595644c31adefdea2b7f2c9ba8f14536ba5874 Mon Sep 17 00:00:00 2001 From: Petr Ivanov Date: Tue, 10 May 2022 11:08:45 +0400 Subject: [PATCH 28/30] fix: fix line breaks for yes/no question (#2457) Co-authored-by: Petr Ivanov --- ignite/cmd/scaffold.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/ignite/cmd/scaffold.go b/ignite/cmd/scaffold.go index 9df999cc43..9d8ab21c2c 100644 --- a/ignite/cmd/scaffold.go +++ b/ignite/cmd/scaffold.go @@ -4,14 +4,13 @@ import ( "errors" "fmt" - "github.com/manifoldco/promptui" - "github.com/spf13/cobra" - flag "github.com/spf13/pflag" - + "github.com/AlecAivazis/survey/v2" "github.com/ignite-hq/cli/ignite/pkg/cliui/clispinner" "github.com/ignite-hq/cli/ignite/pkg/placeholder" "github.com/ignite-hq/cli/ignite/pkg/xgit" "github.com/ignite-hq/cli/ignite/services/scaffolder" + "github.com/spf13/cobra" + flag "github.com/spf13/pflag" ) // flags related to component scaffolding @@ -131,11 +130,11 @@ func addGitChangesVerifier(cmd *cobra.Command) *cobra.Command { } if !getYes(cmd) && !changesCommitted { - prompt := promptui.Prompt{ - Label: "Your saved project changes have not been committed. To enable reverting to your current state, commit your saved changes. Do you want to proceed with scaffolding without committing your saved changes", - IsConfirm: true, + var confirmed bool + prompt := &survey.Confirm{ + Message: "Your saved project changes have not been committed. To enable reverting to your current state, commit your saved changes. Do you want to proceed with scaffolding without committing your saved changes", } - if _, err := prompt.Run(); err != nil { + if err := survey.AskOne(prompt, &confirmed); err != nil || !confirmed { return errors.New("said no") } } From fcd10e2353af363aa6dfdd478b9f31ddf7946540 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0lker=20G=2E=20=C3=96zt=C3=BCrk?= Date: Tue, 10 May 2022 18:50:37 +0300 Subject: [PATCH 29/30] docs(changelog): add v0.21.0 logs (#2462) --- changelog.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 7cf63ee602..8ce53d4597 100644 --- a/changelog.md +++ b/changelog.md @@ -1,12 +1,18 @@ # Changelog +## [`v0.21.0`](https://github.com/ignite-hq/cli/releases/tag/v0.21.0) + +### Features + +- Support simple app names when scaffolding chains. e.g.: `ignite scaffold chain mars` +- Ask confirmation when scaffolding over changes that are not committed yet + ## [`v0.20.4`](https://github.com/ignite-hq/cli/releases/tag/v0.20.4) ### Fixes - Use `protoc` binary compiled in an older version of macOS AMD64 for backwards compatibility in code generation - ## [`v0.20.3`](https://github.com/ignite-hq/cli/releases/tag/v0.20.3) ### Fixes From 161dc1d4be1ab303455040c86e5500d08708551d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 10 May 2022 18:51:06 +0300 Subject: [PATCH 30/30] docs(cli): update generated docs (#2425) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ilgooz Co-authored-by: İlker G. Öztürk --- docs/cli/index.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/cli/index.md b/docs/cli/index.md index 3e2e2a790c..4e6252f449 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -431,6 +431,7 @@ ignite generate dart [flags] ``` -h, --help help for dart + -y, --yes Answers interactive yes/no questions with yes ``` **Options inherited from parent commands** @@ -456,6 +457,7 @@ ignite generate openapi [flags] ``` -h, --help help for openapi + -y, --yes Answers interactive yes/no questions with yes ``` **Options inherited from parent commands** @@ -481,6 +483,7 @@ ignite generate proto-go [flags] ``` -h, --help help for proto-go + -y, --yes Answers interactive yes/no questions with yes ``` **Options inherited from parent commands** @@ -507,6 +510,7 @@ ignite generate vuex [flags] ``` -h, --help help for vuex --proto-all-modules Enables proto code generation for 3rd party modules used in your chain + -y, --yes Answers interactive yes/no questions with yes ``` **Options inherited from parent commands** @@ -647,6 +651,7 @@ ignite scaffold band [queryName] --module [moduleName] [flags] --module string IBC Module to add the packet into -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -693,6 +698,7 @@ ignite scaffold flutter [flags] ``` -h, --help help for flutter -p, --path string path to scaffold content of the Flutter app (default "./flutter") + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -717,6 +723,7 @@ ignite scaffold list NAME [field]... [flags] --no-simulation Disable CRUD simulation scaffolding -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -742,6 +749,7 @@ ignite scaffold map NAME [field]... [flags] --no-simulation Disable CRUD simulation scaffolding -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -767,6 +775,7 @@ ignite scaffold message [name] [field1] [field2] ... [flags] -p, --path string path of the app (default ".") -r, --response strings Response fields --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -796,6 +805,7 @@ ignite scaffold module [name] [flags] --params strings scaffold module params -p, --path string path of the app (default ".") --require-registration if true command will fail if module can't be registered + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -824,6 +834,7 @@ ignite scaffold packet [packetName] [field1] [field2] ... --module [moduleName] --no-message Disable send message scaffolding -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -848,6 +859,7 @@ ignite scaffold query [name] [request_field1] [request_field2] ... [flags] --paginated Define if the request can be paginated -p, --path string path of the app (default ".") -r, --response strings Response fields + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -872,6 +884,7 @@ ignite scaffold single NAME [field]... [flags] --no-simulation Disable CRUD simulation scaffolding -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -896,6 +909,7 @@ ignite scaffold type NAME [field]... [flags] --no-simulation Disable CRUD simulation scaffolding -p, --path string path of the app (default ".") --signer string Label for the message signer (default: creator) + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO** @@ -916,6 +930,7 @@ ignite scaffold vue [flags] ``` -h, --help help for vue -p, --path string path to scaffold content of the Vue.js app (default "./vue") + -y, --yes Answers interactive yes/no questions with yes ``` **SEE ALSO**