Dev Note #1: Moving schema.rs from examples to bin

Simon Warta
CosmWasm
Published in
3 min readDec 9, 2022

Welcome to CosmWasm Dev Notes, an experimental format for the CosmWasm community. The deal is this. We are busy building for you, but communication is important. However, fully-fledged marketing material takes a lot of effort. So a lot of valuable information ends up on Twitter which is hard to find later on. Or it remains hidden in code and GitHub discussions. The rules for dev notes are they might feel rough, expect typos, come irregularly, and any note might be the last one, mid-level CosmWasm/CosmJS understanding is required as it will get nerdy. Let’s go!

Recently the fabulous Mike published a video on CosmWasm contract best practices. One aspect there was moving the schema generator out of examples into a folder called “schema-maker. At Confio, we agree that the schema generator should not be an “example” for the very reason Mike mentioned as well.

Since schema.rs is not an example at all (it generates an important build artifact!), it's a confusing layout and probably not the proper place for this code. [Tom from Confio, 2022–07–18]

In the following months, we migrated all contracts that we did not miss from examples/schema.rs to bin/schema.rs and adapted the alias in .cargo/config to schema = "run --bin schema" such that you can use cargo schema just like before to generate the schemas.

🤝 with Mike

This solution is pretty much the same as the one Mike is proposing. And it is the result of the same motivation. A subtle difference is that by using conventions of the Cargo build system (the src/bin folder), we do not need to add the [[bin]] section in Cargo.toml. This magically works and does the same thing behind the scenes.

Problems and mitigations

In contrast to examples, the bin targets are built as part of the default cargo build. But CosmWasm contracts do not contain any bin which is compiled to Wasm. It is all happening in the lib part. Now a cargo build --target wasm32-unknown-unknown would try to build the schema generator to Wasm, which does not work. In order to avoid that, we need to restrict the contract build using --lib. So you now see this extra argument in the aliases:

[alias]
wasm = "build --release --lib --target wasm32-unknown-unknown"
wasm-debug = "build --lib --target wasm32-unknown-unknown"
unit-test = "test --lib"
integration-test = "test --test integration"
schema = "run --bin schema"

This change was also applied to rust-optimizer and needs to be applied to other tools like the community project cw-optimizoor.

Perfect solution?

We think the new way is better, but it is not perfect.

A clean solution would require extracting interface types into a separate Rust library project, which is then used by the contract project and a schema generator project. The other option is having an external AST tool that generates schemas from reading Rust source or some definition file that has not yet been invented. Both come with big overhead, but we might be seeing telescope/ts-codegen by Cosmology exploring this in the future.

You could argue that schema.rs and cargo schema are not descriptive enough, and we should take Mike’s naming suggestion and rename them to “make_schema” or something like that.

For now, I think we have reached the “good enough” state, but the conversation will move on if I’m wrong here.

Ps.: Schemas got significantly simpler and more powerful with CosmWasm 1.1.

--

--