Hi everyone,
It was required me to generate custom business ids for each new contract of a given Template.
Imagine the following template:
template Policy with
business_id : Text
data : Text
owner : Party
system : Party
where
signatory owner
observer system
key (system, business_id) : (Party, Text)
maintainer key._1
controller system can
Policy_Gen_Business_Id : ContractId Policy
do
create this with business_id = genBusinessId
What I have imagined to solve this problem, would be to have a choice for a system party, where it would execute the function genBusinessId.
This function would have the algorithm to generate an unique business_id.
Since it should be generated once upon a contract creation, is there a better approach for this problem ?
Note: It is also required to not use an external algorithm to generate this business id, the algorithm needs to be “inside” daml code
There are a few options depending on your usecase:
- The easiest way to get unique identifiers in Daml is to rely on contract ids instead of trying to create separate identifiers. The main downside here is that you cannot use contract ids in keys and that you cannot convert it to a
Text
in Daml.
- If that’s not an option, my recommendation would usually be to generate something like a UUID outside of Daml. You mentioned that this isn’t an option but maybe you could expand on why that’s the case? Maybe we can find a solution that allows you to go down that route.
- If neither of those two options work for your usecase then you can try generating it in Daml. The simplest example of doing something like that is to have a contract with an incrementing counter for your ids. Keep in mind though that first, you rely on the signatories of
T
to go through IdCounter
instead of creating T
directly. So if you don’t trust them you cannot rely on the ids being unique and second, you are creating a sequential bottleneck because everything goes through IdCounter
now. If that becomes an issue you could try sharding across multiple identifier generators and have each add a prefix before their counter.
module Main where
import Daml.Script
import DA.Assert ((===))
template IdCounter
with
current : Int
p : Party
where
signatory p
key p : Party
maintainer key
choice CreateT : ContractId T
controller p
do cid <- create (T current p)
create this with current = current + 1
pure cid
template T
with
id : Int
p : Party
where
signatory p
test = do
p <- allocateParty "p"
submit p $ createCmd (IdCounter 0 p)
submit p $ exerciseByKeyCmd @IdCounter p CreateT
submit p $ exerciseByKeyCmd @IdCounter p CreateT
submit p $ exerciseByKeyCmd @IdCounter p CreateT
ts <- query @T p
map snd ts === [T 0 p, T 1 p, T 2 p]
pure ()
1 Like
Thank you for your response. It was very helpful