-
Notifications
You must be signed in to change notification settings - Fork 119
Pallet Decoupling
Georgi Zlatarev edited this page Jul 27, 2021
·
1 revision
- Verbosity
- Readability
- Debug
- Maintainability
- ...
Example:
// Definition
pub trait Trait: frame_sysmte::Trait + module1::Trait + module2::Trait + ... {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
...
}
// usage
{
...
// read storages
let module1_value = <module1::ModuleStorage1<T>>::get(key1);
let module2_value = <module2::ModuleStorage2<T>>::get(key2);
// write storages
<module1::ModuleStorage1<T>>::mutate(&key1, |val| {
// some change here
});
<module2::ModuleStorage2<T>>::mutate(&key2, |val| {
// some change here
});
...
}
And you have to import module1 and module2 to your current cargo.toml.
module1 = { path = ".." }
module2 = { path = ".." }
There's a pallet named Exchange
that wants to read/write pallet Token
’s storage.
Token
has a storage:
decl_storage! {
trait Store for Module<T: Trait> as Token {
pub AccountToken get(fn token): map hasher(blake2_128_concat) (T::AccountId, Symbol) => Token;
}
}
- Define a trait(Better do define it in a crate only execept
Token
)
pub trait TokenTrait<AccountId> {
fn decrease(who: &AccountId, symbol: Symbol, amount: u128);
fn increase(who: &AccountId, symbol: Symbol, amount: u128);
fn get_token(who: &AccountId, symbol: Symbol) -> Token;
fn has_token(who: &AccountId, symbol: Symbol) -> bool;
}
- Impl this trait for module
Token
// impl this trait for others module can access and modyfy token'data
impl<T: Trait> token_primitives::TokenTrait<T::AccountId> for Module<T> {
fn decrease(who: &T::AccountId, symbol: Symbol, amount: u128) {
<AccountToken<T>>::mutate((who, symbol), |token| {
token.balance = token.balance.saturating_sub(amount);
});
}
fn increase(who: &T::AccountId, symbol: Symbol, amount: u128) {
<AccountToken<T>>::mutate((who, symbol), |token| {
token.balance = token.balance.saturating_add(amount);
});
}
fn get_token(who: &T::AccountId, symbol: Symbol) -> Token {
<AccountToken<T>>::get((who, symbol))
}
fn has_token(who: &T::AccountId, symbol: Symbol) -> bool {
<AccountToken<T>>::contains_key((who, symbol))
}
}
- Register a trait handler for module
Exchange
.
use token_primitives::{Symbol, TokenTrait};
pub trait Trait: frame_system::Trait {
type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;
/// Token trait handler
type TokenTrait: TokenTrait<Self::AccountId>;
}
// usage
ensure!(
T::TokenTrait::has_token(&exchanger, exchange_symbol) && T::TokenTrait::has_token(&exchanger, target_symbol),
Error::<T>::UserHasNoThisToken
);
ensure!(
T::TokenTrait::get_token(&exchanger, exchange_symbol).balance >= amount,
Error::<T>::ExchangeTooMuch
);
- Connect them in runtime
// configure token for runtime
impl token::Trait for Runtime {
type Event = Event;
}
// configure token exchange for runtime
impl token_exchange::Trait for Runtime {
type Event = Event;
type TokenTrait = Token; // this is the key for decoupling modules
}
construct_runtime!(
pub enum Runtime where
Block = Block,
NodeBlock = node_primitives::Block,
UncheckedExtrinsic = UncheckedExtrinsic
{
…
// construct token and exchange fo runtime
Token: token::{Pallet, Call, Storage, Event<T>},
TokenExchange: token_exchange::{Pallet, Call, Storage, Event<T>},
}
);