diff --git a/go.mod b/go.mod
index f568902241c5e6f12dc03b85cc80b317a629d45e..3a2695cb410099fa0a550eea796a72bc62750fcc 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,6 @@ require (
 	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/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487
 	github.com/imdario/mergo v0.3.13
 	github.com/json-iterator/go v1.1.12
 	github.com/test-go/testify v1.1.4
@@ -22,6 +21,7 @@ require (
 
 require (
 	github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
+	github.com/alecthomas/kong v0.6.1 // 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
diff --git a/go.sum b/go.sum
index 0e23b8c893a178e90846f9bfa387d48efe7d59f0..5359d0a43de72680f3371a9fb5b04faffd0fae56 100644
--- a/go.sum
+++ b/go.sum
@@ -43,13 +43,13 @@ git.tuxpa.in/a/zlog v1.32.0 h1:KKXbRF1x8kJDSzUoGz/pivo+4TVY6xT5sVtdFZ6traY=
 git.tuxpa.in/a/zlog v1.32.0/go.mod h1:vUa2Qhu6DLPLqmfRy99FiPqaY2eb6/KQjtMekW3UNnA=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
-github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
 github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
+github.com/alecthomas/kong v0.6.1 h1:1kNhcFepkR+HmasQpbiKDLylIL8yh5B5y1zPp5bJimA=
+github.com/alecthomas/kong v0.6.1/go.mod h1:JfHWDzLmbh/puW6I3V7uWenoh56YNVONW+w8eKeUr9I=
+github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
 github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
 github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
@@ -62,13 +62,9 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
 github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
 github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
 github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
-github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
-github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 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 v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
 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=
@@ -86,7 +82,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
 github.com/ethereum/go-ethereum v1.10.22 h1:HbEgsDo1YTGIf4KB/NNpn+XH+PiNJXUZ9ksRxiqWyMc=
 github.com/ethereum/go-ethereum v1.10.22/go.mod h1:EYFyF19u3ezGLD4RqOkLq+ZCXzYbLoNDdZlMt7kyKFg=
 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
@@ -98,17 +93,13 @@ 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.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 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.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 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.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
 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.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 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=
@@ -121,14 +112,10 @@ github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1
 github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
 github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
-github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
 github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
 github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
-github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
 github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
 github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY=
-github.com/gobuffalo/packr/v2 v2.6.0/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08=
 github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=
 github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=
 github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
@@ -206,8 +193,6 @@ github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORR
 github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
 github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487 h1:NyaWOSkqFK1d9o+HLfnMIGzrHuUUPeBNIZyi5Zoe/lY=
-github.com/gregdhill/go-openrpc v0.0.0-20220114144539-ae6f44720487/go.mod h1:a1eRkbhd3DYpRH2lnuUsVG+QMTI+v0hGnsis8C9hMrA=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
 github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -231,11 +216,9 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
 github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
 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.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 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/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 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=
@@ -245,25 +228,20 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
 github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA=
 github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
 github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
 github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.10.3 h1:OP96hzwJVBIHYU52pVTI6CczrxPvrGfgqF9N5eTO0Q8=
 github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 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/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 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.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 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=
@@ -285,7 +263,6 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
 github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
 github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
@@ -301,7 +278,6 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 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.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 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=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -312,38 +288,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
-github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
 github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
 github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
-github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
-github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -361,10 +326,8 @@ github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefld
 github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
 github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
 github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
 github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
-github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -385,12 +348,9 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -442,7 +402,6 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -496,16 +455,12 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -573,7 +528,6 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn
 golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
diff --git a/json.go b/json.go
index 41780432e38c1a1281e54788630457c5452d139c..2d7ade351008522de35d31aab66ad5519b4e903c 100644
--- a/json.go
+++ b/json.go
@@ -47,8 +47,9 @@ type jsonrpcMessage struct {
 	ID      *ID             `json:"id,omitempty"`
 	Method  string          `json:"method,omitempty"`
 	Params  json.RawMessage `json:"params,omitempty"`
-	Error   *jsonError      `json:"error,omitempty"`
 	Result  json.RawMessage `json:"result,omitempty"`
+
+	Error *jsonError `json:"error,omitempty"`
 }
 
 func MakeCall(id int, method string, params []any) *JsonRpcMessage {
diff --git a/openrpc/cmd/cli.go b/openrpc/cmd/cli.go
new file mode 100644
index 0000000000000000000000000000000000000000..2805cb04c44f9d62df8e7862414d473b03329cc9
--- /dev/null
+++ b/openrpc/cmd/cli.go
@@ -0,0 +1,97 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"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 {
+	Compile  CompileCommand  `cmd:"" help:"Compile a folder into a single openrpc spec"`
+	Generate GenerateCommand `cmd:"" help:"Compile a folder into a single openrpc spec"`
+}
+
+type CompileCommand struct {
+	Methods []string `name:"methods" short:"m" help:"root of method dirs" type:"path"`
+	Schemas []string `name:"schemas" short:"s" help:"root schema dirs" type:"path"`
+	Output  string   `name:"output" short:"o" help:"path to output file"`
+}
+
+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
+	}
+	return nil
+}
+
+type GenerateCommand struct {
+	Spec      string   `name:"spec" short:"s" help:"path to jopenrpc spec"`
+	Output    string   `name:"output" short:"o" help:"output directory and package"`
+	Templates []string `name:"templates" short:"t" help:"list of template types to generate for"`
+}
+
+func (c *GenerateCommand) Run() error {
+	if c.Spec == "" {
+		return fmt.Errorf("spec file is required")
+	}
+	openrpc, err := readSpec(c.Spec)
+	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 {
+		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)
+	if err != nil {
+		return nil, err
+	}
+
+	return spec, nil
+}
+
+func NewCLI() *kong.Context {
+	ctx := kong.Parse(&CLI)
+	return ctx
+}
diff --git a/openrpc/cmd/main.go b/openrpc/cmd/main.go
index c796afd786179fbb86e33fc82b4590eafff47166..21956534efca5fed8b18a450a5af328143790f8d 100644
--- a/openrpc/cmd/main.go
+++ b/openrpc/cmd/main.go
@@ -1,85 +1,13 @@
 package main
 
 import (
-	"encoding/json"
-	"flag"
 	"fmt"
-	"io/ioutil"
 	"os"
-
-	"gfx.cafe/open/jrpc/openrpc/generate"
-	"gfx.cafe/open/jrpc/openrpc/parse"
-	"gfx.cafe/open/jrpc/openrpc/types"
-	"github.com/gobuffalo/packr/v2"
-)
-
-var (
-	pkgDir         string
-	specFile       string
-	cliGen         bool
-	cliCommandName string
 )
 
-func init() {
-	flag.StringVar(&pkgDir, "dir", "rpc", "set the target directory")
-	flag.StringVar(&specFile, "spec", "", "the openrpc compliant spec")
-	flag.StringVar(&cliCommandName, "cli.name", "CHANGEME", "With -cli, names binary program. Default is FIXME.")
-	flag.BoolVar(&cliGen, "cli", false, "Toggle CLI program generation")
-}
-
-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)
-	if err != nil {
-		return nil, err
-	}
-
-	return spec, nil
-}
-
-func run() error {
-	flag.Parse()
-	if specFile == "" {
-		return fmt.Errorf("spec file is required")
-	}
-
-	openrpc, err := readSpec(specFile)
-	if err != nil {
-		return err
-	}
-
-	parse.GetTypes(openrpc, openrpc.Objects)
-	box := packr.New("template", "./templates")
-
-	if err = generate.WriteFile(box, "server", pkgDir, openrpc); err != nil {
-		return err
-	}
-
-	if err = generate.WriteFile(box, "types", pkgDir, openrpc); err != nil {
-		return err
-	}
-
-	if cliGen {
-		generate.ProgramName = cliCommandName
-		if err = generate.WriteFile(box, "cli", "main", openrpc); err != nil {
-			return err
-		}
-
-		if err = generate.WriteFile(box, "cli_cmd", "cmd", openrpc); err != nil {
-			return err
-		}
-	}
-
-	return nil
-}
-
 func main() {
-	if err := run(); err != nil {
+	ctx := NewCLI()
+	if err := ctx.Run(); err != nil {
 		fmt.Fprintf(os.Stderr, "error: %v\n", err)
 		os.Exit(1)
 	}
diff --git a/openrpc/cmd/main_test.go b/openrpc/cmd/main_test.go
index 691a316bae9794ce01a7b427074032db2e8c589b..3169fb6b4bcc3304047d70d604cd5393e3880b55 100644
--- a/openrpc/cmd/main_test.go
+++ b/openrpc/cmd/main_test.go
@@ -4,9 +4,9 @@ import (
 	"os"
 	"testing"
 
+	"gfx.cafe/open/jrpc/openrpc/generate"
+	"gfx.cafe/open/jrpc/openrpc/parse"
 	packr "github.com/gobuffalo/packr/v2"
-	"github.com/gregdhill/go-openrpc/generate"
-	"github.com/gregdhill/go-openrpc/parse"
 )
 
 func generateExampleProxyServer() error {
diff --git a/openrpc/execution.json b/openrpc/execution.json
new file mode 100644
index 0000000000000000000000000000000000000000..7c73f947dd3ace05c56ce880ec44e6b6c3a8e2d8
--- /dev/null
+++ b/openrpc/execution.json
@@ -0,0 +1,1991 @@
+{
+ "openrpc": "1.0.0",
+ "info": {
+  "title": "gfx.cafe/open/jrpc/openrpc",
+  "version": "0.0.0"
+ },
+ "servers": [],
+ "methods": [
+  {
+   "name": "debug_getRawHeader",
+   "summary": "Returns an RLP-encoded header.",
+   "params": [
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Header RLP",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "debug_getRawBlock",
+   "summary": "Returns an RLP-encoded block.",
+   "params": [
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Block RLP",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "debug_getRawTransaction",
+   "summary": "Returns an array of EIP-2718 binary-encoded transactions.",
+   "params": [
+    {
+     "name": "Transaction hash",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    }
+   ],
+   "result": {
+    "name": "EIP-2718 binary-encoded transaction",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "debug_getRawReceipts",
+   "summary": "Returns an array of EIP-2718 binary-encoded receipts.",
+   "params": [
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Receipts",
+    "schema": {
+     "type": "array",
+     "title": "Receipt array",
+     "items": {
+      "$ref": "#/components/schemas/bytes"
+     }
+    }
+   }
+  },
+  {
+   "name": "debug_getBadBlocks",
+   "summary": "Returns an array of recent bad blocks that the client has seen on the network.",
+   "params": [],
+   "result": {
+    "name": "Blocks",
+    "schema": {
+     "type": "array",
+     "title": "Bad block array",
+     "items": {
+      "$ref": "#/components/schemas/BadBlock"
+     }
+    }
+   }
+  },
+  {
+   "name": "eth_getBlockByHash",
+   "summary": "Returns information about a block by hash.",
+   "params": [
+    {
+     "name": "Block hash",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    },
+    {
+     "name": "Hydrated transactions",
+     "required": true,
+     "schema": {
+      "type": "boolean",
+      "title": "hydrated"
+     }
+    }
+   ],
+   "result": {
+    "name": "Block information",
+    "schema": {
+     "$ref": "#/components/schemas/Block"
+    }
+   }
+  },
+  {
+   "name": "eth_getBlockByNumber",
+   "summary": "Returns information about a block by number.",
+   "params": [
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    },
+    {
+     "name": "Hydrated transactions",
+     "required": true,
+     "schema": {
+      "type": "boolean",
+      "title": "hydrated"
+     }
+    }
+   ],
+   "result": {
+    "name": "Block information",
+    "schema": {
+     "$ref": "#/components/schemas/Block"
+    }
+   }
+  },
+  {
+   "name": "eth_getBlockTransactionCountByHash",
+   "summary": "Returns the number of transactions in a block from a block matching the given block hash.",
+   "params": [
+    {
+     "name": "Block hash",
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction count",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getBlockTransactionCountByNumber",
+   "summary": "Returns the number of transactions in a block matching the given block number.",
+   "params": [
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction count",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getUncleCountByBlockHash",
+   "summary": "Returns the number of uncles in a block from a block matching the given block hash.",
+   "params": [
+    {
+     "name": "Block hash",
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Uncle count",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getUncleCountByBlockNumber",
+   "summary": "Returns the number of transactions in a block matching the given block number.",
+   "params": [
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Uncle count",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_chainId",
+   "summary": "Returns the chain ID of the current network.",
+   "params": [],
+   "result": {
+    "name": "Chain ID",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_syncing",
+   "summary": "Returns an object with data about the sync status or false.",
+   "params": [],
+   "result": {
+    "name": "Syncing status",
+    "schema": {
+     "$ref": "#/components/schemas/SyncingStatus"
+    }
+   }
+  },
+  {
+   "name": "eth_coinbase",
+   "summary": "Returns the client coinbase address.",
+   "params": [],
+   "result": {
+    "name": "Coinbase address",
+    "schema": {
+     "$ref": "#/components/schemas/address"
+    }
+   }
+  },
+  {
+   "name": "eth_accounts",
+   "summary": "Returns a list of addresses owned by client.",
+   "params": [],
+   "result": {
+    "name": "Accounts",
+    "schema": {
+     "type": "array",
+     "title": "Accounts",
+     "items": {
+      "$ref": "#/components/schemas/address"
+     }
+    }
+   }
+  },
+  {
+   "name": "eth_blockNumber",
+   "summary": "Returns the number of most recent block.",
+   "params": [],
+   "result": {
+    "name": "Block number",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_call",
+   "summary": "Executes a new message call immediately without creating a transaction on the block chain.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/GenericTransaction"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Return data",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "eth_estimateGas",
+   "summary": "Generates and returns an estimate of how much gas is necessary to allow the transaction to complete.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/GenericTransaction"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Gas used",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_createAccessList",
+   "summary": "Generates an access list for a transaction.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/GenericTransaction"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Gas used",
+    "schema": {
+     "type": "object",
+     "title": "Access list result",
+     "properties": {
+      "accessList": {
+       "title": "accessList",
+       "$ref": "#/components/schemas/AccessList"
+      },
+      "error": {
+       "type": "string",
+       "title": "error"
+      },
+      "gasUsed": {
+       "title": "Gas used",
+       "$ref": "#/components/schemas/uint"
+      }
+     }
+    }
+   }
+  },
+  {
+   "name": "eth_gasPrice",
+   "summary": "Returns the current price per gas in wei.",
+   "params": [],
+   "result": {
+    "name": "Gas price",
+    "schema": {
+     "title": "Gas price",
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_maxPriorityFeePerGas",
+   "summary": "Returns the current maxPriorityFeePerGas per gas in wei.",
+   "params": [],
+   "result": {
+    "name": "Max priority fee per gas",
+    "schema": {
+     "title": "Max priority fee per gas",
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_feeHistory",
+   "summary": "Transaction fee history",
+   "description": "Returns transaction base fee per gas and effective priority fee per gas for the requested/supported block range.",
+   "params": [
+    {
+     "name": "blockCount",
+     "description": "Requested range of blocks. Clients will return less than the requested range if not all blocks are available.",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    },
+    {
+     "name": "newestBlock",
+     "description": "Highest block of the requested range.",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    },
+    {
+     "name": "rewardPercentiles",
+     "description": "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.",
+     "required": true,
+     "schema": {
+      "type": "array",
+      "title": "rewardPercentiles",
+      "items": {
+       "description": "Floating point value between 0 and 100.",
+       "type": "number",
+       "title": "rewardPercentile"
+      }
+     }
+    }
+   ],
+   "result": {
+    "name": "feeHistoryResult",
+    "description": "Fee history for the returned block range. This can be a subsection of the requested range if not all blocks are available.",
+    "schema": {
+     "description": "Fee history results.",
+     "type": "object",
+     "title": "feeHistoryResults",
+     "required": [
+      "oldestBlock",
+      "baseFeePerGas",
+      "gasUsedRatio"
+     ],
+     "properties": {
+      "baseFeePerGas": {
+       "description": "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.",
+       "type": "array",
+       "title": "baseFeePerGasArray",
+       "items": {
+        "$ref": "#/components/schemas/uint"
+       }
+      },
+      "oldestBlock": {
+       "description": "Lowest number block of returned range.",
+       "title": "oldestBlock",
+       "$ref": "#/components/schemas/uint"
+      },
+      "reward": {
+       "description": "A two-dimensional array of effective priority fees per gas at the requested block percentiles.",
+       "type": "array",
+       "title": "rewardArray",
+       "items": {
+        "description": "An array of effective priority fee per gas data points from a single block. All zeroes are returned if the block is empty.",
+        "type": "array",
+        "title": "rewardPercentile",
+        "items": {
+         "description": "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.",
+         "title": "rewardPercentile",
+         "$ref": "#/components/schemas/uint"
+        }
+       }
+      }
+     }
+    }
+   }
+  },
+  {
+   "name": "eth_newFilter",
+   "summary": "Creates a filter object, based on filter options, to notify when the state changes (logs).",
+   "params": [
+    {
+     "name": "Filter",
+     "schema": {
+      "$ref": "#/components/schemas/Filter"
+     }
+    }
+   ],
+   "result": {
+    "name": "Filter Identifier",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_newBlockFilter",
+   "summary": "Creates a filter in the node, to notify when a new block arrives.",
+   "params": [],
+   "result": {
+    "name": "Filter Identifier",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_newPendingTransactionFilter",
+   "summary": "Creates a filter in the node, to notify when new pending transactions arrive.",
+   "params": [],
+   "result": {
+    "name": "Filter Identifier",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_uninstallFilter",
+   "summary": "Uninstalls a filter with given id.",
+   "params": [
+    {
+     "name": "Filter Identifier",
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   ],
+   "result": {
+    "name": "Success",
+    "schema": {
+     "type": "boolean"
+    }
+   }
+  },
+  {
+   "name": "eth_getFilterChanges",
+   "summary": "Polling method for a filter, which returns an array of logs which occurred since last poll.",
+   "params": [
+    {
+     "name": "Filter Identifier",
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   ],
+   "result": {
+    "name": "Log objects",
+    "schema": {
+     "$ref": "#/components/schemas/FilterResults"
+    }
+   }
+  },
+  {
+   "name": "eth_getFilterLogs",
+   "summary": "Returns an array of all logs matching filter with given id.",
+   "params": [
+    {
+     "name": "Filter Identifier",
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   ],
+   "result": {
+    "name": "Log objects",
+    "schema": {
+     "$ref": "#/components/schemas/FilterResults"
+    }
+   }
+  },
+  {
+   "name": "eth_getLogs",
+   "summary": "Returns an array of all logs matching filter with given id.",
+   "params": [
+    {
+     "name": "Filter",
+     "schema": {
+      "$ref": "#/components/schemas/Filter"
+     }
+    }
+   ],
+   "result": {
+    "name": "Log objects",
+    "schema": {
+     "$ref": "#/components/schemas/FilterResults"
+    }
+   }
+  },
+  {
+   "name": "eth_mining",
+   "summary": "Returns whether the client is actively mining new blocks.",
+   "params": [],
+   "result": {
+    "name": "Mining status",
+    "schema": {
+     "type": "boolean",
+     "title": "miningStatus"
+    }
+   }
+  },
+  {
+   "name": "eth_hashrate",
+   "summary": "Returns the number of hashes per second that the node is mining with.",
+   "params": [],
+   "result": {
+    "name": "Mining status",
+    "schema": {
+     "title": "Hashrate",
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getWork",
+   "summary": "Returns the hash of the current block, the seedHash, and the boundary condition to be met (“target”).",
+   "params": [],
+   "result": {
+    "name": "Current work",
+    "schema": {
+     "type": "array",
+     "items": [
+      {
+       "title": "Proof-of-work hash",
+       "$ref": "#/components/schemas/bytes32"
+      },
+      {
+       "title": "seed hash",
+       "$ref": "#/components/schemas/bytes32"
+      },
+      {
+       "title": "difficulty",
+       "$ref": "#/components/schemas/bytes32"
+      }
+     ]
+    }
+   }
+  },
+  {
+   "name": "eth_submitWork",
+   "summary": "Used for submitting a proof-of-work solution.",
+   "params": [
+    {
+     "name": "nonce",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes8"
+     }
+    },
+    {
+     "name": "hash",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes32"
+     }
+    },
+    {
+     "name": "digest",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Success",
+    "schema": {
+     "type": "boolean"
+    }
+   }
+  },
+  {
+   "name": "eth_submitHashrate",
+   "summary": "Used for submitting mining hashrate.",
+   "params": [
+    {
+     "name": "Hashrate",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes32"
+     }
+    },
+    {
+     "name": "ID",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Success",
+    "schema": {
+     "type": "boolean"
+    }
+   }
+  },
+  {
+   "name": "eth_sign",
+   "summary": "Returns an EIP-191 signature over the provided data.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "Message",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes"
+     }
+    }
+   ],
+   "result": {
+    "name": "Signature",
+    "schema": {
+     "$ref": "#/components/schemas/bytes65"
+    }
+   }
+  },
+  {
+   "name": "eth_signTransaction",
+   "summary": "Returns an RLP encoded transaction signed by the specified account.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/GenericTransaction"
+     }
+    }
+   ],
+   "result": {
+    "name": "Encoded transaction",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "eth_getBalance",
+   "summary": "Returns the balance of the account of given address.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Balance",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getStorageAt",
+   "summary": "Returns the value from a storage position at a given address.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "Storage slot",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/uint256"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Value",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "eth_getTransactionCount",
+   "summary": "Returns the number of transactions sent from an address.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction count",
+    "schema": {
+     "$ref": "#/components/schemas/uint"
+    }
+   }
+  },
+  {
+   "name": "eth_getCode",
+   "summary": "Returns code at a given address.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "Block",
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Bytecode",
+    "schema": {
+     "$ref": "#/components/schemas/bytes"
+    }
+   }
+  },
+  {
+   "name": "eth_getProof",
+   "summary": "Returns the merkle proof for a given account and optionally some storage keys.",
+   "params": [
+    {
+     "name": "Address",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/address"
+     }
+    },
+    {
+     "name": "StorageKeys",
+     "required": true,
+     "schema": {
+      "type": "array",
+      "title": "Storage keys",
+      "items": {
+       "$ref": "#/components/schemas/hash32"
+      }
+     }
+    },
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    }
+   ],
+   "result": {
+    "name": "Account",
+    "schema": {
+     "$ref": "#/components/schemas/AccountProof"
+    }
+   }
+  },
+  {
+   "name": "eth_sendTransaction",
+   "summary": "Signs and submits a transaction.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/GenericTransaction"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction hash",
+    "schema": {
+     "$ref": "#/components/schemas/hash32"
+    }
+   }
+  },
+  {
+   "name": "eth_sendRawTransaction",
+   "summary": "Submits a raw transaction.",
+   "params": [
+    {
+     "name": "Transaction",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/bytes"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction hash",
+    "schema": {
+     "$ref": "#/components/schemas/hash32"
+    }
+   }
+  },
+  {
+   "name": "eth_getTransactionByHash",
+   "summary": "Returns the information about a transaction requested by transaction hash.",
+   "params": [
+    {
+     "name": "Transaction hash",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction information",
+    "schema": {
+     "$ref": "#/components/schemas/TransactionInfo"
+    }
+   }
+  },
+  {
+   "name": "eth_getTransactionByBlockHashAndIndex",
+   "summary": "Returns information about a transaction by block hash and transaction index position.",
+   "params": [
+    {
+     "name": "Block hash",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    },
+    {
+     "name": "Transaction index",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction information",
+    "schema": {
+     "$ref": "#/components/schemas/TransactionInfo"
+    }
+   }
+  },
+  {
+   "name": "eth_getTransactionByBlockNumberAndIndex",
+   "summary": "Returns information about a transaction by block number and transaction index position.",
+   "params": [
+    {
+     "name": "Block",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/BlockNumberOrTag"
+     }
+    },
+    {
+     "name": "Transaction index",
+     "required": true,
+     "schema": {
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   ],
+   "result": {
+    "name": "Transaction information",
+    "schema": {
+     "$ref": "#/components/schemas/TransactionInfo"
+    }
+   }
+  },
+  {
+   "name": "eth_getTransactionReceipt",
+   "summary": "Returns the receipt of a transaction by transaction hash.",
+   "params": [
+    {
+     "name": "Transaction hash",
+     "schema": {
+      "$ref": "#/components/schemas/hash32"
+     }
+    }
+   ],
+   "result": {
+    "name": "Receipt Information",
+    "schema": {
+     "$ref": "#/components/schemas/ReceiptInfo"
+    }
+   }
+  }
+ ],
+ "components": {
+  "schemas": {
+   "AccessList": {
+    "type": "array",
+    "title": "Access list",
+    "items": {
+     "$ref": "#/components/schemas/AccessListEntry"
+    }
+   },
+   "AccessListEntry": {
+    "type": "object",
+    "title": "Access list entry",
+    "properties": {
+     "address": {
+      "$ref": "#/components/schemas/address"
+     },
+     "storageKeys": {
+      "type": "array",
+      "items": {
+       "$ref": "#/components/schemas/hash32"
+      }
+     }
+    }
+   },
+   "AccountProof": {
+    "type": "object",
+    "title": "Account proof",
+    "required": [
+     "address",
+     "accountProof",
+     "balance",
+     "codeHash",
+     "nonce",
+     "storageHash",
+     "storageProof"
+    ],
+    "properties": {
+     "accountProof": {
+      "type": "array",
+      "title": "accountProof",
+      "items": {
+       "$ref": "#/components/schemas/bytes"
+      }
+     },
+     "address": {
+      "title": "address",
+      "$ref": "#/components/schemas/address"
+     },
+     "balance": {
+      "title": "balance",
+      "$ref": "#/components/schemas/uint256"
+     },
+     "codeHash": {
+      "title": "codeHash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "nonce": {
+      "title": "nonce",
+      "$ref": "#/components/schemas/uint64"
+     },
+     "storageHash": {
+      "title": "storageHash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "storageProof": {
+      "type": "array",
+      "title": "storageProof",
+      "items": {
+       "$ref": "#/components/schemas/StorageProof"
+      }
+     }
+    }
+   },
+   "BadBlock": {
+    "type": "object",
+    "title": "Bad block",
+    "required": [
+     "block",
+     "hash",
+     "rlp"
+    ],
+    "properties": {
+     "block": {
+      "title": "Block",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "hash": {
+      "title": "Hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "rlp": {
+      "title": "RLP",
+      "$ref": "#/components/schemas/bytes"
+     }
+    }
+   },
+   "Block": {
+    "type": "object",
+    "title": "Block object",
+    "required": [
+     "parentHash",
+     "sha3Uncles",
+     "miner",
+     "stateRoot",
+     "transactionsRoot",
+     "receiptsRoot",
+     "logsBloom",
+     "number",
+     "gasLimit",
+     "gasUsed",
+     "timestamp",
+     "extraData",
+     "mixHash",
+     "nonce",
+     "size",
+     "transactions",
+     "uncles"
+    ],
+    "properties": {
+     "baseFeePerGas": {
+      "title": "Base fee per gas",
+      "$ref": "#/components/schemas/uint"
+     },
+     "difficulty": {
+      "title": "Difficulty",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "extraData": {
+      "title": "Extra data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "gasLimit": {
+      "title": "Gas limit",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gasUsed": {
+      "title": "Gas used",
+      "$ref": "#/components/schemas/uint"
+     },
+     "logsBloom": {
+      "title": "Bloom filter",
+      "$ref": "#/components/schemas/bytes256"
+     },
+     "miner": {
+      "title": "Coinbase",
+      "$ref": "#/components/schemas/address"
+     },
+     "mixHash": {
+      "title": "Mix hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "nonce": {
+      "title": "Nonce",
+      "$ref": "#/components/schemas/bytes8"
+     },
+     "number": {
+      "title": "Number",
+      "$ref": "#/components/schemas/uint"
+     },
+     "parentHash": {
+      "title": "Parent block hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "receiptsRoot": {
+      "title": "Receipts root",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "sha3Uncles": {
+      "title": "Ommers hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "size": {
+      "title": "Block size",
+      "$ref": "#/components/schemas/uint"
+     },
+     "stateRoot": {
+      "title": "State root",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "timestamp": {
+      "title": "Timestamp",
+      "$ref": "#/components/schemas/uint"
+     },
+     "totalDifficulty": {
+      "title": "Total difficult",
+      "$ref": "#/components/schemas/uint"
+     },
+     "transactions": {
+      "anyOf": [
+       {
+        "type": "array",
+        "title": "Transaction hashes",
+        "items": {
+         "$ref": "#/components/schemas/hash32"
+        }
+       },
+       {
+        "type": "array",
+        "title": "Full transactions",
+        "items": {
+         "$ref": "#/components/schemas/TransactionSigned"
+        }
+       }
+      ]
+     },
+     "transactionsRoot": {
+      "title": "Transactions root",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "uncles": {
+      "type": "array",
+      "title": "Uncles",
+      "items": {
+       "$ref": "#/components/schemas/hash32"
+      }
+     }
+    }
+   },
+   "BlockNumberOrTag": {
+    "title": "Block number or tag",
+    "oneOf": [
+     {
+      "title": "Block number",
+      "$ref": "#/components/schemas/uint"
+     },
+     {
+      "title": "Block tag",
+      "$ref": "#/components/schemas/BlockTag"
+     }
+    ]
+   },
+   "BlockTag": {
+    "description": "`earliest`: The lowest numbered block the client has available; `finalized`: The most recent crypto-economically secure block, cannot be re-orged outside of manual intervention driven by community coordination; `safe`: The most recent block that is safe from re-orgs under honest majority and certain synchronicity assumptions; `latest`: The most recent block in the canonical chain observed by the client, this block may be re-orged out of the canonical chain even under healthy/normal conditions; `pending`: A sample next block built by the client on top of `latest` and containing the set of transactions usually taken from local mempool. Before the merge transition is finalized, any call querying for `finalized` or `safe` block MUST be responded to with `-39001: Unknown block` error",
+    "type": "string",
+    "title": "Block tag",
+    "enum": [
+     "earliest",
+     "finalized",
+     "safe",
+     "latest",
+     "pending"
+    ]
+   },
+   "Filter": {
+    "type": "object",
+    "title": "filter",
+    "properties": {
+     "address": {
+      "title": "Address(es)",
+      "oneOf": [
+       {
+        "title": "Address",
+        "$ref": "#/components/schemas/address"
+       },
+       {
+        "title": "Addresses",
+        "$ref": "#/components/schemas/addresses"
+       }
+      ]
+     },
+     "fromBlock": {
+      "title": "from block",
+      "$ref": "#/components/schemas/uint"
+     },
+     "toBlock": {
+      "title": "to block",
+      "$ref": "#/components/schemas/uint"
+     },
+     "topics": {
+      "title": "Topics",
+      "$ref": "#/components/schemas/FilterTopics"
+     }
+    }
+   },
+   "FilterResults": {
+    "title": "Filter results",
+    "oneOf": [
+     {
+      "type": "array",
+      "title": "new block hashes",
+      "items": {
+       "$ref": "#/components/schemas/hash32"
+      }
+     },
+     {
+      "type": "array",
+      "title": "new transaction hashes",
+      "items": {
+       "$ref": "#/components/schemas/hash32"
+      }
+     },
+     {
+      "type": "array",
+      "title": "new logs",
+      "items": {
+       "$ref": "#/components/schemas/Log"
+      }
+     }
+    ]
+   },
+   "FilterTopic": {
+    "title": "Filter Topic List Entry",
+    "oneOf": [
+     {
+      "type": "null",
+      "title": "Any Topic Match"
+     },
+     {
+      "title": "Single Topic Match",
+      "$ref": "#/components/schemas/bytes32"
+     },
+     {
+      "type": "array",
+      "title": "Multiple Topic Match",
+      "items": {
+       "$ref": "#/components/schemas/bytes32"
+      }
+     }
+    ]
+   },
+   "FilterTopics": {
+    "type": "array",
+    "title": "Filter Topics",
+    "items": {
+     "$ref": "#/components/schemas/FilterTopic"
+    }
+   },
+   "GenericTransaction": {
+    "type": "object",
+    "title": "Transaction object generic to all types",
+    "properties": {
+     "accessList": {
+      "description": "EIP-2930 access list",
+      "title": "accessList",
+      "$ref": "#/components/schemas/AccessList"
+     },
+     "chainId": {
+      "description": "Chain ID that this transaction is valid on.",
+      "title": "chainId",
+      "$ref": "#/components/schemas/uint"
+     },
+     "from": {
+      "title": "from address",
+      "$ref": "#/components/schemas/address"
+     },
+     "gas": {
+      "title": "gas limit",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gasPrice": {
+      "description": "The gas price willing to be paid by the sender in wei",
+      "title": "gas price",
+      "$ref": "#/components/schemas/uint"
+     },
+     "input": {
+      "title": "input data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "maxFeePerGas": {
+      "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei",
+      "title": "max fee per gas",
+      "$ref": "#/components/schemas/uint"
+     },
+     "maxPriorityFeePerGas": {
+      "description": "Maximum fee per gas the sender is willing to pay to miners in wei",
+      "title": "max priority fee per gas",
+      "$ref": "#/components/schemas/uint"
+     },
+     "nonce": {
+      "title": "nonce",
+      "$ref": "#/components/schemas/uint"
+     },
+     "to": {
+      "title": "to address",
+      "$ref": "#/components/schemas/address"
+     },
+     "type": {
+      "title": "type",
+      "$ref": "#/components/schemas/byte"
+     },
+     "value": {
+      "title": "value",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "Log": {
+    "type": "object",
+    "title": "log",
+    "required": [
+     "transactionHash"
+    ],
+    "properties": {
+     "address": {
+      "title": "address",
+      "$ref": "#/components/schemas/address"
+     },
+     "blockHash": {
+      "title": "block hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "blockNumber": {
+      "title": "block number",
+      "$ref": "#/components/schemas/uint"
+     },
+     "data": {
+      "title": "data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "logIndex": {
+      "title": "log index",
+      "$ref": "#/components/schemas/uint"
+     },
+     "removed": {
+      "type": "boolean",
+      "title": "removed"
+     },
+     "topics": {
+      "type": "array",
+      "title": "topics",
+      "items": {
+       "$ref": "#/components/schemas/bytes32"
+      }
+     },
+     "transactionHash": {
+      "title": "transaction hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "transactionIndex": {
+      "title": "transaction index",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "ReceiptInfo": {
+    "type": "object",
+    "title": "Receipt info",
+    "required": [
+     "blockHash",
+     "blockNumber",
+     "from",
+     "cumulativeGasUsed",
+     "gasUsed",
+     "logs",
+     "logsBloom",
+     "transactionHash",
+     "transactionIndex",
+     "effectiveGasPrice"
+    ],
+    "properties": {
+     "blockHash": {
+      "title": "block hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "blockNumber": {
+      "title": "block number",
+      "$ref": "#/components/schemas/uint"
+     },
+     "contractAddress": {
+      "description": "The contract address created, if the transaction was a contract creation, otherwise null.",
+      "title": "contract address",
+      "oneOf": [
+       {
+        "$ref": "#/components/schemas/address"
+       },
+       {
+        "type": "null",
+        "name": null
+       }
+      ]
+     },
+     "cumulativeGasUsed": {
+      "description": "The sum of gas used by this transaction and all preceding transactions in the same block.",
+      "title": "cumulative gas used",
+      "$ref": "#/components/schemas/uint"
+     },
+     "effectiveGasPrice": {
+      "description": "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).",
+      "title": "effective gas price",
+      "$ref": "#/components/schemas/uint"
+     },
+     "from": {
+      "title": "from",
+      "$ref": "#/components/schemas/address"
+     },
+     "gasUsed": {
+      "description": "The amount of gas used for this specific transaction alone.",
+      "title": "gas used",
+      "$ref": "#/components/schemas/uint"
+     },
+     "logs": {
+      "type": "array",
+      "title": "logs",
+      "items": {
+       "$ref": "#/components/schemas/Log"
+      }
+     },
+     "logsBloom": {
+      "title": "logs bloom",
+      "$ref": "#/components/schemas/bytes256"
+     },
+     "root": {
+      "description": "The post-transaction state root. Only specified for transactions included before the Byzantium upgrade.",
+      "title": "state root",
+      "$ref": "#/components/schemas/bytes32"
+     },
+     "status": {
+      "description": "Either 1 (success) or 0 (failure). Only specified for transactions included after the Byzantium upgrade.",
+      "title": "status",
+      "$ref": "#/components/schemas/uint"
+     },
+     "to": {
+      "description": "Address of the receiver or null in a contract creation transaction.",
+      "title": "to",
+      "$ref": "#/components/schemas/address"
+     },
+     "transactionHash": {
+      "title": "transaction hash",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "transactionIndex": {
+      "title": "transaction index",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "StorageProof": {
+    "type": "object",
+    "title": "Storage proof",
+    "required": [
+     "key",
+     "value",
+     "proof"
+    ],
+    "properties": {
+     "key": {
+      "title": "key",
+      "$ref": "#/components/schemas/hash32"
+     },
+     "proof": {
+      "type": "array",
+      "title": "proof",
+      "items": {
+       "$ref": "#/components/schemas/bytes"
+      }
+     },
+     "value": {
+      "title": "value",
+      "$ref": "#/components/schemas/uint256"
+     }
+    }
+   },
+   "SyncingStatus": {
+    "title": "Syncing status",
+    "oneOf": [
+     {
+      "type": "object",
+      "title": "Syncing progress",
+      "properties": {
+       "currentBlock": {
+        "title": "Current block",
+        "$ref": "#/components/schemas/uint"
+       },
+       "highestBlock": {
+        "title": "Highest block",
+        "$ref": "#/components/schemas/uint"
+       },
+       "startingBlock": {
+        "title": "Starting block",
+        "$ref": "#/components/schemas/uint"
+       }
+      }
+     },
+     {
+      "description": "Should always return false if not syncing.",
+      "type": "boolean",
+      "title": "Not syncing"
+     }
+    ]
+   },
+   "Transaction1559Signed": {
+    "type": "object",
+    "title": "Signed 1559 Transaction",
+    "allOf": [
+     {
+      "$ref": "#/components/schemas/Transaction1559Unsigned"
+     },
+     {
+      "title": "EIP-1559 transaction signature properties.",
+      "required": [
+       "yParity",
+       "r",
+       "s"
+      ],
+      "properties": {
+       "r": {
+        "title": "r",
+        "$ref": "#/components/schemas/uint"
+       },
+       "s": {
+        "title": "s",
+        "$ref": "#/components/schemas/uint"
+       },
+       "yParity": {
+        "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature.",
+        "title": "yParity",
+        "$ref": "#/components/schemas/uint"
+       }
+      }
+     }
+    ]
+   },
+   "Transaction1559Unsigned": {
+    "type": "object",
+    "title": "EIP-1559 transaction.",
+    "required": [
+     "type",
+     "nonce",
+     "gas",
+     "value",
+     "input",
+     "maxFeePerGas",
+     "maxPriorityFeePerGas",
+     "chainId",
+     "accessList"
+    ],
+    "properties": {
+     "accessList": {
+      "description": "EIP-2930 access list",
+      "title": "accessList",
+      "$ref": "#/components/schemas/AccessList"
+     },
+     "chainId": {
+      "description": "Chain ID that this transaction is valid on.",
+      "title": "chainId",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gas": {
+      "title": "gas limit",
+      "$ref": "#/components/schemas/uint"
+     },
+     "input": {
+      "title": "input data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "maxFeePerGas": {
+      "description": "The maximum total fee per gas the sender is willing to pay (includes the network / base fee and miner / priority fee) in wei",
+      "title": "max fee per gas",
+      "$ref": "#/components/schemas/uint"
+     },
+     "maxPriorityFeePerGas": {
+      "description": "Maximum fee per gas the sender is willing to pay to miners in wei",
+      "title": "max priority fee per gas",
+      "$ref": "#/components/schemas/uint"
+     },
+     "nonce": {
+      "title": "nonce",
+      "$ref": "#/components/schemas/uint"
+     },
+     "to": {
+      "title": "to address",
+      "$ref": "#/components/schemas/address"
+     },
+     "type": {
+      "title": "type",
+      "$ref": "#/components/schemas/byte"
+     },
+     "value": {
+      "title": "value",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "Transaction2930Signed": {
+    "type": "object",
+    "title": "Signed 2930 Transaction",
+    "allOf": [
+     {
+      "$ref": "#/components/schemas/Transaction2930Unsigned"
+     },
+     {
+      "title": "EIP-2930 transaction signature properties.",
+      "required": [
+       "yParity",
+       "r",
+       "s"
+      ],
+      "properties": {
+       "r": {
+        "title": "r",
+        "$ref": "#/components/schemas/uint"
+       },
+       "s": {
+        "title": "s",
+        "$ref": "#/components/schemas/uint"
+       },
+       "yParity": {
+        "description": "The parity (0 for even, 1 for odd) of the y-value of the secp256k1 signature.",
+        "title": "yParity",
+        "$ref": "#/components/schemas/uint"
+       }
+      }
+     }
+    ]
+   },
+   "Transaction2930Unsigned": {
+    "type": "object",
+    "title": "EIP-2930 transaction.",
+    "required": [
+     "type",
+     "nonce",
+     "gas",
+     "value",
+     "input",
+     "gasPrice",
+     "chainId",
+     "accessList"
+    ],
+    "properties": {
+     "accessList": {
+      "description": "EIP-2930 access list",
+      "title": "accessList",
+      "$ref": "#/components/schemas/AccessList"
+     },
+     "chainId": {
+      "description": "Chain ID that this transaction is valid on.",
+      "title": "chainId",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gas": {
+      "title": "gas limit",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gasPrice": {
+      "description": "The gas price willing to be paid by the sender in wei",
+      "title": "gas price",
+      "$ref": "#/components/schemas/uint"
+     },
+     "input": {
+      "title": "input data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "nonce": {
+      "title": "nonce",
+      "$ref": "#/components/schemas/uint"
+     },
+     "to": {
+      "title": "to address",
+      "$ref": "#/components/schemas/address"
+     },
+     "type": {
+      "title": "type",
+      "$ref": "#/components/schemas/byte"
+     },
+     "value": {
+      "title": "value",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "TransactionInfo": {
+    "type": "object",
+    "title": "Transaction information",
+    "allOf": [
+     {
+      "title": "Contextual information",
+      "required": [
+       "blockHash",
+       "blockNumber",
+       "from",
+       "hash",
+       "transactionIndex"
+      ],
+      "properties": {
+       "blockHash": {
+        "title": "block hash",
+        "$ref": "#/components/schemas/hash32"
+       },
+       "blockNumber": {
+        "title": "block number",
+        "$ref": "#/components/schemas/uint"
+       },
+       "from": {
+        "title": "from address",
+        "$ref": "#/components/schemas/address"
+       },
+       "hash": {
+        "title": "transaction hash",
+        "$ref": "#/components/schemas/hash32"
+       },
+       "transactionIndex": {
+        "title": "transaction index",
+        "$ref": "#/components/schemas/uint"
+       }
+      }
+     },
+     {
+      "$ref": "#/components/schemas/TransactionSigned"
+     }
+    ]
+   },
+   "TransactionLegacySigned": {
+    "type": "object",
+    "title": "Signed Legacy Transaction",
+    "allOf": [
+     {
+      "$ref": "#/components/schemas/TransactionLegacyUnsigned"
+     },
+     {
+      "title": "Legacy transaction signature properties.",
+      "required": [
+       "v",
+       "r",
+       "s"
+      ],
+      "properties": {
+       "r": {
+        "title": "r",
+        "$ref": "#/components/schemas/uint"
+       },
+       "s": {
+        "title": "s",
+        "$ref": "#/components/schemas/uint"
+       },
+       "v": {
+        "title": "v",
+        "$ref": "#/components/schemas/uint"
+       }
+      }
+     }
+    ]
+   },
+   "TransactionLegacyUnsigned": {
+    "type": "object",
+    "title": "Legacy transaction.",
+    "required": [
+     "type",
+     "nonce",
+     "gas",
+     "value",
+     "input",
+     "gasPrice"
+    ],
+    "properties": {
+     "chainId": {
+      "description": "Chain ID that this transaction is valid on.",
+      "title": "chainId",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gas": {
+      "title": "gas limit",
+      "$ref": "#/components/schemas/uint"
+     },
+     "gasPrice": {
+      "description": "The gas price willing to be paid by the sender in wei",
+      "title": "gas price",
+      "$ref": "#/components/schemas/uint"
+     },
+     "input": {
+      "title": "input data",
+      "$ref": "#/components/schemas/bytes"
+     },
+     "nonce": {
+      "title": "nonce",
+      "$ref": "#/components/schemas/uint"
+     },
+     "to": {
+      "title": "to address",
+      "$ref": "#/components/schemas/address"
+     },
+     "type": {
+      "title": "type",
+      "$ref": "#/components/schemas/byte"
+     },
+     "value": {
+      "title": "value",
+      "$ref": "#/components/schemas/uint"
+     }
+    }
+   },
+   "TransactionSigned": {
+    "oneOf": [
+     {
+      "$ref": "#/components/schemas/Transaction1559Signed"
+     },
+     {
+      "$ref": "#/components/schemas/Transaction2930Signed"
+     },
+     {
+      "$ref": "#/components/schemas/TransactionLegacySigned"
+     }
+    ]
+   },
+   "TransactionUnsigned": {
+    "oneOf": [
+     {
+      "$ref": "#/components/schemas/Transaction1559Unsigned"
+     },
+     {
+      "$ref": "#/components/schemas/Transaction2930Unsigned"
+     },
+     {
+      "$ref": "#/components/schemas/TransactionLegacyUnsigned"
+     }
+    ]
+   },
+   "address": {
+    "type": "string",
+    "title": "hex encoded address",
+    "pattern": "^0x[0-9,a-f,A-F]{40}$"
+   },
+   "addresses": {
+    "type": "array",
+    "title": "hex encoded address",
+    "items": {
+     "$ref": "#/components/schemas/address"
+    }
+   },
+   "byte": {
+    "type": "string",
+    "title": "hex encoded byte",
+    "pattern": "^0x([0-9,a-f,A-F]?){1,2}$"
+   },
+   "bytes": {
+    "type": "string",
+    "title": "hex encoded bytes",
+    "pattern": "^0x[0-9a-f]*$"
+   },
+   "bytes256": {
+    "type": "string",
+    "title": "256 hex encoded bytes",
+    "pattern": "^0x[0-9a-f]{512}$"
+   },
+   "bytes32": {
+    "type": "string",
+    "title": "32 hex encoded bytes",
+    "pattern": "^0x([0-9a-f][0-9a-f]){0,32}$"
+   },
+   "bytes65": {
+    "type": "string",
+    "title": "65 hex encoded bytes",
+    "pattern": "^0x[0-9a-f]{512}$"
+   },
+   "bytes8": {
+    "type": "string",
+    "title": "8 hex encoded bytes",
+    "pattern": "^0x[0-9a-f]{16}$"
+   },
+   "hash32": {
+    "type": "string",
+    "title": "32 byte hex value",
+    "pattern": "^0x([0-9a-f][0-9a-f]){0,32}$"
+   },
+   "uint": {
+    "type": "string",
+    "title": "hex encoded unsigned integer",
+    "pattern": "^0x([1-9a-f]+[0-9a-f]*|0)$"
+   },
+   "uint256": {
+    "type": "string",
+    "title": "hex encoded unsigned integer",
+    "pattern": "^0x[0-9a-f]{0,64}$"
+   },
+   "uint64": {
+    "type": "string",
+    "title": "hex encoded unsigned integer",
+    "pattern": "^0x([1-9a-f][0-9a-f]{0,15})|0$"
+   }
+  }
+ }
+}
\ No newline at end of file
diff --git a/openrpc/generate/generate_test.go b/openrpc/generate/generate_test.go
index 1e4fa2f3dbcc648a9d35bf72cb4d6a4338c95928..c18a5ec91f9dac0b223fe6808750c27ce4560abf 100644
--- a/openrpc/generate/generate_test.go
+++ b/openrpc/generate/generate_test.go
@@ -7,8 +7,8 @@ import (
 	"testing"
 	"text/template"
 
-	"github.com/gregdhill/go-openrpc/parse"
-	"github.com/gregdhill/go-openrpc/types"
+	"gfx.cafe/open/jrpc/openrpc/parse"
+	"gfx.cafe/open/jrpc/openrpc/types"
 	"github.com/test-go/testify/require"
 )
 
diff --git a/openrpc/parse/testdata/execution-api/debug/getters.yaml b/openrpc/parse/testdata/execution-api/methods/debug/getters.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/debug/getters.yaml
rename to openrpc/parse/testdata/execution-api/methods/debug/getters.yaml
diff --git a/openrpc/parse/testdata/execution-api/engine/README.md b/openrpc/parse/testdata/execution-api/methods/engine/README.md
similarity index 100%
rename from openrpc/parse/testdata/execution-api/engine/README.md
rename to openrpc/parse/testdata/execution-api/methods/engine/README.md
diff --git a/openrpc/parse/testdata/execution-api/engine/authentication.md b/openrpc/parse/testdata/execution-api/methods/engine/authentication.md
similarity index 100%
rename from openrpc/parse/testdata/execution-api/engine/authentication.md
rename to openrpc/parse/testdata/execution-api/methods/engine/authentication.md
diff --git a/openrpc/parse/testdata/execution-api/engine/specification.md b/openrpc/parse/testdata/execution-api/methods/engine/specification.md
similarity index 100%
rename from openrpc/parse/testdata/execution-api/engine/specification.md
rename to openrpc/parse/testdata/execution-api/methods/engine/specification.md
diff --git a/openrpc/parse/testdata/execution-api/eth/block.yaml b/openrpc/parse/testdata/execution-api/methods/eth/block.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/block.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/block.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/client.yaml b/openrpc/parse/testdata/execution-api/methods/eth/client.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/client.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/client.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/execute.yaml b/openrpc/parse/testdata/execution-api/methods/eth/execute.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/execute.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/execute.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/fee_market.yaml b/openrpc/parse/testdata/execution-api/methods/eth/fee_market.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/fee_market.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/fee_market.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/filter.yaml b/openrpc/parse/testdata/execution-api/methods/eth/filter.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/filter.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/filter.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/mining.yaml b/openrpc/parse/testdata/execution-api/methods/eth/mining.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/mining.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/mining.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/sign.yaml b/openrpc/parse/testdata/execution-api/methods/eth/sign.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/sign.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/sign.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/state.yaml b/openrpc/parse/testdata/execution-api/methods/eth/state.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/state.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/state.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/submit.yaml b/openrpc/parse/testdata/execution-api/methods/eth/submit.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/submit.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/submit.yaml
diff --git a/openrpc/parse/testdata/execution-api/eth/transaction.yaml b/openrpc/parse/testdata/execution-api/methods/eth/transaction.yaml
similarity index 100%
rename from openrpc/parse/testdata/execution-api/eth/transaction.yaml
rename to openrpc/parse/testdata/execution-api/methods/eth/transaction.yaml