1use std::io::{Read, Write};
3
4use crate::crypto::PublicKey;
5use crate::error::{Error, Result};
6use crate::xdr;
7use chrono::{DateTime, Duration, TimeZone, Utc};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ClaimableBalanceId(Vec<u8>);
11
12#[derive(Debug, Clone, PartialEq, Eq)]
13pub struct Claimant {
14 destination: PublicKey,
15 predicate: ClaimPredicate,
16}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum ClaimPredicate {
20 Unconditional,
21 And(Box<ClaimPredicate>, Box<ClaimPredicate>),
22 Or(Box<ClaimPredicate>, Box<ClaimPredicate>),
23 Not(Box<ClaimPredicate>),
24 BeforeAbsoluteTime(DateTime<Utc>),
25 BeforeRelativeTime(Duration),
26}
27
28impl ClaimableBalanceId {
29 pub fn new(hash: Vec<u8>) -> Result<ClaimableBalanceId> {
31 if hash.len() != 32 {
32 Err(Error::InvalidClaimableBalanceIdLength)
33 } else {
34 Ok(ClaimableBalanceId(hash))
35 }
36 }
37
38 pub fn as_bytes(&self) -> &[u8] {
40 &self.0
41 }
42
43 pub fn to_xdr(&self) -> xdr::ClaimableBalanceId {
45 let hash = xdr::Hash(self.0.as_slice().try_into().unwrap());
46 xdr::ClaimableBalanceId::ClaimableBalanceIdTypeV0(hash)
47 }
48
49 pub fn from_xdr(x: &xdr::ClaimableBalanceId) -> Result<ClaimableBalanceId> {
51 match x {
52 xdr::ClaimableBalanceId::ClaimableBalanceIdTypeV0(hash) => {
53 ClaimableBalanceId::new(hash.0.to_vec())
54 }
55 }
56 }
57}
58
59impl Claimant {
60 pub fn new(destination: PublicKey, predicate: ClaimPredicate) -> Claimant {
62 Claimant {
63 destination,
64 predicate,
65 }
66 }
67
68 pub fn to_xdr(&self) -> Result<xdr::Claimant> {
70 let destination = self.destination.to_xdr_account_id()?;
71 let predicate = self.predicate.to_xdr()?;
72 let inner = xdr::ClaimantV0 {
73 destination,
74 predicate,
75 };
76 Ok(xdr::Claimant::ClaimantTypeV0(inner))
77 }
78
79 pub fn from_xdr(x: &xdr::Claimant) -> Result<Claimant> {
81 match x {
82 xdr::Claimant::ClaimantTypeV0(inner) => {
83 let destination = PublicKey::from_xdr_account_id(&inner.destination)?;
84 let predicate = ClaimPredicate::from_xdr(&inner.predicate)?;
85 Ok(Claimant::new(destination, predicate))
86 }
87 }
88 }
89}
90
91impl ClaimPredicate {
92 pub fn new_unconditional() -> ClaimPredicate {
94 ClaimPredicate::Unconditional
95 }
96
97 pub fn new_and(p1: ClaimPredicate, p2: ClaimPredicate) -> ClaimPredicate {
99 ClaimPredicate::And(Box::new(p1), Box::new(p2))
100 }
101
102 pub fn new_or(p1: ClaimPredicate, p2: ClaimPredicate) -> ClaimPredicate {
104 ClaimPredicate::Or(Box::new(p1), Box::new(p2))
105 }
106
107 pub fn new_not(predicate: ClaimPredicate) -> ClaimPredicate {
109 ClaimPredicate::Not(Box::new(predicate))
110 }
111
112 pub fn new_before_absolute_time(datetime: DateTime<Utc>) -> ClaimPredicate {
114 ClaimPredicate::BeforeAbsoluteTime(datetime)
115 }
116
117 pub fn new_before_relative_time(duration: Duration) -> ClaimPredicate {
120 ClaimPredicate::BeforeRelativeTime(duration)
121 }
122
123 pub fn to_xdr(&self) -> Result<xdr::ClaimPredicate> {
125 match self {
126 ClaimPredicate::Unconditional => Ok(xdr::ClaimPredicate::Unconditional),
127 ClaimPredicate::And(p1, p2) => {
128 let p1_xdr = p1.to_xdr()?;
129 let p2_xdr = p2.to_xdr()?;
130 let predicates = vec![p1_xdr, p2_xdr];
131 Ok(xdr::ClaimPredicate::And(predicates.try_into().unwrap()))
132 }
133 ClaimPredicate::Or(p1, p2) => {
134 let p1_xdr = p1.to_xdr()?;
135 let p2_xdr = p2.to_xdr()?;
136 let predicates = vec![p1_xdr, p2_xdr];
137 Ok(xdr::ClaimPredicate::Or(predicates.try_into().unwrap()))
138 }
139 ClaimPredicate::Not(p) => {
140 let p_xdr = p.to_xdr()?;
141 let predicate = Some(Box::new(p_xdr));
142 Ok(xdr::ClaimPredicate::Not(predicate))
143 }
144 ClaimPredicate::BeforeAbsoluteTime(datetime) => {
145 let time = datetime.timestamp();
146 Ok(xdr::ClaimPredicate::BeforeAbsoluteTime(time))
147 }
148 ClaimPredicate::BeforeRelativeTime(duration) => {
149 let time = duration.num_seconds();
150 Ok(xdr::ClaimPredicate::BeforeRelativeTime(time))
151 }
152 }
153 }
154
155 pub fn from_xdr(x: &xdr::ClaimPredicate) -> Result<ClaimPredicate> {
157 match x {
163 xdr::ClaimPredicate::Unconditional => Ok(ClaimPredicate::new_unconditional()),
164 xdr::ClaimPredicate::And(predicates) => {
165 let mut p = predicates.iter();
166 match (p.next(), p.next()) {
167 (Some(p1), Some(p2)) => {
168 let p1 = ClaimPredicate::from_xdr(p1)?;
169 let p2 = ClaimPredicate::from_xdr(p2)?;
170 Ok(ClaimPredicate::new_and(p1, p2))
171 }
172 _ => Err(Error::XdrClaimPredicateError),
173 }
174 }
175 xdr::ClaimPredicate::Or(predicates) => {
176 let mut p = predicates.iter();
177 match (p.next(), p.next()) {
178 (Some(p1), Some(p2)) => {
179 let p1 = ClaimPredicate::from_xdr(p1)?;
180 let p2 = ClaimPredicate::from_xdr(p2)?;
181 Ok(ClaimPredicate::new_or(p1, p2))
182 }
183 _ => Err(Error::XdrClaimPredicateError),
184 }
185 }
186 xdr::ClaimPredicate::Not(predicate) => {
187 if let Some(predicate) = predicate {
188 let p = ClaimPredicate::from_xdr(predicate)?;
189 Ok(ClaimPredicate::new_not(p))
190 } else {
191 Err(Error::XdrClaimPredicateError)
192 }
193 }
194 xdr::ClaimPredicate::BeforeAbsoluteTime(time) => {
195 let datetime = Utc.timestamp_opt(*time, 0).single();
196 datetime
197 .map(ClaimPredicate::new_before_absolute_time)
198 .ok_or(Error::XdrClaimPredicateError)
199 }
200 xdr::ClaimPredicate::BeforeRelativeTime(time) => {
201 let duration = Duration::seconds(*time);
202 Ok(ClaimPredicate::new_before_relative_time(duration))
203 }
204 }
205 }
206}
207
208impl xdr::WriteXdr for Claimant {
209 fn write_xdr<W: Write>(&self, w: &mut xdr::Limited<W>) -> xdr::Result<()> {
210 let xdr = self.to_xdr().map_err(|_| xdr::Error::Invalid)?;
211 xdr.write_xdr(w)
212 }
213}
214
215impl xdr::ReadXdr for Claimant {
216 fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
217 let xdr_result = xdr::Claimant::read_xdr(r)?;
218 Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
219 }
220}
221
222impl xdr::WriteXdr for ClaimPredicate {
223 fn write_xdr<W: Write>(&self, w: &mut xdr::Limited<W>) -> xdr::Result<()> {
224 let xdr = self.to_xdr().map_err(|_| xdr::Error::Invalid)?;
225 xdr.write_xdr(w)
226 }
227}
228
229impl xdr::ReadXdr for ClaimPredicate {
230 fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
231 let xdr_result = xdr::ClaimPredicate::read_xdr(r)?;
232 Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
233 }
234}