Skip to content

Commit

Permalink
First version
Browse files Browse the repository at this point in the history
  • Loading branch information
enoldev committed Oct 21, 2024
1 parent e6e7648 commit cfd8c1a
Show file tree
Hide file tree
Showing 18 changed files with 3,075 additions and 0 deletions.
1 change: 1 addition & 0 deletions server/handler_convo.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
_ "github.com/streamingfast/substreams-codegen/evm-minimal"
_ "github.com/streamingfast/substreams-codegen/injective-events"
_ "github.com/streamingfast/substreams-codegen/injective-minimal"
_ "github.com/streamingfast/substreams-codegen/sol-anchor"
_ "github.com/streamingfast/substreams-codegen/sol-minimal"
_ "github.com/streamingfast/substreams-codegen/sol-transactions"
_ "github.com/streamingfast/substreams-codegen/starknet-events"
Expand Down
130 changes: 130 additions & 0 deletions sol-anchor/convo.go

Large diffs are not rendered by default.

24 changes: 24 additions & 0 deletions sol-anchor/convo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package solanchor

import (
"testing"

codegen "github.com/streamingfast/substreams-codegen"
"github.com/streamingfast/substreams-codegen/loop"
"github.com/stretchr/testify/assert"
)

func TestConvoNextStep(t *testing.T) {
convo := New()
next := func() loop.Msg {
return convo.NextStep()()
}
p := convo.(*Convo).State

assert.Equal(t, codegen.AskProjectName{}, next())
p.Name = "my-proj"

res := p.Generate()
assert.NoError(t, res.Err)
assert.NotEmpty(t, res.ProjectFiles)
}
25 changes: 25 additions & 0 deletions sol-anchor/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package solanchor

import (
"embed"

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

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

// use the output type form the Project to render the templates
func (p *Project) Generate() codegen.ReturnGenerate {
return codegen.GenerateTemplateTree(p, templatesFS, map[string]string{
"proto/program.proto.gotmpl": "proto/program.proto",
"idls/program.json.gotmpl": "idls/program.json",
"src/lib.rs.gotmpl": "src/lib.rs",
"src/idl/mod.rs.gotmpl": "src/idl/mod.rs",
".gitignore.gotmpl": ".gitignore",
"buf.gen.yaml.gotmpl": "buf.gen.yaml",
"Cargo.lock.gotmpl": "Cargo.lock",
"Cargo.toml.gotmpl": "Cargo.toml",
"substreams.yaml.gotmpl": "substreams.yaml",
})
}
242 changes: 242 additions & 0 deletions sol-anchor/idl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
package solanchor

import (
"encoding/json"
"fmt"
"strings"
"unicode"
)

type IDL struct {
Events []Event `json:"events"`
Metadata Metadata `json:"metadata"`
Types []Type `json:"types"`
}

type Metadata struct {
Address string `json:"address"`
}

// --- EVENTS

type Event struct {
Name string `json:"name"`
Fields []Field `json:"fields"`
}

func (e *Event) SnakeCaseName() string {
return toSnakeCase(e.Name)
}

// --- FIELDS

type Field struct {
Name string `json:"name"`
Type FieldType `json:"type"`
Index bool `json:"index"`
}

func (f *Field) SnakeCaseName() string {
return toSnakeCase(f.Name)
}

type FieldType struct {
Simple string
Defined string
Array string
}

func (t *FieldType) IsSimple() bool {
return t.Simple != ""
}

func (t *FieldType) IsSimplePubKey() bool {
return t.Simple == "publicKey"
}

func (t *FieldType) IsDefined() bool {
return t.Defined != ""
}

func (t *FieldType) IsArray() bool {
return t.Array != ""
}

func (t *FieldType) Resolve() string {
if t.IsSimplePubKey() {
return "PubKey"
}

if t.IsSimple() {
return t.Simple
}

if t.IsDefined() {
return t.Defined
}

if t.IsArray() {
return t.Array
}

return ""
}

func (t *FieldType) ResolveProtobufType() string {
return ToProtobufType(t.Resolve())
}

func ToProtobufType(rustType string) string {
switch rustType {
case "u8":
return "uint64"
case "u64":
return "uint64"
case "i64":
return "int64"
case "f64":
return "double"
case "f32":
return "float"
case "i32":
return "int32"
case "u32":
return "uint32"
case "PubKey":
return "string"
}

return rustType
}

func (t *FieldType) UnmarshalJSON(data []byte) error {
var simpleType string
if err := json.Unmarshal(data, &simpleType); err == nil {
t.Simple = simpleType
return nil
}

var definedType struct {
Defined string `json:"defined"`
}
if err := json.Unmarshal(data, &definedType); err == nil && definedType.Defined != "" {
t.Defined = definedType.Defined
return nil
}

var arrayType struct {
Array []interface{} `json:"array"`
}
if err := json.Unmarshal(data, &arrayType); err == nil && len(arrayType.Array) > 0 {
stringType, ok1 := arrayType.Array[0].(string)
//_, _ := arrayType.Array[1].(int)
if ok1 {
t.Array = stringType
}
return nil
}

return fmt.Errorf("failed to unmarshal Type: %s", string(data))
}

// --- TYPES

type Type struct {
Name string `json:"name"`
Type TypeDetails `json:"type"`
}

func (t *Type) SnakeCaseName() string {
return toSnakeCase(t.Name)
}

type TypeDetails struct {
Kind string
Struct *TypeStruct
Enum *TypeEnum
}

func (t *TypeDetails) IsStruct() bool {
return t.Kind == "struct"
}

func (t *TypeDetails) IsEnum() bool {
return t.Kind == "enum"
}

func (t *TypeDetails) UnmarshalJSON(data []byte) error {
var kindType struct {
Kind string `json:"kind"`
}
if err := json.Unmarshal(data, &kindType); err == nil {
switch kindType.Kind {
case "enum":
var typeEnum TypeEnum
if err := json.Unmarshal(data, &typeEnum); err == nil {
t.Kind = "enum"
t.Enum = &typeEnum
return nil
}
case "struct":
var typeStruct TypeStruct
if err := json.Unmarshal(data, &typeStruct); err == nil {
t.Kind = "struct"
t.Struct = &typeStruct
return nil
}
}
return nil
}

return fmt.Errorf("failed to unmarshal Type: %s", string(data))
}

type TypeStruct struct {
Kind string `json:"kind"`
Fields []TypeStructField `json:"fields"`
}

type TypeStructField struct {
Name string `json:"name"`
Type FieldType `json:"type"`
}

func (f *TypeStructField) SnakeCaseName() string {
return toSnakeCase(f.Name)
}

type TypeEnum struct {
Kind string `json:"kind"`
Variants []TypeEnumVariant `json:"variants"`
}

type TypeEnumVariant struct {
Name string `json:"name"`
}

func (f *TypeEnumVariant) SnakeCaseName() string {
return strings.ToUpper(toSnakeCase(f.Name))
}

// --- UTILS

func toSnakeCase(str string) string {
var result []rune

for i, r := range str {
// Check if the character is uppercase
if unicode.IsUpper(r) {
// Add an underscore before the uppercase letter if it's not the first character
if i > 0 {
result = append(result, '_')
}
// Convert the uppercase letter to lowercase
result = append(result, unicode.ToLower(r))
} else {
// Just add the character as is
result = append(result, r)
}
}

return string(result)
}
7 changes: 7 additions & 0 deletions sol-anchor/logging.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package solanchor

import (
"github.com/streamingfast/logging"
)

var zlog, tracer = logging.PackageLogger("sol-anchor", "github.com/streamingfast/substreams-codegen/codegen/sol-anchor")
21 changes: 21 additions & 0 deletions sol-anchor/state.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package solanchor

import (
"strings"
)

type Project struct {
Name string `json:"name"`
ChainName string `json:"chainName"`
Compile bool `json:"compile,omitempty"` // optional field to write in state and automatically compile with no confirmation.
Download bool `json:"download,omitempty"`
InitialBlock uint64 `json:"initialBlock,omitempty"`
InitialBlockSet bool `json:"initialBlockSet,omitempty"`
Idl *IDL `json:"idl,omitempty"`
IdlString string `json:"idlString,omitempty"`

generatedCodeCompleted bool
}

func (p *Project) ModuleName() string { return strings.ReplaceAll(p.Name, "-", "_") }
func (p *Project) KebabName() string { return strings.ReplaceAll(p.Name, "_", "-") }
13 changes: 13 additions & 0 deletions sol-anchor/templates/.gitignore.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# substreams auth file
.substreams.env

# Compiled source files
target/

# Sink data when running any sinker
sink-data/

# The spkg packed by the subtreams cli
*.spkg

replay.log
Loading

0 comments on commit cfd8c1a

Please sign in to comment.