--- name: cosmwasm-contract description: Axone contract structure and Abstract SDK patterns. Use when scaffolding or refactoring contracts, deciding layer boundaries, wiring AppContract entrypoints, or adding module metadata and replies. license: BSD-3-Clause metadata: author: axone.xyz version: "1.0" --- # CosmWasm Contract Structure ## Companion Skills Use `rust-contract-domain-modeling` for invariant-heavy domain design, `api-design` for message surfaces, `api-doc-comments` for schema-facing documentation, `rust-testing` for tests, and `rust-quality-gates` for validation gates. ## Repository Structure The repository has: - a workspace-level `Makefile.toml` for shared tasks - a contract-level `Makefile.toml` in each contract for local helpers - one directory per contract under `contracts/` ## Minimal Contract Skeleton Start from this minimal shape: ```text contracts// ├── Cargo.toml ├── Makefile.toml ├── README.md ├── metadata.json ├── src/ │ ├── lib.rs │ ├── contract.rs │ ├── msg.rs │ ├── state.rs │ ├── error.rs │ ├── handlers/ │ │ ├── mod.rs │ │ ├── instantiate.rs │ │ ├── execute.rs │ │ ├── query.rs │ │ └── migrate.rs │ └── bin/ │ ├── schema.rs │ ├── publish.rs │ └── install.rs └── tests/ └── integration.rs ``` Add extra layers only when they clarify boundaries. ## Optional Layers Already Used In This Repo Current repository layers include: - `domain/` for explicit business concepts and invariants - `services/` for orchestration and environment-aware composition - `gateway/` for external module interaction and protocol I/O - `queries/` for query string / payload builders - `replies/` for reply handlers `axone-gov` is the reference example for the richer layered shape. ## Layer Boundaries - `msg.rs` defines the public contract surface. - `contract.rs` wires the `AppContract` entrypoints and module metadata. - `handlers/` should stay thin: decode messages, call domain/services, build responses. - `domain/` should own invariants and canonical representations. - `services/` should coordinate enriched flows or external calls without becoming a second handler layer. - `gateway/` should isolate external query / module plumbing. - `state.rs` should persist and reconstruct values, not silently redefine business rules. ## `lib.rs` Pattern Keep module identity constants explicit: ```rust pub const AXONE_NAMESPACE: &str = "axone"; pub const CONTRACT_NAME: &str = "my-contract"; pub const CONTRACT_ID: &str = const_format::concatcp!(AXONE_NAMESPACE, ":", CONTRACT_NAME); pub const APP_VERSION: &str = env!("CARGO_PKG_VERSION"); ``` ## `contract.rs` Pattern The baseline `AppContract` wiring looks like this: ```rust use abstract_app::AppContract; pub type MyContract = AppContract< MyContractError, MyContractInstantiateMsg, MyContractExecuteMsg, MyContractQueryMsg, MyContractMigrateMsg, >; const APP: MyContract = MyContract::new(CONTRACT_ID, APP_VERSION, None) .with_instantiate(handlers::instantiate_handler) .with_execute(handlers::execute_handler) .with_query(handlers::query_handler) .with_migrate(handlers::migrate_handler) .with_dependencies(&[]); #[cfg(feature = "export")] abstract_app::export_endpoints!(APP, MyContract); abstract_app::cw_orch_interface!(APP, MyContract, MyContractInterface); ``` Repository-specific refinements: - Use `Some(APP_METADATA_URL)` when the contract publishes metadata from a tagged GitHub URL. - Add `.with_replies(...)` when the contract has reply-driven flows. - Keep `.with_dependencies(&[])` explicit unless real module dependencies exist. - Add the non-wasm `DependencyCreation` impl when the interface needs the standard installation path used in this repo. ## Message Wiring Use `abstract_app::app_msg_types!(...)` in `msg.rs` when following the repository's Abstract app pattern. Keep message docs and response typing aligned with: - `api-design` - `api-doc-comments` ## Error Design Error enums should include the standard conversion layers used by the contract and then domain-specific errors. Do not hide domain invariants in generic `StdError` messages if a dedicated error variant would make the failure explicit. ## Replies and Metadata Two patterns matter in this repository: - `metadata.json` is part of the contract deliverable and should stay aligned with the module identity. - reply handlers are normal when contract setup involves follow-up callbacks or submessage completion. Treat both as first-class contract structure, not optional afterthoughts. ## Construction Rules - Put invariant checks close to domain object creation. - Keep handler branches short; move validation-heavy logic out of handlers. - Prefer explicit constructors such as `new`, `try_new`, or `from_state`. - Reuse canonical domain types rather than passing partially validated strings across layers.