1use std::str::FromStr;
2
3use pallas::{
4 codec::utils::Set,
5 ledger::primitives::{
6 conway::Certificate::{
7 self as PallasCertificate, PoolRegistration as PallasPoolRegistration,
8 },
9 Fragment,
10 },
11};
12use whisky_common::WError;
13
14use crate::wrapper::transaction_body::{
15 parse_rational_number, Anchor, DRep, PoolMetadata, Relay, RewardAccount, StakeCredential,
16};
17
18pub enum CertificateKind {
19 StakeRegistration {
20 stake_credential: StakeCredential,
21 },
22 StakeDeregistration {
23 stake_credential: StakeCredential,
24 },
25 StakeDelegation {
26 stake_credential: StakeCredential,
27 pool_key_hash: String,
28 },
29 PoolRegistration {
30 operator: String, vrf_keyhash: String, pledge: u64,
33 cost: u64,
34 margin: (u64, u64), reward_account: RewardAccount,
36 pool_owners: Vec<String>, relays: Vec<Relay>,
38 pool_metadata: Option<PoolMetadata>, },
40 PoolRetirement {
41 pool_key_hash: String,
42 epoch: u64,
43 },
44
45 Reg {
46 stake_credential: StakeCredential,
47 amount: u64,
48 },
49 UnReg {
50 stake_credential: StakeCredential,
51 amount: u64,
52 },
53 VoteDeleg {
54 stake_credential: StakeCredential,
55 drep: DRep,
56 },
57 StakeVoteDeleg {
58 stake_credential: StakeCredential,
59 pool_key_hash: String,
60 drep: DRep,
61 },
62 StakeRegDeleg {
63 stake_credential: StakeCredential,
64 pool_key_hash: String,
65 amount: u64,
66 },
67 VoteRegDeleg {
68 stake_credential: StakeCredential,
69 drep: DRep,
70 amount: u64,
71 },
72 StakeVoteRegDeleg {
73 stake_credential: StakeCredential,
74 pool_key_hash: String,
75 drep: DRep,
76 amount: u64,
77 },
78 AuthCommitteeHot {
79 committee_cold_cred: StakeCredential,
80 committee_hot_cred: StakeCredential,
81 },
82 ResignCommitteeCold {
83 committee_cold_cred: StakeCredential,
84 anchor: Option<Anchor>,
85 },
86 RegDRepCert {
87 drep_cred: StakeCredential,
88 amount: u64,
89 anchor: Option<Anchor>,
90 },
91 UnRegDRepCert {
92 drep_cred: StakeCredential,
93 amount: u64,
94 },
95 UpdateDRepCert {
96 drep_cred: StakeCredential,
97 anchor: Option<Anchor>,
98 },
99}
100
101#[derive(Debug, PartialEq, Eq, Clone)]
102pub struct Certificate {
103 pub inner: PallasCertificate,
104}
105
106impl Certificate {
107 pub fn new(certificate_kind: CertificateKind) -> Result<Self, WError> {
108 let pallas_certificate = match certificate_kind {
109 CertificateKind::StakeRegistration { stake_credential } => {
110 PallasCertificate::StakeRegistration(stake_credential.inner)
111 }
112 CertificateKind::StakeDeregistration { stake_credential } => {
113 PallasCertificate::StakeDeregistration(stake_credential.inner)
114 }
115 CertificateKind::StakeDelegation {
116 stake_credential,
117 pool_key_hash,
118 } => {
119 let pallas_pool_key_hash = pallas::ledger::primitives::Hash::<28>::from_str(
120 &pool_key_hash,
121 )
122 .map_err(|_| {
123 WError::new(
124 "WhiskyPallas - Creating Certificate",
125 "invalid pool key hash",
126 )
127 })?;
128 PallasCertificate::StakeDelegation(stake_credential.inner, pallas_pool_key_hash)
129 }
130 CertificateKind::PoolRegistration {
131 operator,
132 vrf_keyhash,
133 pledge,
134 cost,
135 margin,
136 reward_account,
137 pool_owners,
138 relays,
139 pool_metadata,
140 } => {
141 let pallas_operator = pallas::ledger::primitives::Hash::<28>::from_str(&operator)
142 .map_err(|_| {
143 WError::new(
144 "WhiskyPallas - Creating Certificate",
145 "invalid operator pool key hash",
146 )
147 })?;
148 let pallas_vrf_keyhash = pallas::ledger::primitives::Hash::<32>::from_str(
149 &vrf_keyhash,
150 )
151 .map_err(|_| {
152 WError::new(
153 "WhiskyPallas - Creating Certificate",
154 "invalid vrf key hash",
155 )
156 })?;
157 let mut pallas_pool_owners_vec = Vec::new();
158 for owner in pool_owners {
159 let pallas_owner = pallas::ledger::primitives::Hash::<28>::from_str(&owner)
160 .map_err(|_| {
161 WError::new(
162 "WhiskyPallas - Creating Certificate",
163 "invalid pool owner key hash",
164 )
165 })?;
166 pallas_pool_owners_vec.push(pallas_owner);
167 }
168 let pallas_relays: Vec<pallas::ledger::primitives::conway::Relay> =
169 relays.into_iter().map(|r| r.inner).collect();
170 let pallas_pool_metadata = match pool_metadata {
171 Some(pm) => Some(pm.inner),
172 None => None,
173 };
174 PallasPoolRegistration {
175 operator: pallas_operator,
176 vrf_keyhash: pallas_vrf_keyhash,
177 pledge,
178 cost,
179 margin: parse_rational_number(margin),
180 reward_account: reward_account.inner,
181 pool_owners: Set::from(pallas_pool_owners_vec),
182 relays: pallas_relays,
183 pool_metadata: pallas_pool_metadata,
184 }
185 }
186 CertificateKind::PoolRetirement {
187 pool_key_hash,
188 epoch,
189 } => {
190 let pallas_pool_key_hash = pallas::ledger::primitives::Hash::<28>::from_str(
191 &pool_key_hash,
192 )
193 .map_err(|_| {
194 WError::new(
195 "WhiskyPallas - Creating Certificate",
196 "invalid pool key hash",
197 )
198 })?;
199 PallasCertificate::PoolRetirement(pallas_pool_key_hash, epoch)
200 }
201 CertificateKind::Reg {
202 stake_credential,
203 amount,
204 } => PallasCertificate::Reg(stake_credential.inner, amount),
205 CertificateKind::UnReg {
206 stake_credential,
207 amount,
208 } => PallasCertificate::UnReg(stake_credential.inner, amount),
209 CertificateKind::VoteDeleg {
210 stake_credential,
211 drep,
212 } => PallasCertificate::VoteDeleg(stake_credential.inner, drep.inner),
213 CertificateKind::StakeVoteDeleg {
214 stake_credential,
215 pool_key_hash,
216 drep,
217 } => {
218 let pallas_pool_key_hash = pallas::ledger::primitives::Hash::<28>::from_str(
219 &pool_key_hash,
220 )
221 .map_err(|_| {
222 WError::new(
223 "WhiskyPallas - Creating Certificate",
224 "invalid pool key hash",
225 )
226 })?;
227 PallasCertificate::StakeVoteDeleg(
228 stake_credential.inner,
229 pallas_pool_key_hash,
230 drep.inner,
231 )
232 }
233 CertificateKind::StakeRegDeleg {
234 stake_credential,
235 pool_key_hash,
236 amount,
237 } => {
238 let pallas_pool_key_hash = pallas::ledger::primitives::Hash::<28>::from_str(
239 &pool_key_hash,
240 )
241 .map_err(|_| {
242 WError::new(
243 "WhiskyPallas - Creating Certificate",
244 "invalid pool key hash",
245 )
246 })?;
247 PallasCertificate::StakeRegDeleg(
248 stake_credential.inner,
249 pallas_pool_key_hash,
250 amount,
251 )
252 }
253 CertificateKind::VoteRegDeleg {
254 stake_credential,
255 drep,
256 amount,
257 } => PallasCertificate::VoteRegDeleg(stake_credential.inner, drep.inner, amount),
258 CertificateKind::StakeVoteRegDeleg {
259 stake_credential,
260 pool_key_hash,
261 drep,
262 amount,
263 } => {
264 let pallas_pool_key_hash = pallas::ledger::primitives::Hash::<28>::from_str(
265 &pool_key_hash,
266 )
267 .map_err(|_| {
268 WError::new(
269 "WhiskyPallas - Creating Certificate",
270 "invalid pool key hash",
271 )
272 })?;
273 PallasCertificate::StakeVoteRegDeleg(
274 stake_credential.inner,
275 pallas_pool_key_hash,
276 drep.inner,
277 amount,
278 )
279 }
280 CertificateKind::AuthCommitteeHot {
281 committee_cold_cred,
282 committee_hot_cred,
283 } => PallasCertificate::AuthCommitteeHot(
284 committee_cold_cred.inner,
285 committee_hot_cred.inner,
286 ),
287 CertificateKind::ResignCommitteeCold {
288 committee_cold_cred,
289 anchor,
290 } => PallasCertificate::ResignCommitteeCold(
291 committee_cold_cred.inner,
292 anchor.map(|a| a.inner),
293 ),
294 CertificateKind::RegDRepCert {
295 drep_cred,
296 amount,
297 anchor,
298 } => PallasCertificate::RegDRepCert(drep_cred.inner, amount, anchor.map(|a| a.inner)),
299 CertificateKind::UnRegDRepCert { drep_cred, amount } => {
300 PallasCertificate::UnRegDRepCert(drep_cred.inner, amount)
301 }
302 CertificateKind::UpdateDRepCert { drep_cred, anchor } => {
303 PallasCertificate::UpdateDRepCert(drep_cred.inner, anchor.map(|a| a.inner))
304 }
305 };
306
307 Ok(Self {
308 inner: pallas_certificate,
309 })
310 }
311
312 pub fn encode(&self) -> String {
313 hex::encode(
314 self.inner
315 .encode_fragment()
316 .expect("encoding failed at Certificate"),
317 )
318 }
319
320 pub fn decode_bytes(bytes: &[u8]) -> Result<Self, String> {
321 let inner = PallasCertificate::decode_fragment(&bytes)
322 .map_err(|e| format!("Fragment decode error: {}", e.to_string()))?;
323 Ok(Self { inner })
324 }
325}