Skip to main content

df_hyperliquid_core/deploy/outcomes/actions/
operation.rs

1//! What an `outcomeDeploy` does: each register, settle and sub-deployer grant, the key it travels
2//! under and the body it carries.
3
4use crate::deploy::outcomes::actions::bounded::FeeScale;
5use crate::deploy::outcomes::actions::grant::{Grant, Permission};
6use crate::deploy::outcomes::actions::instance::Instance;
7use crate::deploy::outcomes::actions::settlement::Settlement;
8use crate::utils::sign::{Map, Value};
9
10/// What an `outcomeDeploy` does, under the key naming it.
11#[derive(Debug, Clone, PartialEq, Eq)]
12pub enum Operation {
13    /// `registerStandaloneOutcomeFromTemplate`: one outcome with two sides.
14    RegisterStandalone { instance: Instance, fee_scale: FeeScale },
15    /// `registerQuestionFromTemplate`: a question and its named outcomes, in
16    /// the order given, which is the order they are shown in. The venue adds
17    /// a fallback, so N named outcomes make N + 1.
18    RegisterQuestion { question: Instance, fee_scale: FeeScale, named: Vec<Instance> },
19    /// `registerAndAssociateNamedOutcomeFromTemplate`: one more named outcome
20    /// on a live question, at the question's fee scale.
21    RegisterAndAssociate { question: u32, named: Instance },
22    /// `settleOutcome`. Pays out at once and cannot be undone.
23    SettleOutcome(Settlement),
24    /// `settleQuestion2`: every named outcome of the question not yet
25    /// settled, exactly one of them at 1, the fallback left out. Pays out at
26    /// once and cannot be undone.
27    SettleQuestion { question: u32, settlements: Vec<Settlement>, name: String, description: String },
28    /// `setSubDeployers`.
29    SetSubDeployers(Vec<Grant>),
30}
31
32impl Operation {
33    /// The key the operation travels under.
34    #[must_use]
35    pub const fn wire_name(&self) -> &'static str {
36        match self {
37            Operation::RegisterStandalone { .. } => "registerStandaloneOutcomeFromTemplate",
38            Operation::RegisterQuestion { .. } => "registerQuestionFromTemplate",
39            Operation::RegisterAndAssociate { .. } => "registerAndAssociateNamedOutcomeFromTemplate",
40            Operation::SettleOutcome(_) => "settleOutcome",
41            Operation::SettleQuestion { .. } => "settleQuestion2",
42            Operation::SetSubDeployers(_) => "setSubDeployers",
43        }
44    }
45
46    /// The grant a sub-deployer needs to send this; `None` for
47    /// `setSubDeployers`, which no grant covers.
48    #[must_use]
49    pub const fn permission(&self) -> Option<Permission> {
50        match self {
51            Operation::RegisterStandalone { .. } => Some(Permission::RegisterStandalone),
52            Operation::RegisterQuestion { .. } => Some(Permission::RegisterQuestion),
53            Operation::RegisterAndAssociate { .. } => Some(Permission::RegisterAndAssociate),
54            Operation::SettleOutcome(_) => Some(Permission::SettleOutcome),
55            Operation::SettleQuestion { .. } => Some(Permission::SettleQuestion),
56            Operation::SetSubDeployers(_) => None,
57        }
58    }
59
60    /// Settling pays out at once and cannot be undone.
61    #[must_use]
62    pub const fn is_settlement(&self) -> bool {
63        matches!(self, Operation::SettleOutcome(_) | Operation::SettleQuestion { .. })
64    }
65
66    #[must_use]
67    pub fn body(&self) -> Value {
68        match self {
69            Operation::RegisterStandalone { instance, fee_scale } => instance.wire_with(*fee_scale).into(),
70            Operation::RegisterQuestion { question, fee_scale, named } => Map::new()
71                .put("questionTemplateInstance", question.wire_with(*fee_scale))
72                .put("namedOutcomeTemplateInstances", Value::array(named.iter().map(Instance::wire)))
73                .into(),
74            Operation::RegisterAndAssociate { question, named } => {
75                Map::new().put("question", *question).put("namedOutcomeTemplateInstance", named.wire()).into()
76            }
77            Operation::SettleOutcome(settlement) => settlement.wire().into(),
78            Operation::SettleQuestion { question, settlements, name, description } => Map::new()
79                .put("question", *question)
80                .put("outcomeSettlements", Value::array(settlements.iter().map(Settlement::wire)))
81                .put("nameAndDescription", Value::array([name.clone(), description.clone()]))
82                .into(),
83            Operation::SetSubDeployers(grants) => Value::array(grants.iter().map(Grant::wire)),
84        }
85    }
86}
87
88#[cfg(test)]
89#[path = "tests/operation.rs"]
90mod tests;