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.

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. :pray: :pray: :pray: :pray: :pray: :pray:

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, :smile: :smile: :smile:

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 :blush: :blush:

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. :pray: :pray: :pray: :pray:

Use the query function. For example, in your script you can use query @Asset cms.

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!!! :pray: :pray: :pray: :pray: :pray: feel like sending you a bottle of champagne for your help!! I am so grateful. :smiley:

Thank you thank you thank you