6 releases

0.1.5 Jun 27, 2023
0.1.4 May 16, 2023
0.1.2 Apr 10, 2023
0.0.0 Mar 7, 2023

#139 in HTTP client

MIT license

275KB
1.5K SLoC

I am groot

[Proof of Concept] Rust code generator from OpenRPC spec

OpenRPC spec

JSON-RPC spec

StarkNet OpenRPC spec

Usage

  • Generate the code and then run suggested example:
# git restore examples/gen.rs
# manually remove `mod gen` from the examples/gen.rs (generated code is commited now)
cargo run -- CODE ./api/starknet_api_openrpc.json ./api/starknet_write_api.json ./api/starknet_trace_api_openrpc.json >> examples/gen.rs && cargo fmt
cargo run --example gen
cargo run -- CODE ./api/eth.json >> examples/eth.rs && cargo fmt
cargo run --example eth
  • Dump the AST (for debugging):
cargo run -- TREE ./api/starknet_api_openrpc.json ./api/starknet_write_api.json > tree.txt
  • JSON-roundtrip and JSON-aware comparison with the input file (validate bindings):
cargo run -- JSON ./api/test/input.openrpc 2>/dev/null | jq . > debug.json
diff <(jq --sort-keys . ./api/test/input.openrpc) <(jq --sort-keys . debug.json)

TODO

  1. async version of the Rpc trait
  2. Seamless inclusion into a build process
    • extract -build sub-crate for [build-dependencies]

DONE

  • validation of schema.{minimum, maximum}
  • (eth) Handle "anonymous enums"
    • params (#/components/contentDescriptors/Filter:address)
    • result (#/methods{name='eth_syncing'}:syncing)
    • try "title"? (make mandatory)
  • (eth) Add module-wise Null constant?
    • (de)serialized as null
  • consistent ordering of generated structs
  • validation (against schema.pattern to start with)
    • for primitive types: generate named value-object wrapper when validation is necessary
    • (OK) impl TryFrom<T> + #[serde(try_from = "T")] (see example val)
    • (NO) generate custom (de)serializers for such properties/types?
    • (NO) use serde_valid?
  • value-objects wrappers (Felt, NumAsHex etc)
  • add working example for each starknet_* method
  • align errors with the spec
  • extract name-conflict-aware cache
  • error enum/constants
  • wrap non-required properties with Option<_>
  • wrap non-required arguments with Option<_>
  • add #[serde(flatten)] for reusable chunks included via allOf
  • resolve naming collisions (might required slightly patching the specs)
    • e.g. starknet_getStateUpdate.result vs starknet_getBlockWithTxs.result
  • use value-objects instead of type aliases
    • value-objects without validation do not make much sense (e.g. match against regex)
    • library (vs. framework) approach is to avoid making decisions for the client code
    • is client code allowed to send "invalid" data?
    • is client code allowed to receive "invalid" data?
    • up to client code - thus no validation (at least out of the box, at least for now)
  • run against most recent Starknet specs
  • support multiple files with specs
  • generate the Rpc trait
  • generate handle function of method handlers
  • provide OpenRPC and JSON-RPC bindings
  • add batch support by the spec
    • out of scope: can be easily supported on web-framework level
  • impl notifications by the spec
    • out of scope: on web-framework level just don't send the response
  • HTTP-based server generation (?)
    • nope: can be easily built around trait Rpc impl
  • HTTP-based client generation (?)
    • nope: can be easily built around trait Rpc impl

Misc

Total lines of code: find . -type f -name "*.rs" | xargs grep . | wc -l

Dependencies

~3.5–6MB
~105K SLoC