Write your first Daml Contract I Jatin Pandya
ETHGlobal·Tue, Jun 9, 2026, 12:00 AM
In this workshop, Jatin Pandya walks through writing a first DAML smart contract on the Canton network and building, testing, and inspecting it using DPM, the DAML package manager. He starts by pointing developers to docs.canton.network where they can find tutorials including Module 2, which compares Canton to Ethereum for hackathon builders coming from a Solidity background. Jatin explains that DPM is a CLI tool covering the full lifecycle of DAML development, from scaffolding new projects to building, testing, and interacting with smart contracts. Jatin live codes an invoice smart contract featuring two parties (seller and buyer), an amount, a paid status, and a description. He explains DAML's core concepts: templates instead of smart contracts, choices instead of functions, and the proof of stakeholders model using signatories (who must sign actions) and observers (who can see state changes). The contract includes ensure clauses to validate positive amounts, a pay choice that returns a receipt, and a dispute choice with a required reason. He runs dpm build to compile the DAML code into a DAR file ready for ledger deployment, dpm test to execute test scripts achieving 100% pass rate, and dpm damlc inspect-dar to retrieve the package hex string used as the contract's identity on the Canton ledger. 00:00 Introduction 00:20 Where to Find Canton Documentation 01:19 What Is DPM (DAML Package Manager) 02:00 Installing DPM and Checking Versions 03:43 Exploring DPM Commands 04:51 Listing Available DAML Templates 06:01 Creating a New DAML Project from Scratch 07:23 Setting Up the Invoice DAML File 07:58 DAML VS Code Extensions Overview 08:53 Writing the Module and Importing DAML Script 09:50 Defining a Template with Parameters 11:14 Understanding Parties as Canton Addresses 12:27 Signatories vs Observers: Proof of Stakeholders 14:09 Using Ensure to Validate Amount 15:23 Choices: The DAML Version of Functions 16:18 Writing the Pay Choice with Controller 19:47 Adding a Dispute Choice with Reason 22:07 Completed Smart Contract Walkthrough 23:18 Writing Test Scripts with Alice and Bob 24:44 Running DPM Build to Generate the DAR File 26:01 Running DPM Test for Coverage Summary 27:13 Using DPM DAMLC to Inspect DAR Files 28:04 Extracting Package Hex String for Ledger Identity 29:44 Closing Remarks _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ✅ *Follow ETHGlobal* X: https://x.com/ETHGlobal Website: https://ethglobal.com YouTube: https://www.youtube.com/c/ETHGlobal _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _Are you interested in Ethereum development and entrepreneurship?_ 👉 Sign up for the next ETHGlobal event: https://ethglobal.com/events 🎁 Get exclusive access and perks with ETHGlobal Plus! https://ethglobal.com/plus 📣 Want us to throw an event in your city? Tell us where! https://ethglobal.com/city _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Transcript
Hey everybody, welcome to this video. And in this particular video, we will be writing our first Daml smart contract and build and test it using DPM, which is the Daml package manager. Now, if you're somebody who is just getting started on Canton Network by building your first project, the first place you should come to is documentation to build on top of the network, as well as find all the tools and SDKs. Now, if you're the first person here, you should go to the app development category, where you will find different modules available that takes you the entire life cycle from zero to 100 about building on Canton. If you're currently sitting in a Ethereum hackathon thinking about building your first Canton project, module two is specifically for you.
So, you can compare the different nuances of Ethereum versus Canton, whether it's the privacy model or whether it's the different paradigm and nuances in a smart contract language. In this particular module, you can go through the entire page to build your first project. But in this video, we will be writing our first Daml smart contract and use DPM to build and test it. Now, you must be thinking what is this DPM that this guy is talking about? So, now to talk more about DPM, DPM is actually Daml package manager.
It's our CLI tool that we use to build and test our Daml smart contract, but it also allows you to interact with your smart contract, to play around with it. It has all the tools and the resources available to inspect your smart contract and basically do everything possible as as a CLI, including having different components to have different features. So, I feel like this is something that we should get started by and write the first Daml contract. And you know what? It's time to go to the actual demo.
Let's come back to the VS Code window that we have set up. Okay. So, now we will just install it. Now, for me, DPM is already installed. So, it might just come back install the latest version of Daml SDK, but I feel like I already have the Daml SDK with the latest version.
If not, then hey, you can never be super updated all the time, am I right? So, let's wait for it to get installed and come back when it is done. So, it's still getting installed. As you would see, it's latest SDK version of for Daml is 3.4.
11, and it's downloading the whole SDK, and you know, it's at 44, 45. Pretty fast, right? So, it's getting installed, and let's wait till it get installed. I think it's a good time to take a transaction, like and it's installed. Now, it says, "Please add DPM to your path, and after that successfully, you'll be able to use DPM."
But since I already have it in my path, I don't think I should need to do that again. I'll just type DPM version. So, when you say DPM /v, it gives you the version of DPM available in your system here. But if you want to taste specifically what version of Daml SDK does it use, we will use DPM version. And when you type this command, it gives you the Daml SDK available, and it's in the green, it shows you the active version that you'll be using in your Daml file when you're creating a project here is 3.
4.11. So, we are super updated, and that's a good thing to go. So, now you would ask me what to do now? So, let's explore what DPM does.
So, when you type DPM, it gives you a list of all the commands available. So, I would say never a good time to explore a command than now, right? So, DPM commands have installation, the meta commands, then you have the DPM SDK. So, you build a certain DAML file into a JAR which you use to upload on DevNet, TestNet, and MainNet. Then, there is a sandbox command available, a canton console committing to a remote participant, and you can do a sandbox environment.
Clean, just clean a package. Code generation, Java compiler, JavaScript compiler is also there. So, no matter who you are, there is a place for you all already when you are trying to develop it. My personal favorite is DAML-LEC. It is compiler and IDE backend for DAML programming language.
So, it is a good place to be, and it basically decouples everything, and you know what? Let's talk about it when we even use it. The one that we would be using is new. So, DAM- DPM new gives you a list of templates that you can use to start your first project scaffolding, you know? So, let's go.
We will sort of go all the way down. I want to clear this whole just to get the mess out. We will say DPM new list. So, when we type DPM new list, it gives you a list of all the available templates already available, right? So, it has DAML intro choices, compose constraint, DAML scripts, and whatnot.
Empty skeleton to get started, finance lifecycle, payoff modeling, settlement, upgrades, multi-package, quick start finance, quick start JavaScript skeleton. So much, right? So, but since we are making a demo, we'll do everything from the scratch, right? So, we will be creating a sample smart contract, simplest ever, Alice and Bob, the classic demo names like, you know, John Doe, but well, Alice and Bob for Daml. Just make a normal invoicing Daml smart contracts where you can either pay, accept, or debate, you know, a certain invoice with each other and we'll add some testing use cases and then we will use Daml build and Daml test to see how it all works together.
So, but we need to get started. How do we do that? We will use the DPM new. Now, we will add the name of the project that we want to create in this target folder here is let us just say demo uh J. Uh my name is Jatin.
My short form is J. And then, we will specify which template do we want to use, but since it's a demo, I just want to do everything from scratch. Well, I know my way around Daml. Right? So, we will use the empty skeleton and voila, we have a new project of Daml demo J.
It already It gives you all the files needed, attributes, get ignore, and ignore everything. The main file that we need here is daml. The YAML file. It specifies the DPM's SDK version, the name, source, version of the DPM. It gives you all the scripts available.
Now, it's actually a good thing because now you don't need to worry about, you know, version mismatch and whatnot and that's why I use this particular feature and I would advise you to do the same. So, let's again clear the terminal. It gives us a good room to breathe. Let's zoom out so we can look at the code and we will create a new file in this. Let's come to the main folder here.
We will you know, not this one, but here we'll create another subfolder called as Daml because that's the source and inside the Daml folder we'll create like invoice. daml and now we a new daml file generated and we need to start coding. So, if you really want an extension that helps you basically code better in daml, you can even go to the extension, type daml like this. And I'm pretty sure it will give you this one. So, this is a daml by Digital Asset uh Holdings LLC.
It helps you to trust more and like build better in daml. But you also have a uh like daml AI coder by the Denzil. I would say this is also pretty much good like an AI-powered daml smart contract assistant and this is also something that you can try. Then we have one from LimeChain like a daml formatter. You can also use this if you want to start coding in daml.
Right? This is also something let's try out this one. But uh yeah, we have more. So, as you would see we already have some extensions available. But in our case, I am just going to uninstall it all.
I want to show everything on the ad scratch as possible. So, you know what? No shortcut for us. Normal raw code in front of you, me, you typing out the code right now. Okay?
So, let's get started. module uh So, we start a daml code by in specifying a module invoice where and if you start learning daml, you would realize a lot of it is lesser than loops and functions and logics and more of about defining the access of things or like access control logic. So, that's why daml might feel a really good space for you if you're coming from a very complex Solidity or Rust background and it is a really good language if you ask me, you know. So, let's import now. So, as you would see we already have module invoice where.
Now we will start the whole daml smart contract. So, now we need to see Daml script and we need to import Daml script here because well, it's very important. And this are the major two things that we need to be done. And now our main thing is going to be to squeeze the logic, the use case into actual Daml access way. But how that looks like is You know what?
Let's get started anyway. So, in Daml instead of functions and what not, we are have templates. So, instead of calling smart contracts, we call templates, right? So, we start by thing called as templates. Template would be invoice.
Uh nice, thank you. An invoice is the template in this case. Now, inside the template you need to define the parameters. So, our invoice will have multiple parameters. Who is the buyer?
Who is the seller? How much of the amount? And uh well, is it paid or not, right? So, we need to define all that in as a parameter of invoice. So, let's describe the parameter.
And you might feel like I'm typing English, but to be honest, Daml it genuinely is pretty good. So, let's get started. So, template invoice with Now, we have to describe the parameter. So, let's just say we have a seller, we have a buyer. We need to specify amount.
We need to define if it is paid or unpaid or maybe the description. The description of the invoice, like it should be an invoice for construction. So, we can just define an invoice description, paid amount, buyer, seller. Yeah, I think that's pretty much enough for parameters that we can get started, right? So, now we need to get started with So, a seller would be a party.
So, if you don't know what a party is, so party is basically the Canton's version of an address, but in a UTXO style. So, instead of addresses on Canton, you get a party ID to, well, interact with the blockchain. So, a seller will be one party, buyer will be a totally one party, amount will be in decimal. Similarly, uh paid would be more of like a condition. Mhm.
Like yes or no, so we will define it as a boolean. Description would be a text. Yep, I think that's pretty much it. So, now we have our first template already ready. As you would see, we have template of invoice with the parameters of seller, buyer, amount paid, boolean of a paid like logic, and a description about it.
So, this defines our first template parameter and just defining of the template. Now, it does not end here. Now, we need to define where that means that now we have defined like all this like buyer, seller, and whatnot, but we need to define who has what access. And this access control, this is known as proof of stakeholders. This gives DAML a specific edge to actually provide the best access possible and privacy on the smart contract level.
So, let's define signatory. So, signatory should be the seller, uh because seller is selling the whole thing. Uh then, buyer should be the observer, right? So, yeah, we need to keep keep the buyer as an observer. Mhm, or I guess that's it.
Ob- server would be buyer. So, now we have defined access control of what's the parameter of an invoice, what will do what, and how much access. The signatories are basically the admins in a way where they are the ones that needs to sign for an action to take place. But, observers are the one who are allowed to see the change of the the state of the smart contract, the things get emitted, the events get that emitted, how things actually get executed, and the and the basically everything that leads into the whole smart contract. You need to be an observer to do it.
Observers, signatory, everything in between. But, if you're not everything in between, you can't see anything. And that's what makes Canton's privacy model special. So, you're basically seeing the whole proof of stake holder mechanism in real time, right? So, let's move ahead.
Now, in template, we everything is defined. Now, it's a time to make sure that nobody gives a negative or zero invoice, right? We can use ensure um ensure amount. Ensure amount should be more than, I guess, 0.0.
So, this basically what what it does here is that it ensures that whatever invoice amount that you declare here should be more than zero. So, this basically protects our invoice from all the people who want to create like a negative or a zero invoice. We definitely want a positive numerical as an invoice. Even if I want to get an invoice of 1 cent, it should be 1 cent. An invoice of zero dollars doesn't make sense, right?
Um even zero CC doesn't make sense. But, yeah. This is the first structure. So, congratulations. We are able to not only code the whole thing, but we're also able to define what a template looks like, how signatory and observer looks like, and even how you would define parameter inside it, right?
Isn't that cool? Now, we need to move ahead into the next part of a DAML smart contract, which is the functions. Wait. Smart contracts like Solidity has function. So, what's the DAML version of that?
We have something called as choices. So, choices is something that you define inside the template that acts as a function. You can define logic, you can define loops, you can basically define how something should react in a way uh using the choice. So, we will write our first choice here inside the whole uh smart template, right? So, let's get started.
Choice. Right? So, now choice is basically what functions are for in DAML. Now, we need to Okay, uh Okay, just want to make sure it's inside the template. Uh so, now choice would be that um a buyer needs to pay the invoice that the seller is uh putting out there, and it should basically just come back with a receipt once they pay with it.
So, yeah, I mean, so let's do two things. We will be adding two choices. Either a buyer can pay an invoice uh or can dispute uh with it, right? So, if there is a dispute within the whole thing, then there should be a way to dispute or raise a concern. Or if it is called good, it needs to be a pay.
So, what I'm going to do here is to find a choice or a functionality of paying it, and then we will just move forward to define the dispute, right? So, I would say choice pay contract uh ID of receipt. I would say that is pretty much it. So, we need uh the pay Once you pay, basically, then it should have a receipt that uh you have already paid with the contract ID. I think that basically makes sense.
So, that should be how the flow looks like. And as we move ahead about kick code. Now, we need to define the controller. Who is the buyer? Now, you would ask me, "Jatin, what is a controller?"
Now, we have signatory and observer. What is a controller? So, this particular choice has to be controlled by the buyer because buyer is the one who is actually deciding that if they are paid using the invoice or they need to pay the invoice, right? In any condition like that, buyer is the one that needs to put the final word at here. So, we need to define the controller as the buyer to be able to control this whole thing, right?
But, what would they do? Uh nope. Do not recommend me this description. We will now type two. Uh Jeez.
Uh yeah, but okay. Jatin, this is Isn't this pure English? Well, I told you Tamil was simpler, right? You didn't believe me in the first place. Now, controller is the buyer.
Now, what should this choice do? Now, here is a chance to define the logic inside this function of what would this function do in the first place? Now, if I am okay to pay, then it should create a receipt that I am done with the payment, right? So, what we do is create a receipt. It should create a receipt with Again, when whenever we say with, we have to define the parameters that we want to be inside of it, right?
So, once a receipt is generated, we would want to have, of course, the seller. You want to have course, We want to have the amount, I guess. Uh we also want to have if it is paid. So, if it is paid, uh I think it should be defined in the receipt if it is paid. You know what?
I mean, it's anyway new paid, so why would we need it so you know what? We can go over with description. So, if it is already paid, we don't need to define the boolean rate yes or no because it is already paid. So, who is the seller? Who is the buyer?
How much was the amount? And what is the description? Like, what is the invoice is for? That would do it. Uh okay.
Now, we have officially paid the damn export in the room. So, now another choice is dispute the whole thing. It should also come with contract ID and this disputed invoice should be the return. Yeah. Invoice should be the return.
So, for example, if somebody is disputing your your invoice in the first place, then I think it should return with smart contract ID and the disputed invoice, right? So, here the controller needs to be the seller in a in a way. Um But anyway, I think we don't need to define that because it is a dispute, right? So, we just need to define what the disputed invoice should have as a parameter, I guess. But at the same time, we need a reason why it got disputed in the first place.
So, I think the best would be uh to have a reason into this whole thing. So, we need to have a reason that would be a text here. So, we need to have a reason of why it got uh like, you know, disputed in the first place. And now we're defining who is the controller here. Controller is again the buyer because buyer is the one who's actually putting the dispute.
So, controller has to be the buyer. Now, when the buyer is the controller, they're basically giving you a reason and after the reason, all you are doing is just come back with a dispute invoice back to the seller. And that is what we need to define, right? Seller or buyer, pretty much the same thing. Of course, the description of the invoice and amount in the invoice.
Uh I think the reason that we will define when we want to dispute it, that should also be a part of it. Huh, but that said, now we have officially wrote a proper DAML smart contract code and I mean pardon me if I'm looking like this like this because I'm talking to you guys and I'm also writing the code at the same place, right? So, it got to be the human interaction here. But, coming on to the whole thing. So, what did we learn in the end, people?
We have wrote so much code. Right? We have a module, we have an import DAML script, we defined our first template which was the invoice with the parameters, and we defined the access controls. We ensured that it should be more than zero, of course. It should not be negative or zero.
We defined our first choice which is the functionality that if I'm okay with the pay, then here is the pay, you will get a receipt of the pay. But, if I want to dispute the invoice, then I should have a reason and you are just giving me seller, buyer, description, amount, and reason back, right? Uh this is definitely not the whole DAML smart contract, but you would see how you would define a choice and a template and everything up. Now, I'm going to complete the rest of the smart contract, so you know, we don't need to waste time here like and like this, the whole smart contract is complete. To be To be it took me like almost close to five more minutes to do this, but well, it's a demo.
Now, what we have done rest is define a template structure of what the receipt would look like. We have defined a template structure of what would an disputed invoice would look like. Like everything else, then what we have done is so when you write a DAML smart contract, you need to define some test scripts in the DAML smart contracts accord against which you can test if everything works right or not, right? For example, we have a new testing flow here that you would see. The testing flow says that you will identify the script if the parties Alice and Bob, right?
Then you would define the wholesaler should do this, this, this. Define the services in Q1, then you have a receipt ID that should be submitted by the buyer and receipt ID should be queried and buyer should have a receipt ID that which is verified and if it is not found, that means it is not right. And sincerely, we also add one more submit must fail. So, I mean, to be honest, an amount should not be a bad invoice. I didn't want to have like a negative invoice.
For example, something like minus $100 doesn't make sense. So, even though we have insured using the insured amount, but you know, it doesn't hurt to add a stress testing in terms, right? So, I would say we have a pretty good DAML smart contract here. So, what we would do is we need to take our terminal all the way up here. So, because we're done with the DAML script, now we need to use the DPM to take it next in the action.
So, let's get started on this one. Basically, now we need to CD into the target file. So, our target uh project is inside the demo. It is known as demo. j where our whole DAML file exist.
So, let's go to CD demo. j and yep, we are at a good place. So, the first thing that we do is to try out DPM built. So, what DPM built does is convert your whole damage smart contract into a DAR file. Um yeah, I mean, it basically does that.
So, it the DAR file will be used to push onto the ledger using an API call with your ledger API to be able to deploy on top of devnet, testnet, mainnet, right? So, we will click on DPM built and let this whole smart contract convert into an actual DAR file. So, as you would see, it ran smoothly. Uh just hearing here warnings, but well, we are the coders. We don't care about the warnings, do we?
Right? But, what to think about is created the DAR file here. So, we will go to dot daml, we'll go to dist, and then as you would see, here we have a DAR file that we can use to upload on the ledger. But, uh that is the least of our issues right now. Come back to it uh happily completed with the daml built.
Now, we need to test if the whole thing is good, if there are issues against the daml contract or not. We have written some test scripts that will help us identify that. So, for that, again, to keep it pretty simple, we will use So, DPM test basically use all the type scripts that we have written to create test. You can get a test summary here, right? Internal templates three defined, two exercised.
Internal templates choices, five defined, one exercised. And why one out of five is because we have only written scripts for the pay, not for the disputed, not for the archived, only for the pay, because it's a demo. But, you can write more complex testing scripts to give better testing and debugging experience. And overall, we have 100% 100% 100% external test. Um so, we have passed this whole thing with the flying colors.
Now, DPM test DPM built, you have a DAR file, you have a DAML smart contract, which is totally built, and this is why I love DPM because it makes building on top of Canton much more easier in a lot of ways. You can actually use the the REST stops. One of the commands that we were talking about is DPM command known as DPM leg, which is basically a compiler and ID back end for your DAML language. So, we will use DPM, and I'm just going to show you what happens. DAML leg.
So, when we type this, you need a command DPM DAML leg. Now, you need to invoke the compiler. But, okay. So, we need to define the path where your DAR file is installed to be able to use this, you know? But, let's see it in action, right?
Why hesitate since we're already this far? Um and let's see it in action. And DAML leg. So, now one of the things that I love about DAML leg is inspect DAR. So, what inspect DAR does is basically it just decouples your DAR file.
It gives you every dependency, every package, but most of all, it gives you your package hex string. Not the name, not the version. Your package hex is your identity on the Canton ledger. And instead of going around in the binary or trying to fetch it from the ledger, you can use this. You can root the path of your DAR profile and get it.
So, let's see that in action as the last thing that we do on this one, right? So, we have DPM DAML leg inspect DAR. Now, we need to give the root for the DAR. So, DAR is currently available in DAML slash dist. Um my bad.
This {slash} we have the name of the DAR file here. We will just going to copy the path and uh I am really messy, but that's what makes me authentic uh in a in a way. Um yes, so we are since we're already inside the target folder, we don't need to give like the whole path, but we can give this particular path of dart camel {slash} dist {slash} demo.j uh of this path, and I hope this works. Uh nice.
So, as I would say, it gives us a good uh a lot of things here, but it gives you the hex string of almost everything that works. You know, DAR archive contains the following packages. It gives you all the following packages in this one. So, you might not know what to make sense of this one, but you can just copy-paste it into any AI model and ask it to simplify it for you. So, it might give you like a table format or something of the available packages, their hex strings, and whatnot.
You can store it for future references, but this is a very like, you know, useful program if you're working on top Canton, and we will clear everything up. As always, I'll put this whole thing on my GitHub if you want to use it. The link will be in the reply of this demo. But, thank you so much for basically working with me on this demo and to understand how DPM works. DPM is an amazing tool that can be used as the best experience to develop on top of Canton.
So, make sure that you try it, build it, and if you build anything, tag me on Discord or X and let me know how I can help you. So, till then, bye-bye.
Automatic transcript — names and jargon may be misspelled.