ddk_messages/
contract_msgs.rs

1//! Structure containing information about contract details.
2
3use bitcoin::Amount;
4use lightning::ln::msgs::DecodeError;
5use lightning::util::ser::{Readable, Writeable, Writer};
6use oracle_msgs::OracleInfo;
7
8#[derive(Clone, PartialEq, Debug, Eq)]
9#[cfg_attr(
10    any(test, feature = "use-serde"),
11    derive(serde::Deserialize, serde::Serialize),
12    serde(rename_all = "camelCase")
13)]
14/// Represents a single outcome of a DLC contract and the associated offer party
15/// payout.
16pub struct ContractOutcome {
17    /// The outcome represented as a string.
18    pub outcome: String,
19    /// The payout of the offer party for the outcome.
20    pub offer_payout: Amount,
21}
22
23impl_dlc_writeable!(ContractOutcome, {(outcome, string), (offer_payout, writeable)});
24
25#[derive(Clone, Debug, PartialEq)]
26#[cfg_attr(
27    feature = "use-serde",
28    derive(serde::Serialize, serde::Deserialize),
29    serde(rename_all = "camelCase")
30)]
31/// Contains information about the contract outcomes, payouts and oracles.
32#[allow(clippy::large_enum_variant)]
33pub enum ContractInfo {
34    /// A contract that is based on a single event.
35    SingleContractInfo(SingleContractInfo),
36    /// A contract that is based on multiple events.
37    DisjointContractInfo(DisjointContractInfo),
38}
39
40impl_dlc_writeable_enum!(ContractInfo,
41    (0, SingleContractInfo), (1, DisjointContractInfo);;;
42);
43
44impl ContractInfo {
45    /// Returns the total collateral locked inside the contract.
46    pub fn get_total_collateral(&self) -> Amount {
47        match self {
48            ContractInfo::SingleContractInfo(v0) => v0.total_collateral,
49            ContractInfo::DisjointContractInfo(v1) => v1.total_collateral,
50        }
51    }
52
53    /// Return the smallet maturity date amongst all events and oracle announcements
54    /// used in the contract.
55    pub fn get_closest_maturity_date(&self) -> u32 {
56        match self {
57            ContractInfo::SingleContractInfo(s) => {
58                s.contract_info.oracle_info.get_closest_maturity_date()
59            }
60            ContractInfo::DisjointContractInfo(d) => d
61                .contract_infos
62                .iter()
63                .map(|x| x.oracle_info.get_closest_maturity_date())
64                .min()
65                .expect("to have at least one element"),
66        }
67    }
68}
69
70#[derive(Clone, Debug, PartialEq)]
71#[cfg_attr(
72    feature = "use-serde",
73    derive(serde::Serialize, serde::Deserialize),
74    serde(rename_all = "camelCase")
75)]
76/// Information for a contract based on a single event.
77pub struct SingleContractInfo {
78    /// The total collateral locked in the contract.
79    pub total_collateral: Amount,
80    /// Information about the contract outcomes, payout and oracles.
81    pub contract_info: ContractInfoInner,
82}
83
84impl_dlc_writeable!(SingleContractInfo, { (total_collateral, writeable), (contract_info, writeable) });
85
86#[derive(Clone, Debug, PartialEq)]
87#[cfg_attr(
88    feature = "use-serde",
89    derive(serde::Serialize, serde::Deserialize),
90    serde(rename_all = "camelCase")
91)]
92/// Information for a contract based on a multiple events.
93pub struct DisjointContractInfo {
94    /// The total collateral locked in the contract.
95    pub total_collateral: Amount,
96    /// Information about the contract outcomes, payout and oracles.
97    pub contract_infos: Vec<ContractInfoInner>,
98}
99
100impl_dlc_writeable!(DisjointContractInfo, { (total_collateral, writeable), (contract_infos, vec)});
101
102#[derive(Clone, Debug, PartialEq)]
103#[cfg_attr(
104    feature = "use-serde",
105    derive(serde::Serialize, serde::Deserialize),
106    serde(rename_all = "camelCase")
107)]
108/// Payout and oracle information for a contract.
109pub struct ContractInfoInner {
110    /// Payout information for the contract.
111    pub contract_descriptor: ContractDescriptor,
112    /// Oracle information for the contract.
113    pub oracle_info: OracleInfo,
114}
115
116impl_dlc_writeable!(ContractInfoInner, { (contract_descriptor, writeable), (oracle_info, writeable) });
117
118#[derive(Clone, Debug, PartialEq)]
119#[cfg_attr(
120    feature = "use-serde",
121    derive(serde::Serialize, serde::Deserialize),
122    serde(rename_all = "camelCase")
123)]
124/// Information about the outcomes and payouts of a contract.
125pub enum ContractDescriptor {
126    /// Used for contract based on enumerated outcomes.
127    EnumeratedContractDescriptor(EnumeratedContractDescriptor),
128    /// Used for contract based on numerical outcomes.
129    NumericOutcomeContractDescriptor(NumericOutcomeContractDescriptor),
130}
131
132impl_dlc_writeable_enum!(
133    ContractDescriptor, (0, EnumeratedContractDescriptor), (1, NumericOutcomeContractDescriptor);;;
134);
135
136#[derive(Clone, Debug, PartialEq, Eq)]
137#[cfg_attr(
138    feature = "use-serde",
139    derive(serde::Serialize, serde::Deserialize),
140    serde(rename_all = "camelCase")
141)]
142/// Information about outcomes and payouts for a contract based on enumerated
143/// outcome event.
144pub struct EnumeratedContractDescriptor {
145    /// The payouts for the different outcomes.
146    pub payouts: Vec<ContractOutcome>,
147}
148
149impl_dlc_writeable!(EnumeratedContractDescriptor, { (payouts, vec) });
150
151#[derive(Clone, Debug, PartialEq)]
152#[cfg_attr(
153    feature = "use-serde",
154    derive(serde::Serialize, serde::Deserialize),
155    serde(rename_all = "camelCase")
156)]
157/// Information about outcomes and payouts for a contract based on numerical
158/// outcome event.
159pub struct NumericOutcomeContractDescriptor {
160    /// The number of digits used by the oracle with smallest number of digits.
161    pub num_digits: u16,
162    /// The function representing the payout depending on the outcomes.
163    pub payout_function: PayoutFunction,
164    /// The rounding intervals to be applied to the payouts.
165    pub rounding_intervals: RoundingIntervals,
166}
167
168impl_dlc_writeable!(NumericOutcomeContractDescriptor, { (num_digits, writeable), (payout_function, writeable), (rounding_intervals, writeable) });
169
170#[derive(Clone, Debug, PartialEq)]
171#[cfg_attr(
172    feature = "use-serde",
173    derive(serde::Serialize, serde::Deserialize),
174    serde(rename_all = "camelCase")
175)]
176/// Function representing the payouts based on the outcomes of a numerical contract.
177pub struct PayoutFunction {
178    /// The pieces that make up the function.
179    pub payout_function_pieces: Vec<PayoutFunctionPiece>,
180    /// The right most point of the function.
181    pub last_endpoint: PayoutPoint,
182}
183
184impl_dlc_writeable!(PayoutFunction, {(payout_function_pieces, vec), (last_endpoint, writeable)});
185
186#[derive(Clone, Debug, PartialEq)]
187#[cfg_attr(
188    feature = "use-serde",
189    derive(serde::Serialize, serde::Deserialize),
190    serde(rename_all = "camelCase")
191)]
192/// A piece of a [`PayoutFunction`].
193pub struct PayoutFunctionPiece {
194    /// The left end point of the piece.
195    pub end_point: PayoutPoint,
196    /// The function describing the curve for this piece.
197    pub payout_curve_piece: PayoutCurvePiece,
198}
199
200impl_dlc_writeable!(PayoutFunctionPiece, { (end_point, writeable), (payout_curve_piece, writeable) });
201
202#[derive(Clone, Debug, PartialEq)]
203#[cfg_attr(
204    feature = "use-serde",
205    derive(serde::Serialize, serde::Deserialize),
206    serde(rename_all = "camelCase")
207)]
208/// Representations of functions describing the payout curve over a given interval.
209pub enum PayoutCurvePiece {
210    /// Used for curves represented as polynomial functions.
211    PolynomialPayoutCurvePiece(PolynomialPayoutCurvePiece),
212    /// Used for curves represented as hyperbola functions.
213    HyperbolaPayoutCurvePiece(HyperbolaPayoutCurvePiece),
214}
215
216impl_dlc_writeable_enum!(PayoutCurvePiece,
217  (0, PolynomialPayoutCurvePiece),
218  (1, HyperbolaPayoutCurvePiece);;;
219);
220
221#[derive(Clone, Debug, PartialEq, Eq)]
222#[cfg_attr(
223    feature = "use-serde",
224    derive(serde::Serialize, serde::Deserialize),
225    serde(rename_all = "camelCase")
226)]
227/// A payout curve represented by a polynomial function.
228pub struct PolynomialPayoutCurvePiece {
229    /// The points to be used to interpolate the polynomial.
230    pub payout_points: Vec<PayoutPoint>,
231}
232
233impl_dlc_writeable!(PolynomialPayoutCurvePiece, { (payout_points, vec) });
234
235#[derive(Clone, Debug, PartialEq, Eq)]
236#[cfg_attr(
237    feature = "use-serde",
238    derive(serde::Serialize, serde::Deserialize),
239    serde(rename_all = "camelCase")
240)]
241/// A point on a payout curve.
242pub struct PayoutPoint {
243    /// The event outcome for this point (X coordinate).
244    pub event_outcome: u64,
245    /// The payout for this point (Y coordinate).
246    pub outcome_payout: Amount,
247    /// Extra precision to be applied when computing the payout.
248    pub extra_precision: u16,
249}
250
251impl_dlc_writeable!(PayoutPoint, { (event_outcome, writeable), (outcome_payout, writeable), (extra_precision, writeable) });
252
253#[derive(Clone, Debug, PartialEq)]
254#[cfg_attr(
255    feature = "use-serde",
256    derive(serde::Serialize, serde::Deserialize),
257    serde(rename_all = "camelCase")
258)]
259/// A payout curve represented as an hyperbola.
260pub struct HyperbolaPayoutCurvePiece {
261    /// Whether to use the positive or negative piece represented by this
262    /// hyperbola.
263    pub use_positive_piece: bool,
264    /// Parameter to the hyperbola curve.
265    pub translate_outcome: f64,
266    /// Parameter to the hyperbola curve.
267    pub translate_payout: f64,
268    /// Parameter to the hyperbola curve.
269    pub a: f64,
270    /// Parameter to the hyperbola curve.
271    pub b: f64,
272    /// Parameter to the hyperbola curve.
273    pub c: f64,
274    /// Parameter to the hyperbola curve.
275    pub d: f64,
276}
277
278impl_dlc_writeable!(HyperbolaPayoutCurvePiece, {
279    (use_positive_piece, writeable),
280    (translate_outcome, float),
281    (translate_payout, float),
282    (a, float),
283    (b, float),
284    (c, float),
285    (d, float)
286});
287
288#[derive(Clone, Debug, PartialEq, Eq)]
289#[cfg_attr(
290    feature = "use-serde",
291    derive(serde::Serialize, serde::Deserialize),
292    serde(rename_all = "camelCase")
293)]
294/// Rounding interval to be applied to an interval to increase the set of points
295/// with common payouts.
296pub struct RoundingInterval {
297    /// The beggining of the interval on which to apply the associated rounding.
298    pub begin_interval: u64,
299    /// The modulus to apply for the rounding.
300    pub rounding_mod: u64,
301}
302
303impl_dlc_writeable!(RoundingInterval, { (begin_interval, writeable), (rounding_mod, writeable) });
304
305#[derive(Clone, Debug, PartialEq, Eq)]
306#[cfg_attr(
307    feature = "use-serde",
308    derive(serde::Serialize, serde::Deserialize),
309    serde(rename_all = "camelCase")
310)]
311/// A set of [`RoundingInterval`].
312pub struct RoundingIntervals {
313    /// The intervals to be used to round payouts.
314    pub intervals: Vec<RoundingInterval>,
315}
316
317impl_dlc_writeable!(RoundingIntervals, { (intervals, vec) });