The Evolve SDK uses an account-centric module system where every module is an account implementing the AccountCode trait. This guide covers architecture, best practices, and common pitfalls.
Architecture Overview
Creating a Module
Storage Collections
Determinism Requirements
Error Handling
Testing
use evolve_core:: { account_impl, AccountState } ;
use evolve_collections:: { item:: Item , map:: Map } ;
#[ account_impl( MyModule ) ]
pub mod account {
use evolve_core:: { AccountId , Environment , SdkResult } ;
use evolve_macros:: { exec, init, query} ;
#[ derive( evolve_core:: AccountState ) ]
pub struct MyModule {
#[ storage( 0 ) ]
pub counter : Item < u64 > ,
#[ storage( 1 ) ]
pub balances : Map < AccountId , u128 > ,
}
impl MyModule {
#[ init]
pub fn initialize ( & self , initial_value : u64 , env : & mut dyn Environment ) -> SdkResult < ( ) > {
self . counter . set ( & initial_value, env) ?;
Ok ( ( ) )
}
#[ exec]
pub fn increment ( & self , env : & mut dyn Environment ) -> SdkResult < u64 > {
let current = self . counter . get ( env) ?;
let new_value = current + 1 ;
self . counter . set ( & new_value, env) ?;
Ok ( new_value)
}
#[ query]
pub fn get_counter ( & self , env : & mut dyn EnvironmentQuery ) -> SdkResult < u64 > {
self . counter . get ( env)
}
}
}
Concept
Description
AccountCode
Core trait all modules implement
Environment
Mutable execution context (can write state)
EnvironmentQuery
Read-only query context
#[account_impl]
Macro that generates message routing
#[derive(AccountState)]
Generates storage initialization with validation
#[storage(n)]
Assigns unique storage prefix to a field
Environment vs EnvironmentQuery
EnvironmentQuery : Read-only operations (query functions)
whoami() - Current account ID
sender() - Transaction sender
funds() - Attached funds
do_query() - Call another account's query
Environment : Extends EnvironmentQuery with write operations (init, exec functions)
do_exec() - Execute on another account (can modify state)
Attribute
Purpose
Mutates State
Payable
#[init]
Account initialization
Yes
#[init(payable)]
#[exec]
State-mutating operations
Yes
#[exec(payable)]
#[query]
Read-only queries
No
Never