Side-by-Side Syntax Comparison
template MyContract
with
owner : Party
data : Text
where
signatory owner
choice DoSomething : ContractId MyContract
with param : Text
controller owner
do
create this with data = param
#[entry_point]
pub fn instantiate(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
let state = State { owner: info.sender, data: msg.data };
STATE.save(deps.storage, &state)?;
Ok(Response::new())
}
#[entry_point]
pub fn execute(
deps: DepsMut,
_env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
match msg {
ExecuteMsg::DoSomething { param } => { /* ... */ }
}
}
-- In a choice or script
cid <- create MyContract with
owner = party
data = "hello"
// Via CLI or another contract
let msg = WasmMsg::Instantiate {
admin: Some(admin.to_string()),
code_id,
msg: to_json_binary(&InstantiateMsg { data: "hello".into() })?,
funds: vec![],
label: "my-contract".into(),
};
PartyAddrContractId aAddr (contract address)TextStringInti64 / i128DecimalDecimal / Uint128BoolboolTimeTimestampDateTimestamp (seconds)[a] (List)Vec<T>Optional aOption<T>Map k vMap<K, V> (cw-storage-plus)data Status
= Pending
| Active
| Completed
deriving (Eq, Show)
data Order = Order with
id : Text
amount : Decimal
status : Status
#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub enum Status {
Pending,
Active,
Completed,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct Order {
pub id: String,
pub amount: Uint128,
pub status: Status,
}
-- Query by contract ID
Some contract <- queryContractId party cid
-- Query all contracts of a type
contracts <- query @MyContract party
-- Query with filter
results <- queryFilter @MyContract party
(\c -> c.owner == party)
// Load single item
let state = STATE.load(deps.storage)?;
// Load from map
let order = ORDERS.load(deps.storage, &order_id)?;
// Optional load
let maybe = ORDERS.may_load(deps.storage, &id)?;
// Range query
let orders: Vec<_> = ORDERS
.range(deps.storage, None, None, Order::Ascending)
.take(10)
.collect::<StdResult<_>>()?;
-- Built into controller declaration
choice Transfer : ContractId Asset
with newOwner : Party
controller owner -- Only owner can call
do
create this with owner = newOwner
-- Additional runtime checks
choice Withdraw : ()
with amount : Decimal
controller owner
do
assertMsg "Insufficient balance" (amount <= balance)
-- ...
pub fn execute_transfer(
deps: DepsMut,
info: MessageInfo,
new_owner: String,
) -> Result<Response, ContractError> {
let state = STATE.load(deps.storage)?;
// Manual authorization check
if info.sender != state.owner {
return Err(ContractError::Unauthorized {});
}
// Additional checks
ensure!(
amount <= state.balance,
ContractError::InsufficientBalance {}
);
// ...
}
template TimeLock
with
owner : Party
unlockTime : Time
where
signatory owner
choice Unlock : ()
controller owner
do
now <- getTime
assertMsg "Too early" (now >= unlockTime)
pub fn execute_unlock(
deps: DepsMut,
env: Env,
info: MessageInfo,
) -> Result<Response, ContractError> {
let lock = TIMELOCK.load(deps.storage)?;
if env.block.time < lock.unlock_time {
return Err(ContractError::TooEarly {
unlock_time: lock.unlock_time,
});
}
// Proceed with unlock...
}
-- Using assert
assertMsg "Amount must be positive" (amount > 0.0)
-- Using exceptions
exception InsufficientFunds with
requested : Decimal
available : Decimal
where
message "Insufficient funds"
-- Throwing
when (amount > balance) do
throw InsufficientFunds with
requested = amount
available = balance
// Define errors
#[derive(Error, Debug)]
pub enum ContractError {
#[error("{0}")]
Std(#[from] StdError),
#[error("Insufficient funds: need {requested}, have {available}")]
InsufficientFunds { requested: Uint128, available: Uint128 },
#[error("Unauthorized")]
Unauthorized {},
}
// Use ensure! macro
ensure!(amount > Uint128::zero(), ContractError::InvalidAmount {});
// Or explicit return
if amount > balance {
return Err(ContractError::InsufficientFunds { requested: amount, available: balance });
}
daml new my-project
cargo generate --git cw-template
daml build
cargo wasm
daml test
cargo test
daml start
docker run cosmwasm/optimizer
daml script --dar app.dar --script-name Main:setup
wasmd tx wasm store contract.wasm
daml damlc docs
wasmd tx wasm instantiate $CODE_ID '{}'
// Start Canton
bin/canton -c canton.conf
// Connect to domain
participant1.domains.connect_local(mydomain)
// Upload DAR
participant1.dars.upload("app.dar")
// List parties
participant1.parties.list()
// Health check
participant1.health.status()
# Query contract
wasmd query wasm contract-state smart $ADDR '{"get_count":{}}'
# Execute
wasmd tx wasm execute $ADDR '{"increment":{}}' --from wallet
# List contracts
wasmd query wasm list-contract-by-code $CODE_ID
# Get contract info
wasmd query wasm contract $ADDR
# Migrate contract
wasmd tx wasm migrate $ADDR $NEW_CODE '{}' --from admin
template -- Define contract type
with -- Contract fields
where -- Contract body
signatory -- Required signers
observer -- Can see contract
controller -- Can exercise choice
choice -- Define action
nonconsuming -- Don't archive on exercise
preconsuming -- Archive before exercise
postconsuming -- Archive after exercise
key -- Unique contract key
maintainer -- Key maintainer
ensure -- Creation precondition
agreement -- Human-readable text
create -- Create new contract
exercise -- Call a choice
fetch -- Get contract data
archive -- Archive contract
assertMsg -- Runtime assertion
getTime -- Current ledger time
forA -- Loop with actions
foldlA -- Fold with actions
// Core types
use cosmwasm_std::{
entry_point, // Mark entry points
DepsMut, Deps, // Storage access
Env, // Block info, contract addr
MessageInfo, // Sender, funds
Response, // Return type
StdResult, // Result alias
StdError, // Standard errors
Addr, // Validated address
Uint128, // 128-bit unsigned
Decimal, // Fixed-point decimal
Coin, coins, // Native tokens
BankMsg, // Send tokens
WasmMsg, // Call contracts
to_json_binary, // Serialize
from_json, // Deserialize
};
// Storage
use cw_storage_plus::{
Item, // Single value
Map, // Key-value map
IndexedMap, // Map with indexes
};
// Standard interfaces
use cw2::set_contract_version;
use cw20::{Cw20ExecuteMsg, Cw20QueryMsg};