chain-module-sdk-rust/README.md
flemming-it 5cbdb5324e
Some checks failed
CI / Linux x86_64 (Forgejo) (push) Failing after 1s
chore: finish fai->chain naming in README, repository URL, macro internals
README still documented the crate as fai-module-sdk with a
fai_module_sdk::prelude import; the workspace repository field
pointed at the pre-rename module-sdk-rust URL; the #[fai_module]
expansion used a __fai_module_sdk_internal hygiene module. All
three now carry the chain-module-sdk name. Also note the WIT
contract is chain:platform@1.1 (additive emit-event on the
frozen 1.0 base) and document ctx.emit in the surface table.

Signed-off-by: flemming-it <sf@flemming.it>
2026-07-07 13:43:09 +02:00

60 lines
2.2 KiB
Markdown

# chain-module-sdk
Stable, ergonomic Rust surface for writing Ch∆In modules.
A module written against this crate looks like:
```rust
use chain_module_sdk::prelude::*;
#[fai_module]
fn invoke(_ctx: Context, inputs: Inputs) -> Result<Outputs, ModuleError> {
let text = inputs.require_text("input")?;
Ok(Outputs::new().with_text("output", format!("echo: {text}")))
}
```
That single function — plus a `Cargo.toml` listing
`chain-module-sdk` as a dependency — is the entire module. The
`#[fai_module]` macro generates the `wit_bindgen` invocation, the
`Guest` implementation, the type conversions, and the
`wit_bindgen::export!` glue behind the scenes.
## What the SDK gives you
| You get | Instead of |
|---------|-----------|
| `Inputs::require_text("name")` | manual `match payload { Payload::Text(s) => ..., _ => ... }` |
| `Outputs::new().with_json(...)?` | building `Vec<(String, Payload)>` by hand |
| `ModuleError::invalid_input("...")` | constructing WIT `invocation-error` variants |
| `ctx.emit("progress", ...)` | hand-rolling the `host.emit-event` import (WIT 1.1) |
| `#[fai_module]` | `wit_bindgen::generate!` + `Guest` impl + `export!` + `#![allow(unsafe_op_in_unsafe_fn)]` |
## Stability
The SDK insulates module code from the underlying WIT contract
(`chain:platform`, currently v1.1 — frozen base v1.0 plus the
additive 1.1 `emit-event` import). The WIT may evolve in
additive minor versions or, eventually, a coordinated v2.0; the
SDK absorbs that change so existing module code keeps compiling.
The SDK ships its own copy of `wit/world.wit` so that the
proc-macro can embed the contract via `include_str!` at compile
time. A snapshot test (`crates/chain-module-sdk/tests/wit_freeze.rs`)
asserts the SHA-256 matches the platform's frozen hash — if the
two ever drift, CI fails.
## Versioning
| Track | Stability |
|-------|-----------|
| WIT contract (`chain:platform`) | v1.1; base frozen at v1.0, minors are additive |
| `chain-module-sdk` Rust API | Semver; v0.x while ergonomics evolve |
| Per-module versions | Each module repo's own concern |
## License
Apache-2.0. See `LICENSE`.
Author: Dr. Stefan Flemming, Flemming.AI <chain@flemming.ai>
Repository: https://git.flemming.ai/fai/chain-module-sdk-rust