I am working on converting some scenarios to scripts so that I can use them to initialize my ledger. I have written/adjusted scripts before to initialize versions of the ex-bond-issuance and ex-bond-trading model, and am now working with our version of ex-cdm-swaps.
The scenarios in the Event.daml file here reference various helper scenarios in various files and subdirectories in the Test folder.
From the docs steps 1-5 are fairly straightforward. I am having trouble with step 6 when it comes to initializing the parties.
Currently, the scenario imports the parties from the Counterparty.daml file which are the results of their own scenarios.
My initial thought was to convert the scenarios in the Counterparty.daml file to scripts and import the results in the Event.daml. This is the code I tried and the error I received at the **starred line** of code :
module Test.ExampleData.Counterparty where
import Daml.Script
import Prelude hiding (getParty)
getParty : Text -> Script Party
getParty name = allocatePartyWithHint name (PartyIdHint name)
data Counterparty = Counterparty
with
damlParty : Party
partyId : Text
account : Text
name : Text
p01_1 : Counterparty -> Script ()
p01_1 = do
**damlParty <- getParty "CSD-P01"**
return Counterparty with
damlParty
partyId = "5264151754007"
account = "P01547927812"
name = "CSD-P01"
The error:
> C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Test\ExampleData\Counterparty.daml:20:3: error:
> • Couldn't match expected type ‘Counterparty -> Script ()’
> with actual type ‘Script Counterparty’
> • In a stmt of a 'do' block: damlParty <- getParty "CSD-P01"
> In the expression:
> do damlParty <- getParty "CSD-P01"
> return
> Counterparty
> {damlParty, partyId = "5264151754007", account = "P01547927812",
> name = "CSD-P01"}
> In an equation for ‘p01_1’:
> p01_1
> = do damlParty <- getParty "CSD-P01"
> return
> Counterparty
> {damlParty, partyId = "5264151754007", account = "P01547927812",
> name = "CSD-P01"}
I have tried a few different ways, but each step keeps leading to a different type error and then I’m back to square one.
Does this approach make sense? And if so does anyone have any suggestions as to how I can assign the parties and then assign them to the Counterparty data constructor?
Or should I be considering initializing my parties in the test Event.daml which will ultimately be used to initialize the ledger?
The issue in your example is the type of p01_1. If you look at the definition, you can see that it takes no arguments, operates in the Script action and produces a Counterparty at the end. So the correct type here is Script Counterparty and indeed that compiles:
p01_1 : Script Counterparty
p01_1 = do
damlParty <- getParty "CSD-P01"
return Counterparty with
damlParty
partyId = "5264151754007"
account = "P01547927812"
name = "CSD-P01"
As for how you should handle party allocation in DAML Scripts, I generally recommend to separate your scripts in a few different definitions, I’ll use ex-bond-issuance as an example that handles this similarly:
A datatype that defines all parties that you will use in your script.
The actual script logic which accepts a value of the datatype defined in 1. This function does not allocate any parties itself. It gets all parties from the argument. When running against a real ledger, you will can then handle party allocation outside of the daml script which can be convenient if you need the parties outside of daml script as well and just pass in the value via --input-file.
Thanks for the advice and breaking down those elements found in ex-bond-issuance.
So here, instead of type Party I could use type Counterparty.
data cdmParties =
srmParties with
d03_5 : Counterparty
p01_1 : Counterparty
d02_2 : Counterparty
centralBank : Party
operator : Party
And then for 2.
Something like this:
setupMarket : Script ()
setupMarket = do
debug "Ledger is being initialized..."
let do3_5 = Counterparty with
damlParty = getParty "CSD-P01"
partyId = "5264151754007"
account = "P01547927812"
name = "CSD-P01"
(with the rest of the parties here)
setupMarketWithParties $ cdmParties with ..
One minor correction, getParty is of type Text -> Script Party. You have to bind it in the do block instead of directly assigning it to damlParty. So something like:
setupMarket : Script ()
setupMarket = do
debug "Ledger is being initialized..."
p <- getParty "CSD-P01"
let do3_5 = Counterparty with
damlParty = p
partyId = "5264151754007"
account = "P01547927812"
name = "CSD-P01"
(with the rest of the parties here)
setupMarketWithParties $ cdmParties with ..
Hmmm… There must be some other piece I am missing. I will keep investigating.
getParty : Text -> Script Party
getParty name = allocatePartyWithHint name (PartyIdHint name)
setupMarket : Script ()
setupMarket = do
debug "Ledger is being initialized..."
p <- getParty "CSD-P01"
let do3_5 = Counterparty with
damlParty = p
partyId = "5264151754007"
account = "P01547927812"
name = "DEALER-D03"
b <- getParty "CSD-P01"
let d02_2 = Counterparty with
damlParty = b
partyId = "9377538274179"
account = "D03225622378"
name = "DEALER-D02"
r <- getParty "CSD-P01"
let p01_1 = Counterparty with
damlParty = r
partyId = "9377538274179"
account = "D03225622378"
name = "CSD-P01"
centralBank <- getParty "CentralBank"
operator <- getParty "Operator"
setupMarketWithParties $ CdmParties with ..
data CdmParties =
CdmParties with
d03_5 : Counterparty
p01_1 : Counterparty
d02_2 : Counterparty
centralBank : Party
operator : Party
Here are the errors:
`C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Test\Event.daml:27:17: error:
• Couldn't match type ‘DA.Internal.Desugar.Party’
with ‘Party’
NB: ‘Party’ is defined at
C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Org\Issa\Srm\Classes.daml:(8192,1)-(8208,28)
‘DA.Internal.Desugar.Party’
is defined in ‘DA.Internal.LF’ in package ‘daml-stdlib-1.8.0’
Expected type: Script Party
Actual type: Script DA.Internal.Desugar.Party
• In the expression: allocatePartyWithHint name (PartyIdHint name)
In an equation for ‘getParty’:
getParty name = allocatePartyWithHint name (PartyIdHint name)`
I get this error at p, b, and r:
C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Test\Event.daml:34:35: error:
• Couldn't match expected type ‘DA.Internal.Desugar.Party’
with actual type ‘Party’
NB: ‘Party’ is defined at
C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Org\Issa\Srm\Classes.daml:(8192,1)-(8208,28)
‘DA.Internal.Desugar.Party’
is defined in ‘DA.Internal.LF’ in package ‘daml-stdlib-1.8.0’
• In the ‘damlParty’ field of a record
In the expression:
Counterparty
{damlParty = p, partyId = "5264151754007",
account = "P01547927812", name = "DEALER-D03"}
In an equation for ‘do3_5’:
do3_5
= Counterparty
{damlParty = p, partyId = "5264151754007",
account = "P01547927812", name = "DEALER-D03"}
The error comes from the fact that you’ve defined your own type called Party in addition to the builtin one. If you look closely at the error, it tells you the location of the two definitions:
NB: ‘Party’ is defined at
C:\Users\James Jaworski\OneDrive\BloqbookV2\sandbox-srm\src\daml\DA\srm\Org\Issa\Srm\Classes.daml:(8192,1)-(8208,28)
‘DA.Internal.Desugar.Party’
is defined in ‘DA.Internal.LF’ in package ‘daml-stdlib-1.8.0’
DA.Internal.Desugar is the builtin one. The other one is the one you defined. You have to resolve the ambiguity in some way and tell the compiler which one you mean. There are a few different options:
Rename the one you defined. In this case, this is probably what I’d recommend just because Party is so common that having something else with the same name is going to confuse whoever reads that code.
Don’t import the one you defined. There are a few different options for that, either don’t import the module Org.Issa.Srm.Classes at all, import only the definitions you need (assuming party is not one of them) via import Org.Issa.Srm.Classes (names, of, the, definitions, you, reference) or import everything except for Party via import Org.Issa.Srm.Classes hiding Party.
import qualified Org.Issa.Srm.Classes as SomeModuleName. That will allow you to reference the definitions from Org.Issa.Srm.Classes as SomeModuleName.SomeDefinition so SomeModuleName.Party will give you the Party type you defined while Party refers to the builtin one.
Reference the builtin one via Prelude.Party. Prelude refers to the module that is implicitly imported everywhere so this way you can make sure to reference the builtin party type.
Thanks for the explanation. That was really helpful. I had not realized that Prelude was referencing the universal module. If I see errors that start with “DA.internal…” then it is referring to some error/ambiguity/etc. from the Prelude module?
I was also a bit confused because some errors from the compiler specifically say “ambiguous reference”. Once broken down it was easier for me to recognize that it was an ambiguous reference, it wasn’t obvious to me from the start.
DAML allows one module to reexport definitions from another module. So in this case Prelude is reexporting the definition from DA.Internal.*. While it is not enforced, you can usually assume that something referencing DA.Internal.* is reexported from Prelude and you imported it that way.