Project to learn Substrate by developing custom kitties
pallet.
The project contains two starter applications:
- Substrate Front End Template (
tutorials/solutions/kitties
branch) - Substrate Node Template
To run the project you can either manually run docker-compose up
or take advantage of VS Code dev containers as shown in rust-devcontainer.
Once the container is running you can start the Substrate node by running the following:
cd /apps/node
cargo build --release
/tmp/target/release/node-template --dev
To connect to the Substrate node backend you can run the Substrate frontend app that uses Polkadot JS:
cd /apps/frontend
yarn install
yarn start
The quickest way of building a custom pallet is to start with the example pallets/template.
cp -rf node/pallets/template node/pallets/kitties
Rename the package name in the new pallet's Cargo.toml
[package]
-name = "pallet-template"
+name = "pallet-kitties"
version = "4.0.0-dev"
description = "FRAME pallet template for defining custom runtime logic."
authors = ["Substrate DevHub <https://github.com/substrate-developer-hub>"]
Add pallet project to node
Cargo workspace
members = [
"node",
"pallets/template",
+ "pallets/kitties",
"runtime",
]
Build project to confirm that pallet was correctly configured.
cargo build -p pallet-kitties
Now that we have a skeleton of our custom pallet we can start adding custom logic to suit our business needs. For our pallet to be usable we need to create dispatchable (i.e. extrinsic) function. To achieve that we need the fulfill the following requirements:
-
Pallet Config
For pallet to be used on the blockchain we need to define the custom parameters and types that our pallet will work with. This is defined in pallet'slib.rs
file. For example: KittyRandomness. -
Custom Type
Define your custom types that represent your custom assets/objects. This is defined in pallet'slib.rs
file. For example: Kitty. -
Custom Storage
Define your custom storage to track the states in your pallet. This is defined in pallet'slib.rs
file. For example: CountForKitties. -
Custom Events
Your pallet will emit custom events for different state transitions. This needs to be defined inEvent<T: Config>
enum. This is defined in pallet'slib.rs
file. For example: Created. -
Custom Errors
Your pallet can run into issues and we would want to throw pallet specific errors. This needs to be defined inError<T>
enum. This is defined in pallet'slib.rs
file. For example: NoKitty. -
Dispatchable functions
To allow others on the blockchain to interact with our pallet we need to expose functions that can be called from external source. These functions are calledextrinsic
and is defined insideimpl
block ofPallet<T>
withpallet::call
macro. This is defined in pallet'slib.rs
file. For example: create_kitty. -
Internal helper functions
Any function that is used only internally should be defined insideimpl
block ofPallet<T>
. This is defined in pallet'slib.rs
file. For example: gen_dna.
Once we have completed our pallet development we need to add this pallet in our runtime. This can be done by performing the following steps:
- Add our pallet as dependency to runtime's Cargo.toml
pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" }
+pallet-kitties = { version = "4.0.0-dev", default-features = false, path = "../pallets/kitties" }
- Add additional dependencies (i.e. crates) that is WASM compatible
pallet-kitties = { version = "4.0.0-dev", default-features = false, path = "../pallets/kitties" }
+pallet-insecure-randomness-collective-flip = { git = "https://github.com/paritytech/substrate", package = "pallet-insecure-randomness-collective-flip", default-features = false, branch = "polkadot-v0.9.42" }
Note: It is important that the branch
of additional dependency is of the same version as other Substrate crates (e.g. sp-core
)
- Configure concreate types for your pallet. This is defined in pallet's
node/runtime/src/lib.rs
file. For example:
impl pallet_kitties::Config for Runtime {
type RuntimeEvent = RuntimeEvent;
type WeightInfo = pallet_kitties::weights::SubstrateWeight<Runtime>;
type Currency = Balances;
type MaxKittiesOwned = frame_support::pallet_prelude::ConstU32<100>;
type KittyRandomness = RandomnessCollectiveFlip;
}
- Add our pallet to
construct_runtime!
macro innode/runtime/src/lib.rs
TemplateModule: pallet_template,
+ RandomnessCollectiveFlip: pallet_insecure_randomness_collective_flip,
+ Kitties: pallet_kitties,
We can now build and launch the blockchain which includes our custom pallet.
cd /apps/node
cargo build --release
/tmp/target/release/node-template --dev
Interact with our kitties
pallet using frontend
cd /apps/frontend
yarn start
Our local blockchain is now accessible at http://localhost:8000
Here's a list of some references that were very helpful in understanding Substrate pallet development:
- Substrate Collectables (Workshop)
- Substrate Collectables (Workshop) - Video
- Build the Substrate Kitties Chain
- Substrate Knowledge Map
- Learn Rust syntax for Substrate
- Architecture and Rust libraries
- Custom pallets
- Deep dive into FRAME V2 pallet macros
That's it. Happy chaining!