From 9e2f9e2b0453457d2a8f65f8ee1ba4ba3d1ed680 Mon Sep 17 00:00:00 2001 From: arnaudberger Date: Mon, 29 Jul 2024 13:03:08 -0400 Subject: [PATCH] first commit --- ethfull/convo.go | 22 +++++++++++++++++++- ethfull/generate.go | 44 +++++++++++++++++++++++++++++++++------ injective-events/convo.go | 2 +- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/ethfull/convo.go b/ethfull/convo.go index 3f67f20..97d8448 100644 --- a/ethfull/convo.go +++ b/ethfull/convo.go @@ -22,6 +22,7 @@ type outputType string const outputTypeSQL = "sql" const outputTypeSubgraph = "subgraph" +const outputTypeSubstreams = "substreams" type Convo struct { factory *codegen.MsgWrapFactory @@ -36,6 +37,14 @@ func init() { for _, conf := range ChainConfigs { supportedChains = append(supportedChains, conf.DisplayName) } + codegen.RegisterConversation( + "ethereum-events-calls", + "Decode Ethereum events/calls and generate a fully functional substreams", + `Given a list of contracts and their ABIs, this will build an Ethereum substreams that decodes events and/or calls. +Supported networks: `+strings.Join(supportedChains, ", "), + codegen.ConversationFactory(NewOnlySubstreams), + 80, + ) codegen.RegisterConversation( "ethereum-subgraph", "Decode Ethereum events/calls and and use them as triggers to feed your Subgraph", @@ -80,6 +89,16 @@ func NewWithSubgraph(factory *codegen.MsgWrapFactory) codegen.Conversation { return h } +func NewOnlySubstreams(factory *codegen.MsgWrapFactory) codegen.Conversation { + h := &Convo{ + state: &Project{currentContractIdx: -1}, + factory: factory, + outputType: outputTypeSubstreams, + remoteBuildState: &codegen.RemoteBuildState{}, + } + return h +} + func (h *Convo) msg() *codegen.MsgWrap { return h.factory.NewMsg(h.state) } func (h *Convo) action(element any) *codegen.MsgWrap { return h.factory.NewInput(element, h.state) @@ -114,6 +133,7 @@ func (c *Convo) validate() error { if c.state.SqlOutputFlavor != "" { return fmt.Errorf("cannot have SqlOutputFlavor set on this code generator") } + case outputTypeSubstreams: default: return fmt.Errorf("invalid output type %q (should not happen, this is a bug)", c.outputType) } @@ -973,7 +993,7 @@ message {{.Proto.MessageName}} {{.Proto.OutputModuleFieldName}} { ).AddFile( "substreams_src.zip", msg.SubstreamsSourceZip, - "application/zip", + "application/x-zip+extract", "\nGenerated source code ready to compile.\nThis module is a Rust-based module, and you can compile it with \"make all\" in the root directory.\n", ).Cmd()) diff --git a/ethfull/generate.go b/ethfull/generate.go index 5fcf68d..1b75fe6 100644 --- a/ethfull/generate.go +++ b/ethfull/generate.go @@ -83,14 +83,18 @@ func (p *Project) generate(outType outputType) (substreamsZip, projectZip []byte return nil, nil, fmt.Errorf("rendering template: %w", err) } - substreamsZip, err = codegen.ZipFiles(srcFiles) - if err != nil { - return nil, nil, fmt.Errorf("zipping: %w", err) + if len(srcFiles) != 0 { + substreamsZip, err = codegen.ZipFiles(srcFiles) + if err != nil { + return nil, nil, fmt.Errorf("zipping: %w", err) + } } - projectZip, err = codegen.ZipFiles(projFiles) - if err != nil { - return nil, nil, fmt.Errorf("zipping: %w", err) + if len(projFiles) != 0 { + projectZip, err = codegen.ZipFiles(projFiles) + if err != nil { + return nil, nil, fmt.Errorf("zipping: %w", err) + } } return @@ -212,6 +216,18 @@ func (p *Project) Render(outType outputType) (substreamsFiles map[string][]byte, } switch outType { + case outputTypeSubstreams: + templateFiles = map[string]string{ + "proto/contract.proto.gotmpl": "proto/contract.proto", + "src/abi/mod.rs.gotmpl": "src/abi/mod.rs", + "src/pb/mod.rs.gotmpl": "src/pb/mod.rs", + "src/lib.rs.gotmpl": "src/lib.rs", + "build.rs.gotmpl": "build.rs", + "Cargo.toml.gotmpl": "Cargo.toml", + "rust-toolchain.toml": "rust-toolchain.toml", + ".gitignore": ".gitignore", + "substreams.yaml.gotmpl": "substreams.yaml", + } case outputTypeSQL: templateFiles["sql/substreams-Makefile.gotmpl"] = "substreams/Makefile" templateFiles["sql/Makefile.gotmpl"] = "Makefile" @@ -262,6 +278,7 @@ func (p *Project) Render(outType outputType) (substreamsFiles map[string][]byte, default: return nil, nil, fmt.Errorf("unknown subgraph output flavor %q", p.SubgraphOutputFlavor) } + default: return nil, nil, fmt.Errorf("invalid output type %q", p.outputType) } @@ -283,6 +300,13 @@ func (p *Project) Render(outType outputType) (substreamsFiles map[string][]byte, } } + if p.outputType == outputTypeSubstreams { + if strings.HasPrefix(finalFileName, "substreams/") { + projectFiles[finalFileName] = content + continue + } + } + if strings.HasPrefix(finalFileName, "substreams/") { substreamsFiles[finalFileName] = content } else if strings.HasPrefix(finalFileName, "BOTH/") { @@ -295,10 +319,18 @@ func (p *Project) Render(outType outputType) (substreamsFiles map[string][]byte, } for _, contract := range p.Contracts { + if p.outputType == outputTypeSubstreams { + projectFiles[fmt.Sprintf("abi/%s_contract.abi.json", contract.Name)] = []byte(contract.abi.raw) + continue + } substreamsFiles[fmt.Sprintf("substreams/abi/%s_contract.abi.json", contract.Name)] = []byte(contract.abi.raw) } for _, dds := range p.DynamicContracts { + if p.outputType == outputTypeSubstreams { + projectFiles[fmt.Sprintf("abi/%s_contract.abi.json", dds.Name)] = []byte(dds.abi.raw) + continue + } substreamsFiles[fmt.Sprintf("substreams/abi/%s_contract.abi.json", dds.Name)] = []byte(dds.abi.raw) } diff --git a/injective-events/convo.go b/injective-events/convo.go index 971bdb5..eb6e853 100644 --- a/injective-events/convo.go +++ b/injective-events/convo.go @@ -411,7 +411,7 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd { cmds = append(cmds, c.msg().Message("Code generation complete!").Cmd()) cmds = append(cmds, c.action(codegen.RunBuild{}).DownloadFiles(). AddFile("project.zip", msg.ProjectZip, "application/x-zip+extract", "\nProject files, schemas, dev environment..."). - AddFile("substreams_src.zip", msg.SubstreamsSourceZip, "application/zip", ""). + AddFile("substreams_src.zip", msg.SubstreamsSourceZip, "application/x-zip+extract", ""). Cmd()) c.state.generatedCodeCompleted = true