Retrieving contract - issues
Hi Everyone!
I still have problems in retrieving contracts. I am very sorry, I read the resources and documentation but I cannot quite understand how to make my workflow work. Here is what I want to do:
1- I create an asset
2- I update the asset (new docs, new descriptions …)
3- Then I want to retrieve the last updated contract (if there are any updates, otherwise the original contract)
4- Finally I want to sell the last updated contract
In this case, my understanding is that it’s best to use keys as the contractId might be archived if there is an update. Last week I had lots of help from Wallace (Wallace thank you again!) and he’s right, I should not include the entire Asset instance I should just reference the asset with either ContractId or FetchBy Key. I attach the link to the previous post.
Welcome back, @claudia_giannoni! Does your Asset template include a Contract Key in its definition? Knowing that and how it is defined will help us answer your question. If not, try adding a key to the Asset template as described here and let us know how it goes. Also, keep in mind that keys are not required to fetch contracts. You can reference contracts either by key or ContractId, as explained in that referenced page. The approach you use depends on your workflow. By the way, thanks for p…
Therefore, I restarted my work and modified the code as below:
module Asset where
type AssetId = ContractId Asset
template Asset
with
ownerSolicitor : Party
owner : Party
auctionHouse :Party --also makes sure that all parties are legit
address :Text
idCode: Text --To check how to create an asset ID. To be generated offline
a_description : Text
a_documents : [Text]
a_docLink : Text --to be reviwed to create a link to the documents
v_description : Text
v_documents : [Text]
v_docLink : Text --to be reviwed to create a link to the documents
date: Time
where
signatory ownerSolicitor
observer owner,auctionHouse
key (ownerSolicitor, idCode) : (Party, Text)
maintainer key._1
choice UpdateAsset
: ContractId Asset
with
new_owner : Party
new_address :Text
new_idCode: Text
new_a_description : Text
new_a_documents : [Text]
new_a_docLink : Text
new_v_description : Text
new_v_documents : [Text]
new_v_docLink : Text
new_date:Time
controller ownerSolicitor
do
create this with
owner = new_owner
address = new_address
idCode = new_idCode
a_description = new_a_description
a_documents = a_documents ++ new_a_documents
a_docLink = new_a_docLink
v_description = new_v_description
v_documents = v_documents ++ new_v_documents
v_docLink = new_v_docLink
date = new_date
choice FetchAssetByKey : (ContractId Asset, Asset)
with
assetKey : (Party, Text)
controller ownerSolicitor
do
fetchByKey @Asset assetKey
module Main where
import Asset
import Daml.Script
setup : Script ()
setup = script do
cms <- allocatePartyWithHint "CMS" (PartyIdHint "CMS")
claudia <- allocatePartyWithHint "Claudia" (PartyIdHint "Claudia")
christie<- allocatePartyWithHint "Christie" (PartyIdHint "Christie")
claudia_Budha <- allocatePartyWithHint "Claudia_Budha" (PartyIdHint "Claudia_Budha")
mishconDeReya <- allocatePartyWithHint "MishconDeReya" (PartyIdHint "MishconDeReya")
silvia <- allocatePartyWithHint "Silvia" (PartyIdHint "Silvia")
time <- getTime
assetId <- submit cms do
createCmd Asset with
ownerSolicitor = cms
owner = claudia
auctionHouse = christie
address = "Mulholland Drive"
idCode = "XX2325XXX"
a_description = "Villa by the sea"
a_documents = ["VillaDoc1", "VillaDoc2", "VillaDoc3" ]
a_docLink = "http://villaDocumetsLocation"
v_description = "Portrait of Adele Bloch-Bauer - Klimt"
v_documents = ["KlimtDoc1", "KlimtDoc2", "KlimtDoc3" ]
v_docLink = "http://valuableDocumentsLocation"
date = time
updateAsset <- submit cms do
exerciseCmd assetId UpdateAsset with
new_owner = claudia_Budha
new_address = "Mulholland Drive 135"
new_idCode = "AAA123BBB"
new_a_description = "Villa by the sea with view"
new_a_documents = ["VillaDoc4", "VillaDoc5", "Villa6" ]
new_a_docLink = "http://villaDocumetsLocation_Updated"
new_v_description = "Klimt and Le Moulin de la Galette -Renoir"
new_v_documents = ["Renoir1", "Renoir2", "Renoir3" ]
new_v_docLink = "http://valuableDocumentsLocation_updated"
new_date = time
Some asset <- queryContractId cms updateAsset
submit cms do
exerciseCmd updateAsset FetchAssetByKey
return ()
I would really appreciate some help to understand how to make my workflow work. I also do not understand from the documentation why I need and Helper template to call ‘fetchByKey’ and how to use it.
Again, I am sorry for being a pain, I am lost. If someone could give me some help with a bit of patience, I would be very very grateful.
![]()
Hi, @claudia_giannoni! It appears you are making great progress!
Let’s address this first:
I also do not understand from the documentation why I need and Helper template to call ‘fetchByKey’
I’m assuming you read this thread in which cocreature explained that fetchByKey cannot be called from a Daml Script.
In summary, fetchByKey can only be used in a choice. It cannot be used in a script. Consequently, if you want to write a script that retrieves a contract based on a key, you will need to first write a choice that calls fetchByKey. That choice needs to be on a template. You might as well name that template with “helper” in the name to clarify that its purpose is to help with some other template.
I also do not understand from the documentation … how to use it.
The general idea of fetching a contract by key is that the key does not change… even as a contract is updated. When a contract is updated, the contract id changes. If you have defined a key on a contract that stays the same even as the contract is changed, then you can always retrieve the “current version” of the asset.
However, notice that in your code, the UpdateAsset choice allows the idCode to be changed. You probably don’t want to do that. The idea with keys is that they don’t change. You probably want to remove the new_idCode parameter from your UpdateAsset choice, so that the idCode can never be changed after the contract is initially created.
Additionally, I see in your code that you have a choice named FetchAssetByKey on the Asset template. That’s a good start, but does not actually make sense. The reason it does not make sense is that to exercise that FetchAssetByKey choice, you would need to already have the contract id of the asset. If you already have the contract id of the asset, you do not need to fetch it by key.
So imagine you don’t know the contract id of an asset (because the asset has been updated a couple times since it was created and gets a new contract id on every update). But, you do know the key (the idCode in your example).
That is where the concept of a “helper” comes into play. You need a whole new AssetHelper template, with a FetchByKey choice. Here is a sample implementation:
template AssetHelper
with
caller : Party
where
signatory caller
choice GetAssetByIdCode : (AssetId, Asset)
with idCode : Text
controller caller
do
fetchByKey @Asset (caller, idCode)
With the above defined, you can create new instances of the AssetHelper and exercise the GetAssetByIdCode choice whenever you want. Like this, for example:
(currentAssetId, currentAsset) <- submit cms do
createAndExerciseCmd (AssetHelper cms) GetAssetByIdCode with
idCode = "XX2325XXX"
Notice the above expressions returns the current asset that has the key XX2325XXX. You can place the above createAndExerciseCmd in your script after the asset is initially created and after the contract has been updated. In both cases, it will give you the “current” version of contract XX2325XXX.
Does that get you moving forward again?
Hi Wallace,
![]()
This is enlightening!! Very clear and extremely helpful. I find the documentation sometimes a bit complicated and the example with the bank account (in FetchByKey) was a bit confusing to me.
I have added the code below and created the code to sell the asset, thank you ever so much!!!
I only have two questions if you still can spare one minute
![]()
1- What if I don’t know the code, I want to see all contract cms has submitted?
2- In " createAndExerciseCmd (AssetHelper cms)" is cms the key in the contract or the maintainer?
Thank you a lot again, you saved my day.
![]()
1- What if I don’t know the code, I want to see all contract cms has submitted?
Use the query function. For example, in your script you can use query @Asset cms.
2- In " createAndExerciseCmd (AssetHelper cms)" is cms the key in the contract or the maintainer?
In createAndExerciseCmd (AssetHelper cms), the party cms is the parameter being passed for the creation of the AssetHelper contract. Notice how AssetHelper is defined:
template AssetHelper
with
caller : Party
An equivalent syntax to
createAndExerciseCmd (AssetHelper cms)
would be the more verbose
createAndExerciseCmd (AssetHelper with caller=cms).
So if the question is “is cms the key in the contract or the maintainer”… it is neither. It is the caller in the AssetHelper contract.
Now, a more complete answer would point out that the caller in the AssetHelper is used later in a choice. It is used as the first member of a tuple. Here is that line from the choice:
fetchByKey @Asset (caller, idCode)
In the above code, the tuple (caller, idCode) is the key being queried for.
Again, your explanation is invaluable!!! I can progress now. Thank you ever so much!!!
feel like sending you a bottle of champagne for your help!! I am so grateful. ![]()
Thank you thank you thank you