DHL language reference
The file
A contract is Markdown. Front matter first, then any mix of prose and fenced ```dhl blocks; the blocks are read in order as one program. Indentation is four spaces. # starts a comment line inside a block.
---
namespace: sam.tools.loan
version: 1.0.0
merge: Lend=exclusive, Return=exclusive
durability: confirmed
---
Prose for people.
```dhl
aggregate Loan
state
public item: Text(len=200)
```
Front matter
| Key | Required | Meaning |
|---|---|---|
namespace | yes | The contract's name, dotted, lowercase (com.acme.orders.order). Names starting mandala. are reserved. |
version | yes | A semantic version for people; the artifact hash is what identifies behavior. |
merge | no | How concurrent changes from different devices merge, per action: commutes, last_writer or exclusive (the default). See Merge rules for sync. |
durability | no | confirmed (default), grouped, or buffered(100ms). See Durability classes. |
Neither merge nor durability changes the artifact.
struct
A named record type for arguments, list items and query rows.
struct LoanRow
id: Identity
item: Text(len=200)
due: Timestamp?
aggregate
The record's state: one state block of fields, each public or private, with an optional default.
aggregate Loan
state
public owner: Identity
public item: Text(len=200)
public status: Text(len=20)
public revision: Int = 0
private note: Text(len=500)
public fields can be read by queries and clients; private fields only by the contract's own rules. A field without a default starts at its type's zero value.
external
What an action may read from outside its own state:
external
time: [clock_ms]
identity: [root_subject]
datasets: [lines: List<SubjectRef<CartLine>>(capacity=16) from CartLines]
| Entry | Gives |
|---|---|
time: [clock_ms] | context.clock.milliseconds, the decision's clock |
identity: [root_subject] | context.root_subject |
datasets: [name: Type from Query] | dataset.name, the result of one of this contract's queries |
action
action Return(owner: Identity, note: Text(len=500))
api authenticated
authorize dhl
validate
state.status == "out"
context.signer == owner
owner == state.owner
apply
state.status = "back"
state.note = note
state.revision = state.revision + 1
| Line or block | Meaning |
|---|---|
api authenticated / api public | Exposes the action in the generated API. Without it, the action is internal. |
authorize dhl | The contract's own rules decide (the usual choice). |
observe <ref> where <field> == arg.<name> | Reads another record as evidence: the action is refused unless that record matches. Used to check delegations. |
requires | Actions on other records that must succeed with this one, all or nothing. |
validate | One condition per line. All must be true, or the action is refused and nothing changes. |
apply | Assignments to state.*, in order. |
certify upgrade from <artifact id> + migrate | Makes the action an upgrade from an archived version. See Upgrading a contract. |
In expressions
| Name | Is |
|---|---|
state.<field> | The record's current state |
<arg> or arg.<arg> | An argument |
context.signer | The identity that signed |
context.clock.milliseconds | The decision's time (with external time) |
dataset.<name> | An external dataset |
self | This record (in requires) |
Operators: ==, !=, <, <=, >, >=, and / &&, or / ||, not, in, +, -, *, /, %. Text and lists have .len; contains(list, value) tests membership. Strings use double quotes.
requires
action AddLine(line: SubjectRef<CartLine>, product_id: Identity, quantity: Int)
api authenticated
authorize dhl
requires
line.Open(cart=self, buyer=state.buyer, product_id=arg.product_id, quantity=arg.quantity)
validate
quantity > 0
Each required action runs on its own record, is authorized by that record's contract, and is signed by the original signer. for entry in entries repeats one for each item of a list argument.
observe (delegation)
observe delegation where active == true
observe delegation where party == arg.owner
observe delegation where delegate == arg.writer
observe delegation where scope == arg.delegation_scope
The action carries a delegation: SubjectRef<Delegation> argument; DHL checks that record's state matches each line. This is how std.business.payable accepts "Sam for Acme Trading".
query
query Out(owner: Identity, after: Text(len=100))
returns List<LoanRow>
api authenticated
dhlq
sam.tools.loan
| where owner == $owner and status == "out" and ref > $after
| sort ref
| take 100
| select subject as id, ref, item, status
returns names the row type; dhlq starts the query, whose first line is its source (self or a namespace). Arguments are $name. See DHLQ query reference.
Compile errors
The compiler refuses unknown section keywords, types that don't fit, assignments to unknown fields and queries over unknown fields, with the line. Try in the The Workbench until it compiles.