The state changes triggered by the POST requests should still be synchronous and may return errors to the frontend if the action within the backend fails.
This makes it easy to achieve things like disabling a button while an action is being performed or triggering a toast with an error message.
To keep our UI stateless and responsive, we always update the local state of our daemon first (and emit an event for it).
Only once the local state is updated, we engage with other systems like the maker/taker daemon.
Applying state changes locally first allows us to record the user's intention and provide instant (UI) feedback that we are working on making it happen.
Even if the user restarts the entire application, we can pick up where we left of and finish what we were meant to be doing.
A downside of an actor system is that it is composed at runtime rather than compile-time.
In other words, it is fairly easy to write code that compiles and sends messages to actors but does not actually work at runtime because the required actor is not alive.
Thus, the primary risk we need to eliminate with our tests is the wiring of our actors, i.e. do all the individual actors send the correct messages at the right point in time?
We deliberately write these tests against the actor system.
Any component not tested as part of this (like projections for the frontend) either need to be so simple that they don't require testing or should be moved into the actor system.
### Library only exposes pure transition functions rather than a state machine
The protocol implemented in the library can be thought of as a state machine that is pushed forward by each party.
To remain flexible in how the protocol is used, the library MUST only expose pure functions to go from one state to the other rather than representing the actual states itself.
This allows applications on top to shape their states and messages as they wish, only reaching into the library for doing the heavy lifting of cryptography and other protocol-specific functionality.