Schema exporter in json/dict format for ccdexplorer.io

Can the Rust to Python converter be expanded to allow the Explorer to display the schema? For example by adding a method that exposes the schema as a json/dict here: ccdexplorer-schema-parser/src/lib.rs at main · ccdexplorer/ccdexplorer-schema-parser · GitHub?

CCDScan does this: CCDScan (tab Schema).

I tried to parse the schema property (from the Schema object) in Python, which is a byte array. However, decoding this gives many decoding error that I can’t seem to solve.

There is a to_json_template() method on the schema that displays the schema in a json template format.

https://docs.rs/concordium-rust-sdk/latest/concordium_rust_sdk/types/smart_contracts/concordium_contracts_common/schema/enum.Type.html#method.to_json_template

https://docs.rs/concordium-rust-sdk/latest/concordium_rust_sdk/types/smart_contracts/concordium_contracts_common/schema/enum.Fields.html#method.to_json_template

For example, at the sc-tools(https://sctools.mainnet.concordium.software/) front end, we display the schema at the front-end as a JSON-template, by invoking the to_json_template rust-binding:

https://github.com/Concordium/concordium-node-sdk-js/blob/04c6a9d136796a946d4bebcc892a228331212fea/packages/rust-bindings/packages/dapp/src/aux_functions.rs#L196 https://github.com/Concordium/concordium-smart-contract-tools/blob/main/front-end-tools/src/components/ReadComponent.tsx#L113

Thanks.
I’ve tried to add the following function to lib.rs, but it fails on build:

#[pyfunction]
fn schema_to_json(
    versioned_module_schema: Vec<u8>,
    contract_name: &str,
    event_data: Vec<u8>,
) -> PyResult<String> {
    let schema: VersionedModuleSchema = match from_bytes(&versioned_module_schema) {
        Ok(s) => s,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Unable to parse schema: {e}"
            )))
        }
    };
    match schema.get_event_schema(contract_name) {
        Ok(s) => match s.to_json_template() {
            Ok(v) => v,
            Err(e) => Err(PyValueError::new_err(format!("Unable to output schema to json"))),
        },
        Err(e) => Err(PyValueError::new_err(format!(""))),
    }
}

Errors:

❯ cargo build
   Compiling ccdexplorer-schema-parser v0.1.9 (/Users/sander/Developer/open_source/ccdexplorer-schema-parser)
error[E0308]: mismatched types
  --> src/lib.rs:84:13
   |
83 |         Ok(s) => match s.to_json_template() {
   |                        -------------------- this expression has type `serde_json::value::Value`
84 |             Ok(v) => v,
   |             ^^^^^ expected `Value`, found `Result<_, _>`
   |
   = note: expected enum `serde_json::value::Value`
              found enum `Result<_, _>`

error[E0308]: mismatched types
  --> src/lib.rs:85:13
   |
83 |         Ok(s) => match s.to_json_template() {
   |                        -------------------- this expression has type `serde_json::value::Value`
84 |             Ok(v) => v,
85 |             Err(e) => Err(PyValueError::new_err(format!("Unable to output schema to json"))),
   |             ^^^^^^ expected `Value`, found `Result<_, _>`
   |
   = note: expected enum `serde_json::value::Value`
              found enum `Result<_, _>`

Given my lack of Rust knowledge, I don’t know what to do here?

As the error suggests, the return value of to_json_template is serde_json::value::Value.

Meaning your function schema_to_json needs to return that value as well instead of a String.

#[pyfunction]
fn schema_to_json(
    versioned_module_schema: Vec<u8>,
    contract_name: &str,
    event_data: Vec<u8>,
) -> PyResult<serde_json::value::Value> {
    let schema: VersionedModuleSchema = match from_bytes(&versioned_module_schema) {
        Ok(s) => s,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Unable to parse schema: {e}"
            )))
        }
    };
    match schema.get_event_schema(contract_name) {
        Ok(s) => s.to_json_template() ,
        Err(e) => Err(PyValueError::new_err(format!("error getting json template"))),
    }
}

Thank you. Tried that, cargo complained about Failed to resolve: use of undeclared crate or module serde_json , which I added in cargo.toml, leading to the next set of build errors:

❯ cargo build
   Compiling ccdexplorer-schema-parser v0.1.9 (/Users/sander/Developer/open_source/ccdexplorer-schema-parser)
error[E0308]: mismatched types
  --> src/lib.rs:83:18
   |
73 | ) -> PyResult<serde_json::value::Value> {
   |      ---------------------------------- expected `Result<serde_json::Value, PyErr>` because of return type
...
83 |         Ok(s) => s.to_json_template() ,
   |                  ^^^^^^^^^^^^^^^^^^^^ expected `Result<Value, PyErr>`, found `Value`
   |
   = note: expected enum `Result<serde_json::Value, PyErr>`
              found enum `serde_json::Value`
help: try wrapping the expression in `Ok`
   |
83 |         Ok(s) => Ok(s.to_json_template()) ,
   |                  +++                    +

error[E0277]: the trait bound `Result<serde_json::Value, PyErr>: OkWrap<_>` is not satisfied
  --> src/lib.rs:68:1
   |
68 | #[pyfunction]
   | ^^^^^^^^^^^^^ the trait `OkWrap<_>` is not implemented for `Result<serde_json::Value, PyErr>`
   |
   = help: the trait `OkWrap<T>` is implemented for `Result<T, E>`
   = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `ccdexplorer-schema-parser` (lib) due to 2 previous errors```

The Ok( ) is missing in my above code snippet. The arms of the match expression should return the same Result type. Can you add the Ok(..) please

Ok(s) => Ok(s.to_json_template()) ,

Current method:

#[pyfunction]
fn schema_to_json(
    versioned_module_schema: Vec<u8>,
    contract_name: &str,
    event_data: Vec<u8>,
) -> PyResult<serde_json::value::Value> {
    let schema: VersionedModuleSchema = match from_bytes(&versioned_module_schema) {
        Ok(s) => s,
        Err(e) => {
            return Err(PyValueError::new_err(format!(
                "Unable to parse schema: {e}"
            )))
        }
    };
    match schema.get_event_schema(contract_name) {
        Ok(s) => Ok(s.to_json_template()) ,
        Err(e) => Err(PyValueError::new_err(format!("error getting json template"))),
    }
}

Current error:

❯ cargo build
   Compiling ccdexplorer-schema-parser v0.1.9 (/Users/sander/Developer/open_source/ccdexplorer-schema-parser)
error[E0277]: the trait bound `Result<serde_json::Value, PyErr>: OkWrap<_>` is not satisfied
  --> src/lib.rs:68:1
   |
68 | #[pyfunction]
   | ^^^^^^^^^^^^^ the trait `OkWrap<_>` is not implemented for `Result<serde_json::Value, PyErr>`
   |
   = help: the trait `OkWrap<T>` is implemented for `Result<T, E>`
   = note: this error originates in the attribute macro `pyfunction` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `ccdexplorer-schema-parser` (lib) due to 1 previous error

Have you tried to convert it to a HexString/String and then return it as a HexString/String by your function?