Module handlers
StreamingFast Substreams module handlers
To begin creating the custom module handlers initialize a new Rust project by using the
cargo
init
command.# Creates a empty Rust project suitable for WASM compilation
cargo init --lib
Cargo.toml
1
[package]
2
name = "substreams-template"
3
version = "0.1.0"
4
description = "Substream template demo project"
5
edition = "2021"
6
repository = "https://github.com/streamingfast/substreams-template"
7
8
[lib]
9
name = "substreams"
10
crate-type = ["cdylib"]
11
12
[dependencies]
13
ethabi = "17"
14
hex-literal = "0.3.4"
15
prost = "0.11"
16
# Use latest from https://crates.io/crates/substreams
17
substreams = "0.5"
18
# Use latest from https://crates.io/crates/substreams-ethereum
19
substreams-ethereum = "0.9"
20
21
# Required so ethabi > ethereum-types build correctly under wasm32-unknown-unknown
22
[target.wasm32-unknown-unknown.dependencies]
23
getrandom = { version = "0.2", features = ["custom"] }
24
25
[build-dependencies]
26
anyhow = "1"
27
substreams-ethereum = "0.8"
28
29
[profile.release]
30
lto = true
31
opt-level = 's'
32
strip = "debuginfo"
You compile the Rust code into WebAssembly (WASM), a binary instruction format that runs in a virtual machine. The compilation process generates a .so file.
Build the Rust dynamic system library after the
package
by using:Cargo.toml excerpt
...
[lib]
crate-type = ["cdylib"]
Note: Module handlers compile down to a WASM module. Explicitly specify the target
asm32-unknown-unknown
by using [target.wasm32-unknown-unknown.dependencies]
.The
ethabi
crate is used to decode events from the application binary interface (ABI) and is required for substreams-ethereum
ABI capabilities.The
substreams-ethereum
crate offers all the Ethereum constructs including blocks, transactions, eth, and useful ABI decoding capabilities.Because code is being built by WASM output it's necessary to configure Rust to match the correct architecture. Create and add a
rust-toolchain.toml
configuration file at the root of your Substreams directory.rust-toolchain.toml
1
[toolchain]
2
channel = "1.65"
3
components = [ "rustfmt" ]
4
targets = [ "wasm32-unknown-unknown" ]
Build the code by using:
cargo build --target wasm32-unknown-unknown --release
When running
cargo build
the target is set to wasm32-unknown-unknown
, which is important because it specifies the goal is to generate compiled WASM code.To avoid having to specify the target
wasm32-unknown-unknown
for every cargo
command, create a config.toml
configuration file in the .cargo
directory at the root of the Substreams project. The config.toml
configuration file allows the target to be set automatically for all cargo
commands.The content for the
config.toml
configuration file is:.cargo/config.toml
[build]
target = "wasm32-unknown-unknown"
The
config.toml
configuration file updates the default cargo build
command to cargo build --target wasm32-unknown-unknown
eliminating the need to specify the target manually every time you build.The
substreams-ethereum
crate offers an Abigen
API to generate Rust types from a smart contract's ABI.Before building a package, Cargo compiles a build script into an executable if it has not already been built. The build script runs as part of the build process responsible for performing a variety of tasks.
To cause Cargo to compile and run a script before building a package, place a file called
build.rs
in the root of the package.build.rs
1
use anyhow::{Ok, Result};
2
use substreams_ethereum::Abigen;
3
4
fn main() -> Result<(), anyhow::Error> {
5
Abigen::new("ERC721", "abi/erc721.json")?
6
.generate()?
7
.write_to_file("src/abi/erc721.rs")?;
8
9
Ok(())
10
}
Run the build script to generate the ABI directory and files.
cargo build --target wasm32-unknown-unknown --release
src/abi/mod.rs
1
pub mod erc721;
Last modified 7mo ago