Skip to content

Commit

Permalink
Small fixes to docs (#64)
Browse files Browse the repository at this point in the history
* Add docs to Bundle

* Rename CI workflow
  • Loading branch information
ferranbt authored Mar 14, 2024
1 parent cc829ee commit 762f32c
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 12 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/check-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Check forge-gen
on:
push:
branches:
- main
pull_request:

env:
FOUNDRY_PROFILE: ci

jobs:
check-docs-gen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Install deps
run: forge install

- name: Build the contracts
run: forge build

- name: Generate forge-docs
run: cd tools/docs-gen && go run main.go --suave-std ../../
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cache/
out/
src-forge-test/
docs/
docs/
suave-std-gen/
3 changes: 2 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[profile.ci.fuzz]
[profile.default]
runs = 10_000
solc_version = "0.8.23"
ast = true
[profile.suave]
whitelist = ["*"]
5 changes: 5 additions & 0 deletions src/protocols/Bundle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import "solady/src/utils/JSONParserLib.sol";

/// @notice Bundle is a library with utilities to interact with the Flashbots bundle API described in https://docs.flashbots.net/flashbots-auction/advanced/rpc-endpoint#eth_sendbundle
library Bundle {
/// @notice BundleObj is a struct that represents a bundle to be sent to the Flashbots relay.
/// @param blockNumber the block number at which the bundle should be executed.
/// @param minTimestamp the minimum timestamp at which the bundle should be executed.
/// @param maxTimestamp the maximum timestamp at which the bundle should be executed.
/// @param txns the transactions to be included in the bundle.
struct BundleObj {
uint64 blockNumber;
uint64 minTimestamp;
Expand Down
99 changes: 89 additions & 10 deletions tools/docs-gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"path/filepath"
"strconv"
"strings"
"unicode"

"github.com/Kunde21/markdownfmt/v3"
"github.com/Kunde21/markdownfmt/v3/markdown"
Expand Down Expand Up @@ -53,14 +54,77 @@ func main() {

// apply the template and write the docs
for _, contract := range contractDefs {
if err := applyTemplate(contract); err != nil {
if err := applyTemplate(contractDefs, contract); err != nil {
log.Fatal(err)
}
}
}

func applyTemplate(contract *ContractDef) error {
t, err := template.New("template").Parse(docsTemplate)
func applyTemplate(all []*ContractDef, contract *ContractDef) error {
curPath := filepath.Dir(contract.Path)

funcMap := template.FuncMap{
"desc": func(s string) string {
// uppercase the fist letter in the string
chars := []rune(s)

// Check if the first character is a letter
if len(chars) > 0 && unicode.IsLetter(chars[0]) {
// Capitalize the first letter
chars[0] = unicode.ToUpper(chars[0])
}

s = string(chars)

// if the last character is not a period, add one
if !strings.HasSuffix(s, ".") {
s += "."
}
return s
},
"quote": func(s string) string {
return fmt.Sprintf("`%s`", s)
},
"type": func(s *Field) string {
if s.TypeReference == 0 {
// basic type with quotes
return fmt.Sprintf("`%s`", s.Type)
}

// find the reference type
for _, contract := range all {
for _, structRef := range contract.Structs {
if structRef.ID == s.TypeReference {

dstPath := filepath.Dir(contract.Path)
dstFile := filepath.Base(contract.Path)

// try to add a link to the struct
rel, err := filepath.Rel(curPath, dstPath)
if err != nil {
panic(err)
}

anchorName := strings.ToLower(structRef.Name)

var link string
if rel == "." {
// same file, just create the reference
link = fmt.Sprintf("[%s](#%s)", structRef.Name, anchorName)
} else {
link = fmt.Sprintf("[%s](%s#%s)", structRef.Name, filepath.Join(rel, dstFile), anchorName)
}

return link
}
}
}

log.Printf("Link for type not found: %s", s.Type)
return fmt.Sprintf("`%s`", s.Type)
},
}
t, err := template.New("template").Funcs(funcMap).Parse(docsTemplate)
if err != nil {
return err
}
Expand All @@ -78,6 +142,7 @@ func applyTemplate(contract *ContractDef) error {
return err
}
output = string(outputB)
output = strings.Replace(output, "'", "'", -1)

// get the relative path with respect to src
relPath := strings.TrimPrefix(contract.Path, "src/")
Expand All @@ -99,27 +164,27 @@ func applyTemplate(contract *ContractDef) error {
var docsTemplate = `
# {{.Name}}
{{.Description}}
{{desc .Description}}
{{$Path := .Path}}
## Functions
{{range .Functions}}
### [{{.Name}}](https://github.com/flashbots/suave-std/tree/main/{{$Path}}#L{{.Pos.FromLine}})
{{.Description}}
{{desc .Description}}
{{ if ne (len .Input) 0 -}}
Input:
{{range .Input}}
- "{{.Name}}": {{.Description}}
- {{quote .Name}} ({{type .}}): {{desc .Description}}
{{end}}
{{end}}
{{ if ne (len .Output) 0 -}}
Output:
{{range .Output}}
- "{{.Name}}": {{.Description}}
- {{quote .Name}} ({{type .}}): {{desc .Description}}
{{end}}
{{end}}
Expand All @@ -131,10 +196,10 @@ Output:
{{range .Structs}}
### [{{.Name}}](https://github.com/flashbots/suave-std/tree/main/{{$Path}}#L{{.Pos.FromLine}})
{{.Description}}
{{desc .Description}}
{{range .Fields}}
- "{{.Name}}": {{.Description}}
- {{quote .Name}} ({{type .}}): {{desc .Description}}
{{- end}}
{{end}}
Expand Down Expand Up @@ -182,6 +247,11 @@ var (
)

func readForgeArtifacts(path string) ([]*artifact, error) {
// validate that the path exists
if _, err := os.Stat(path); err != nil {
return nil, err
}

artifacts := []*artifact{}
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, _ error) error {
if d.IsDir() {
Expand All @@ -201,6 +271,12 @@ func readForgeArtifacts(path string) ([]*artifact, error) {
return err
}

fmt.Println("-- artifact --")
fmt.Println(path)
fmt.Println(artifact)
fmt.Println(artifact.Ast)
fmt.Println(artifact.Ast.AbsolutePath)

// skip artifacts not in the 'src' repo
if !strings.HasPrefix(artifact.Ast.AbsolutePath, "src/") {
return nil
Expand Down Expand Up @@ -234,6 +310,7 @@ type astNode struct {
ReturnParameters *astNode
Parameters json.RawMessage
ReferencedDeclaration uint64
PathNode *astNode
}

func (a *astNode) hasDocs() bool {
Expand Down Expand Up @@ -429,8 +506,10 @@ func fillSpecTypes(natValues []natSpecValue, astValues []*astNode) ([]*Field, er
} else if astVal.TypeName.NodeType == "UserDefinedTypeName" {
// find the resource reference.... it is the same!
field.TypeReference = astVal.TypeName.ReferencedDeclaration
field.Type = astVal.TypeName.PathNode.Name
} else if astVal.TypeName.NodeType == "ArrayTypeName" {
// TODO
// TODO: Fix
field.Type = astVal.TypeName.Name
} else {
return nil, fmt.Errorf("not found %s", astVal.TypeName.NodeType)
}
Expand Down

0 comments on commit 762f32c

Please sign in to comment.