Daml Cheat Sheet
Daml is an open-source smart contract language designed to build composable applications on an abstract ledger model.
Daml is a high level language that focuses on data privacy and authorization of distributed applications. These concepts are represented first class in the language.
By abstracting data privacy and authorization, Daml takes the burden off the programmer to think about concrete cryptographic primitives and lets her focus on workflow logic.
Daml is a statically typed functional language.
The full documentation of Daml can be found here.
|
A party represents a person or legal entity (for example a bank). Parties can create contracts and exercise choices and are represented by the |
|
Signatories, observers, and controllers are parties involved in actions taken on a contract, i.e., actions that are exercised on a contract. Signatories, observers, and controllers are therefore represented by the |
|
Contracts are created from blueprints called
Every contract is a template instance stored as a row on the ledger. Contracts are immutable: once they are created on the ledger, the information in the contract cannot be changed. In order to “change” a contract you need to create a new one with the desired contract data. |
|
A choice is something that a party can exercise (take action) on a contract. Choices give you a way to transform the data in a contract: while the contract itself is immutable, you can write a choice that archives the contract and creates a new version of it with the updated data. A choice can only be exercised by its controller and contains the |
|
The ledger represents the database where all contracts are recorded. More information on Daml Ledgers can be found here. |
If you are interested you can find the detailed glossary here.
Install the daml assistant |
|
Create a new Daml project |
|
Create a new Daml/React full stack project |
|
Start the IDE |
|
Build project |
|
Build project, start the sandbox and JSON-API |
|
Start the sandbox ledger (in wall-clock time-mode) |
|
Start the sandbox ledger (in static time-mode) |
|
Start the JSON-API server (requires a running ledger) |
|
Upload a dar to the ledger |
|
Run all test scripts and output test coverage report |
|
Project configuration file |
|
End-of-line comment |
|
Delimited comment |
|
Every Daml file starts with a module header like this: module Foo where
Type annotation |
|
Builtin types |
|
Type synonym |
|
Lists |
|
Tuples |
|
Polymorphic types |
|
Record |
|
Product type |
|
Sum type |
|
Record with type parameters |
|
Deriving Show/Eq instances |
|
Signature |
|
Definition |
|
Lambda definition |
|
Polymorphic functions |
|
Function application |
|
Partial application of functions
salute : Text -> Text
salute = f "Hello"
Functions are first class members of Daml, in particular, functions can be arguments to functions
apply : (Text -> Text) -> Text -> Text
apply h x = h x
apply salute "John" -- "Hello John"
Contract templates describe data that will be stored on the ledger. Templates determine who can read and write data; and by whom and how this data can be altered. A contract template is defined with the template keyword:
template MyData
with
i : Int
party1 : Party
party2 : Party
dataKey : (Party, Text)
where
signatory party1
observer party2
key dataKey : (Party, Text)
maintainer key._1
choice MyChoice : ()
...
with
and where
are keywords to structure the template.
|
Observes the contract and its evolution. Gives the signatory’s authority to all the defined contract updates in the contract choices. |
|
Observes the contract and its evolution. |
|
A field of the contract data used as primary index of contracts defined by this template, see |
|
A set of parties that guarantee uniqueness of contract keys of this template on the ledger, see |
Contract keys are unique and stable references to a contract that won’t change even if the contract id of that contract changes due to an update.
Contract keys are optional.
Contract keys have an associated set of key maintainer parties. These parties guarantee the uniqueness of their maintained keys.
Contract keys are specified on a contract template with the key
and maintainer
keywords. If you specify a key you also have to specify its maintainers
.
|
Can be any expression of the contract arguments that does not contain a contract id. It must include all maintainer parties specified in the |
|
Keys are unique for all specified maintainers. The maintainers need to be a projection of the expression specified with |
The choices of a contract template specify the rules on how and by whom contract data can be changed.
(nonconsuming) choice NameOfChoice : ()
-- optional nonconsuming annotation, name and choice return type
with
party1 : Party -- choice arguments
party2 : Party
i : Int
controller party1, party2 -- parties that can execute this choice
do -- the update that will be executed
assert (i == 42)
create ...
exercise ...
return ()
Choices can be consuming
or nonconsuming
.
|
The default. The contract is consumed by this choice. Trying to exercise another choice on the same contract id will fail. |
|
The contract is not consumed by this choice and more choices can be exercised. |
Updates specify the transactions that will be committed to the ledger. Updates are described within a do block:
do
cid <- create NewContract with field1 = 1
, field2 = "hello world"
let answer = 42
exercise cid SomeChoice with choiceArgument = "123"
return answer
|
create an instance of the given template on the ledger
|
|
exercise a choice on a given contract by contract id
|
|
exercise a choice on a given contract by contract key
|
|
fetch the contract data from the ledger by contract id
|
|
fetch the contract id and data from the ledger by contract key
|
|
check whether a contract with the given key exists and if yes, return the contract id
|
|
abort a transaction with an error message, the transaction will not be committed to the ledger
|
|
assert that a given predicate holds, otherwise fail the transaction
|
|
get the ledger effective time
|
|
return a value from a do block
|
|
bind a local variable or define a local function within the update do block let createContract x = create NameOfContract with issuer = x; owner = x
let answer = 42
|
|
refers to the current contract data that contains this update in a choice
|
|
run a for loop of actions over a list
|
Daml script is a scripting language to run Daml commands against a ledger. For example:
module Test where
import Daml.Script
test : Script ()
test = do
alice <- allocateParty "Alice"
bob <- allocateParty "Bob"
c <- submit alice $ createCmd NewContract with ...
submit bob $ exerciseCmd c Accept with ...
Scripts are compiled like usual Daml code to a dar
package with the daml build
command.
Running a script |
|
Running a script with initial arguments given |
|
Allocating a party on the ledger |
|
List all known parties on the ledger |
|
Query for a given contract template visible to a given party |
|
Create a new contract |
|
Exercise a choice on a contract |
|
Exercise a choice on a contract by contract key |
|
Create and then exercise a choice on the created contract |
|
Pass time on the ledger (only applicable for a ledger running in STATIC TIME MODE, like the in-memory ledger of Daml Studio or |
|
Set time on the ledger (only applicable for a ledger running in STATIC TIME MODE, like the in-memory ledger of Daml Studio or |
|
Daml ledgers expose a unified API for interaction.
The following describes how to interact with a ledger using the TypeScript libraries @daml/ledger
, @daml/react
in a frontend build with React.
Import the libraries via:
import Ledger from @daml/ledger
import {useParty, ...} from @daml/react
React entry point:
import DamlLeddger from @daml/react
const App: React.FC = () => {
<DamlLedger
token: <your authentication token>
httpBaseUrl?: <optional http base url>
wsBaseUrl?: <optional websocket base url>
party: <the logged in party>
>
<MainScreen />
</DamlLedger>
};
Get the logged in party |
const party = useParty();
...
<h1> You're logged in as {party} </h1>
|
Query the ledger |
|
Query for contract keys |
|
Reload the query results |
reload = useReload();
...
onClick={() => reload()}
|
Query the ledger, returns a refreshing stream |
|
Query for contract keys, returns a refreshing stream |
|
Create a contract on the ledger |
const ledger = useLedger();
const newContract = await ledger.create(ContractTemplate, arguments)
|
Archive a contract on the ledger |
const ledger = useLedger();
const archiveEvent = await ledger.archive(ContractTemplate, contractId)
|
Exercise a contract choice on the ledger |
const ledger = useLedger();
const [choiceReturnValue, events] = await ledger.exercise(ContractChoice, contractId, choiceArguments)
|