Notification /Feedback for Cancelling or Rejecting a contract

This is more of a general question as opposed to some issue I’m facing.

Say I have a proposalContract to which a recipient can reject or I can cancel. Once rejected, the proposalContract is archived.

How can I make this interaction more responsive on the UI side, eg on the sender’s view “recipient has rejected your offer” ?

Or from the recipients view “sender has cancelled transaction” ? As of now, the data just disappears once archived.

There needs to be some sort of post-exercise template created, or a message being sent right?

Not just from a UI perspective, but for any system downstream of a Daml ledger, you need to keep state of your active contracts.

Then specifically from a UI point of you, over the websocket you do get a list of Events that can be either a created or archived.

So store a set of contract ids, and once a proposal is archived, you know that it has been rejected if no agreement has been created, for example.

2 Likes

Another option is that you have a two step process:
Instead of archiving a proposal on rejection, you create a RejectedProposal contract and then you have some automation in the background which archives all rejected proposals older than X. That way you can recover the information you need purely from looking at active contracts which can be a bit easier in particular when working with the JSON API.

3 Likes

Thanks, this is an interesting approach.

I strongly recommend against using archived events from websockets as UI-positive data models. They should only be used to remove a previous created event.

So for example if you have a display of created contracts, then you would deal with an archived event by removing that contract from your display. That is fine, because it is consistent with what happens if you reload the stream from scratch: you get only created events for the active contracts, not any contracts that have been archived.

By contrast, if you list the archived events from a stream, and you reload the stream from scratch, you will get a smaller list of archived events, because they have been elided with their created counterparts (which have also been removed from the stream).

So if your “recipient has rejected your offer” message is just like a shout into the void, and it’s ok for your UI to never show it sometimes in case of offer rejection, then either approach works. Otherwise, if reliably displaying it every time matters, consider something like @cocreature’s suggestion.

1 Like

Agreed. My advice is contingent on not modeling that state explicitly.

2 Likes

and just to follow up with regards to “you need to keep state of your active contracts”
From am implementation perspective, what does that mean? I need to store the state of the active contracts on a separate database?
Meaning I’m feeding data from the ledger to a database that is used to keep state of the acs? I’m a bit confused, isn’t the ledger meant to be THE place to store the source of truth. If I keep state of ACS somewhere else, wouldn’t that lead to possibilities of a mismatch?

It depends on your requirements. My point about keeping track of your ACS is that in your app there’s something, even if it is an implicit display in the UI, that is storing that data. If you do it explicitly, (ex. a map in the browsers memory) then you can react to those changes.

With respect to the broader question of storing data off ledger, it very much depends on what type of data you need and how fast you need it. Yes, it is always available to you by replaying the transaction stream, but that might not be suitable to your NFRs.

Thanks for the explanation, really helps with my understanding!

JSON API’s maintenance of your ACS is meant to be “usually good enough”. It’s up-to-date on query, whenever you query. But for a well-performing application you’re usually going to be using the websocket endpoint, which gives you an ACS of your query at the start, but thereafter just feeds you ledger updates to that query, which you’re expected to apply to your local copy. You can always just reload, but this isn’t typically what a reactive front-end application wants to do.

1 Like