Once these messages are handled by dedicated actors, this will reduce
the amount to runtime errors a la "this message should be handled by
someone else".
See #696.
Instead of passing the whole HashMap to the projection actor, only send what has
actually changed.
Provide separate messages to update settlement proposal and roll over proposals,
as they will be sent from different actors.
Either of the roles has to record the outcome of the setup, which should be the same for them.
In order to handle this in our event model we need `Completed` in the model so it is not role specific.
Oracle event-id and Dlc have to exist together, one without the other is incomplete, hence we move the event id inside.
Note that the ID is actually already know to the Dlc as part of the `cet` hashmap, but this was not cleaned up in this patch.
This patch goes towards getting the model boundaries right to transition the architecture towards an event model.
It only makes sense to allow proposing a settlement when in `Open` state.
Theoretically we could argue that it should be allowed in `PendingRefund` and `PendingCommit`, but I don't see an advantage in that.
Note: This only guards the taker side, no guards were added to the maker side because it remains unclear if the deamon should contain logic for this, or we always want to handle acceptance criteria for settlement from the outside.
The projection actor is responsible in preparing data for the HTTP API and consequently for the UI.
While this is commit provides only the foundation, in the long run we can:
- Reduce the logic happening in the rocket layer. `ToSseEvent` can likely go away.
- Reduce the complexity for other actors in what needs to be updated when. All they should care about is sending updates to the projection actor. (mostly done)
- Improve test coverage. With a dedicated actor that does the projection, we should be able to write assertions in our integration tests that are closer to the UI.
`do_send` on `MessageChannel` suffers from the same problems as
`Address#do_send` and `Address#do_send_async`.
Our uses only send messages that never fail so we don't need to adjust
anything.
Connection actor takes care of establishing a connection to the maker and is
monitoring its status.
The connection actor:
- listens for periodically sent heartbeat messages from the maker,
- publish the maker status on a watch::channel feed outside TakerActorSystem,
- observe changes on the watch channel and shut down Rocket if maker goes offline
Note: this is a stepping stone resulting in temporary behaviour. Eventually,
we'd want to support reconnecting to the maker as well as operating the
taker without the maker being online (with a limited set of actions).
Co-authored-by: Thomas Eizinger <thomas@eizinger.io>
Add configurable log levels on taker and maker and start tracing connection related information to track down a problem where the taker does not receive orders but there are not connection errors on both sides.
In case we already have a cfd for the received order we bail, because that should not happen.
If we already know the order, but don't have a related cfd we don't insert but still send it out on the order feed.
Only the attestation relevant for the cfds, based on the event id, should trigger monitoring for the CET.
We now properly filter the monitoring parameters by event id upon attestation.
Without the filter we ran into the error `No CET for oracle event found`, which is expected when trying to find CETs for an event that does not match.
Since an error in the loop can also have unwanted side effects we wrap it with a `try_continue`.
Invoke user actions (cfd actions & taking an order) synchronously in
order to be able to communicate the results.
Use HttpApiProblem to send error details to the frontend in a standard way.
Created new Timestamp struct that only uses seconds (as i64 in order
to play nice with both sqlx and chrono) and removed use of SytemTime::now()
throughout in the process.
This PR addresses #352 but also had the effect of doing a better job of
addressing #434, making #435 pointless.
Addresses #357 and #365. Although not a very large change, this PR ends up touching rather a lot of code.
* Converted types `Usd`, `Leverage` and `Percent` to something that is appropriate to this application
* Created new types `Price` and `InversePrice` to use for BTC/USD exchange rate with appropriate algebraic ops implemented as well.
* Added new positive tests
* The function `daemon::model::calculate_profit()` has been changed substantially as the updated types make the existing workflow needlessly complex
* Some tests (mostly in `cfd.rs` required updating) in order to make use of the new types.
* Minor edit to `.gitignore` to avoid accidental pushing of DB to repository--should have been it's own item, added here to fix a problem that arose during this work.
NOTE:
* There may be an excess of algebraic ops implemented, some pruning may be appropriate.
Fetching new events all over the place is cumbersome and it is likely that we will forget about doing so (e.g. atm we forgot doing this when receiving a roll-over request at the maker). Hence, we now fetch on a regular interval for a fixed timespan:
When starting up we fetch oracle events for the next 24h. Afterwards we check every 5 minutes again if there is a new event to check. This should ensure that we always know about needed events.
Include a generic Wallet actor constructor in the actor systems and allow
passing in a generic Wallet actor implementing xtra::Handlers into the cfd
actors.
Rename 'Maker' and 'Taker' to 'MakerActorSystem' and 'TakerActorSystem' for
readability.
Co-authored-by: Mariusz Klochowicz <mariusz@klochowicz.com>
This allows us to avoid the use of the constant in two places which
removes the dependency on the constant from the taker entirely.
The logic here is generally not great - in particular having the taker
anticipate, which announcement it is going to be - but this is the
least invasive way of making the term dynamic.
We have a 1:1 relationship (and the fact that we don't remove cfds) between cfd and order at the moment, so once the cfd was inserted we cannot creat another cfd for the same order.
Thus, we should remove the order from the feel by sending `None`.
If the maker tells the taker that the take request was for an invalid
order ID, we should do something other than panic. For example,
logging and treating the situation as if the maker had rejected the
take request.