How can an observer verify he has a contract

G-d willing

Hello,
assuming the following template

template Agreement
  with 
    sideA: Party
    sideB: Party
    identifier: Text
  where
    signatory sideA
    observer sideB
    key (sideA, sideB, identifier): (Party, Party, Text)
    maintainer key._1

While sideA can do lookupByKey and then, in case there is a contract, he can do fetchByKey, how can sideB know if sideA created an Agreement contract for him without having a chance to get an exception?
If executing lookupByKey, it won’t return any contract since sideB is not a signatory. And executing “fetchByKey” alone, can fail if there is no contract.

So, how can I verify there is a contract before doing “fetchByKey”?

Thanks

The issue with visibleByKey/lookupByKey you’ll hit here is not that sideB is not a signatory, per se, but that at the point of querying they do not have the authorization of all the maintainers. Now, you do need to be a signatory to be a maintainer, but you don’t need to be a signatory to have the authority of the maintainers.

For example:

module Main where

import Daml.Script

template Agreement
  with 
    sideA: Party
    sideB: Party
    identifier: Text
  where
    signatory sideA
    observer sideB
    key (sideA, sideB, identifier): (Party, Party, Text)
    maintainer key._1

template TryVisible
  with
    submitter: Party
    requester: Party
  where
    signatory submitter
    observer requester
    preconsuming choice VisibleKey: Bool
      with
        key: (Party, Party, Text)
      controller requester
      do
        visibleByKey @Agreement key


setup : Script ()
setup = script do
  alice <- allocatePartyWithHint "Alice" (PartyIdHint "Alice")
  bob <- allocatePartyWithHint "Bob" (PartyIdHint "Bob")
  aliceId <- validateUserId "alice"
  bobId <- validateUserId "bob"
  createUser (User aliceId (Some alice)) [CanActAs alice]
  createUser (User bobId (Some bob)) [CanActAs bob]

  ag_alice <- submit alice do
    createCmd Agreement with
      sideA = alice
      sideB = bob
      identifier = "1"
  
  q <- submit alice do
    createCmd (TryVisible alice bob)
  bob_can_see <- submit bob do
    exerciseCmd q (VisibleKey (alice, bob, "1"))

  assert bob_can_see

  pure ()
1 Like

Thanks @Gary_Verhaegen for the detailed answer with the example.
In your example, in order for Bob to view the agreement, he has to know the contract id of the “TryVisible” contract.
Well, that brings the issue back from a different angle… how can bob knows that there is a “TryVisible” contract?

The only way I can think of resolving it is by adding a new type of contract that defines the relationship between him and Alice, and in that contract, Alice will store the contract id of the Agreement. And in that contract, Bob will be the maintainer. But I find this approach kind of extravagant.
Creating a new contract in order to be aware of another, sounds unright to me… if there is nothing else than that, I won’t have any other choice but to follow this approach.

Right, so there are two different issues here, and I got confused.

On the one hand, there is the question of how does Bob, the “person” behind the Party and the entity sending gRPC requests to create contracts and execute choices, know about contracts they’re an observer on.

On the other hand, there is the question of how, from Daml code, the bob party can fetch a contract by key when they are a non-signatory observer of said contract.

Hopefully my previous message answers the second question, so I’ll focus on the first one now. But please do not hesitate to ask follow-up questions on both.

As an entity interacting with the ledger, Bob needs to be using the gRPC API. (For our purposes here, the HTTP JSON API, if used, is transparent.) The gRPC API, broadly speaking, lets Bob do two things:

  1. Act on the ledger: send Create and Exercise commands to “make things happen”, or, from another perspective, “record” things on the ledger.
  2. Subscribe to the ledger to get notified when other people do things.

That second point is very important. The ledger is a synchronization point between multiple parties and, when you create a contract, you do want to know when someone else exercises a choice on your contracts. Similarly, you also want to know when someone else creates a contract you’re an observer on.

The Script mechanics you can use in the IDE accurately reflects point 1, but sort of sidesteps point 2 completely. In a real Daml system, point 2 is essential and every entity involved with a given Daml ledger will be listening to ledger updates in some form.

Exactly how you subscribe to notifications will depend on what your program is and does, but any application (or UI, as in the getting started example app) that interacts with a Daml ledger will have some form of subscription to change notifications.

@Gary_Verhaegen I truly appreciate your detailed answers.

Basically, I am trying to do it only using the Daml code, and I will explain why.
Let’s say Alice is a seller, Bob is a broker, while Charlie and David are potential buyers.
Alice is telling Bob that she wants to sell a product she is having, and notifying Bob she is publishing a bid for it.
For that, Bob needs to notify all of his buyers about the bid. Note: Alice is not aware of Bob’s buyers.
Bob’s job is to pass Alice all of the offers he received from his buyers without any filtering.
So I don’t want the UI to go through all the offers (one by one) and send them to Alice. In this approach, a bug can cause an offer not to be sent to Alice. In addition, the UI cannot be a part of the business logic.

Hence, I want to exercise a choice where all of the buyers’ offers will be sent to Alice.
I hope this explains what I need to do, and that there is a nice solution for it.

The details will depend a lot on exactly who can know what in your model, but the basic issue here is that there is no query mechanism in choices.

So you have to work around that, for example by having a single contract that keeps track of all the offers, and that Alice would be an observer on.

In short, discovering contracts should be done through the observer mechanism, as explained in my previous post. That leads to the next problem, which is the discovery of party IDs, and that one is simply not covered within the ledger. We assume parties are somehow communicated off band: with all of its privacy features, Daml is designed for people who already know who they want to talk to.

Things like open chat rooms (or, in this case, bids) that anyone can join are thus a bit tricky to model in a Daml system (though not impossible).

Thank you very much @Gary_Verhaegen
So I guess my own solution is to have another template that will store the contract id of the agreement contract.