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