From 11206b6e0e6ddefd2679f719c116a1574efafeda Mon Sep 17 00:00:00 2001 From: Garet Halliday <ghalliday@gfxlabs.io> Date: Wed, 21 Sep 2022 12:44:21 -0500 Subject: [PATCH] make it more better --- go.mod | 14 +- go.sum | 33 +- openrpc/cmd/cli.go | 54 +- openrpc/eth-api.json | 2 +- openrpc/generate/generate.go | 271 ++------- openrpc/generate/generate_test.go | 83 --- openrpc/out/types.go | 929 +++++++++++------------------- openrpc/parse/parse.go | 121 ---- openrpc/parse/parse_test.go | 73 --- openrpc/parse/parsing.go | 102 ---- openrpc/templates/types.gotmpl | 72 ++- openrpc/types/objects.go | 79 --- openrpc/types/types.go | 288 ++------- 13 files changed, 486 insertions(+), 1635 deletions(-) delete mode 100644 openrpc/generate/generate_test.go delete mode 100644 openrpc/parse/parse_test.go delete mode 100644 openrpc/parse/parsing.go delete mode 100644 openrpc/types/objects.go diff --git a/go.mod b/go.mod index 66405e8..abc8a8b 100644 --- a/go.mod +++ b/go.mod @@ -9,31 +9,23 @@ require ( github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/ethereum/go-ethereum v1.10.22 - github.com/go-openapi/spec v0.20.7 github.com/gobuffalo/packr/v2 v2.8.3 - github.com/imdario/mergo v0.3.13 + github.com/iancoleman/strcase v0.2.0 github.com/json-iterator/go v1.1.12 - github.com/test-go/testify v1.1.4 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce nhooyr.io/websocket v1.8.7 - sigs.k8s.io/yaml v1.3.0 ) require ( github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect github.com/go-ole/go-ole v1.2.1 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.20.0 // indirect - github.com/go-openapi/swag v0.19.15 // indirect github.com/go-stack/stack v1.8.0 // indirect github.com/gobuffalo/logger v1.0.6 // indirect github.com/gobuffalo/packd v1.0.1 // indirect github.com/gorilla/websocket v1.4.2 // indirect - github.com/josharian/intern v1.0.0 // indirect github.com/karrick/godirwalk v1.16.1 // indirect github.com/klauspost/compress v1.10.3 // indirect - github.com/mailru/easyjson v0.7.6 // indirect github.com/markbates/errx v1.1.0 // indirect github.com/markbates/oncer v1.0.0 // indirect github.com/markbates/safe v1.0.1 // indirect @@ -41,15 +33,11 @@ require ( github.com/mattn/go-isatty v0.0.14 // indirect github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/stretchr/testify v1.7.2 // indirect github.com/tklauser/go-sysconf v0.3.5 // indirect github.com/tklauser/numcpus v0.2.2 // indirect golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 523fc55..1b02745 100644 --- a/go.sum +++ b/go.sum @@ -67,7 +67,6 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -94,16 +93,6 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E= github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= -github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= -github.com/go-openapi/spec v0.20.7 h1:1Rlu/ZrOCCob0n+JKKJAWhNWMPW8bOZRg8FJaY+0SKI= -github.com/go-openapi/spec v0.20.7/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= -github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -215,13 +204,11 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= +github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= -github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -239,15 +226,9 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= @@ -276,8 +257,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -319,8 +298,6 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/test-go/testify v1.1.4 h1:Tf9lntrKUMHiXQ07qBScBTSA0dhYQlu83hswqelv1iE= -github.com/test-go/testify v1.1.4/go.mod h1:rH7cfJo/47vWGdi4GPj16x3/t1xGOj2YxzmNQzk2ghU= github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4= github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI= github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA= @@ -680,8 +657,6 @@ google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/l google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= @@ -692,9 +667,7 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -709,5 +682,3 @@ nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0 rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/openrpc/cmd/cli.go b/openrpc/cmd/cli.go index 2805cb0..ba7c40d 100644 --- a/openrpc/cmd/cli.go +++ b/openrpc/cmd/cli.go @@ -1,16 +1,14 @@ package main +import "C" import ( "encoding/json" "fmt" - "io/ioutil" + "gfx.cafe/open/jrpc/openrpc/generate" "os" - "gfx.cafe/open/jrpc/openrpc/generate" - "gfx.cafe/open/jrpc/openrpc/parse" "gfx.cafe/open/jrpc/openrpc/types" "github.com/alecthomas/kong" - "github.com/gobuffalo/packr/v2" ) var CLI struct { @@ -25,28 +23,7 @@ type CompileCommand struct { } func (c *CompileCommand) Run() error { - openrpc := types.NewOpenRPCSpec1() - var err error - for _, v := range c.Methods { - err = openrpc.AddMethods(v) - if err != nil { - return err - } - } - for _, v := range c.Schemas { - err = openrpc.AddSchemas(v) - if err != nil { - return err - } - } - jzn, err := json.MarshalIndent(openrpc, "", " ") - if err != nil { - return err - } - err = os.WriteFile(c.Output, jzn, 0644) - if err != nil { - return err - } + // TODO return nil } @@ -64,31 +41,24 @@ func (c *GenerateCommand) Run() error { if err != nil { return err } - parse.GetTypes(openrpc, openrpc.Objects) - box := packr.New("template", "./templates") - if err = generate.WriteFile(box, "server", c.Output, openrpc); err != nil { - return err - } - if err = generate.WriteFile(box, "types", c.Output, openrpc); err != nil { + if err = generate.Generate(openrpc, c.Templates, c.Output); err != nil { return err } + return nil } -func readSpec(file string) (*types.OpenRPCSpec1, error) { - data, err := ioutil.ReadFile(file) - if err != nil { - return nil, err - } - - spec := types.NewOpenRPCSpec1() - err = json.Unmarshal(data, spec) +func readSpec(file string) (out *types.OpenRPC, err error) { + var data []byte + data, err = os.ReadFile(file) if err != nil { - return nil, err + return } - return spec, nil + out = new(types.OpenRPC) + err = json.Unmarshal(data, out) + return } func NewCLI() *kong.Context { diff --git a/openrpc/eth-api.json b/openrpc/eth-api.json index da2e5c0..06d85ef 100644 --- a/openrpc/eth-api.json +++ b/openrpc/eth-api.json @@ -1959,7 +1959,7 @@ }, "bytes65": { "type": "string", - "title": "bytes645", + "title": "bytes65", "pattern": "^0x[0-9a-f]{512}$" }, "bytes8": { diff --git a/openrpc/generate/generate.go b/openrpc/generate/generate.go index 63e0334..c7268ed 100644 --- a/openrpc/generate/generate.go +++ b/openrpc/generate/generate.go @@ -2,242 +2,77 @@ package generate import ( "bytes" - "encoding/json" "fmt" + "gfx.cafe/open/jrpc/openrpc/types" + "github.com/iancoleman/strcase" "go/format" "os" - "path" "path/filepath" - "regexp" - "strings" "text/template" - - "gfx.cafe/open/jrpc/openrpc/types" - "gfx.cafe/open/jrpc/openrpc/util" - "github.com/go-openapi/spec" - "github.com/gobuffalo/packr/v2" - "github.com/imdario/mergo" ) -const ( - params = "Params" - result = "Result" - goExt = "go" - goTmplExt = goExt + "tmpl" -) - -var ProgramName = "CHANGME" - -func schemaAsJSONPretty(s spec.Schema) string { - b, err := json.MarshalIndent(s, "", " ") - if err != nil { - return "" - } - b = bytes.ReplaceAll(b, []byte("{"), []byte("")) - b = bytes.ReplaceAll(b, []byte("}"), []byte("")) - b = bytes.ReplaceAll(b, []byte(`"`), []byte("")) - b = bytes.ReplaceAll(b, []byte(`$ref: #`), []byte("")) - - // Remove empty JSON $refs - reg := regexp.MustCompile(`^\s*\$ref.*$/mg`) - ss := reg.ReplaceAllString(string(b), "") - - return ss -} - -func maybeLookupComponentsContentDescriptor(cmpnts *types.Components, cd *types.ContentDescriptor) (rootCD *types.ContentDescriptor, err error) { - rootCD = cd - if cd == nil || cmpnts == nil { - return - } - if strings.Contains(cd.Schema.Ref.String(), "contentDescriptors") { - r := filepath.Base(cd.Schema.Ref.String()) - rootCD = cmpnts.ContentDescriptors[r] - return - } - return -} - -func schemaHazRef(sch spec.Schema) bool { - return sch.Ref.String() != "" +var defaultTemplates = []string{ + "./templates/types.gotmpl", } -func derefSchemaRecurse(cts *types.Components, sch spec.Schema) spec.Schema { - if schemaHazRef(sch) { - sch = getSchemaFromRef(cts, sch.Ref) - sch = derefSchemaRecurse(cts, sch) - } - for i := range sch.OneOf { - got := derefSchemaRecurse(cts, sch.OneOf[i]) - if err := mergo.Merge(&got, sch.OneOf[i]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.OneOf[i] = got - } - for i := range sch.AnyOf { - got := derefSchemaRecurse(cts, sch.AnyOf[i]) - if err := mergo.Merge(&got, sch.AnyOf[i]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.AnyOf[i] = got - } - for i := range sch.AllOf { - got := derefSchemaRecurse(cts, sch.AllOf[i]) - if err := mergo.Merge(&got, sch.AllOf[i]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.AllOf[i] = got - } - for k := range sch.Properties { - got := derefSchemaRecurse(cts, sch.Properties[k]) - if err := mergo.Merge(&got, sch.Properties[k]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.Properties[k] = got - } - for k := range sch.PatternProperties { - got := derefSchemaRecurse(cts, sch.PatternProperties[k]) - if err := mergo.Merge(&got, sch.PatternProperties[k]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.PatternProperties[k] = got - } - if sch.Items == nil { - return sch - } - if sch.Items.Len() > 1 { - for i := range sch.Items.Schemas { - got := derefSchemaRecurse(cts, sch.Items.Schemas[i]) - if err := mergo.Merge(&got, sch.Items.Schemas[i]); err != nil { - panic(err.Error()) - } - got.Schema = "" - sch.Items.Schemas[i] = got - } - } else { - // Is schema - got := derefSchemaRecurse(cts, *sch.Items.Schema) - if err := mergo.Merge(&got, sch.Items.Schema); err != nil { - panic(err.Error()) +var funcs = template.FuncMap{ + "list": func(v ...any) []any { + return v + }, + "camelCase": func(v string) string { + return strcase.ToCamel(v) + }, + "goType": func(v string) string { + switch v { + case "boolean": + return "bool" + case "number": + return "float64" + case "string": + return "string" + case "null": + return "struct{}" + default: + panic(fmt.Sprintln("unknown go type:", v)) } - got.Schema = "" - sch.Items.Schema = &got - } - - return sch -} - -func getSchemaFromRef(cmpnts *types.Components, ref spec.Ref) (sch spec.Schema) { - if cmpnts == nil || ref.String() == "" { - return - } - r := filepath.Base(ref.String()) - sch = cmpnts.Schemas[r] // Trust parser - return -} - -func maybeMethodParams(method types.Method) string { - if len(method.Params) > 0 { - return fmt.Sprintf("%s%s", util.CamelCase(method.Name), params) - } - return "" -} - -func maybeMethodResult(method types.Method) string { - if method.Result != nil { - return fmt.Sprintf("%s%s", util.CamelCase(method.Name), result) - } - return "" -} - -func maybeMethodComment(method types.Method) string { - if comment := util.FirstOf(method.Description, method.Summary); comment != "" { - return fmt.Sprintf("// %s", comment) - } - return "" + }, + "refName": func(v string) string { + return filepath.Base(v) + }, } -func maybeFieldComment(desc string) string { - if desc != "" { - return fmt.Sprintf("// %s", desc) +func Generate(rpc *types.OpenRPC, templates []string, output string) error { + if len(templates) == 0 { + templates = defaultTemplates } - return "" -} - -func getProgramName() string { - return ProgramName -} -type object struct { - Name string - Fields *types.FieldMap -} - -func funcMap(openrpc *types.OpenRPCSpec1) template.FuncMap { - return template.FuncMap{ - "programName": getProgramName, - "derefSchema": derefSchemaRecurse, - "schemaHasRef": schemaHazRef, - "schemaAsJSONPretty": schemaAsJSONPretty, - "lookupContentDescriptor": maybeLookupComponentsContentDescriptor, - "sanitizeBackticks": util.SanitizeBackticks, - "inspect": util.Inpect, - "slice": util.Slice, - "camelCase": util.CamelCase, - "lowerFirst": util.LowerFirst, - "maybeMethodComment": maybeMethodComment, - "maybeMethodParams": maybeMethodParams, - "maybeMethodResult": maybeMethodResult, - "maybeFieldComment": maybeFieldComment, - "getObjects": func(om *types.ObjectMap) []object { - keys := om.GetKeys() - objects := make([]object, 0, len(keys)) - for _, k := range keys { - objects = append(objects, object{Name: k, Fields: om.Get(k)}) - } - return objects - }, - "getFields": func(fm *types.FieldMap) []types.BasicType { - keys := fm.GetKeys() - fields := make([]types.BasicType, 0, len(keys)) - for _, k := range keys { - fields = append(fields, fm.Get(k)) - } - return fields - }, - "indent": func(spaces int, v string) string { - pad := strings.Repeat(" ", spaces) - return pad + strings.Replace(v, "\n", "\n"+pad, -1) - }, - } -} + var wr bytes.Buffer + for _, tmpl := range templates { + name := filepath.Base(tmpl) -func WriteFile(box *packr.Box, name, pkg string, openrpc *types.OpenRPCSpec1) error { - data, err := box.Find(fmt.Sprintf("%s.%s", name, goTmplExt)) - if err != nil { - return err - } + t, err := template.New(name).Funcs(funcs).ParseFiles(tmpl) + if err != nil { + return err + } - tmp, err := template.New(name).Funcs(funcMap(openrpc)).Parse(string(data)) - if err != nil { - return err - } + err = t.Execute(&wr, rpc) + if err != nil { + return err + } - tmpl := new(bytes.Buffer) - err = tmp.Execute(tmpl, openrpc) - if err != nil { - return err - } + var fmtd []byte + fmtd, err = format.Source(wr.Bytes()) + if err != nil { + return err + } + wr.Reset() - fmtd, err := format.Source(tmpl.Bytes()) - if err != nil { - return err + name = name[:len(name)-len(filepath.Ext(name))] + err = os.WriteFile(filepath.Join(output, name+".go"), fmtd, 0777) + if err != nil { + return err + } } - return os.WriteFile(path.Join(pkg, fmt.Sprintf("%s.%s", name, goExt)), fmtd, 0644) + return nil } diff --git a/openrpc/generate/generate_test.go b/openrpc/generate/generate_test.go deleted file mode 100644 index c18a5ec..0000000 --- a/openrpc/generate/generate_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package generate - -import ( - "bytes" - "encoding/json" - "io/ioutil" - "testing" - "text/template" - - "gfx.cafe/open/jrpc/openrpc/parse" - "gfx.cafe/open/jrpc/openrpc/types" - "github.com/test-go/testify/require" -) - -var exp = `package generate -type ServiceMethodParams struct { -// this is a desc -Param1 string -// this is a desc -Param2 string - -Param3 string -// this is an object -Param4 -} -type Param4 struct { -// this is a foo -Foo string -// this is a bar -Bar string -} -type ServiceMethodResult struct { -// the requested data -Data string -} -` - -func tmpl(t *testing.T) string { - data, err := ioutil.ReadFile("test.json") - require.NoError(t, err) - - spec := types.NewOpenRPCSpec1() - err = json.Unmarshal(data, spec) - require.NoError(t, err) - - parse.GetTypes(spec, spec.Objects) - - data, err = ioutil.ReadFile("test.gotmpl") - require.NoError(t, err) - tmp, err := template.New("server").Funcs(funcMap(spec)).Parse(string(data)) - require.NoError(t, err) - - buf := new(bytes.Buffer) - err = tmp.Execute(buf, spec) - require.NoError(t, err) - - return buf.String() -} - -func TestGenerate(t *testing.T) { - - t.Run("Should be same at least once, in a while", func(t *testing.T) { - require.Equal(t, exp, tmpl(t)) - }) - - t.Skip("isaac gets fail here") - t.Run("Should be deterministic", func(t *testing.T) { - for i := 0; i < 20; i++ { - got := tmpl(t) - if exp == got { - t.Log("same same") - continue - } - t.Log("but different") - require.Equal(t, exp, got) - } - }) -} - -func TestMaybeComment(t *testing.T) { - require.Equal(t, "", maybeFieldComment("")) - require.Equal(t, "// hello, world", maybeFieldComment("hello, world")) -} diff --git a/openrpc/out/types.go b/openrpc/out/types.go index 6bb0777..da062d3 100644 --- a/openrpc/out/types.go +++ b/openrpc/out/types.go @@ -4,663 +4,382 @@ package main type GoOpenRPCService interface { // Returns an RLP-encoded header. - DebugGetRawHeader(*DebugGetRawHeaderParams) (*DebugGetRawHeaderResult, error) + DebugGetRawHeader( + Block BlockNumberOrTag, + ) (HeaderRLP Bytes) // Returns an RLP-encoded block. - DebugGetRawBlock(*DebugGetRawBlockParams) (*DebugGetRawBlockResult, error) + DebugGetRawBlock( + Block BlockNumberOrTag, + ) (BlockRLP Bytes) // Returns an array of EIP-2718 binary-encoded transactions. - DebugGetRawTransaction(*DebugGetRawTransactionParams) (*DebugGetRawTransactionResult, error) + DebugGetRawTransaction( + TransactionHash Hash32, + ) (EIP2718BinaryEncodedTransaction Bytes) // Returns an array of EIP-2718 binary-encoded receipts. - DebugGetRawReceipts(*DebugGetRawReceiptsParams) (*DebugGetRawReceiptsResult, error) + DebugGetRawReceipts( + Block BlockNumberOrTag, + ) (Receipts []Bytes) // Returns an array of recent bad blocks that the client has seen on the network. - DebugGetBadBlocks() (*DebugGetBadBlocksResult, error) + DebugGetBadBlocks() (Blocks []BadBlock) // Returns information about a block by hash. - EthGetBlockByHash(*EthGetBlockByHashParams) (*EthGetBlockByHashResult, error) + EthGetBlockByHash( + BlockHash Hash32, + HydratedTransactions bool, + ) (BlockInformation Block) // Returns information about a block by number. - EthGetBlockByNumber(*EthGetBlockByNumberParams) (*EthGetBlockByNumberResult, error) + EthGetBlockByNumber( + Block BlockNumberOrTag, + HydratedTransactions bool, + ) (BlockInformation Block) // Returns the number of transactions in a block from a block matching the given block hash. - EthGetBlockTransactionCountByHash(*EthGetBlockTransactionCountByHashParams) (*EthGetBlockTransactionCountByHashResult, error) + EthGetBlockTransactionCountByHash( + BlockHash Hash32, + ) (TransactionCount Uint) // Returns the number of transactions in a block matching the given block number. - EthGetBlockTransactionCountByNumber(*EthGetBlockTransactionCountByNumberParams) (*EthGetBlockTransactionCountByNumberResult, error) + EthGetBlockTransactionCountByNumber( + Block BlockNumberOrTag, + ) (TransactionCount Uint) // Returns the number of uncles in a block from a block matching the given block hash. - EthGetUncleCountByBlockHash(*EthGetUncleCountByBlockHashParams) (*EthGetUncleCountByBlockHashResult, error) + EthGetUncleCountByBlockHash( + BlockHash Hash32, + ) (UncleCount Uint) // Returns the number of transactions in a block matching the given block number. - EthGetUncleCountByBlockNumber(*EthGetUncleCountByBlockNumberParams) (*EthGetUncleCountByBlockNumberResult, error) + EthGetUncleCountByBlockNumber( + Block BlockNumberOrTag, + ) (UncleCount Uint) // Returns the chain ID of the current network. - EthChainId() (*EthChainIdResult, error) + EthChainId() (ChainID Uint) // Returns an object with data about the sync status or false. - EthSyncing() (*EthSyncingResult, error) + EthSyncing() (SyncingStatus SyncingStatus) // Returns the client coinbase address. - EthCoinbase() (*EthCoinbaseResult, error) + EthCoinbase() (CoinbaseAddress Address) // Returns a list of addresses owned by client. - EthAccounts() (*EthAccountsResult, error) + EthAccounts() (Accounts []Address) // Returns the number of most recent block. - EthBlockNumber() (*EthBlockNumberResult, error) + EthBlockNumber() (BlockNumber Uint) // Executes a new message call immediately without creating a transaction on the block chain. - EthCall(*EthCallParams) (*EthCallResult, error) + EthCall( + Transaction GenericTransaction, + Block BlockNumberOrTag, + ) (ReturnData Bytes) // Generates and returns an estimate of how much gas is necessary to allow the transaction to complete. - EthEstimateGas(*EthEstimateGasParams) (*EthEstimateGasResult, error) + EthEstimateGas( + Transaction GenericTransaction, + Block BlockNumberOrTag, + ) (GasUsed Uint) // Generates an access list for a transaction. - EthCreateAccessList(*EthCreateAccessListParams) (*EthCreateAccessListResult, error) + EthCreateAccessList( + Transaction GenericTransaction, + Block BlockNumberOrTag, + ) (GasUsed struct { + AccessList AccessList + Error string + GasUsed Uint + }) // Returns the current price per gas in wei. - EthGasPrice() (*EthGasPriceResult, error) + EthGasPrice() (GasPrice Uint) // Returns the current maxPriorityFeePerGas per gas in wei. - EthMaxPriorityFeePerGas() (*EthMaxPriorityFeePerGasResult, error) - // Returns transaction base fee per gas and effective priority fee per gas for the requested/supported block range. - EthFeeHistory(*EthFeeHistoryParams) (*EthFeeHistoryResult, error) + EthMaxPriorityFeePerGas() (MaxPriorityFeePerGas Uint) + // Transaction fee history + EthFeeHistory( + BlockCount Uint, + NewestBlock BlockNumberOrTag, + RewardPercentiles []float64, + ) (FeeHistoryResult struct { + BaseFeePerGas []Uint + OldestBlock Uint + Reward [][]Uint + }) // Creates a filter object, based on filter options, to notify when the state changes (logs). - EthNewFilter(*EthNewFilterParams) (*EthNewFilterResult, error) + EthNewFilter( + Filter Filter, + ) (FilterIdentifier Uint) // Creates a filter in the node, to notify when a new block arrives. - EthNewBlockFilter() (*EthNewBlockFilterResult, error) + EthNewBlockFilter() (FilterIdentifier Uint) // Creates a filter in the node, to notify when new pending transactions arrive. - EthNewPendingTransactionFilter() (*EthNewPendingTransactionFilterResult, error) + EthNewPendingTransactionFilter() (FilterIdentifier Uint) // Uninstalls a filter with given id. - EthUninstallFilter(*EthUninstallFilterParams) (*EthUninstallFilterResult, error) + EthUninstallFilter( + FilterIdentifier Uint, + ) (Success bool) // Polling method for a filter, which returns an array of logs which occurred since last poll. - EthGetFilterChanges(*EthGetFilterChangesParams) (*EthGetFilterChangesResult, error) + EthGetFilterChanges( + FilterIdentifier Uint, + ) (LogObjects FilterResults) // Returns an array of all logs matching filter with given id. - EthGetFilterLogs(*EthGetFilterLogsParams) (*EthGetFilterLogsResult, error) + EthGetFilterLogs( + FilterIdentifier Uint, + ) (LogObjects FilterResults) // Returns an array of all logs matching filter with given id. - EthGetLogs(*EthGetLogsParams) (*EthGetLogsResult, error) + EthGetLogs( + Filter Filter, + ) (LogObjects FilterResults) // Returns whether the client is actively mining new blocks. - EthMining() (*EthMiningResult, error) + EthMining() (MiningStatus bool) // Returns the number of hashes per second that the node is mining with. - EthHashrate() (*EthHashrateResult, error) + EthHashrate() (MiningStatus Uint) // Returns the hash of the current block, the seedHash, and the boundary condition to be met (“targetâ€). - EthGetWork() (*EthGetWorkResult, error) + EthGetWork() (CurrentWork []Bytes32) // Used for submitting a proof-of-work solution. - EthSubmitWork(*EthSubmitWorkParams) (*EthSubmitWorkResult, error) + EthSubmitWork( + Nonce Bytes8, + Hash Bytes32, + Digest Bytes32, + ) (Success bool) // Used for submitting mining hashrate. - EthSubmitHashrate(*EthSubmitHashrateParams) (*EthSubmitHashrateResult, error) + EthSubmitHashrate( + Hashrate Bytes32, + Id Bytes32, + ) (Success bool) // Returns an EIP-191 signature over the provided data. - EthSign(*EthSignParams) (*EthSignResult, error) + EthSign( + Address Address, + Message Bytes, + ) (Signature Bytes65) // Returns an RLP encoded transaction signed by the specified account. - EthSignTransaction(*EthSignTransactionParams) (*EthSignTransactionResult, error) + EthSignTransaction( + Transaction GenericTransaction, + ) (EncodedTransaction Bytes) // Returns the balance of the account of given address. - EthGetBalance(*EthGetBalanceParams) (*EthGetBalanceResult, error) + EthGetBalance( + Address Address, + Block BlockNumberOrTag, + ) (Balance Uint) // Returns the value from a storage position at a given address. - EthGetStorageAt(*EthGetStorageAtParams) (*EthGetStorageAtResult, error) + EthGetStorageAt( + Address Address, + StorageSlot Uint256, + Block BlockNumberOrTag, + ) (Value Bytes) // Returns the number of transactions sent from an address. - EthGetTransactionCount(*EthGetTransactionCountParams) (*EthGetTransactionCountResult, error) + EthGetTransactionCount( + Address Address, + Block BlockNumberOrTag, + ) (TransactionCount Uint) // Returns code at a given address. - EthGetCode(*EthGetCodeParams) (*EthGetCodeResult, error) + EthGetCode( + Address Address, + Block BlockNumberOrTag, + ) (Bytecode Bytes) // Returns the merkle proof for a given account and optionally some storage keys. - EthGetProof(*EthGetProofParams) (*EthGetProofResult, error) + EthGetProof( + Address Address, + StorageKeys []Hash32, + Block BlockNumberOrTag, + ) (Account AccountProof) // Signs and submits a transaction. - EthSendTransaction(*EthSendTransactionParams) (*EthSendTransactionResult, error) + EthSendTransaction( + Transaction GenericTransaction, + ) (TransactionHash Hash32) // Submits a raw transaction. - EthSendRawTransaction(*EthSendRawTransactionParams) (*EthSendRawTransactionResult, error) + EthSendRawTransaction( + Transaction Bytes, + ) (TransactionHash Hash32) // Returns the information about a transaction requested by transaction hash. - EthGetTransactionByHash(*EthGetTransactionByHashParams) (*EthGetTransactionByHashResult, error) + EthGetTransactionByHash( + TransactionHash Hash32, + ) (TransactionInformation TransactionInfo) // Returns information about a transaction by block hash and transaction index position. - EthGetTransactionByBlockHashAndIndex(*EthGetTransactionByBlockHashAndIndexParams) (*EthGetTransactionByBlockHashAndIndexResult, error) + EthGetTransactionByBlockHashAndIndex( + BlockHash Hash32, + TransactionIndex Uint, + ) (TransactionInformation TransactionInfo) // Returns information about a transaction by block number and transaction index position. - EthGetTransactionByBlockNumberAndIndex(*EthGetTransactionByBlockNumberAndIndexParams) (*EthGetTransactionByBlockNumberAndIndexResult, error) + EthGetTransactionByBlockNumberAndIndex( + Block BlockNumberOrTag, + TransactionIndex Uint, + ) (TransactionInformation TransactionInfo) // Returns the receipt of a transaction by transaction hash. - EthGetTransactionReceipt(*EthGetTransactionReceiptParams) (*EthGetTransactionReceiptResult, error) + EthGetTransactionReceipt( + TransactionHash Hash32, + ) (ReceiptInformation ReceiptInfo) } -type BlockNumberOrTag struct { - FieldUint string `json:"uint"` -} -type DebugGetRawHeaderParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type DebugGetRawHeaderResult struct { - FieldBytes string `json:"bytes"` -} -type DebugGetRawBlockParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type DebugGetRawBlockResult struct { - FieldBytes string `json:"bytes"` -} -type DebugGetRawTransactionParams struct { - FieldHash32 string `json:"hash32"` +type AccessList []AccessListEntry +type AccessListEntry struct { + Address Address + StorageKeys []Hash32 } -type DebugGetRawTransactionResult struct { - FieldBytes string `json:"bytes"` -} -type DebugGetRawReceiptsParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type ReceiptArray struct { - FieldBytes string `json:"bytes"` -} -type DebugGetRawReceiptsResult struct { - FieldBytes string `json:"bytes"` - - FieldReceiptArray []string `json:"receiptArray"` +type AccountProof struct { + AccountProof []Bytes + Address Address + Balance Uint256 + CodeHash Hash32 + Nonce Uint64 + StorageHash Hash32 + StorageProof []StorageProof +} +type BadBlock struct { + Block Bytes + Hash Hash32 + Rlp Bytes } type Block struct { - FieldBytes string `json:"bytes"` -} -type Hash struct { - FieldHash32 string `json:"hash32"` -} -type Rlp struct { - FieldBytes string `json:"bytes"` -} -type BadBlockArray struct { - BadBlock -} -type DebugGetBadBlocksResult struct { - BadBlock - - FieldBadBlockArray []BadBlock `json:"badBlockArray"` -} -type EthGetBlockByHashParams struct { - FieldHash32 string `json:"hash32"` - - FieldHydrated bool `json:"hydrated"` -} -type StateRoot struct { - FieldHash32 string `json:"hash32"` -} -type TransactionsRoot struct { - FieldHash32 string `json:"hash32"` -} -type GasLimit struct { - FieldUint string `json:"uint"` -} -type MixHash struct { - FieldHash32 string `json:"hash32"` -} -type Nonce struct { - FieldBytes8 string `json:"bytes8"` - - FieldUint string `json:"uint"` - - FieldUint64 string `json:"uint64"` -} -type Number struct { - FieldUint string `json:"uint"` -} -type Size struct { - FieldUint string `json:"uint"` -} -type Difficulty struct { - FieldBytes string `json:"bytes"` -} -type ExtraData struct { - FieldBytes string `json:"bytes"` -} -type LogsBloom struct { - FieldBytes256 string `json:"bytes256"` -} -type Sha3Uncles struct { - FieldHash32 string `json:"hash32"` -} -type Timestamp struct { - FieldUint string `json:"uint"` -} -type BaseFeePerGas struct { - // An array of block base fees per gas. This includes the next block after the newest of the returned range, because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks. - FieldUint string `json:"uint"` - // An array of block base fees per gas. This includes the next block after the newest of the returned range, because this value can be derived from the newest block. Zeroes are returned for pre-EIP-1559 blocks. - FieldBaseFeePerGas []string `json:"baseFeePerGas"` -} -type GasUsed struct { - // The amount of gas used for this specific transaction alone. - FieldUint string `json:"uint"` -} -type Miner struct { - FieldAddress string `json:"address"` -} -type Uncles struct { - FieldHash32 string `json:"hash32"` - - FieldUncles []string `json:"uncles"` -} -type ParentHash struct { - FieldHash32 string `json:"hash32"` -} -type ReceiptsRoot struct { - FieldHash32 string `json:"hash32"` -} -type TotalDifficulty struct { - FieldUint string `json:"uint"` -} -type EthGetBlockByHashResult struct { - BlockObject -} -type EthGetBlockByNumberParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` - - FieldHydrated bool `json:"hydrated"` -} -type EthGetBlockByNumberResult struct { - BlockObject -} -type EthGetBlockTransactionCountByHashParams struct { - FieldHash32 string `json:"hash32"` -} -type EthGetBlockTransactionCountByHashResult struct { - FieldUint string `json:"uint"` -} -type EthGetBlockTransactionCountByNumberParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetBlockTransactionCountByNumberResult struct { - FieldUint string `json:"uint"` -} -type EthGetUncleCountByBlockHashParams struct { - FieldHash32 string `json:"hash32"` -} -type EthGetUncleCountByBlockHashResult struct { - FieldUint string `json:"uint"` -} -type EthGetUncleCountByBlockNumberParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetUncleCountByBlockNumberResult struct { - FieldUint string `json:"uint"` -} -type EthChainIdResult struct { - FieldUint string `json:"uint"` -} -type CurrentBlock struct { - FieldUint string `json:"uint"` -} -type HighestBlock struct { - FieldUint string `json:"uint"` -} -type StartingBlock struct { - FieldUint string `json:"uint"` -} -type SyncingStatus struct { - SyncingProgress -} -type EthSyncingResult struct { - FieldSyncingStatus SyncingProgress `json:"syncingStatus"` -} -type EthCoinbaseResult struct { - FieldAddress string `json:"address"` -} -type Accounts struct { - FieldAddress string `json:"address"` -} -type EthAccountsResult struct { - FieldAddress string `json:"address"` - - FieldAccounts []string `json:"accounts"` -} -type EthBlockNumberResult struct { - FieldUint string `json:"uint"` -} -type Address struct { - FieldAddress string `json:"address"` -} -type StorageKeys struct { - FieldHash32 string `json:"hash32"` - - FieldStorageKeys []string `json:"storageKeys"` -} -type AccessList struct { - // EIP-2930 access list - AccessListEntry - // EIP-2930 access list - FieldAccessList []AccessListEntry `json:"accessList"` -} -type MaxFeePerGas struct { - // The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei - FieldUint string `json:"uint"` -} -type Type struct { - FieldByte string `json:"byte"` -} -type To struct { - // Address of the receiver or null in a contract creation transaction. - FieldAddress string `json:"address"` -} -type ChainId struct { - // Chain ID that this transaction is valid on. - FieldUint string `json:"uint"` -} -type From struct { - FieldAddress string `json:"address"` -} -type Gas struct { - FieldUint string `json:"uint"` -} -type GasPrice struct { - // The gas price willing to be paid by the sender in wei - FieldUint string `json:"uint"` -} -type Input struct { - FieldBytes string `json:"bytes"` -} -type MaxPriorityFeePerGas struct { - // Maximum fee per gas the sender is willing to pay to miners in wei - FieldUint string `json:"uint"` -} -type Value struct { - FieldUint string `json:"uint"` - - FieldUint256 string `json:"uint256"` -} -type EthCallParams struct { - TransactionObjectGenericToAllTypes - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthCallResult struct { - FieldBytes string `json:"bytes"` -} -type EthEstimateGasParams struct { - TransactionObjectGenericToAllTypes - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthEstimateGasResult struct { - FieldUint string `json:"uint"` -} -type EthCreateAccessListParams struct { - TransactionObjectGenericToAllTypes - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type Error struct { - FieldError string `json:"error"` -} -type EthCreateAccessListResult struct { - AccessListResult -} -type EthGasPriceResult struct { - FieldUint string `json:"uint"` -} -type EthMaxPriorityFeePerGasResult struct { - FieldUint string `json:"uint"` -} -type EthFeeHistoryParams struct { - // Requested range of blocks. Clients will return less than the requested range if not all blocks are available. - FieldUint string `json:"uint"` - // Highest block of the requested range. - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` - // Floating point value between 0 and 100. - FieldRewardPercentile float64 `json:"rewardPercentile"` - // A monotonically increasing list of percentile values. For each block in the requested range, the transactions will be sorted in ascending order by effective tip per gas and the coresponding effective tip for the percentile will be determined, accounting for gas consumed. - FieldRewardPercentiles []float64 `json:"rewardPercentiles"` -} -type RewardPercentiles struct { - // Floating point value between 0 and 100. - FieldRewardPercentile float64 `json:"rewardPercentile"` -} -type OldestBlock struct { - // Lowest number block of returned range. - FieldUint string `json:"uint"` + BaseFeePerGas Uint + Difficulty Bytes + ExtraData Bytes + GasLimit Uint + GasUsed Uint + LogsBloom Bytes256 + Miner Address + MixHash Hash32 + Nonce Bytes8 + Number Uint + ParentHash Hash32 + ReceiptsRoot Hash32 + Sha3Uncles Hash32 + Size Uint + StateRoot Hash32 + Timestamp Uint + TotalDifficulty Uint + Transactions struct { + Option0 []Hash32 + Option1 []TransactionSigned + } + TransactionsRoot Hash32 + Uncles []Hash32 } -type RewardPercentile struct { - // A given percentile sample of effective priority fees per gas from a single block in ascending order, weighted by gas used. Zeroes are returned if the block is empty. - FieldUint string `json:"uint"` -} -type Reward struct { - // A given percentile sample of effective priority fees per gas from a single block in ascending order, weighted by gas used. Zeroes are returned if the block is empty. - FieldUint string `json:"uint"` - // An array of effective priority fee per gas data points from a single block. All zeroes are returned if the block is empty. - FieldRewardPercentile []string `json:"rewardPercentile"` - // A two-dimensional array of effective priority fees per gas at the requested block percentiles. - FieldReward []array `json:"reward"` -} -type EthFeeHistoryResult struct { - // Fee history results. - FeeHistoryResults -} -type FromBlock struct { - FieldUint string `json:"uint"` -} -type ToBlock struct { - FieldUint string `json:"uint"` -} -type FilterTopicListEntry struct { - FieldAnyTopicMatch null `json:"anyTopicMatch"` -} -type FilterTopics struct { - FieldFilterTopicListEntry null `json:"filterTopicListEntry"` -} -type Topics struct { - FieldFilterTopicListEntry null `json:"filterTopicListEntry"` - - FieldFilterTopics []FilterTopicListEntry `json:"filterTopics"` - - FieldBytes32 string `json:"bytes32"` - - FieldTopics []string `json:"topics"` -} -type EthNewFilterParams struct { - Filter -} -type EthNewFilterResult struct { - FieldUint string `json:"uint"` -} -type EthNewBlockFilterResult struct { - FieldUint string `json:"uint"` -} -type EthNewPendingTransactionFilterResult struct { - FieldUint string `json:"uint"` -} -type EthUninstallFilterParams struct { - FieldUint string `json:"uint"` -} -type EthUninstallFilterResult struct { - FieldSuccess bool `json:"success"` -} -type EthGetFilterChangesParams struct { - FieldUint string `json:"uint"` -} -type NewBlockHashes struct { - FieldHash32 string `json:"hash32"` +type BlockNumberOrTag struct { + Option0 Uint + Option1 BlockTag +} +type BlockTag string +type Filter struct { + Address struct { + Option0 Address + Option1 Addresses + } + FromBlock Uint + ToBlock Uint + Topics FilterTopics } type FilterResults struct { - FieldHash32 string `json:"hash32"` - - FieldNewBlockHashes []string `json:"newBlockHashes"` -} -type EthGetFilterChangesResult struct { - FieldFilterResults array `json:"filterResults"` -} -type EthGetFilterLogsParams struct { - FieldUint string `json:"uint"` -} -type EthGetFilterLogsResult struct { - FieldFilterResults array `json:"filterResults"` -} -type EthGetLogsParams struct { - Filter -} -type EthGetLogsResult struct { - FieldFilterResults array `json:"filterResults"` -} -type EthMiningResult struct { - FieldMiningStatus bool `json:"miningStatus"` -} -type EthHashrateResult struct { - FieldUint string `json:"uint"` -} -type EthGetWorkResult struct { - FieldCurrentWork []string `json:"currentWork"` -} -type EthSubmitWorkParams struct { - FieldBytes8 string `json:"bytes8"` - - FieldBytes32 string `json:"bytes32"` -} -type EthSubmitWorkResult struct { - FieldSuccess bool `json:"success"` -} -type EthSubmitHashrateParams struct { - FieldBytes32 string `json:"bytes32"` -} -type EthSubmitHashrateResult struct { - FieldSuccess bool `json:"success"` -} -type EthSignParams struct { - FieldAddress string `json:"address"` - - FieldBytes string `json:"bytes"` -} -type EthSignResult struct { - FieldBytes645 string `json:"bytes645"` -} -type EthSignTransactionParams struct { - TransactionObjectGenericToAllTypes -} -type EthSignTransactionResult struct { - FieldBytes string `json:"bytes"` -} -type EthGetBalanceParams struct { - FieldAddress string `json:"address"` - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetBalanceResult struct { - FieldUint string `json:"uint"` -} -type EthGetStorageAtParams struct { - FieldAddress string `json:"address"` - - FieldUint256 string `json:"uint256"` - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetStorageAtResult struct { - FieldBytes string `json:"bytes"` -} -type EthGetTransactionCountParams struct { - FieldAddress string `json:"address"` - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetTransactionCountResult struct { - FieldUint string `json:"uint"` -} -type EthGetCodeParams struct { - FieldAddress string `json:"address"` - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type EthGetCodeResult struct { - FieldBytes string `json:"bytes"` -} -type EthGetProofParams struct { - FieldAddress string `json:"address"` - - FieldHash32 string `json:"hash32"` - - FieldStorageKeys []string `json:"storageKeys"` - - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` -} -type AccountProof struct { - FieldBytes string `json:"bytes"` - - FieldAccountProof []string `json:"accountProof"` -} -type Balance struct { - FieldUint256 string `json:"uint256"` -} -type CodeHash struct { - FieldHash32 string `json:"hash32"` -} -type StorageHash struct { - FieldHash32 string `json:"hash32"` -} -type Key struct { - FieldHash32 string `json:"hash32"` -} -type Proof struct { - FieldBytes string `json:"bytes"` - - FieldProof []string `json:"proof"` + Option0 []Hash32 + Option1 []Hash32 + Option2 []Log +} +type FilterTopic struct { + Option0 struct{} + Option1 Bytes32 + Option2 []Bytes32 +} +type FilterTopics []FilterTopic +type GenericTransaction struct { + AccessList AccessList + ChainId Uint + From Address + Gas Uint + GasPrice Uint + Input Bytes + MaxFeePerGas Uint + MaxPriorityFeePerGas Uint + Nonce Uint + To Address + Type Byte + Value Uint +} +type Log struct { + Address Address + BlockHash Hash32 + BlockNumber Uint + Data Bytes + LogIndex Uint + Removed bool + Topics []Bytes32 + TransactionHash Hash32 + TransactionIndex Uint +} +type ReceiptInfo struct { + BlockHash Hash32 + BlockNumber Uint + ContractAddress struct { + Option0 Address + Option1 struct{} + } + CumulativeGasUsed Uint + EffectiveGasPrice Uint + From Address + GasUsed Uint + Logs []Log + LogsBloom Bytes256 + Root Bytes32 + Status Uint + To Address + TransactionHash Hash32 + TransactionIndex Uint } type StorageProof struct { - FieldStorageProof []StorageProof `json:"storageProof"` -} -type EthGetProofResult struct { - AccountProof -} -type EthSendTransactionParams struct { - TransactionObjectGenericToAllTypes -} -type EthSendTransactionResult struct { - FieldHash32 string `json:"hash32"` -} -type EthSendRawTransactionParams struct { - FieldBytes string `json:"bytes"` -} -type EthSendRawTransactionResult struct { - FieldHash32 string `json:"hash32"` -} -type EthGetTransactionByHashParams struct { - FieldHash32 string `json:"hash32"` -} -type EthGetTransactionByHashResult struct { - FieldTransactionInformation object `json:"transactionInformation"` -} -type EthGetTransactionByBlockHashAndIndexParams struct { - FieldHash32 string `json:"hash32"` - - FieldUint string `json:"uint"` -} -type EthGetTransactionByBlockHashAndIndexResult struct { - FieldTransactionInformation object `json:"transactionInformation"` -} -type EthGetTransactionByBlockNumberAndIndexParams struct { - FieldBlockNumberOrTag string `json:"blockNumberOrTag"` - - FieldUint string `json:"uint"` -} -type EthGetTransactionByBlockNumberAndIndexResult struct { - FieldTransactionInformation object `json:"transactionInformation"` -} -type EthGetTransactionReceiptParams struct { - FieldHash32 string `json:"hash32"` -} -type EffectiveGasPrice struct { - // The actual value per gas deducted from the senders account. Before EIP-1559, this is equal to the transaction's gas price. After, it is equal to baseFeePerGas + min(maxFeePerGas - baseFeePerGas, maxPriorityFeePerGas). - FieldUint string `json:"uint"` -} -type Status struct { - // Either 1 (success) or 0 (failure). Only specified for transactions included after the Byzantium upgrade. - FieldUint string `json:"uint"` -} -type BlockNumber struct { - FieldUint string `json:"uint"` -} -type ContractAddress struct { - FieldAddress string `json:"address"` - // The contract address created, if the transaction was a contract creation, otherwise null. - FieldContractAddress string `json:"contractAddress"` -} -type BlockHash struct { - FieldHash32 string `json:"hash32"` -} -type CumulativeGasUsed struct { - // The sum of gas used by this transaction and all preceding transactions in the same block. - FieldUint string `json:"uint"` -} -type Root struct { - // The post-transaction state root. Only specified for transactions included before the Byzantium upgrade. - FieldBytes32 string `json:"bytes32"` -} -type TransactionHash struct { - FieldHash32 string `json:"hash32"` -} -type TransactionIndex struct { - FieldUint string `json:"uint"` -} -type Data struct { - FieldBytes string `json:"bytes"` -} -type LogIndex struct { - FieldUint string `json:"uint"` -} -type Removed struct { - FieldRemoved bool `json:"removed"` -} -type Logs struct { - Log - - FieldLogs []Log `json:"logs"` -} -type EthGetTransactionReceiptResult struct { - ReceiptInfo + Key Hash32 + Proof []Bytes + Value Uint256 } +type SyncingStatus struct { + Option0 struct { + CurrentBlock Uint + HighestBlock Uint + StartingBlock Uint + } + Option1 bool +} +type Transaction1559Signed struct { +} +type Transaction1559Unsigned struct { + AccessList AccessList + ChainId Uint + Gas Uint + Input Bytes + MaxFeePerGas Uint + MaxPriorityFeePerGas Uint + Nonce Uint + To Address + Type Byte + Value Uint +} +type Transaction2930Signed struct { +} +type Transaction2930Unsigned struct { + AccessList AccessList + ChainId Uint + Gas Uint + GasPrice Uint + Input Bytes + Nonce Uint + To Address + Type Byte + Value Uint +} +type TransactionInfo struct { +} +type TransactionLegacySigned struct { +} +type TransactionLegacyUnsigned struct { + ChainId Uint + Gas Uint + GasPrice Uint + Input Bytes + Nonce Uint + To Address + Type Byte + Value Uint +} +type TransactionSigned struct { + Option0 Transaction1559Signed + Option1 Transaction2930Signed + Option2 TransactionLegacySigned +} +type TransactionUnsigned struct { + Option0 Transaction1559Unsigned + Option1 Transaction2930Unsigned + Option2 TransactionLegacyUnsigned +} +type Address string +type Addresses []Address +type Byte string +type Bytes string +type Bytes256 string +type Bytes32 string +type Bytes65 string +type Bytes8 string +type Hash32 string +type Uint string +type Uint256 string +type Uint64 string diff --git a/openrpc/parse/parse.go b/openrpc/parse/parse.go index 5f43a25..fe2554d 100644 --- a/openrpc/parse/parse.go +++ b/openrpc/parse/parse.go @@ -1,122 +1 @@ package parse - -import ( - "fmt" - "path" - "reflect" - - "gfx.cafe/open/jrpc/openrpc/types" - "gfx.cafe/open/jrpc/openrpc/util" - "github.com/go-openapi/spec" -) - -const ( - params = "Params" - result = "Result" -) - -func persistTitleAndDesc(prev, next spec.Schema) spec.Schema { - next.Title = util.FirstOf(next.Title, prev.Title) - next.Description = util.FirstOf(next.Description, prev.Description) - return next -} - -func persistFields(prev, next spec.Schema) spec.Schema { - next.Title = util.FirstOf(next.Title, prev.Title, path.Base(prev.Ref.String())) - next.Description = util.FirstOf(next.Description, prev.Description) - if next.Items == nil { - next.Items = prev.Items - } - return next -} - -func resolveSchema(openrpc *types.OpenRPCSpec1, sch spec.Schema) spec.Schema { - pt := sch.Ref.GetPointer() - doc, _, _ := pt.Get(openrpc) - if s, ok := doc.(spec.Schema); ok { - sch = persistFields(sch, s) - } else if cd, ok := doc.(*types.ContentDescriptor); ok { - sch = persistFields(sch, cd.Schema) - } - - if sch.Ref.GetURL() != nil { - return resolveSchema(openrpc, sch) - } - return sch -} - -func getConcreteType(in string) string { - switch in { - case reflect.Bool.String(), "boolean": - return reflect.Bool.String() - case "number": - return "float64" - default: - return in - } -} - -func getObjectType(openrpc *types.OpenRPCSpec1, sch spec.Schema) string { - sch = resolveSchema(openrpc, sch) - - if len(sch.Properties) > 0 || len(sch.Type) < 1 { - return util.CamelCase(sch.Title) - } - - return getConcreteType(sch.Type[0]) -} - -func dereference(openrpc *types.OpenRPCSpec1, name string, sch spec.Schema, om *types.ObjectMap) { - // resolve all pointers - sch = resolveSchema(openrpc, sch) - - if len(sch.Properties) > 0 { - for key, value := range sch.Properties { - value.Title = key - dereference(openrpc, key, value, om) - } - om.Set(name, types.BasicType{ - Desc: sch.Description, Name: sch.Title, Type: util.CamelCase(sch.Title)}) - return - } else if len(sch.OneOf) > 0 { - next := sch.OneOf[0] - dereference(openrpc, sch.Title, next, om) - om.Set(name, types.BasicType{Desc: sch.Description, Name: sch.Title, Type: getObjectType(openrpc, resolveSchema(openrpc, next))}) - return - } else if sch.Items != nil { - if sch.Items.Schema != nil { - dereference(openrpc, sch.Title, *sch.Items.Schema, om) - dereference(openrpc, name, persistTitleAndDesc(sch, *sch.Items.Schema), om) - om.Set(name, types.BasicType{Desc: sch.Description, Name: sch.Title, Type: fmt.Sprintf("[]%s", getObjectType(openrpc, persistTitleAndDesc(sch, *sch.Items.Schema)))}) - } else if len(sch.Items.Schemas) > 0 { - om.Set(name, types.BasicType{Desc: sch.Description, Name: sch.Title, Type: "[]string"}) - } - return - } - if len(sch.Type) == 0 { - return - } - om.Set(name, types.BasicType{Desc: sch.Description, Name: sch.Title, Type: getConcreteType(sch.Type[0])}) - return -} - -// GetTypes constructs all possible type definitions from the spec -func GetTypes(openrpc *types.OpenRPCSpec1, om *types.ObjectMap) { - for _, m := range openrpc.Methods { - name := fmt.Sprintf("%s%s", util.CamelCase(m.Name), params) - for _, param := range m.Params { - sch := param.Schema - sch.Title = util.FirstOf(sch.Title, param.Name) - sch.Description = util.FirstOf(sch.Description, param.Description) - dereference(openrpc, name, sch, om) - } - if m.Result != nil { - name = fmt.Sprintf("%s%s", util.CamelCase(m.Name), result) - res := m.Result - sch := res.Schema - sch.Title = util.FirstOf(sch.Title, res.Name) - sch.Description = util.FirstOf(sch.Description, res.Description) - dereference(openrpc, name, sch, om) - } - } -} diff --git a/openrpc/parse/parse_test.go b/openrpc/parse/parse_test.go deleted file mode 100644 index 6326ec1..0000000 --- a/openrpc/parse/parse_test.go +++ /dev/null @@ -1,73 +0,0 @@ -package parse - -import ( - "encoding/json" - "io/ioutil" - "testing" - - "gfx.cafe/open/jrpc/openrpc/types" - "github.com/test-go/testify/require" -) - -func TestParse(t *testing.T) { - data, err := ioutil.ReadFile("testdata/eth_openrpc.json") - require.NoError(t, err) - spec := types.NewOpenRPCSpec1() - err = json.Unmarshal(data, spec) - require.NoError(t, err) - GetTypes(spec, spec.Objects) - - result := spec.Objects.Get("GetBlockByHashResult") - require.NotNil(t, result) - require.Len(t, result.GetKeys(), 1) - - result = spec.Objects.Get("EthBlockNumberResult") - require.NotNil(t, result) - require.Len(t, result.GetKeys(), 1) - - result = spec.Objects.Get("BlockNumber") - require.NotNil(t, result) - require.Len(t, result.GetKeys(), 1) - - result = spec.Objects.Get("EthAccountsResult") - require.NotNil(t, result) - bt := result.Get("Addresses") - require.Equal(t, "Addresses", bt.Name) - require.Equal(t, "[]string", bt.Type) - - result = spec.Objects.Get("EthGetTransactionReceiptResult") - require.NotNil(t, result) - bt = result.Get("Receipt") - require.Equal(t, "Receipt", bt.Name) - require.Equal(t, "Receipt", bt.Type) - - result = spec.Objects.Get("EthSyncingResult") - require.NotNil(t, result) - bt = result.Get("Syncing") - require.Equal(t, "Syncing", bt.Name) - require.Equal(t, "SyncStatus", bt.Type) - - result = spec.Objects.Get("EthGetTransactionByHashResult") - require.NotNil(t, result) - bt = result.Get("Transaction") - require.Equal(t, "Transaction", bt.Name) - - result = spec.Objects.Get("Transaction") - require.NotNil(t, result) - bt = result.Get("BlockHash") - require.Equal(t, "BlockHash", bt.Name) -} - -func TestParseMulti(t *testing.T) { - sp := types.NewOpenRPCSpec1() - var err error - err = sp.AddSchemas("./testdata/execution-api/schemas") - require.NoError(t, err) - err = sp.AddMethods("./testdata/execution-api/eth") - require.NoError(t, err) - err = sp.AddMethods("./testdata/execution-api/engine") - require.NoError(t, err) - err = sp.AddMethods("./testdata/execution-api/debug") - require.NoError(t, err) - // TODO: finish this test -} diff --git a/openrpc/parse/parsing.go b/openrpc/parse/parsing.go deleted file mode 100644 index 1b26d9e..0000000 --- a/openrpc/parse/parsing.go +++ /dev/null @@ -1,102 +0,0 @@ -package parse - -import ( - "strings" - - "gfx.cafe/open/jrpc/openrpc/types" - "gfx.cafe/open/jrpc/openrpc/util" - "github.com/go-openapi/spec" -) - -type GoGlobal struct { - Structs map[string]*GoStruct - Types map[string]*GoType - Methods map[string]*GoMethod -} - -type GoStruct struct { - Name string - Description string - - Fields map[string]string -} -type GoField struct { - Name string - Type *GoType - Optional bool - - Description string -} - -type GoType struct { - Name string - Type string - - Description string -} - -type GoMethod struct { - Input string - Output string - Name string -} - -func (g *GoGlobal) ReadOpenRPC(s types.OpenRPCSpec1) { - for k, v := range s.Components.Schemas { - g.AddSchema(k, v) - } - for _, v := range s.Methods { - g.AddMethod(v.Name, v) - } -} - -func (g *GoGlobal) AddSchema(name string, m spec.Schema) { - if len(m.Type) > 0 { - switch m.Type[0] { - case "string": - case "number": - case "boolean": - case "object": - case "array": - default: - } - return - } - if len(m.OneOf) > 0 { - //todo: handle - return - } -} - -func (g *GoGlobal) AddMethod(name string, m types.Method) { - inStruct := "Params" + util.CamelCase(name) - outStruct := "" - if m.Result != nil { - outStruct = "Result" + util.CamelCase(name) - } - g.Methods[name] = &GoMethod{ - Input: inStruct, - Output: outStruct, - Name: util.CamelCase(name), - } -} - -func (g *GoGlobal) AddStruct(name string, m spec.Schema) { - s := &GoStruct{} - g.Structs[name] = s - s.Name = name - s.Description = m.Description - s.Fields = map[string]string{} - for k, v := range m.Properties { - g.AddSchema(k, v) - if ref := v.Ref.GetPointer(); ref != nil { - refstr := strings.ToTitle(ref.String()) - s.Fields[k] = refstr - } else { - if len(v.Type) > 0 { - refstr := v.Type[0] - s.Fields[k] = refstr - } - } - } -} diff --git a/openrpc/templates/types.gotmpl b/openrpc/templates/types.gotmpl index 045e28d..69370af 100644 --- a/openrpc/templates/types.gotmpl +++ b/openrpc/templates/types.gotmpl @@ -2,34 +2,54 @@ package main +{{define "schemaType" -}} + {{if not (eq .Ref "") -}} + {{camelCase (refName .Ref)}} + {{- else if eq .Type "object" -}} + struct { + {{range $name, $property := .Properties -}} + {{camelCase $name}} {{template "schemaType" $property}} + {{end -}} + } + {{- else if eq .Type "array" -}} + []{{template "schemaType" (index .Items 0)}} + {{- else if not (eq (len .OneOf) 0) -}} + struct{ + {{range $idx, $v := .OneOf -}} + Option{{$idx}} {{template "schemaType" $v}} + {{end -}} + } + {{- else if not (eq (len .AnyOf) 0) -}} + struct{ + {{range $idx, $v := .AnyOf -}} + Option{{$idx}} {{template "schemaType" $v}} + {{end -}} + } + {{- else if not (eq (len .AllOf) 0) -}} + struct{ + {{range $idx, $v := .AllOf -}} + Field{{$idx}} {{template "schemaType" $v}} + {{end -}} + } + {{- else if not (eq (len .Enum) 0) -}} + string + {{- else -}} + {{goType .Type}} + {{- end}} +{{- end -}} + type GoOpenRPCService interface { - {{- range .Methods }} - {{- $name := .Name | camelCase }} - {{- $params := (maybeMethodParams .) }} - {{- $result := (maybeMethodResult .) }} - {{ maybeMethodComment . }} - {{$name}} - {{- if $params -}} - (*{{$params}}) - {{- else -}} - () - {{- end }} - {{- if $result }} (*{{$result}}, error) - {{- else }} error - {{- end }} - {{- end }} + {{range .Methods -}} + // {{.Summary}} + {{camelCase .Name}}( + {{range .Params -}} + {{camelCase .Name}} {{template "schemaType" .Schema}}, + {{end -}} + ) ({{camelCase .Result.Name}} {{template "schemaType" .Result.Schema}}) + {{end -}} } -{{- range (getObjects .Objects) }} -type {{.Name}} struct { - {{- range (getFields .Fields) }} - {{ maybeFieldComment .Desc }} - {{- if (eq .Name .Type) }} - {{ .Name }} - {{- else }} - Field{{camelCase .Name}} {{.Type}} `json:"{{lowerFirst .Name}}"` - {{- end }} - {{- end }} -} +{{- range $name, $component := .Components.Schemas }} + type {{camelCase $name}} {{template "schemaType" $component}} {{- end }} diff --git a/openrpc/types/objects.go b/openrpc/types/objects.go deleted file mode 100644 index 0400292..0000000 --- a/openrpc/types/objects.go +++ /dev/null @@ -1,79 +0,0 @@ -package types - -import "gfx.cafe/open/jrpc/openrpc/util" - -type BasicType struct { - Desc string - Name string - Type string -} - -type FieldMap struct { - fields map[string]BasicType - keys []string -} - -func NewFieldMap() *FieldMap { - return &FieldMap{ - fields: make(map[string]BasicType, 0), - keys: make([]string, 0), - } -} - -func (fm *FieldMap) Set(key string, value BasicType) { - key = util.CamelCase(key) - value.Name = util.CamelCase(value.Name) - _, exists := fm.fields[key] - fm.fields[key] = value - if !exists { - fm.keys = append(fm.keys, key) - } -} - -func (fm *FieldMap) Get(key string) BasicType { - a := fm.fields[key] - return a -} - -func (fm *FieldMap) GetKeys() []string { - return fm.keys -} - -type ObjectMap struct { - objects map[string]*FieldMap - keys []string -} - -func NewObjectMap() *ObjectMap { - return &ObjectMap{ - objects: make(map[string]*FieldMap, 0), - keys: make([]string, 0), - } -} - -func (om *ObjectMap) Set(key string, value BasicType) { - if key == "" { - return - } else if value.Name == "" { - return - } else if util.CamelCase(key) == value.Type { - return - } - key = util.CamelCase(key) - _, exists := om.objects[key] - if !exists { - if om.objects[key] == nil { - om.objects[key] = NewFieldMap() - } - om.keys = append(om.keys, key) - } - om.objects[key].Set(value.Name, value) -} - -func (om *ObjectMap) Get(key string) *FieldMap { - return om.objects[key] -} - -func (om *ObjectMap) GetKeys() []string { - return om.keys -} diff --git a/openrpc/types/types.go b/openrpc/types/types.go index 9227c79..f8461de 100644 --- a/openrpc/types/types.go +++ b/openrpc/types/types.go @@ -2,264 +2,70 @@ package types import ( "encoding/json" - "os" - "path" - "path/filepath" - - "github.com/go-openapi/spec" - "sigs.k8s.io/yaml" + "fmt" ) -type Contact struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` - Email string `json:"email,omitempty"` -} - -type License struct { - Name string `json:"name,omitempty"` - URL string `json:"url,omitempty"` -} - type Info struct { - Title string `json:"title"` - Description string `json:"description,omitempty"` - TermsOfService string `json:"termsOfService,omitempty"` - Contact *Contact `json:"contact,omitempty"` - License *License `json:"license,omitempty"` - Version string `json:"version"` -} - -type ServerVariable struct { - Enum []string `json:"enum,omitempty"` - Default string `json:"default,omitempty"` - Description string `json:"description,omitempty"` -} - -type Server struct { - Name string `json:"name"` - URL string `json:"url"` - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - Variables map[string]ServerVariable `json:"variables,omitempty"` -} - -type ExternalDocs struct { - Description string `json:"description,omitempty"` - URL string `json:"url,omitempty"` -} - -type Tag struct { - Name string `json:"name"` - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"` -} - -type Content struct { - Name string `json:"name"` - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - Required bool `json:"required,omitempty"` - Deprecated bool `json:"deprecated,omitempty"` - Schema spec.Schema `json:"schema"` + Title string `json:"title"` + Version string `json:"version"` } -type ContentDescriptor struct { - Content -} - -func (cd *ContentDescriptor) UnmarshalJSON(data []byte) error { - cont := new(Content) - err := json.Unmarshal(data, cont) - if err != nil { - return err - } - cd.Content = *cont - - params := make(map[string]interface{}) - err = json.Unmarshal(data, ¶ms) - if err != nil { - return err - } +type Items []Schema - if _, ok := params["$ref"]; ok { - sch := new(spec.Schema) - err = json.Unmarshal(data, sch) - if err != nil { - return err +func (I *Items) UnmarshalJSON(b []byte) error { + switch b[0] { + case '{': + *I = []Schema{ + {}, } - cd.Schema = *sch + return json.Unmarshal(b, &(*I)[0]) + case '[': + return json.Unmarshal(b, (*[]Schema)(I)) + default: + return fmt.Errorf("expected array or object") } - return nil - } -// https://www.jsonrpc.org/specification#error_object -type Error struct { - Code int `json:"code"` - Message string `json:"message"` - Data interface{} `json:"data"` -} +var _ json.Unmarshaler = (*Items)(nil) -type Link struct { - Name string `json:"name"` - Description string `json:"description"` - Summary string `json:"summary"` - Method string `json:"method"` - Params map[string]interface{} `json:"params"` - Server Server `json:"server"` +type Schema struct { + Ref string `json:"$ref,omitempty"` + Type string `json:"type,omitempty"` + Title string `json:"title"` + Required []string `json:"required,omitempty"` + Items Items `json:"items,omitempty"` + Properties map[string]Schema `json:"properties,omitempty"` + OneOf []Schema `json:"oneOf,omitempty"` + AnyOf []Schema `json:"anyOf,omitempty"` + AllOf []Schema `json:"allOf,omitempty"` + Enum []string `json:"enum,omitempty"` + Pattern string `json:"pattern"` } -type Example struct { - Name string `json:"name"` - Summary string `json:"summary"` - Description string `json:"description"` - Value interface{} `json:"value"` - ExternalValue string `json:"externalValue"` +type Param struct { + Name string `json:"name"` + Required bool `json:"required"` + Schema Schema `json:"schema"` } -type ExamplePairing struct { - Name string `json:"name"` - Description string `json:"description"` - Summary string `json:"summary"` - Params []Example `json:"params"` - Result Example `json:"result"` +type Result struct { + Name string `json:"name"` + Schema Schema `json:"schema"` } type Method struct { - Name string `json:"name"` - Tags []Tag `json:"tags,omitempty"` - Summary string `json:"summary,omitempty"` - Description string `json:"description,omitempty"` - ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"` - Params []*ContentDescriptor `json:"params"` - Result *ContentDescriptor `json:"result"` - Deprecated bool `json:"deprecated,omitempty"` - Servers []Server `json:"servers,omitempty"` - Errors []Error `json:"errors,omitempty"` - Links []Link `json:"links,omitempty"` - ParamStructure string `json:"paramStructure,omitempty"` - Examples []ExamplePairing `json:"examples,omitempty"` -} - -type Components struct { - ContentDescriptors map[string]*ContentDescriptor `json:"contentDescriptors,omitempty"` - Schemas map[string]spec.Schema `json:"schemas,omitempty"` - Examples map[string]Example `json:"examples,omitempty"` - Links map[string]Link `json:"links,omitempty"` - Errors map[string]Error `json:"errors,omitempty"` - ExamplePairingObjects map[string]ExamplePairing `json:"examplePairingObjects,omitempty"` - Tags map[string]Tag `json:"tags,omitempty"` -} - -type OpenRPCSpec1 struct { - OpenRPC string `json:"openrpc"` - Info Info `json:"info"` - Servers []Server `json:"servers"` - Methods []Method `json:"methods"` - Components Components `json:"components"` - ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"` - - Objects *ObjectMap `json:"-"` -} - -func NewOpenRPCSpec1() *OpenRPCSpec1 { - return &OpenRPCSpec1{ - OpenRPC: "1.0.0", - Info: Info{ - Title: "gfx.cafe/open/jrpc/openrpc", - Version: "0.0.0", - }, - Servers: make([]Server, 0), - Methods: make([]Method, 0), - - Objects: NewObjectMap(), - } -} - -func (o *OpenRPCSpec1) AddSchemas(pth string) error { - dr, err := os.ReadDir(pth) - if err != nil { - return err - } - for _, v := range dr { - if v.IsDir() { - if err := o.AddSchemas(path.Join(pth, v.Name())); err != nil { - return err - } - } else { - if err := o.AddSchema(path.Join(pth, v.Name())); err != nil { - return err - } - } - } - return nil -} - -func (o *OpenRPCSpec1) AddSchema(pth string) error { - schem := map[string]spec.Schema{} - bts, err := os.ReadFile(pth) - if err != nil { - return err - } - ext := filepath.Ext(path.Base(pth)) - switch ext { - case ".json": - err = json.Unmarshal(bts, &schem) - case ".yml", ".yaml": - err = yaml.Unmarshal(bts, &schem) - } - if err != nil { - return err - } - if o.Components.Schemas == nil { - o.Components.Schemas = map[string]spec.Schema{} - } - for k, v := range schem { - o.Components.Schemas[k] = v - } - return nil -} - -func (o *OpenRPCSpec1) AddMethods(pth string) error { - dr, err := os.ReadDir(pth) - if err != nil { - return err - } - for _, v := range dr { - if v.IsDir() { - if err := o.AddMethods(path.Join(pth, v.Name())); err != nil { - return err - } - } else { - if err := o.AddMethod(path.Join(pth, v.Name())); err != nil { - return err - } - } - } - return nil -} - -func (o *OpenRPCSpec1) AddMethod(pth string) error { - var meth []Method - bts, err := os.ReadFile(pth) - if err != nil { - return err - } - switch filepath.Ext(path.Base(pth)) { - case ".json": - err = json.Unmarshal(bts, &meth) - case ".yml", ".yaml": - err = yaml.Unmarshal(bts, &meth) - if err != nil { - return err - } - } - if err != nil { - return err - } - o.Methods = append(o.Methods, meth...) - return nil + Name string `json:"name"` + Summary string `json:"summary"` + Params []Param `json:"params"` + Result Result `json:"result"` +} + +type OpenRPC struct { + Version string `json:"openrpc"` + Info Info `json:"info"` + Methods []Method `json:"methods"` + Components struct { + Schemas map[string]Schema `json:"schemas"` + } `json:"components"` } -- GitLab