View Routes
View routes are read-only entry points. They can inspect entity state but cannot modify it, send messages, or perform side effects. Use them to expose queries to callers and other entities.
Syntax
View routes are declared with the view keyword and a return type:
view get_balance() -> U256 => [
return(m_balance)
]
Return Type
A view route should declare a return type with -> Type (omitting it is only
a warning, but such a view is useless to callers) and include a
return(value) action:
view get_owner() -> address => [
return(m_owner)
]
view get_name() -> String => [
return(m_name)
]
view total_supply() -> U256 => [
return(m_total_supply)
]
Read-Only Guarantee
View routes have the following restrictions:
| Allowed | Forbidden |
|---|---|
| Read member values | Modify members (no transforms) |
| Call pure functions | Send messages or value (~>) |
Use if/else, match | Deploy entities |
| Compute intermediate values | Emit events |
call a state-changing route |
Cambrian rejects a view that calls a route with member transforms or
state-changing actions (directly or through further calls). On EVM it also
rejects a view whose body emits, sends, or deploys, since Solidity does not
allow these in a view function.
Computed Views
View routes can perform computations on state before returning:
view get_balance_of(account: address) -> U256 => [
return(m_balances[account])
]
Indexing a HashMap with a missing key yields the value type’s default
(0 here), so no explicit “absent” handling is needed. Nested maps are
indexed twice:
view is_approved(owner: address, spender: address) -> bool => [
let allowance = m_allowances[owner][spender];
return(allowance > 0)
]
Conditional Returns
Views can use if/else and match to determine the return value:
view get_status_label() -> String => [
let label = match m_status {
Status::Active => "active",
Status::Paused => "paused",
Status::Closed => "closed",
_ => "unknown"
};
return(label)
]
Views with Parameters
View routes can accept parameters to query specific data:
view get_listing(id: u64) -> Listing => [
return(m_listings[id])
]
view get_vote_count(proposal_id: u64) -> u64 => [
return(m_votes[proposal_id])
]
No Member Transforms
View routes do not appear in member transform blocks. Since views cannot
modify state, no member declares in get_balance() => .... If you find
yourself writing a member transform for a view route, you need a regular route
instead.
Complete Example
An entity with multiple view routes:
entity Token {
routes {
// ... regular routes ...
view name() -> String => [
return(m_name)
]
view symbol() -> String => [
return(m_symbol)
]
view total_supply() -> U256 => [
return(m_total_supply)
]
view balance_of(account: address) -> U256 => [
return(m_balances[account])
]
view allowance(owner: address, spender: address) -> U256 => [
return(m_allowances[owner][spender])
]
}
m_name: String {}
m_symbol: String {}
m_total_supply: U256 {}
m_balances: HashMap<address, U256> {}
m_allowances: HashMap<address, HashMap<address, U256>> {}
}