diff --git a/go.mod b/go.mod index 3498b0fec7..6437bf414c 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/gookit/color v1.2.7 github.com/gorilla/mux v1.8.0 github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 + github.com/iancoleman/strcase v0.1.3 github.com/imdario/mergo v0.3.11 github.com/improbable-eng/grpc-web v0.13.0 github.com/jpillora/chisel v1.7.3 diff --git a/go.sum b/go.sum index 86f4e12ed7..4ae60d3bb4 100644 --- a/go.sum +++ b/go.sum @@ -422,6 +422,8 @@ github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDG github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= +github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ilgooz/analytics-go v3.1.1-0.20200723195510-acde4190c655+incompatible/go.mod h1:36xDpOWfOEZLx5a4Qra2Ntu7by75m/qwZZx9/YrPrtY= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= diff --git a/starport/pkg/cosmosanalysis/module/module.go b/starport/pkg/cosmosanalysis/module/module.go index a13d0a770c..640d0265ca 100644 --- a/starport/pkg/cosmosanalysis/module/module.go +++ b/starport/pkg/cosmosanalysis/module/module.go @@ -38,8 +38,8 @@ type Module struct { // Name of the module. Name string - // TypesImportPath is the Go import path of the types pkg of the module. - TypesImportPath string + // Pkg holds the proto package info. + Pkg protoanalysis.Package // Msg is a list of sdk.Msg implementation of the module. Msgs []Msg @@ -103,9 +103,9 @@ func Discover(sourcePath string) ([]Module, error) { var ( spname = strings.Split(xproto.Name, ".") m = Module{ - Name: spname[len(spname)-1], - TypesImportPath: xproto.GoImportName, - Msgs: msgs, + Name: spname[len(spname)-1], + Pkg: xproto, + Msgs: msgs, } ) diff --git a/starport/pkg/cosmosgen/generate.go b/starport/pkg/cosmosgen/generate.go index 63fcd0e42d..9bfc03e066 100644 --- a/starport/pkg/cosmosgen/generate.go +++ b/starport/pkg/cosmosgen/generate.go @@ -2,19 +2,21 @@ package cosmosgen import ( "context" + "embed" "io/ioutil" "os" "path/filepath" - "strings" + "text/template" + "github.com/iancoleman/strcase" "github.com/otiai10/copy" "github.com/pkg/errors" "github.com/tendermint/starport/starport/pkg/cmdrunner" "github.com/tendermint/starport/starport/pkg/cmdrunner/step" + "github.com/tendermint/starport/starport/pkg/cosmosanalysis/module" "github.com/tendermint/starport/starport/pkg/gomodule" "github.com/tendermint/starport/starport/pkg/nodetime/protobufjs" "github.com/tendermint/starport/starport/pkg/nodetime/sta" - "github.com/tendermint/starport/starport/pkg/protoanalysis" "github.com/tendermint/starport/starport/pkg/protoc" "github.com/tendermint/starport/starport/pkg/protopath" "golang.org/x/mod/modfile" @@ -37,9 +39,20 @@ var ( fileTypes = "types" ) +//go:embed templates/* +var templates embed.FS + +var tpl = template.Must( + template.New("client.js.tpl"). + Funcs(template.FuncMap{ + "camelCase": strcase.ToLowerCamel, + }). + ParseFS(templates, "templates/client.js.tpl"), +) + type generateOptions struct { gomodPath string - jsOut func(protoanalysis.Package, string) string + jsOut func(module.Module) string } // TODO add WithInstall. @@ -48,7 +61,7 @@ type generateOptions struct { type Target func(*generateOptions) // WithJSGeneration adds JS code generation. -func WithJSGeneration(out func(pkg protoanalysis.Package, moduleName string) (path string)) Target { +func WithJSGeneration(out func(module.Module) (path string)) Target { return func(o *generateOptions) { o.jsOut = out } @@ -151,14 +164,14 @@ func (g *generator) generateGo() error { defer os.RemoveAll(tmp) // discover every sdk module. - pkgs, err := protoanalysis.DiscoverPackages(g.protoPath) + modules, err := module.Discover(g.projectPath) if err != nil { return err } // code generate for each module. - for _, pkg := range pkgs { - if err := protoc.Generate(g.ctx, tmp, pkg.Path, includePaths, protocOuts); err != nil { + for _, m := range modules { + if err := protoc.Generate(g.ctx, tmp, m.Pkg.Path, includePaths, protocOuts); err != nil { return err } } @@ -181,26 +194,21 @@ func (g *generator) generateJS() error { } // discover every sdk module. - pkgs, err := protoanalysis.DiscoverPackages(g.protoPath) + modules, err := module.Discover(g.projectPath) if err != nil { return err } // code generate for each module. - for _, pkg := range pkgs { - var ( - msp = strings.Split(pkg.Name, ".") - moduleName = msp[len(msp)-1] - - out = g.o.jsOut(pkg, moduleName) - ) + for _, m := range modules { + out := g.o.jsOut(m) // generate protobufjs types for each module. err = protobufjs.Generate( g.ctx, out, fileTypes, - pkg.Path, + m.Pkg.Path, jsIncludePaths, ) if err != nil { @@ -217,7 +225,7 @@ func (g *generator) generateJS() error { err = protoc.Generate( g.ctx, oaitemp, - pkg.Path, + m.Pkg.Path, oaiIncludePaths, openAPIOut, ) @@ -233,6 +241,27 @@ func (g *generator) generateJS() error { if err := sta.Generate(g.ctx, outjs, srcspec); err != nil { return err } + + // generate the client, the js wrapper. + outclient := filepath.Join(out, "index.js") + f, err := os.OpenFile(outclient, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) + if err != nil { + return err + } + defer f.Close() + + err = tpl.Execute(f, struct { + Module module.Module + TypesPath string + RESTPath string + }{ + m, + "./types", + "./rest", + }) + if err != nil { + return err + } } return nil diff --git a/starport/pkg/cosmosgen/templates/client.js.tpl b/starport/pkg/cosmosgen/templates/client.js.tpl new file mode 100644 index 0000000000..3b52847acc --- /dev/null +++ b/starport/pkg/cosmosgen/templates/client.js.tpl @@ -0,0 +1,38 @@ +import { coins } from "@cosmjs/launchpad"; +import { SigningStargateClient } from "@cosmjs/stargate"; +import { Registry, DirectSecp256k1HdWallet } from "@cosmjs/proto-signing"; +import Types from "{{ .TypesPath }}"; +import { Api } from "{{ .RESTPath }}"; + +const types = [ + {{ range .Module.Msgs }}["/{{ .URI }}", Types.{{ .URI }}], + {{ end }} +]; + +const registry = new Registry(types); + +const txClient = async (wallet, { addr: addr } = { addr: "http://localhost:26657" }) => { + if (!wallet) throw new Error("wallet is required"); + + const client = await SigningStargateClient.connectWithWallet(addr, wallet, { registry }); + const { address } = wallet; + const fee = { + amount: coins(0, "token"), + gas: "200000", + }; + + return { + signAndBroadcast: (msgs) => client.signAndBroadcast(address, msgs, fee), + {{ range .Module.Msgs }}{{ camelCase .Name }}: (data) => ({ typeUrl: "/{{ .URI }}", value: data }), + {{ end }} + }; +}; + +const queryClient = async ({ addr: addr } = { addr: "http://localhost:1317" }) => { + return new Api({ baseUrl: addr }).{{ .Module.Name }}; +}; + +export { + txClient, + queryClient, +}; diff --git a/starport/services/chain/build.go b/starport/services/chain/build.go index 79459eefc4..94ae7906e7 100644 --- a/starport/services/chain/build.go +++ b/starport/services/chain/build.go @@ -13,12 +13,12 @@ import ( starporterrors "github.com/tendermint/starport/starport/errors" "github.com/tendermint/starport/starport/pkg/cmdrunner" "github.com/tendermint/starport/starport/pkg/cmdrunner/step" + "github.com/tendermint/starport/starport/pkg/cosmosanalysis/module" "github.com/tendermint/starport/starport/pkg/cosmosgen" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/giturl" "github.com/tendermint/starport/starport/pkg/gocmd" "github.com/tendermint/starport/starport/pkg/goenv" - "github.com/tendermint/starport/starport/pkg/protoanalysis" "github.com/tendermint/starport/starport/pkg/xos" ) @@ -184,8 +184,8 @@ func (c *Chain) buildProto(ctx context.Context) error { // generate Vuex code as well if it is enabled. if conf.Client.Vuex.Path != "" { - targets = append(targets, cosmosgen.WithJSGeneration(func(pkg protoanalysis.Package, moduleName string) string { - return filepath.Join(c.app.Path, conf.Client.Vuex.Path, giturl.UserAndRepo(pkg.GoImportName), moduleName, "module") + targets = append(targets, cosmosgen.WithJSGeneration(func(m module.Module) string { + return filepath.Join(c.app.Path, conf.Client.Vuex.Path, giturl.UserAndRepo(m.Pkg.GoImportName), m.Name, "module") })) } diff --git a/starport/services/scaffolder/init.go b/starport/services/scaffolder/init.go index 67b6a6875f..f91b2ad15e 100644 --- a/starport/services/scaffolder/init.go +++ b/starport/services/scaffolder/init.go @@ -11,11 +11,11 @@ import ( "github.com/gobuffalo/genny" conf "github.com/tendermint/starport/starport/chainconf" "github.com/tendermint/starport/starport/errors" + "github.com/tendermint/starport/starport/pkg/cosmosanalysis/module" "github.com/tendermint/starport/starport/pkg/cosmosgen" "github.com/tendermint/starport/starport/pkg/cosmosver" "github.com/tendermint/starport/starport/pkg/giturl" "github.com/tendermint/starport/starport/pkg/gomodulepath" - "github.com/tendermint/starport/starport/pkg/protoanalysis" "github.com/tendermint/starport/starport/pkg/xos" "github.com/tendermint/starport/starport/templates/app" ) @@ -112,8 +112,8 @@ func (s *Scaffolder) protoc(projectPath, gomodPath string, version cosmosver.Maj // generate Vuex code as well if it is enabled. if conf.Client.Vuex.Path != "" { - targets = append(targets, cosmosgen.WithJSGeneration(func(pkg protoanalysis.Package, moduleName string) string { - return filepath.Join(projectPath, conf.Client.Vuex.Path, giturl.UserAndRepo(pkg.GoImportName), moduleName, "module") + targets = append(targets, cosmosgen.WithJSGeneration(func(m module.Module) string { + return filepath.Join(projectPath, conf.Client.Vuex.Path, giturl.UserAndRepo(m.Pkg.GoImportName), m.Name, "module") })) }