Skip to content

Commit f59c79d

Browse files
authored
Merge pull request #12 from selesy/feat/local-openrpc-and-debug
Feat/local openrpc and debug
2 parents d716ecd + 980b4f2 commit f59c79d

23 files changed

+1094
-130
lines changed

.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,3 @@
3232
go.work
3333

3434
# End of https://www.toptal.com/developers/gitignore/api/go,direnv,dotenv
35-
36-
// Custom
37-
go.work.sum

.tool-versions

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
golang 1.24.4
1+
golang 1.25.4
22
golangci-lint 2.4.0
33
pre-commit 4.2.0
44
python 3.10.4

gen/go.mod

Lines changed: 0 additions & 25 deletions
This file was deleted.

gen/go.sum

Lines changed: 0 additions & 37 deletions
This file was deleted.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
- name: debug_storageRangeAt
2+
summary: Returns the storage range at a given block hash and transaction index
3+
params:
4+
- name: blockHash
5+
schema:
6+
$ref: '../../schemas.yaml#/components/schemas/BLOCK_HASH'
7+
- name: txIndex
8+
schema:
9+
type: integer
10+
- name: address
11+
schema:
12+
$ref: '../../schemas.yaml#/components/schemas/ADDRESS'
13+
- name: startKey
14+
schema:
15+
$ref: '../../schemas.yaml#/components/schemas/HASH'
16+
- name: maxResult
17+
schema:
18+
type: integer
19+
result:
20+
name: storage
21+
schema:
22+
$ref: '../../schemas.yaml#/components/schemas/StorageRange'
23+
- name: debug_traceBlock
24+
summary: The traceBlock method returns the full trace of a block.
25+
params:
26+
- name: blockRlp
27+
schema:
28+
$ref: '../../schemas.yaml#/components/schemas/BYTES'
29+
- name: options
30+
schema:
31+
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
32+
result:
33+
name: trace
34+
schema:
35+
type: array
36+
items:
37+
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
38+
- name: debug_traceBlockByHash
39+
summary: The traceBlockByHash method returns the full trace of a block.
40+
params:
41+
- name: blockHash
42+
schema:
43+
$ref: '../../schemas.yaml#/components/schemas/BLOCK_HASH'
44+
- name: options
45+
schema:
46+
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
47+
result:
48+
name: trace
49+
schema:
50+
type: array
51+
items:
52+
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
53+
- name: debug_traceBlockByNumber
54+
summary: The traceBlockByNumber method returns the full trace of a block.
55+
params:
56+
- name: blockNumber
57+
schema:
58+
$ref: '../../schemas.yaml#/components/schemas/BLOCK_NUMBER'
59+
- name: options
60+
schema:
61+
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
62+
result:
63+
name: trace
64+
schema:
65+
type: array
66+
items:
67+
$ref: '../../schemas.yaml#/components/schemas/BlockTrace'
68+
- name: debug_traceTransaction
69+
summary: The traceTransaction method returns the full trace of a transaction.
70+
params:
71+
- name: txHash
72+
schema:
73+
$ref: '../../schemas.yaml#/components/schemas/TX_HASH'
74+
- name: options
75+
schema:
76+
$ref: '../../schemas.yaml#/components/schemas/TraceOptions'
77+
result:
78+
name: trace
79+
schema:
80+
$ref: '../../schemas.yaml#/components/schemas/TransactionTrace'
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
components:
2+
schemas:
3+
TraceOptions:
4+
type: object
5+
properties:
6+
disableStorage:
7+
type: boolean
8+
description: 'Setting this to true will disable storage capture (default: false).'
9+
disableStack:
10+
type: boolean
11+
description: 'Setting this to true will disable stack capture (default: false).'
12+
enableMemory:
13+
type: boolean
14+
description: 'Setting this to true will enable memory capture (default: false).'
15+
enableReturnData:
16+
type: boolean
17+
description: 'Setting this to true will enable return data capture (default: false).'
18+
tracer:
19+
type: string
20+
description: 'The name of the tracer to use (e.g. "callTracer").'
21+
timeout:
22+
type: string
23+
description: 'The timeout for the tracer (e.g. "5s").'

gen/internal/scraper/scraper.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"log/slog"
88
"os"
9+
"path/filepath"
910

1011
"github.com/google/go-github/v74/github"
1112

@@ -46,10 +47,90 @@ func (s *Scraper) Run(ctx context.Context) ([]openrpc.Method, error) {
4647
return nil, err
4748
}
4849

50+
localMethodSrc, err := s.LocalSource(ctx, "_schemas.yaml")
51+
if err != nil {
52+
return nil, err
53+
}
54+
s.log.InfoContext(ctx, "Local method files retrieved", "methods", len(localMethodSrc))
55+
methodSrc = append(methodSrc, localMethodSrc...)
56+
4957
schemaSrc, err := s.SchemaSource(ctx)
5058
if err != nil {
5159
return nil, err
5260
}
5361

62+
localSchemaSrc, err := s.LocalSource(ctx, "trace.yaml")
63+
if err != nil {
64+
return nil, err
65+
}
66+
s.log.InfoContext(ctx, "Local schema files retrieved", "schemas", len(localSchemaSrc))
67+
schemaSrc = append(schemaSrc, localSchemaSrc...)
68+
5469
return s.MergeMethodsAndDefinitions(ctx, methodSrc, schemaSrc)
5570
}
71+
72+
// LocalSource returns the OpenRPC source for all methods defined by the
73+
// local OpenRPC specifications.
74+
func (s *Scraper) LocalSource(ctx context.Context, filter string) ([]string, error) {
75+
root, err := s.findProjectRoot()
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
dir := filepath.Join(root, "gen", "internal", "openrpc", "data")
81+
files, err := os.ReadDir(dir)
82+
if err != nil {
83+
return nil, err
84+
}
85+
86+
var sources []string
87+
for _, file := range files {
88+
if file.IsDir() {
89+
continue
90+
}
91+
92+
if filepath.Ext(file.Name()) != ".yaml" {
93+
continue
94+
}
95+
96+
if filter == "trace.yaml" && file.Name() == "trace.yaml" {
97+
continue
98+
}
99+
100+
if filter == "_schemas.yaml" && file.Name() != "trace.yaml" {
101+
continue
102+
}
103+
104+
path := filepath.Join(dir, file.Name())
105+
path = filepath.Clean(path)
106+
s.log.DebugContext(ctx, "Reading local method file", "path", path)
107+
108+
data, err := os.ReadFile(path)
109+
if err != nil {
110+
return nil, err
111+
}
112+
s.log.DebugContext(ctx, "Read local method file", "path", path)
113+
sources = append(sources, string(data))
114+
}
115+
116+
return sources, nil
117+
}
118+
119+
func (s *Scraper) findProjectRoot() (string, error) {
120+
dir, err := os.Getwd()
121+
if err != nil {
122+
return "", err
123+
}
124+
125+
for {
126+
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
127+
return dir, nil
128+
}
129+
130+
if dir == filepath.Dir(dir) {
131+
return "", os.ErrNotExist
132+
}
133+
134+
dir = filepath.Dir(dir)
135+
}
136+
}

go.mod

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
11
module github.com/selesy/ethereum-mcp
22

3-
go 1.24.4
3+
go 1.24
4+
5+
toolchain go1.25.4
46

57
tool (
68
github.com/selesy/ethereum-mcp/gen
79
golang.org/x/vuln/cmd/govulncheck
810
)
911

10-
require github.com/mark3labs/mcp-go v0.39.0
12+
require (
13+
github.com/dave/jennifer v1.7.1
14+
github.com/google/go-github/v74 v74.0.0
15+
github.com/invopop/yaml v0.3.1
16+
github.com/lmittmann/tint v1.1.2
17+
github.com/mark3labs/mcp-go v0.39.0
18+
github.com/selesy/jsonschema v0.14.0-rc1
19+
github.com/stretchr/testify v1.11.0
20+
github.com/wk8/go-ordered-map/v2 v2.1.8
21+
gotest.tools/v3 v3.5.2
22+
)
1123

1224
require (
1325
github.com/bahlo/generic-list-go v0.2.0 // indirect
1426
github.com/buger/jsonparser v1.1.1 // indirect
15-
github.com/dave/jennifer v1.7.1 // indirect
16-
github.com/google/go-github/v74 v74.0.0 // indirect
27+
github.com/davecgh/go-spew v1.1.1 // indirect
28+
github.com/google/go-cmp v0.7.0 // indirect
1729
github.com/google/go-querystring v1.1.0 // indirect
1830
github.com/invopop/jsonschema v0.13.0 // indirect
19-
github.com/invopop/yaml v0.3.1 // indirect
20-
github.com/lmittmann/tint v1.1.2 // indirect
2131
github.com/mailru/easyjson v0.7.7 // indirect
22-
github.com/selesy/ethereum-mcp/gen v0.4.0 // indirect
23-
github.com/selesy/jsonschema v0.14.0-rc1 // indirect
32+
github.com/pmezard/go-difflib v1.0.0 // indirect
2433
github.com/spf13/cast v1.7.1 // indirect
25-
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
2634
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
2735
golang.org/x/mod v0.22.0 // indirect
2836
golang.org/x/sync v0.10.0 // indirect
@@ -32,5 +40,3 @@ require (
3240
golang.org/x/vuln v1.1.4 // indirect
3341
gopkg.in/yaml.v3 v3.0.1 // indirect
3442
)
35-
36-
replace github.com/selesy/ethereum-mcp/gen => ./gen

pkg/doc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
////go:generate go tool gen
1+
//go:generate go tool gen
22

33
package pkg

pkg/proxy/params.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package proxy
2+
3+
// ParamsSpec contains the "specification" needed to service each JSON-RPC
4+
// method.
5+
type ParamsSpec struct {
6+
order []string
7+
required map[string]struct{}
8+
}
9+
10+
// Order returns an ordered list of parameter names which can be used to
11+
// convert a JSON-RPC "params" value from named parameters to positional
12+
// parameters.
13+
func (p *ParamsSpec) Order() []string {
14+
return p.order
15+
}
16+
17+
// Required returns a set of which parameters are required. For positional
18+
// parameters, the parameters in this set should be those that are first
19+
// in the list returned by Order.
20+
func (p *ParamsSpec) Required() map[string]struct{} {
21+
return p.required
22+
}

0 commit comments

Comments
 (0)