# 为 Gear 合约添加自定义状态查询函数 ## 上节回顾: [使用 `gmeta` 为 Gear 合约生成 Metadata](https://hackmd.io/@btwiuse/gear-metadata) https://github.com/gear-dapps/app 在 `./src/lib.rs` 中定义 wasm 入口函数 ``` #[no_mangle] extern "C" fn init() { ... } #[no_mangle] extern "C" fn handle() { ... } #[no_mangle] extern "C" fn state() { ... } ``` 在 `./io/src/lib.rs` 中定义 Metadata ``` use gmeta::{InOut, Metadata}; use gstd::{prelude::*, ActorId}; ... pub struct ContractMetadata; impl Metadata for ContractMetadata { type Init = (); type Handle = InOut<PingPong, PingPong>; type Others = (); type Reply = (); type Signal = (); type State = Vec<(ActorId, u128)>; } // Metadata::repr() -> MetadataRepr ``` 在 `./build.rs` 中生成 `app.meta.txt` 以及 `app.opt.wasm` ``` use app_io::ContractMetadata; fn main() { gear_wasm_builder::build_with_metadata::<ContractMetadata>(); } ``` ## 查询合约状态 https://idea.gear-tech.io/programs/0x56cc25f6e1f2102563bb2bbf1365d756b8a647d6cba993836515e524a31e99f9?node=wss%3A%2F%2Fnode-workshop.gear.rs ``` [ [ "0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d", 2 ] ] ``` ## 查询部分状态 ### 在 `./state` 中创建 "app-state" crate #### `./Cargo.toml` 注册路径 ``` # It's necessary to include all metawasm crates in the workspace section, # otherwise they'll be ignored by Cargo and won't be built. [workspace] members = ["state"] ``` #### `./state/Cargo.toml` 导入依赖 ``` [package] name = "app-state" version = "0.1.0" edition = "2021" [dependencies] gstd = { git = "https://github.com/gear-tech/gear.git", branch = "testnet" } gmeta = { git = "https://github.com/gear-tech/gear.git", branch = "testnet", features = ["codegen"] } app-io = { path = "../io" } [build-dependencies] gear-wasm-builder = { git = "https://github.com/gear-tech/gear.git", branch = "testnet", features = ["metawasm"] } ``` #### `./state/src/lib.rs` 自定义查询函数 ``` use app_io::*; use gmeta::{metawasm, Metadata}; use gstd::{prelude::*, ActorId}; #[metawasm] pub mod metafns { pub type State = <ContractMetadata as Metadata>::State; pub fn pingers(state: State) -> Vec<ActorId> { state.into_iter().map(|(pinger, _)| pinger).collect() } pub fn ping_count(state: State, actor: ActorId) -> u128 { state .into_iter() .find_map(|(pinger, ping_count)| (pinger == actor).then_some(ping_count)) .unwrap_or_default() } } ``` #### `./state/build.rs` 构建脚本 ``` fn main() { gear_wasm_builder::build_metawasm(); } ``` 最终编译为 `./target/wasm32-unknown-unknown/release/app_state.meta.wasm` ## 上传到 Gear IDEA https://idea.gear-tech.io/programs/0x56cc25f6e1f2102563bb2bbf1365d756b8a647d6cba993836515e524a31e99f9?node=wss%3A%2F%2Fnode-workshop.gear.rs # 作业 在 GitHub 上 Fork https://github.com/gear-dapps/app, 增加名为 `counts` 的自定义状态查询函数, 用于获取合约收到 PING 消息的总数, 并在 [Gear IDEA](https://idea.gear-tech.io) 上部署,将调用 `counts` 函数结果的截图放在 README 中 作业提交频道: https://t.me/Gear_CN <!-- pub fn counts(state: State) -> u128 { state.into_iter().map(|(_, count)| count).sum() } --> ## 附: `#[metawasm]` 属性宏定义与参考文档 https://github.com/gear-tech/gear/blob/master/gmeta/codegen/src/lib.rs