Browse Source

Integrate settlement endpoint into actions

Caused trouble because of route collisions, so the integration was done now.
Required distinguishing Maker and Taker on the cfd level, which comes in handy anyway.
We distinguish by order origin, but still map to a `Role` enum (`Taker` / `Maker`) for readability.
To avoid duplication the `Role` from contract setup was moved into the model and used throughout.
upload-correct-windows-binary
Daniel Karzel 3 years ago
parent
commit
550bdcdd22
No known key found for this signature in database GPG Key ID: 30C3FC2E438ADB6E
  1. 5
      daemon/src/maker_cfd.rs
  2. 24
      daemon/src/model/cfd.rs
  3. 5
      daemon/src/routes_maker.rs
  4. 27
      daemon/src/routes_taker.rs
  5. 9
      daemon/src/setup_contract.rs
  6. 1
      daemon/src/taker.rs
  7. 4
      daemon/src/taker_cfd.rs
  8. 16
      daemon/src/to_sse_event.rs
  9. 1
      frontend/src/components/Types.tsx
  10. 5
      frontend/src/components/cfdtables/CfdTable.tsx

5
daemon/src/maker_cfd.rs

@ -5,7 +5,8 @@ use crate::db::{
};
use crate::maker_inc_connections::TakerCommand;
use crate::model::cfd::{
Cfd, CfdState, CfdStateChangeEvent, CfdStateCommon, Dlc, Order, OrderId, SettlementProposal,
Cfd, CfdState, CfdStateChangeEvent, CfdStateCommon, Dlc, Order, OrderId, Role,
SettlementProposal,
};
use crate::model::{TakerId, Usd};
use crate::monitor::MonitorParams;
@ -358,7 +359,7 @@ impl Actor {
(self.oracle_pk, nonce_pks),
cfd,
self.wallet.clone(),
setup_contract::Role::Maker,
Role::Maker,
);
let this = ctx

24
daemon/src/model/cfd.rs

@ -39,12 +39,30 @@ impl<'v> FromParam<'v> for OrderId {
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
// TODO: Could potentially remove this and use the Role in the Order instead
/// Origin of the order
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
pub enum Origin {
Ours,
Theirs,
}
/// Role in the Cfd
#[derive(Debug, Copy, Clone)]
pub enum Role {
Maker,
Taker,
}
impl From<Origin> for Role {
fn from(origin: Origin) -> Self {
match origin {
Origin::Ours => Role::Maker,
Origin::Theirs => Role::Taker,
}
}
}
/// A concrete order created by a maker for a taker
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Order {
@ -667,6 +685,10 @@ impl Cfd {
| CfdState::ContractSetup { .. }
)
}
pub fn role(&self) -> Role {
self.order.origin.into()
}
}
#[derive(Debug, Clone)]

5
daemon/src/routes_maker.rs

@ -151,6 +151,11 @@ pub async fn post_cfd_action(
.await
.expect("actor to always be available");
}
CfdAction::Settle => {
return Err(status::BadRequest(Some(
"Collaborative settlement can only be triggered by taker".to_string(),
)));
}
}
Ok(status::Accepted(None))

27
daemon/src/routes_taker.rs

@ -96,27 +96,12 @@ pub async fn post_order_request(
.expect("actor to always be available");
}
#[rocket::post("/cfd/<id>/settle")]
pub async fn post_settlement_proposal(
id: OrderId,
cfd_actor_inbox: &State<Address<taker_cfd::Actor>>,
quote_updates: &State<watch::Receiver<bitmex_price_feed::Quote>>,
) {
let current_price = quote_updates.borrow().for_taker();
cfd_actor_inbox
.do_send_async(taker_cfd::ProposeSettlement {
order_id: id,
current_price,
})
.await
.expect("actor to always be available");
}
#[rocket::post("/cfd/<id>/<action>")]
pub async fn post_cfd_action(
id: OrderId,
action: CfdAction,
cfd_actor_address: &State<Address<taker_cfd::Actor>>,
quote_updates: &State<watch::Receiver<bitmex_price_feed::Quote>>,
) -> Result<status::Accepted<()>, status::BadRequest<String>> {
match action {
CfdAction::Accept | CfdAction::Reject => {
@ -129,6 +114,16 @@ pub async fn post_cfd_action(
.await
.map_err(|e| status::BadRequest(Some(e.to_string())))?;
}
CfdAction::Settle => {
let current_price = quote_updates.borrow().for_taker();
cfd_actor_address
.do_send_async(taker_cfd::ProposeSettlement {
order_id: id,
current_price,
})
.await
.expect("actor to always be available");
}
}
Ok(status::Accepted(None))

9
daemon/src/setup_contract.rs

@ -1,4 +1,4 @@
use crate::model::cfd::{Cfd, Dlc};
use crate::model::cfd::{Cfd, Dlc, Role};
use crate::wallet::Wallet;
use crate::wire::{Msg0, Msg1, Msg2, SetupMsg};
use crate::{model, payout_curve};
@ -190,13 +190,6 @@ pub async fn new(
})
}
#[allow(dead_code)]
/// Role of the actor's owner in the upcoming contract
pub enum Role {
Maker,
Taker,
}
/// A convenience struct for storing PartyParams and PunishParams of both
/// parties and the role of the caller.
struct AllParams {

1
daemon/src/taker.rs

@ -213,7 +213,6 @@ async fn main() -> Result<()> {
rocket::routes![
routes_taker::feed,
routes_taker::post_order_request,
routes_taker::post_settlement_proposal,
routes_taker::get_health_check,
routes_taker::margin_calc,
routes_taker::post_cfd_action,

4
daemon/src/taker_cfd.rs

@ -4,7 +4,7 @@ use crate::db::{
load_cfd_by_order_id, load_order_by_id,
};
use crate::model::cfd::{
Cfd, CfdState, CfdStateChangeEvent, CfdStateCommon, Dlc, Order, OrderId, Origin,
Cfd, CfdState, CfdStateChangeEvent, CfdStateCommon, Dlc, Order, OrderId, Origin, Role,
};
use crate::model::Usd;
use crate::monitor::{self, MonitorParams};
@ -226,7 +226,7 @@ impl Actor {
(self.oracle_pk, nonce_pks),
cfd,
self.wallet.clone(),
setup_contract::Role::Taker,
Role::Taker,
);
let this = ctx

16
daemon/src/to_sse_event.rs

@ -1,4 +1,4 @@
use crate::model::cfd::OrderId;
use crate::model::cfd::{OrderId, Role};
use crate::model::{Leverage, Position, TradingPair, Usd};
use crate::{bitmex_price_feed, model};
use bdk::bitcoin::Amount;
@ -37,6 +37,7 @@ pub enum CfdAction {
Accept,
Reject,
Commit,
Settle,
}
impl<'v> FromParam<'v> for CfdAction {
@ -115,7 +116,7 @@ impl ToSseEvent for CfdsWithCurrentPrice {
profit_btc,
profit_usd,
state: cfd.state.clone().into(),
actions: actions_for_state(cfd.state.clone()),
actions: actions_for_state(cfd.state.clone(), cfd.role()),
state_transition_timestamp: cfd
.state
.get_transition_timestamp()
@ -221,12 +222,15 @@ fn into_unix_secs(time: SystemTime) -> u64 {
.as_secs()
}
fn actions_for_state(state: model::cfd::CfdState) -> Vec<CfdAction> {
match state {
model::cfd::CfdState::IncomingOrderRequest { .. } => {
fn actions_for_state(state: model::cfd::CfdState, role: Role) -> Vec<CfdAction> {
match (state, role) {
(model::cfd::CfdState::IncomingOrderRequest { .. }, Role::Maker) => {
vec![CfdAction::Accept, CfdAction::Reject]
}
model::cfd::CfdState::Open { .. } => vec![CfdAction::Commit],
(model::cfd::CfdState::Open { .. }, Role::Taker) => {
vec![CfdAction::Commit, CfdAction::Settle]
}
(model::cfd::CfdState::Open { .. }, Role::Maker) => vec![CfdAction::Commit],
_ => vec![],
}
}

1
frontend/src/components/Types.tsx

@ -140,6 +140,7 @@ export enum Action {
ACCEPT = "accept",
REJECT = "reject",
COMMIT = "commit",
SETTLE = "settle",
}
const enum StateKey {

5
frontend/src/components/cfdtables/CfdTable.tsx

@ -1,4 +1,5 @@
import {
CheckCircleIcon,
CheckIcon,
ChevronRightIcon,
ChevronUpIcon,
@ -189,6 +190,8 @@ function iconForAction(action: Action): any {
return <CloseIcon />;
case Action.COMMIT:
return <WarningIcon />;
case Action.SETTLE:
return <CheckCircleIcon />;
}
}
@ -200,6 +203,8 @@ function colorSchemaForAction(action: Action): string {
return "red";
case Action.COMMIT:
return "red";
case Action.SETTLE:
return "green";
}
}

Loading…
Cancel
Save