DAML Associate Certification Exam Study Notes
The Syllabus of the DAML Associate Certification is listed below with my study notes in each item.
Daml Language Basics (20%)
Daml Template structure and syntax
Reference: Basic Contracts — Daml SDK 2.2.0 documentation
Contracts contain data. Contracts are instances of templates. The with
block defines the data type.
If we take the RDBMS as the analogue, each template corresponds to a DB table. Each field in the with
block of a template corresponds to a column in that table. Each contract of that template corresponds to a table row.
The signatories of a contract are the parties whose authority is required to create the contract or archive it. The signatories of a contract are guaranteed to see the creation and archival of that contract.
We can declare a Script
as a top-level variable and introduce it using script do
It then calls command to submit transaction to create contract. allocateParty
is the function to create party. Finally, we call pure () on the last line of our script to match the type Script.
Archiving contracts works just like creating them, but using archiveCmd instead of createCmd. Where createCmd takes an instance of a template, archiveCmd takes a reference (contract id) to a contract.
Contract is immutable. To update the contract content, we need to submit a transaction with 2 commands: archive the contract and then create a new contract with new values.
queryContractId
function, which retrieves the arguments of an active contract using its contract ID. If there is no active contract with the given identifier visible to the given party, queryContractId
returns None
. Here, we use a pattern match on Some
which will abort the script if queryContractId
returns None
In the template structure, the key
defines the primary key of a template, with the ability to look up contracts by key. (FetchAccountByKey
). Each key
expression must come with a maintainer
expression. maintainer
takes one or several parties, all of which have to be signatories of the contract.
To define Record struct data type, we can use data
and with
to define the key and its attributes.
Basics of choices and controllers
Reference: Transform Data Using Choices — Daml SDK 2.2.0 documentation
Composing choices
Choices are permissioned functions that result in an Update contract. The controller
owner says that this choice is controlled by owner, meaning owner is the only party that is allowed to exercise them. exercise choices using the exercise function, which takes a ContractId
as argument.
If no qualifier is present, choices are consuming: the contract is archived before the evaluation of the choice body and both the controllers and all contract stakeholders see all consequences of the action.
Just like for createCmd
and create
, there is also exerciseCmd
and exercise
. The versions with the cmd
suffix is always used on the client side to build up the list of commands on the ledger. The versions without the suffix are used within choices and are executed directly on the server.
Other party sees the Contact. This is because party is specified as an observer
in the template. Make sure that you add that party as an observer, otherwise they won’t be able to see the contract (and therefore won’t be able to exercise the choice). The choice observers are a list of parties that, in addition to the stakeholders, will see all consequences of the action.
Reference: Choices — Daml SDK 2.2.0 documentation
There are two ways you can start a choice:
- start with the choice keyword
- start with the controller keyword
The main difference is that starting with choice means that you can pass in a Party to use as a controller. In contrast, if you start with controller, the controller is automatically added as an observer
Transaction is a list of actions, and there are just four kinds of action: create
, exercise
, fetch
and key assertion
. Each action can be visualized as a tree, where the action is the root node, and its children are its consequences.
Expressions in Daml are pure in the sense that they have no side-effects: they neither read nor modify any external state.
Parties and authority
Each action has a set of required authorizers — the parties that must authorize that action — and each transaction has a set of authorizers — the parties that did actually authorize the transaction.
The required authorizers of an exercise action are the controllers on the corresponding choice.
The required authorizers of a create action are the signatories of the contract.
- The root transaction of a commit is authorized by the submitting party.
- The consequences of an exercise action are authorized by the actors of that action plus the signatories of the contract on which the action was taken.
Testing templates via Daml Script
daml damlc — test — files Token_Test.daml. If your file contains more than one script, all of them will be run.
To test for failing submits and keep the script running thereafter, or fail if the submission succeeds, you can use the submitMustFail function
daml script — dar .daml/dist/script-example-0.0.1.dar — script-name ScriptExample:allocateParties — ledger-host localhost — ledger-port 6865 — output-file ledger-parties.json
Daml Contracts and Privacy
The following are the Design patterns to illustrate how to authorization and Privacy are achieved in DAML.
The Initiate and Accept Pattern
The Multiple Party Agreement Pattern
Daml Application Architecture Basics (20%)
Interacting with a Daml Ledger
When you use the create-daml-app template application
, you can start a Daml Sandbox together with a JSON API server by running the following command in the root of the project. We can interact with the DAML Ledger (DAML sandbox) with the API server.
daml start — start-navigator=no
Ledger authentication and authorization
Reference: Authorization — Daml SDK 2.2.0 documentation
The Backend checks for every Ledger API request whether the request contains an access token that is valid and sufficient to authorize the request.
User access tokens are JWTs that follow the OAuth 2.0 standard
First, the Daml application contacts a token issuer to get an access token. The token issuer verifies the identity of the requesting application, looks up the privileges of the application, and generates a signed access token describing those privileges.
Then, the Daml application sends the access token along with every Ledger API request.
Ledger API
Reference: The Ledger API — Daml SDK 2.2.0 documentation
The API services are:
- Submit command
- Read transaction and contract
- Allocating and find parties
- Utility service such as query package ID, ledger ID, configurations, user info, versions, metering reports and ledger time
Access to the API includes (1) Java bindings (RxJava), (2) gRPC, and (3) HTTP JSON.
The API is structured as two separate data streams:
- A stream of commands TO the ledger that allow an application to submit transactions and change state.
- A stream of transactions and corresponding events FROM the ledger that indicate all state changes that have taken place on the ledger.
Commands are the only way an application can cause the state of the ledger to change, and events are the only mechanism to read those changes. Ledger API is asynchronous, so Ledger state changes are indicated by events received asynchronously from the command submissions that cause them
A call to the command submission service will return as soon as the ledger server has parsed the command, and has either accepted or rejected it. This does not mean the command has been execute, The on-ledger effect of the command execution will be reported via the transaction service. Your application should receive completions, correlate them with command submission.
Each intended ledger change is identified by its change ID: 3 components
- The submitting parties, i.e., the union of party and act_as
- the application ID
- The command ID
Transactions detail the changes on the ledger, and contains all the events (create, exercise, archive of contracts) that had an effect in that transaction.
Transactions contain a transaction ID (assigned by the server), the workflow ID, the command ID, and the events in the transaction.
Recommended application architecture and its components
The backend for your application can be any Daml ledger implementation running your DAR (Daml Archive) file.
We recommend using the Daml JSON API as an interface to your frontend. It is served by the HTTP JSON API server connected to the ledger API server.
Client Application Development (20%)
JSON API
Reference: JSON API
The JSON API provides a significantly simpler way to interact with a ledger than the Ledger API by providing basic active contract set functionality:
- creating contracts,
- exercising choices on contracts,
- querying the current active contract set, and
- retrieving all known parties.
other features, use the Ledger API instead.
The goal of this API is to get your distributed ledger application up and running quickly, so we have deliberately excluded complicating concerns including, but not limited to:
- inspecting transactions,
- asynchronous submit/completion workflows,
- temporal queries (e.g. active contracts as of a certain time),
Frontend libraries and their use
The JavaScript Client Libraries are the recommended way to build a frontend for a Daml application. The JavaScript Code Generator can automatically generate JavaScript containing metadata about Daml.
The command daml codegen js generates JavaScript (and TypeScript) that can be used in conjunction with the JavaScript Client Libraries for interacting with a Daml ledger via the HTTP JSON API.
● Error messages
Overview of SDK tooling (20%)
Daml Assistant (daml) — Daml SDK 2.2.0 documentation
Navigator — Daml SDK 2.2.0 documentation
Daml REPL — Daml SDK 2.2.0 documentation
Daml Script — Daml SDK 2.2.0 documentation
Daml Sandbox Deployment options (20%)
Reference: Daml Sandbox — Daml SDK 2.2.0 documentation
Daml supported ledgers
Overview of Daml Ledgers — Daml SDK 2.2.0 documentation
Deploying to a Daml ledger via daml assistant
Deploy to a Generic Daml Ledger — Daml SDK 2.2.0 documentation