DAML Smart Contracts Appetizer
I am very enthusiastic about DAML, and for good reason. DAML has a lot going for it:
- It’s a strongly typed, functional programming language, based on Haskell
- The language and its developer tools are open source
- It comes with a smart contract test framework
- DAML has private transactions out of the box, controlled using a declarative, easy to understand permissions system, without requiring deployment of extra private transaction management software.
- Transaction participants are modeled as a native DAML data type (Party)
- It has a “decimal” data type and can natively do decimal arithmetic which, believe it or not, most smart contract programming stacks can’t do.
- There is a nice Visual Studio Code integration.
- It’s not only a language but also a runtime specification.
- There is a variety of DAML ledger implementations, both open source and commercial, built on top of a wide range or persistence layers, ranging from relational databases to full blown block chains.
- A runtime implementation will typically expose both a gRPC API and a JSON API. This makes it extremely easy for back-end applications written in basically any language to to interact with a DAML runtime.
DAML is Easy To Get Started With
After installing the SDK you can immediately generate a project by typing
daml create-daml-app myapp
Once you’ve done that you can open up the DAML files in VS Code and start writing code and scenarios (tests)
Running the scenarios for the first time will show you all created contracts with their content and disclosure details in a panel. After that, as soon as you modify the code, the results and disclosure details will be updated in real time.
If you want to interact with your smart contracts you need to start the ledger. For that you go to the myapp directory and type
to compile the project and then
daml sandbox — ledgerid my_ledger_id ./.daml/dist/myapp-0.1.0.dar
to start the ledger up.
DAML smart contracts are modeled after paper contracts. In real life, most of the times when you need to enter into an agreement with other parties, you:
- get a contract template
- fill in the blanks
- sign it
- pass it on to the next stakeholders, they read it and if they agree to the terms, they sign it.
Once all the stakeholders have signed, the contract takes effect.
The contract is visible to all the signers of course, but can also be disclosed to certain observers. Observers are typically regulators, court registries, etc.
During the lifetime of the contract, the terms may allow you to exercise various choices, such as backing out of the contract, or modifying the terms or whatnot.
If you choose to modify the terms then the old paper contract gets archived, a new template is filled in with the modified data, and the new version takes effect.
But you can also choose to exercise a choice that does not require to amend the contract, such as sending a notice to someone, or making a payment.
Now let’s see how the real-life concepts above map to DAML.
When you code in DAML, you don’t write contracts, you write contract templates. Here’s a simple example extracted from the default project generated by the CLI.
This source code represents a DAML template.
It is identical in purpose to a paper contract template, in that it codifies the contract’s terms, variables — the blanks — and whatever choices may be exercised during the contract’s life cycle.
Declaration and Data
Lines 3–5 declare the template’s name, followed by the keyword “with” and a set of variables.
These variables are the blanks from the paper contract template, which you will fill in when instantiating the contract. They constitute the contract’s data model.
Lines 6–8 add details about some of the variables. Party “username” is a contract signatory and the parties stored in “following” are observers.
The signatories own the contract and can archive it. Observers can read it. But what exactly does this mean?
Each time a contract is created or archived, all signatories and observers will receive an event describing it, provided the respective party has subscribed to those event types. Also, when any of the signatories and observers query the ledger, they’ll get back any contracts they are named on.
This is the mechanism private transactions rely on: each party will only be notified about, and can only see contracts on which they’ve been named.
Lines 10–11 are important as well. they lay out in plain human readable text the terms of the contract. This way any human who accepts it and interacts with it gets a chance to read it and know exactly what it is about.
Lines 13–14 declare an optional contract key.
This is effectively a business primary key, as opposed to the contract’s technical primary key which is the contract ID. It allows anyone who’s entitled to, to look up the contract using this business key.
In this particular example the contract key uses a single data element, but it may as well be a composite.
Lines 15–23 are showing a choice. Without diving into the DAML language details, the way you should read it is:
The choice “Follow” returns a reference to a contract of type User and takes a Party, referred to as “userToFollow”, as a parameter.
Additionally, line 18 declares a controller. The controller declaration defines which parties can exercise the option. In this particular case, it is the “username” party, which also happens to be the signatory. This means only the signatory of the User contract can add to the list of users to be followed.
Controllers must be one or some of the parties declared in the data model section.
DAML tests are called scenarios. You can define a test scenario at the end of your template declaration or in a separate file.
Here’s an example bellow:
The test scenario is very easy to read:
Lines 2–4 provision parties that will be used during the scenario to simulate interactions with the ledger.
In the following lines, each party creates their own User contract. First two users will create their contracts with no followers, while “User 3” three will create a user contract with two users to follow — “User One” and “User Three”
Lines 15 and 16 show “User one” exercising the “Follow” choice on his contract.
When the test is executed successfully for the first time you’ll see the following results panel in VSCode. After that, it will automatically update as you change your source code.
This shows each contract that has been created on the ledger along with their attributes and disclosure details.
In the disclosure details — the right-most columns — S means signer and O means observer.
You can also see that the “User One” contract was initially created with no users to follow. Later, “User One” has exercised the “Follow” choice, the initial version of the contract has been archived and a new version was created, with “User Two” in the “following” section.
As the title mentions, this first article on DAML is meant as an appetizer, show you how powerful it is and how easy it is to get started.
There will be more articles like this one, diving into the details and drawing parallels with imperative programming languages.