Skip to content

Commit

Permalink
Migrate injective events.
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandre Bourget committed Sep 12, 2024
1 parent e8a6cbb commit a8ce7fe
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 108 deletions.
135 changes: 53 additions & 82 deletions injective-events/convo.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package injective_events
import (
"encoding/json"
"fmt"
"os"
"strconv"
"strings"

Expand All @@ -14,10 +13,8 @@ import (
var QuitInvalidContext = loop.Quit(fmt.Errorf("invalid state context: no current contract"))
var InjectiveTestnetDefaultStartBlock uint64 = 37368800

type InjectiveConvo struct {
codegen.Conversation[*Project]
factory *codegen.MsgWrapFactory
state *Project
type Convo struct {
*codegen.Conversation[*Project]
}

func init() {
Expand All @@ -30,49 +27,22 @@ func init() {
)
}

func New(factory *codegen.MsgWrapFactory) codegen.Conversation {
c := &InjectiveConvo{
factory: factory,
state: &Project{},
}
return c
}

func (c *InjectiveConvo) msg() *codegen.MsgWrap { return c.factory.NewMsg(c.state) }

func (c *InjectiveConvo) action(element any) *codegen.MsgWrap {
return c.factory.NewInput(element, c.state)
}

func (c *InjectiveConvo) validate() error {
if _, err := json.Marshal(c.state); err != nil {
return fmt.Errorf("validating state format: %w", err)
}

return nil
}

func cmd(msg any) loop.Cmd {
return func() loop.Msg {
return msg
}
func New() codegen.Converser {
return &Convo{&codegen.Conversation[*Project]{
State: &Project{},
}}
}

func (c *InjectiveConvo) contextEventDesc() *eventDesc {
if c.state.currentEventIdx > len(c.state.EventDescs)-1 {
func (c *Convo) contextEventDesc() *eventDesc {
if c.State.currentEventIdx > len(c.State.EventDescs)-1 {
return nil
}
return c.state.EventDescs[c.state.currentEventIdx]
return c.State.EventDescs[c.State.currentEventIdx]
}

func (c *InjectiveConvo) NextStep() loop.Cmd {
if err := c.validate(); err != nil {
return loop.Quit(err)
}
return c.state.NextStep()
}
func (c *Convo) NextStep() (out loop.Cmd) {
p := c.State

func (p *Project) NextStep() (out loop.Cmd) {
if p.Name == "" {
return cmd(codegen.AskProjectName{})
}
Expand Down Expand Up @@ -132,34 +102,30 @@ func (p *Project) NextStep() (out loop.Cmd) {
return loop.Quit(nil)
}

func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
if os.Getenv("SUBSTREAMS_DEV_DEBUG_CONVERSATION") == "true" {
fmt.Printf("convo Update message: %T %#v\n-> state: %#v\n\n", msg, msg, c.state)
}

func (c *Convo) Update(msg loop.Msg) loop.Cmd {
switch msg := msg.(type) {
case codegen.MsgStart:
var msgCmd loop.Cmd
if msg.Hydrate != nil {
if err := json.Unmarshal([]byte(msg.Hydrate.SavedState), &c.state); err != nil {
if err := json.Unmarshal([]byte(msg.Hydrate.SavedState), &c.State); err != nil {
return loop.Quit(fmt.Errorf(`something went wrong, here's an error message to share with our devs (%s); we've notified them already`, err))
}
msgCmd = c.msg().Message("Ok, I reloaded your state.").Cmd()
msgCmd = c.Msg().Message("Ok, I reloaded your state.").Cmd()
} else {
msgCmd = c.msg().Message("Ok, let's start a new package.").Cmd()
msgCmd = c.Msg().Message("Ok, let's start a new package.").Cmd()
}
return loop.Seq(msgCmd, c.NextStep())

case codegen.AskProjectName:
return c.action(codegen.InputProjectName{}).
return c.Action(codegen.InputProjectName{}).
TextInput(codegen.InputProjectNameTextInput(), "Submit").
Description(codegen.InputProjectNameDescription()).
DefaultValue("my_project").
Validation(codegen.InputProjectNameRegex(), codegen.InputProjectNameValidation()).
Cmd()

case codegen.InputProjectName:
c.state.Name = msg.Value
c.State.Name = msg.Value
return c.NextStep()

case codegen.AskChainName:
Expand All @@ -168,21 +134,21 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
labels = append(labels, conf.DisplayName)
values = append(values, conf.ID)
}
return c.action(codegen.InputChainName{}).ListSelect("Please select the chain").
return c.Action(codegen.InputChainName{}).ListSelect("Please select the chain").
Labels(labels...).
Values(values...).
Cmd()

case codegen.MsgInvalidChainName:
return c.msg().
Messagef(`Hmm, %q seems like an invalid chain name. Maybe it was supported and is not anymore?`, c.state.ChainName).
return c.Msg().
Messagef(`Hmm, %q seems like an invalid chain name. Maybe it was supported and is not anymore?`, c.State.ChainName).
Cmd()

case codegen.InputChainName:
c.state.ChainName = msg.Value
c.State.ChainName = msg.Value
if isValidChainName(msg.Value) {
return loop.Seq(
c.msg().Messagef("Got it, will be using chain %q", c.state.ChainConfig().DisplayName).Cmd(),
c.Msg().Messagef("Got it, will be using chain %q", c.State.ChainConfig().DisplayName).Cmd(),
c.NextStep(),
)
}
Expand All @@ -191,11 +157,11 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
case AskInitialStartBlockType:
textInputMessage := "At what block do you want to start indexing data?"
defaultValue := "0"
if isTestnet(c.state.ChainName) {
if isTestnet(c.State.ChainName) {
defaultValue = fmt.Sprintf("%d", InjectiveTestnetDefaultStartBlock)
textInputMessage = fmt.Sprintf("At what block do you want to start indexing data? (the first available block on %s is: %s)", c.state.ChainName, defaultValue)
textInputMessage = fmt.Sprintf("At what block do you want to start indexing data? (the first available block on %s is: %s)", c.State.ChainName, defaultValue)
}
return c.action(InputAskInitialStartBlockType{}).
return c.Action(InputAskInitialStartBlockType{}).
TextInput(textInputMessage, "Submit").
DefaultValue(defaultValue).
Validation(`^\d+$`, "The start block cannot be empty and must be a number").
Expand All @@ -206,12 +172,12 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
if err != nil {
return loop.Quit(fmt.Errorf("invalid start block input value %q, expected a number", msg.Value))
}
if isTestnet(c.state.ChainName) && initialBlock < InjectiveTestnetDefaultStartBlock {
if isTestnet(c.State.ChainName) && initialBlock < InjectiveTestnetDefaultStartBlock {
initialBlock = InjectiveTestnetDefaultStartBlock
}

c.state.InitialBlock = initialBlock
c.state.InitialBlockSet = true
c.State.InitialBlock = initialBlock
c.State.InitialBlockSet = true
return c.NextStep()

case AskDataType:
Expand All @@ -220,26 +186,26 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
"All events in transactions where at least one event matches your query",
}
values := []string{EVENTS_DATA_TYPE, EVENT_GROUPS_DATA_TYPE}
return c.action(InputDataType{}).
return c.Action(InputDataType{}).
ListSelect(fmt.Sprintf("This codegen will build a substreams that filters data based on events.\n" +
"Do you want to target:")).
Labels(labels...).
Values(values...).
Cmd()

case InputDataType:
c.state.DataType = msg.Value
c.State.DataType = msg.Value
return c.NextStep()

case AskEventType:
var cmds []loop.Cmd

if len(c.state.EventDescs) == 0 {
cmds = append(cmds, c.msg().Message("Let's start by filtering event types").Cmd())
if len(c.State.EventDescs) == 0 {
cmds = append(cmds, c.Msg().Message("Let's start by filtering event types").Cmd())
}

cmds = append(cmds, c.action(InputEventType{}).
TextInput(fmt.Sprintf("Please enter the type of Event that you want to track.\n\nYou can usually find them under the transaction details in the explorer: %s.\nExamples: message, injective.exchange.v1beta1.EventCancelDerivativeOrder, wasm ...", c.state.ChainConfig().ExplorerLink), "Submit").
cmds = append(cmds, c.Action(InputEventType{}).
TextInput(fmt.Sprintf("Please enter the type of Event that you want to track.\n\nYou can usually find them under the transaction details in the explorer: %s.\nExamples: message, injective.exchange.v1beta1.EventCancelDerivativeOrder, wasm ...", c.State.ChainConfig().ExplorerLink), "Submit").
Validation(`(.|\s)*\S(.|\s)*`, "The event type cannot be empty").
Cmd(),
)
Expand Down Expand Up @@ -267,7 +233,7 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
"All conditions must be met for an event to match. You can define additional events of the same type to match different conditions.\n"+
"Enter either {attribute_key} or {attribute_key}:{attribute_value} to add such a constraint, or leave empty to skip.", evt.EventType, evt.GetEventQuery())
}
return c.action(InputEventAttribute{}).
return c.Action(InputEventAttribute{}).
TextInput(textInput,
"Submit").
Cmd()
Expand Down Expand Up @@ -295,8 +261,8 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {

case AskAnotherEventType:
return loop.Seq(
c.msg().Messagef("Current filtering event types %q", c.state.GetEventsQuery()).Cmd(),
c.action(InputAskAnotherEventType{}).
c.Msg().Messagef("Current filtering event types %q", c.State.GetEventsQuery()).Cmd(),
c.Action(InputAskAnotherEventType{}).
ListSelect("Do you want to add another event type").
Labels("Yes", "No").
Values("yes", "no").Cmd(),
Expand All @@ -305,10 +271,10 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
case InputAskAnotherEventType:
switch msg.Value {
case "yes":
c.state.EventDescs = append(c.state.EventDescs, &eventDesc{Incomplete: true})
c.State.EventDescs = append(c.State.EventDescs, &eventDesc{Incomplete: true})
return c.NextStep()
case "no":
c.state.EventsComplete = true
c.State.EventsComplete = true
return c.NextStep()
default:
return loop.Quit(fmt.Errorf("invalid selection input value %q, expected 'yes', 'more' or 'no'", msg.Value))
Expand All @@ -320,33 +286,32 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
return QuitInvalidContext
}
if evt.EventType != "" {
return c.msg().Messagef("Ok, now let's talk about event %q",
return c.Msg().Messagef("Ok, now let's talk about event %q",
evt.EventType,
).Cmd()
}
return nil

case codegen.RunGenerate:
return loop.Seq(
c.msg().Message("Generating Substreams module code").Cmd(),
c.Msg().Message("Generating Substreams module code").Cmd(),
loop.Batch(
cmdGenerate(c.state),
codegen.CmdGenerate(c.State.Generate),
),
)

case codegen.ReturnGenerate:
if msg.Err != nil {
return loop.Seq(
c.msg().Message("Build failed!").Cmd(),
c.msg().Messagef("The build failed with error: %s", msg.Err).Cmd(),
c.Msg().Message("Build failed!").Cmd(),
c.Msg().Messagef("The build failed with error: %s", msg.Err).Cmd(),
loop.Quit(msg.Err),
)
}

c.state.projectFiles = msg.ProjectFiles
c.state.generatedCodeCompleted = true
c.State.generatedCodeCompleted = true

downloadCmd := c.action(codegen.InputSourceDownloaded{}).DownloadFiles()
downloadCmd := c.Action(codegen.InputSourceDownloaded{}).DownloadFiles()

for fileName, fileContent := range msg.ProjectFiles {
fileDescription := ""
Expand All @@ -357,7 +322,7 @@ func (c *InjectiveConvo) Update(msg loop.Msg) loop.Cmd {
downloadCmd.AddFile(fileName, fileContent, "text/plain", fileDescription)
}

return loop.Seq(c.msg().Messagef("Code generation complete!").Cmd(), downloadCmd.Cmd())
return loop.Seq(c.Msg().Messagef("Code generation complete!").Cmd(), downloadCmd.Cmd())

case codegen.InputSourceDownloaded:
return c.NextStep()
Expand All @@ -373,3 +338,9 @@ func isValidChainName(input string) bool {
func isTestnet(input string) bool {
return ChainConfigByID[input].Network == "injective-testnet"
}

func cmd(msg any) loop.Cmd {
return func() loop.Msg {
return msg
}
}
15 changes: 1 addition & 14 deletions injective-events/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,15 @@ import (
"embed"

codegen "github.com/streamingfast/substreams-codegen"
"github.com/streamingfast/substreams-codegen/loop"
)

//go:embed templates/*
var templatesFS embed.FS

func (p *Project) Generate() (projectFiles map[string][]byte, err error) {
func (p *Project) Generate() codegen.ReturnGenerate {
return codegen.GenerateTemplateTree(p, templatesFS, map[string]string{
".gitignore": ".gitignore",
"README.md.gotmpl": "README.md",
"substreams.yaml.gotmpl": "substreams.yaml",
})
}

func cmdGenerate(p *Project) loop.Cmd {
return func() loop.Msg {
projectFiles, err := p.Generate(outType)
if err != nil {
return codegen.ReturnGenerate{Err: err}
}
return codegen.ReturnGenerate{
ProjectFiles: projectFiles,
}
}
}
12 changes: 0 additions & 12 deletions injective-events/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"sort"
"strings"
"time"
)

const EVENTS_DATA_TYPE = "events"
Expand All @@ -30,17 +29,6 @@ type Project struct {
EventsComplete bool `json:"eventsComplete,omitempty"`

generatedCodeCompleted bool
compilingBuild bool
projectFiles map[string][]byte
sourceFiles map[string][]byte

buildStarted time.Time

// always set by the server
outputType outputType

SqlOutputFlavor string `json:"sql_output_flavor,omitempty"` // either "clickhouse" or "sql"
SubgraphOutputFlavor string `json:"subgraph_output_flavor,omitempty"` // either "trigger" or "entity"
}

func (p *Project) ChainConfig() *ChainConfig { return ChainConfigByID[p.ChainName] }
Expand Down

0 comments on commit a8ce7fe

Please sign in to comment.