Understanding the program metadata and state
In this lesson, we'll demonstrate the role of metadata in:
- Converting data into a structured format
- Enabling data exchange between dApp's smart contracts
- Client-side (JavaScript)
The gmeta
crate describes the metadata interface, which requires a description for all types. Moreover, the lesson presents an illustrative example of defining metadata for a program and accessing its state.
Metadata serves as an interface map, enabling the transformation of a set of bytes into an understandable structure. It plays a crucial role in encoding and decoding all incoming and outgoing data.
By facilitating communication and data exchange, metadata allows the smart contract and the client-side (JavaScript) of a dApp to understand each other effectively.
To describe the metadata interface, we use gmeta
crate:
use gmeta::{InOut, Metadata, Out};
pub struct ProgramMetadata;
impl Metadata for ProgramMetadata {
type Init = InOut<MessageInitIn, MessageInitOut>;
type Handle = InOut<MessageIn, MessageOut>;
type Others = InOut<MessageAsyncIn, Option<u8>>;
type Reply = String;
type Signal = ();
type State = Out<Vec<u128>>;
}
Where:
Init
describes incoming/outgoing types forinit()
function.Handle
describes incoming/outgoing types forhandle()
function.Others
describes incoming/outgoing types formain()
function in case of asynchronous interaction.Reply
describes an incoming type of message performed using thehandle_reply()
function.Signal
describes only the outgoing type from the program while processing the system signal.State
describes the types for the queried state
It is necessary to describe all the types. If any endpoints are missing in your program, you can use ()
instead.
Let's define metadata for our example. We'll start by creating a crate:
hello-world-io
in the directory of our hello-world
program:
cargo new io --lib
The Cargo.toml
of this crate:
[package]
name = "hello-world-io"
version = "0.1.0"
edition = "2021"
[dependencies]
gmeta = { git = "https://github.com/gear-tech/gear.git", tag = "v1.4.1" }
gstd = { git = "https://github.com/gear-tech/gear.git", tag = "v1.4.1" }
parity-scale-codec = { version = "3", default-features = false }
scale-info = { version = "2", default-features = false }
And in the lib.rs
file, we'll define an incoming message for the init
function and the incoming and outgoing messages for the handle
function:
#![no_std]
use codec::{Decode, Encode};
use gmeta::{In, InOut, Metadata, Out};
use gstd::{prelude::*, ActorId};
use scale_info::TypeInfo;
pub struct ProgramMetadata;
impl Metadata for ProgramMetadata {
type Init = In<String>;
type Handle = InOut<InputMessages, String>;
type Reply = ();
type Others = ();
type Signal = ();
type State = Out<String>;
}
#[derive(Encode, Decode, TypeInfo)]
pub enum InputMessages {
SendHelloTo(ActorId),
SendHelloReply,
}
The init
function takes a String
input. On the other hand, the handle function needs an InputMessage
enum as input. Its output is a String
representing the program state, which stores a set greeting.
You can read the program state using the state function, paying zero gas fees. We can define this function in the lib.rs file of the hello-world program:
#[no_mangle]
extern "C" fn state() {
let greeting = unsafe {
GREETING
.as_ref()
.expect("The contract is not initialized")
};
msg::reply(greeting, 0).expect("Failed to share state");
}
It's necessary to add the hello-world-io
crate to build-dependencies
in Cargo.toml
in the hello-world
program:
[package]
name = "hello-world"
version = "0.1.0"
edition = "2021"
# ...
[build-dependencies]
gear-wasm-builder = { git = "https://github.com/gear-tech/gear.git", tag = "v1.4.1", features = ["wasm-opt"] }
hello-world-io = { path = "io" }
We also need to change the build.rs
file using the following code:
use hello_world_io::ProgramMetadata;
fn main() {
gear_wasm_builder::build_with_metadata::<ProgramMetadata>();
}
Once you've built the program, it'll generate a hello_world.meta.txt
file upon compiling the smart contract. This metadata file is valuable for UI applications for engagement with the smart contract.