DAML is an open-source language used to write distributed applications quickly,concisely and correctly. It runs on leading blockchain platforms like Hyperledger Sawtooth , fabric and Corda.
It is used to build smart contracts for distributed ledgers and provide us with ability to focus more on business workflow instead of the blockchain implementation.
In our previous blogs, Building Powerful Smart Contracts, Getting started with building Templates and DAML supported data types we have covered basics of DAML which will help you understand the language and need of language and also a guide to get you started with it. I would recommend you all to go through them before going forward with this blog.
In this blog we will go through DAML design patterns that we should follow while building our application.
What are Design Patterns ?
Design patterns are used to represent some of the best practices adapted by experienced software developers. A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in systems. It describes the problem, the solution, when to apply the solution, and its consequences. It also gives implementation hints and examples.
A design pattern isn’t a finished design that can be transformed directly into code. It is a description or template for how to solve a problem that can be used in many different situations.
They help in speeding up the development process.
Here are some of the DAML design patterns we can use for building applications using DAML
- Initiate and Accept
- Multiparty Agreement
Initiate and Accept
This design pattern demonstrates how we can start building templates when only two parties are involved in the project. As the title suggests one party initiates the workflow by creating a proposal or an invite contract. The other party will accept, reject or renegotiate the contract.
As shown in this diagram the two cards represent two templates. The first template is the initiation template or the invite template and the other is the Accept template which the user will use to accept the invite.
Lets understand better with an example :
In this example we have two templates for Initiation and Acceptance. This example we are to issue coins to the user once the user has accepted the agreement. This code is not in complete
And is just used to give you guys an idea of the concept.
template CoinIssueProposal with coinAgreement: CoinIssueAgreement where signatory coinAgreement.issuer controller coinAgreement.owner can AcceptCoinProposal : ContractId CoinIssueAgreement do create coinAgreement
The CoinIssueProposal contract has Issuer as the signatory, and Owner as the controller to the Accept choice. As we can see the choice available is of only AcceptCoinProposal but in reality different choices like reject or renegotiate are also provided.
template CoinIssueAgreement with issuer: Party owner: Party where signatory issuer, owner controller issuer can nonconsuming Issue : ContractId Coin with amount: Decimal do create Coin with issuer; owner; amount; delegates = 
Once the owner exercises the AcceptCoinProposal choice on the initiate contract to express their consent, it returns a result contract representing the agreement between the two parties. In this example, the result contract is of type CoinIssueAgreement. Note, it has both issuer and owner as the signatories, implying they both need to consent to the creation of this contract. Both parties could be controllers on the result contract, depending on the business case.
In the previous topic we saw the best way to make the contract when only two parties are involved but in the real world multiple parties can be part of the contract. When multiple parties are involved bilateral contracts are not the way to go as no two parties can be sure if there is a conflict between their two contracts and third contract between their partners.
So what approach should we follow in that case? Let’s find out!
The Multiple Party Agreement pattern uses a Pending contract as a wrapper for the Agreement contract. Any one of the signatory parties can kick off the workflow by creating a Pending contract on the ledger, filling in themselves in all the signatory fields. The Agreement contract is not created on the ledger until all parties have agreed to the Pending contract, and replaced the initiator’s signature with their own.
template Agreement with signatories: [Party] where signatory signatories ensure unique signatories-- The rest of the template to be agreed to would follow here
This represents final agreement between all the parties. It has multiple signatories.
template Pending with finalContract: Agreement alreadySigned: [Party] where signatory alreadySigned observer finalContract.signatories ensure -- Can't have duplicate signatories unique alreadySigned -- The parties who need to sign is the finalContract.signatories with alreadySigned filtered out let toSign = filter (`notElem` alreadySigned) finalContract.signatories choice Sign : ContractId Pending with signer : Party controller signer do -- Check the controller is in the toSign list, and if they are, sign the Pending contract assert (signer `elem` toSign) create this with alreadySigned = signer :: alreadySigned choice Finalize : ContractId Agreement with signer : Party controller signer do -- Check that all the required signatories have signed Pending assert (sort alreadySigned == sort finalContract.signatories) create finalContract
This pending contract contains the Agreement as one of the parameters so that all the parties know what they are signing for.
Here the pending contract has the list of parties which have signed the contract and the list of parties which are yet to sign the contract. Once all the parties have signed the contract using the Finalize choice. This checks that all of the signatories for the Agreement have signed the pending contract.
This is an important design pattern because it gives one party the right to exercise a choice on behalf of another party. In the real world this is very useful because there may be many cases where somebody would like to give another person the right to exercise the choice on their behalf. For eg: when a company may give the rights to their chosen bank to hold their securities and settle transactions on their behalf.
Delegation design pattern can be implemented using:
template Coin with owner: Party issuer: Party amount: Decimal delegates : [Party] where signatory issuer, owner observer delegates controller owner can Transfer : ContractId TransferProposal with newOwner: Party do create TransferProposal with coin=this; newOwner Disclose : ContractId Coin with p : Party do create this with delegates = p :: delegates
This contract exists with the choice for Party A to delegate execution of the choice to Party B. Here the control of the choice is given to the owner who can pass the authority to another party to exercise choice on its behalf.
template CoinPoA with attorney: Party principal: Party where signatory principal controller principal can WithdrawPoA : () do return () controller attorney can nonconsuming TransferCoin : ContractId TransferProposal with coinId: ContractId Coin newOwner: Party do exercise coinId Transfer with newOwner
Here the original coin owner is the signatory of delegation. This signatory is required to authorise the transfer choice on the coin. Attorney is the controller of the Delegation choice on the contract. Within the choice, the Principal exercises the choice Transfer on the Coin contract.Coin contracts need to be disclosed to the Attorney before they can be used in an exercise of Transfer. This can be done by adding an Attorney to Coin as an Observer. This is done using the Disclose choice in the pre-condition contract.
In this business world it is very important to make sure that the contracts choices are exercised by the right person. If any person who is not authorized or does not have the permission is able to exercise a choice then it’s consequences can be bad for business.
It is important to make sure that the parties are authorised to before taking part in the business transaction. This can be achieved by using an Authorised pattern model.
template CoinOwnerAuthorization with owner: Party issuer: Party where signatory issuer observer owner controller issuer can WithdrawAuthorization : () do return ()
In this example we can see that issuer is the signatory here and owner is the observer. This makes sure that the owner is an authorised person. This is a simple example, in real business use cases we can add many things.
Locking is an important concept for business contracts. In a real world scenario like in the case of the settlement process between two parties the securities under the ownership of seller need to be locked so they cannot be used for other purposes, and so should be the funds on the buyer’s account. The locked state should remain throughout the settlement Payment versus Delivery process. Once the ownership is exchanged, the lock is lifted for the new owner to have full access.
This can be achieved in three ways: