Toolkit for fetching and parsing contract-level events that follow the Casper Event Standard. Enables the event-driven pattern for Rust applications integrated with Casper blockchain.
NOTE: Casper Event Toolkit is similar to MAKE’s ces-go-parser and ces-js-parser, but enhanced with ability to get events directly from the global storage.
You can find full code example at ./examples/cep78_demo.rs
, which can be executed with:
$ cargo run --example cep78_demo
We will walk through it to understand API of this library.
In order to fetch data from Casper L1, we need RPC client:
let client = CasperClient::default_mainnet();
//let client = CasperClient::default_testnet();
//let client = CasperClient::new(rpc_endpoint_url);
You can rely on predefined endpoints for mainnet and testnet, or provide your own URL.
For given smart contract, we need to find blockchain’s storage address where the following data is stored: . events schema, . events data, . events count.
This is so called CES metadata, and can be fetched with utility:
let smart_contract_hash: &str = "fe03021407879ce6fc5e035b70ff6a90941afdbea325a9164c7a497827efa7ff";
let metadata = CesMetadataRef::fetch_metadata(&client, smart_contract_hash).await?;
By combining RPC client and CES metadata, events fetcher can be constructed:
let fetcher = Fetcher {
client,
ces_metadata: metadata,
};
It can be used for fetching events schema, count and data, which we will cover in the next steps respectively.
Schema is required for parsing events data. It can be loaded locally:
let schemas = cep78::schemas::get_local_schemas();
You can also fetch it from the blockchain using fetcher:
let schemas = fetcher.fetch_schema().await?;
If you know deployment hash and want to parse events based on execution results, you can do it with fetcher and schemas:
let deploy_hash: &str = "657ff0cd295bf398988c12f913d3da62946039aab592da0eb5e577627e9bcaf5"
let events = fetcher.fetch_events_from_deploy(deploy_hash, &schemas).await?;
//println!("{:?}", events);
You should start by querying number of events that were emitted:
let num_events = fetcher.fetch_events_count().await?;
//println!("Events count: {}", num_events);
Then you can fetch particular event - IDs are numbers incrementing from 0:
let event_id = 3;
let event = fetcher.fetch_event(event_id, &schemas).await?;
//println!("{:?}", event);
No matter if you used option A (fetch events from deployment results), or option B (fetch event directly from the storage), you will end up with event(s) containing fields in Casper serialization format i.e. CLValue:
pub struct Event {
pub name: String,
pub fields: Vec<(String, CLValue)>, // CLValue here!!!
}
If you have particular event definition, you can use to_ces_bytes()
utility for parsing it:
#[derive(Event, Debug)]
pub struct Mint {
recipient: Key,
token_id: String,
data: String,
}
// ...
match event.name.as_str() {
"Mint" => {
let data = event.to_ces_bytes()?;
let (mint_event, rem) = cep78::events::Mint::from_bytes(&data)?;
//println!("{:?}", mint_event);
This will give you the access to all named and typed fields.
This project is licensed under the terms of the MIT license.