How can I query for a contract id from within an Update

G-d willing

Hello,
This question is mixed from both the Daml and the Finance world.
I am using the interfaces from the Finance Library and implemented my own Account template which is very similar to the one in the Finance Library.
When I create a new Holding I would like it to be merged with previous Holding contracts.
Since I cannot query for contracts from within a choice, my only way of knowing previous Holding contracts, is by saving it on another contract that holds the details of the Account and a list of Holding contracts Ids.

template CreditHoldingRequest 
  with
    sender: Party
    receiver : Party
    accountKey: AccountKey
    instrumentKey: InstrumentKey
    amount : Int
  where
    signatory sender
    observer receiver

    choice ApproveCreditRequest : ContractId Holding.I
      controller receiver
        do
          
          holdingCid <- Account.exerciseInterfaceByKey @Account.I accountKey accountKey.custodian Account.Credit
            with
              quantity = Instrument.qty (intToNumeric amount) instrumentKey

          -- merge the holdings on the same account - don't want to have multiple holdings
          -- need to add the merge command in here and return the contract Id of it.
          return holdingCid

So, am I missing any relationship between the Finance Library entities in order to know all the Holdings of a specific Account?

Thanks

1 Like

Hi @cohen.avraham,

An alternative approach having a template with the Account alongside the list of active Holding contract Ids would be to pass the list of Holding contract Ids for the specified Account into the choice.

Specific to your scenario, the ApproveCreditRequest could have an input parameter holdingCids : [ContractId Fungible.I] . Whenever the receiver calls this choice, they can query the ACS (Active Contract Set) to get this list of contracts and pass this list as a parameter into the choice. As part of the choice body, you can then call the Merge choice (on the Fungible interface - see here) to merge the list of existing holdings with the new holding.

Please note - only Fungible instruments may be merged.

The downside to maintaining a list of active contract Ids on a separate template is the management overhead and potential contention. Each time a Holding contract is mutated or archived, you’d have to update this list as part of the same atomic transaction to ensure its in sync.

Hope this helps!
Brian

2 Likes

G-d willing

Thanks @Brian_Weir for your response.
Following your suggestion, I feel like going back to square one. Since I need to pass to the choice the list of contract ids, how can I query for all the existing holdings the account has, from within an Update (and not from a Script)?

Thanks

how can I query for all the existing holdings the account has, from within an Update (and not from a Script)?

You cannot query for templates within an Update. The process of querying templates can only be achieved via an off-ledger process, such as within a Script (or via the JavaScript or Java bindings, or calling the Ledger API via GRPC).

Ultimately, it depends on how you envision the ApproveCreditRequest to be called. If you don’t want the receiver to provide the list of contracts to merge when calling the choice then you fall back to the pattern (as you have mentioned above) of having another contract maintain that list of active Holdings which you then have to fetch from inside the Update to extract that list.

1 Like

There’s another consideration that needs to be taken into account when modeling asset holdings in Daml. Referring to the CreditHoldingRequest template in the original post on this thread, if you do somehow merge the asset holdings within ApproveCreditRequest choice (e.g. by passing the ContractIds of the holdings to the choice as parameters), the resulting holdingCid effectively represents the new account balance. The issue is that this resulting Holding contract is revealed to the signatory on the CreditHoldingRequest contract through divulgence. In other words the sender of the credit holding request becomes aware of the entire balance of the receiver’s account, which in most use cases is undesirable. This is one reason why in Daml apps we typically model asset holdings in an account as a set of discrete holding contracts, where the account balance is the sum of the amounts of the holding contracts, rather than as a single holding contract representing the account balance. You can read more about this in the article that explains the asset holdings model in the Wallet Daml Sample App.
@cohen.avraham, I would suggest that you take a close look at the rationale for merging the holdings to see if it still stands in light of the behavior I described here.

4 Likes

@a_putkov your point was in place. And the solution will be changed accordingly. :+1:

G-d willing

@a_putkov @Brian_Weir, can you please explain to me what caused the decision not to have a query functionality to be from within an update?
There are already fetch, fetchByKey, and lookupByKey, so what do lookup or query breaks in this concept?

@cohen.avraham
Please check out previous discussion about implementing query function in the context of an Update on this thread.