---
# System prepended metadata

title: 为 Gear 合约添加自定义状态查询函数

---

# 为 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
