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

KeyRequiredMeaning
namespaceyesThe contract's name, dotted, lowercase (com.acme.orders.order). Names starting mandala. are reserved.
versionyesA semantic version for people; the artifact hash is what identifies behavior.
mergenoHow concurrent changes from different devices merge, per action: commutes, last_writer or exclusive (the default). See Merge rules for sync.
durabilitynoconfirmed (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]
EntryGives
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 blockMeaning
api authenticated / api publicExposes the action in the generated API. Without it, the action is internal.
authorize dhlThe 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.
requiresActions on other records that must succeed with this one, all or nothing.
validateOne condition per line. All must be true, or the action is refused and nothing changes.
applyAssignments to state.*, in order.
certify upgrade from <artifact id> + migrateMakes the action an upgrade from an archived version. See Upgrading a contract.

In expressions

NameIs
state.<field>The record's current state
<arg> or arg.<arg>An argument
context.signerThe identity that signed
context.clock.millisecondsThe decision's time (with external time)
dataset.<name>An external dataset
selfThis 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.