1mod address;
5mod expiration;
6mod governor_address;
7mod immutable_alias_address;
8mod state_controller_address;
9mod storage_deposit_return;
10mod timelock;
11
12use alloc::{boxed::Box, vec::Vec};
13
14use bitflags::bitflags;
15use derive_more::{Deref, From};
16use iterator_sorted::is_unique_sorted;
17use packable::{
18 bounded::BoundedU8,
19 error::{UnpackError, UnpackErrorExt},
20 packer::Packer,
21 prefix::BoxedSlicePrefix,
22 unpacker::Unpacker,
23 Packable,
24};
25
26pub use self::{
27 address::AddressUnlockCondition, expiration::ExpirationUnlockCondition,
28 governor_address::GovernorAddressUnlockCondition, immutable_alias_address::ImmutableAliasAddressUnlockCondition,
29 state_controller_address::StateControllerAddressUnlockCondition,
30 storage_deposit_return::StorageDepositReturnUnlockCondition, timelock::TimelockUnlockCondition,
31};
32use crate::{address::Address, create_bitflags, protocol::ProtocolParameters, Error};
33
34#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, From)]
36#[cfg_attr(
37 feature = "serde",
38 derive(serde::Serialize, serde::Deserialize),
39 serde(tag = "type", content = "data")
40)]
41pub enum UnlockCondition {
42 Address(AddressUnlockCondition),
44 StorageDepositReturn(StorageDepositReturnUnlockCondition),
46 Timelock(TimelockUnlockCondition),
48 Expiration(ExpirationUnlockCondition),
50 StateControllerAddress(StateControllerAddressUnlockCondition),
52 GovernorAddress(GovernorAddressUnlockCondition),
54 ImmutableAliasAddress(ImmutableAliasAddressUnlockCondition),
56}
57
58impl UnlockCondition {
59 pub fn kind(&self) -> u8 {
61 match self {
62 Self::Address(_) => AddressUnlockCondition::KIND,
63 Self::StorageDepositReturn(_) => StorageDepositReturnUnlockCondition::KIND,
64 Self::Timelock(_) => TimelockUnlockCondition::KIND,
65 Self::Expiration(_) => ExpirationUnlockCondition::KIND,
66 Self::StateControllerAddress(_) => StateControllerAddressUnlockCondition::KIND,
67 Self::GovernorAddress(_) => GovernorAddressUnlockCondition::KIND,
68 Self::ImmutableAliasAddress(_) => ImmutableAliasAddressUnlockCondition::KIND,
69 }
70 }
71
72 pub(crate) fn flag(&self) -> UnlockConditionFlags {
74 match self {
75 Self::Address(_) => UnlockConditionFlags::ADDRESS,
76 Self::StorageDepositReturn(_) => UnlockConditionFlags::STORAGE_DEPOSIT_RETURN,
77 Self::Timelock(_) => UnlockConditionFlags::TIMELOCK,
78 Self::Expiration(_) => UnlockConditionFlags::EXPIRATION,
79 Self::StateControllerAddress(_) => UnlockConditionFlags::STATE_CONTROLLER_ADDRESS,
80 Self::GovernorAddress(_) => UnlockConditionFlags::GOVERNOR_ADDRESS,
81 Self::ImmutableAliasAddress(_) => UnlockConditionFlags::IMMUTABLE_ALIAS_ADDRESS,
82 }
83 }
84}
85
86create_bitflags!(
87 pub UnlockConditionFlags,
89 u16,
90 [
91 (ADDRESS, AddressUnlockCondition),
92 (STORAGE_DEPOSIT_RETURN, StorageDepositReturnUnlockCondition),
93 (TIMELOCK, TimelockUnlockCondition),
94 (EXPIRATION, ExpirationUnlockCondition),
95 (STATE_CONTROLLER_ADDRESS, StateControllerAddressUnlockCondition),
96 (GOVERNOR_ADDRESS, GovernorAddressUnlockCondition),
97 (IMMUTABLE_ALIAS_ADDRESS, ImmutableAliasAddressUnlockCondition),
98 ]
99);
100
101impl Packable for UnlockCondition {
102 type UnpackError = Error;
103 type UnpackVisitor = ProtocolParameters;
104
105 fn pack<P: Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
106 match self {
107 UnlockCondition::Address(unlock_condition) => {
108 AddressUnlockCondition::KIND.pack(packer)?;
109 unlock_condition.pack(packer)
110 }
111 UnlockCondition::StorageDepositReturn(unlock_condition) => {
112 StorageDepositReturnUnlockCondition::KIND.pack(packer)?;
113 unlock_condition.pack(packer)
114 }
115 UnlockCondition::Timelock(unlock_condition) => {
116 TimelockUnlockCondition::KIND.pack(packer)?;
117 unlock_condition.pack(packer)
118 }
119 UnlockCondition::Expiration(unlock_condition) => {
120 ExpirationUnlockCondition::KIND.pack(packer)?;
121 unlock_condition.pack(packer)
122 }
123 UnlockCondition::StateControllerAddress(unlock_condition) => {
124 StateControllerAddressUnlockCondition::KIND.pack(packer)?;
125 unlock_condition.pack(packer)
126 }
127 UnlockCondition::GovernorAddress(unlock_condition) => {
128 GovernorAddressUnlockCondition::KIND.pack(packer)?;
129 unlock_condition.pack(packer)
130 }
131 UnlockCondition::ImmutableAliasAddress(unlock_condition) => {
132 ImmutableAliasAddressUnlockCondition::KIND.pack(packer)?;
133 unlock_condition.pack(packer)
134 }
135 }?;
136
137 Ok(())
138 }
139
140 fn unpack<U: Unpacker, const VERIFY: bool>(
141 unpacker: &mut U,
142 visitor: &Self::UnpackVisitor,
143 ) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
144 Ok(match u8::unpack::<_, VERIFY>(unpacker, &()).coerce()? {
145 AddressUnlockCondition::KIND => {
146 UnlockCondition::from(AddressUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?)
147 }
148 StorageDepositReturnUnlockCondition::KIND => UnlockCondition::from(
149 StorageDepositReturnUnlockCondition::unpack::<_, VERIFY>(unpacker, visitor).coerce()?,
150 ),
151 TimelockUnlockCondition::KIND => {
152 UnlockCondition::from(TimelockUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?)
153 }
154 ExpirationUnlockCondition::KIND => {
155 UnlockCondition::from(ExpirationUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?)
156 }
157 StateControllerAddressUnlockCondition::KIND => UnlockCondition::from(
158 StateControllerAddressUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?,
159 ),
160 GovernorAddressUnlockCondition::KIND => {
161 UnlockCondition::from(GovernorAddressUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?)
162 }
163 ImmutableAliasAddressUnlockCondition::KIND => UnlockCondition::from(
164 ImmutableAliasAddressUnlockCondition::unpack::<_, VERIFY>(unpacker, &()).coerce()?,
165 ),
166 k => return Err(Error::InvalidOutputKind(k)).map_err(UnpackError::Packable),
167 })
168 }
169}
170
171pub(crate) type UnlockConditionCount = BoundedU8<0, { UnlockConditions::COUNT_MAX }>;
172
173#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Deref, Packable)]
175#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
176#[packable(unpack_error = Error, with = |e| e.unwrap_item_err_or_else(|p| Error::InvalidUnlockConditionCount(p.into())))]
177#[packable(unpack_visitor = ProtocolParameters)]
178pub struct UnlockConditions(
179 #[packable(verify_with = verify_unique_sorted_packable)] BoxedSlicePrefix<UnlockCondition, UnlockConditionCount>,
180);
181
182impl TryFrom<Vec<UnlockCondition>> for UnlockConditions {
183 type Error = Error;
184
185 #[inline(always)]
186 fn try_from(unlock_conditions: Vec<UnlockCondition>) -> Result<Self, Self::Error> {
187 Self::new(unlock_conditions)
188 }
189}
190
191impl IntoIterator for UnlockConditions {
192 type Item = UnlockCondition;
193 type IntoIter = alloc::vec::IntoIter<Self::Item>;
194
195 fn into_iter(self) -> Self::IntoIter {
196 Vec::from(Into::<Box<[UnlockCondition]>>::into(self.0)).into_iter()
197 }
198}
199
200impl UnlockConditions {
201 pub const COUNT_MAX: u8 = 7;
203
204 pub fn new(unlock_conditions: Vec<UnlockCondition>) -> Result<Self, Error> {
206 let mut unlock_conditions =
207 BoxedSlicePrefix::<UnlockCondition, UnlockConditionCount>::try_from(unlock_conditions.into_boxed_slice())
208 .map_err(Error::InvalidUnlockConditionCount)?;
209
210 unlock_conditions.sort_by_key(UnlockCondition::kind);
211 verify_unique_sorted::<true>(&unlock_conditions)?;
213
214 Ok(Self(unlock_conditions))
215 }
216
217 #[inline(always)]
219 pub fn get(&self, key: u8) -> Option<&UnlockCondition> {
220 self.0
221 .binary_search_by_key(&key, UnlockCondition::kind)
222 .map(|index| &self.0[index])
224 .ok()
225 }
226
227 #[inline(always)]
229 pub fn address(&self) -> Option<&AddressUnlockCondition> {
230 if let Some(UnlockCondition::Address(address)) = self.get(AddressUnlockCondition::KIND) {
231 Some(address)
232 } else {
233 None
234 }
235 }
236
237 #[inline(always)]
239 pub fn storage_deposit_return(&self) -> Option<&StorageDepositReturnUnlockCondition> {
240 if let Some(UnlockCondition::StorageDepositReturn(storage_deposit_return)) =
241 self.get(StorageDepositReturnUnlockCondition::KIND)
242 {
243 Some(storage_deposit_return)
244 } else {
245 None
246 }
247 }
248
249 #[inline(always)]
251 pub fn timelock(&self) -> Option<&TimelockUnlockCondition> {
252 if let Some(UnlockCondition::Timelock(timelock)) = self.get(TimelockUnlockCondition::KIND) {
253 Some(timelock)
254 } else {
255 None
256 }
257 }
258
259 #[inline(always)]
261 pub fn expiration(&self) -> Option<&ExpirationUnlockCondition> {
262 if let Some(UnlockCondition::Expiration(expiration)) = self.get(ExpirationUnlockCondition::KIND) {
263 Some(expiration)
264 } else {
265 None
266 }
267 }
268
269 #[inline(always)]
271 pub fn state_controller_address(&self) -> Option<&StateControllerAddressUnlockCondition> {
272 if let Some(UnlockCondition::StateControllerAddress(state_controller_address)) =
273 self.get(StateControllerAddressUnlockCondition::KIND)
274 {
275 Some(state_controller_address)
276 } else {
277 None
278 }
279 }
280
281 #[inline(always)]
283 pub fn governor_address(&self) -> Option<&GovernorAddressUnlockCondition> {
284 if let Some(UnlockCondition::GovernorAddress(governor_address)) = self.get(GovernorAddressUnlockCondition::KIND)
285 {
286 Some(governor_address)
287 } else {
288 None
289 }
290 }
291
292 #[inline(always)]
294 pub fn immutable_alias_address(&self) -> Option<&ImmutableAliasAddressUnlockCondition> {
295 if let Some(UnlockCondition::ImmutableAliasAddress(immutable_alias_address)) =
296 self.get(ImmutableAliasAddressUnlockCondition::KIND)
297 {
298 Some(immutable_alias_address)
299 } else {
300 None
301 }
302 }
303
304 #[inline(always)]
306 pub fn locked_address<'a>(&'a self, address: &'a Address, milestone_timestamp: u32) -> &'a Address {
307 self.expiration()
308 .and_then(|e| e.return_address_expired(milestone_timestamp))
309 .unwrap_or(address)
310 }
311
312 #[inline(always)]
314 pub fn is_time_locked(&self, milestone_timestamp: u32) -> bool {
315 self.timelock()
316 .map_or(false, |timelock| milestone_timestamp < timelock.timestamp())
317 }
318
319 #[inline(always)]
321 pub fn is_expired(&self, milestone_timestamp: u32) -> bool {
322 self.expiration()
323 .map_or(false, |expiration| milestone_timestamp >= expiration.timestamp())
324 }
325}
326
327#[inline]
328fn verify_unique_sorted<const VERIFY: bool>(unlock_conditions: &[UnlockCondition]) -> Result<(), Error> {
329 if VERIFY && !is_unique_sorted(unlock_conditions.iter().map(UnlockCondition::kind)) {
330 Err(Error::UnlockConditionsNotUniqueSorted)
331 } else {
332 Ok(())
333 }
334}
335
336#[inline]
337fn verify_unique_sorted_packable<const VERIFY: bool>(
338 unlock_conditions: &[UnlockCondition],
339 _: &ProtocolParameters,
340) -> Result<(), Error> {
341 verify_unique_sorted::<VERIFY>(unlock_conditions)
342}
343
344pub(crate) fn verify_allowed_unlock_conditions(
345 unlock_conditions: &UnlockConditions,
346 allowed_unlock_conditions: UnlockConditionFlags,
347) -> Result<(), Error> {
348 for (index, unlock_condition) in unlock_conditions.iter().enumerate() {
349 if !allowed_unlock_conditions.contains(unlock_condition.flag()) {
350 return Err(Error::UnallowedUnlockCondition {
351 index,
352 kind: unlock_condition.kind(),
353 });
354 }
355 }
356
357 Ok(())
358}
359
360#[cfg(test)]
361mod test {
362 use super::*;
363
364 #[test]
365 fn all_flags_present() {
366 assert_eq!(
367 UnlockConditionFlags::ALL_FLAGS,
368 &[
369 UnlockConditionFlags::ADDRESS,
370 UnlockConditionFlags::STORAGE_DEPOSIT_RETURN,
371 UnlockConditionFlags::TIMELOCK,
372 UnlockConditionFlags::EXPIRATION,
373 UnlockConditionFlags::STATE_CONTROLLER_ADDRESS,
374 UnlockConditionFlags::GOVERNOR_ADDRESS,
375 UnlockConditionFlags::IMMUTABLE_ALIAS_ADDRESS
376 ]
377 );
378 }
379}
380
381#[cfg(feature = "dto")]
382#[allow(missing_docs)]
383pub mod dto {
384 use serde::{Deserialize, Serialize, Serializer};
385 use serde_json::Value;
386
387 pub use self::{
388 address::dto::AddressUnlockConditionDto, expiration::dto::ExpirationUnlockConditionDto,
389 governor_address::dto::GovernorAddressUnlockConditionDto,
390 immutable_alias_address::dto::ImmutableAliasAddressUnlockConditionDto,
391 state_controller_address::dto::StateControllerAddressUnlockConditionDto,
392 storage_deposit_return::dto::StorageDepositReturnUnlockConditionDto, timelock::dto::TimelockUnlockConditionDto,
393 };
394 use super::*;
395 use crate::{
396 address::{dto::AddressDto, Address},
397 error::dto::DtoError,
398 };
399
400 #[derive(Clone, Debug, Eq, PartialEq, From)]
401 pub enum UnlockConditionDto {
402 Address(AddressUnlockConditionDto),
404 StorageDepositReturn(StorageDepositReturnUnlockConditionDto),
406 Timelock(TimelockUnlockConditionDto),
408 Expiration(ExpirationUnlockConditionDto),
410 StateControllerAddress(StateControllerAddressUnlockConditionDto),
412 GovernorAddress(GovernorAddressUnlockConditionDto),
414 ImmutableAliasAddress(ImmutableAliasAddressUnlockConditionDto),
416 }
417
418 impl<'de> Deserialize<'de> for UnlockConditionDto {
419 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
420 let value = Value::deserialize(d)?;
421 Ok(
422 match value
423 .get("type")
424 .and_then(Value::as_u64)
425 .ok_or_else(|| serde::de::Error::custom("invalid unlock condition type"))?
426 as u8
427 {
428 AddressUnlockCondition::KIND => {
429 UnlockConditionDto::Address(AddressUnlockConditionDto::deserialize(value).map_err(|e| {
430 serde::de::Error::custom(format!("cannot deserialize address unlock condition: {}", e))
431 })?)
432 }
433 StorageDepositReturnUnlockCondition::KIND => UnlockConditionDto::StorageDepositReturn(
434 StorageDepositReturnUnlockConditionDto::deserialize(value).map_err(|e| {
435 serde::de::Error::custom(format!(
436 "cannot deserialize storage deposit unlock condition: {}",
437 e
438 ))
439 })?,
440 ),
441 TimelockUnlockCondition::KIND => {
442 UnlockConditionDto::Timelock(TimelockUnlockConditionDto::deserialize(value).map_err(|e| {
443 serde::de::Error::custom(format!("cannot deserialize timelock unlock condition: {}", e))
444 })?)
445 }
446 ExpirationUnlockCondition::KIND => UnlockConditionDto::Expiration(
447 ExpirationUnlockConditionDto::deserialize(value).map_err(|e| {
448 serde::de::Error::custom(format!("cannot deserialize expiration unlock condition: {}", e))
449 })?,
450 ),
451 StateControllerAddressUnlockCondition::KIND => UnlockConditionDto::StateControllerAddress(
452 StateControllerAddressUnlockConditionDto::deserialize(value).map_err(|e| {
453 serde::de::Error::custom(format!(
454 "cannot deserialize state controller unlock condition: {}",
455 e
456 ))
457 })?,
458 ),
459 GovernorAddressUnlockCondition::KIND => UnlockConditionDto::GovernorAddress(
460 GovernorAddressUnlockConditionDto::deserialize(value).map_err(|e| {
461 serde::de::Error::custom(format!("cannot deserialize governor unlock condition: {}", e))
462 })?,
463 ),
464 ImmutableAliasAddressUnlockCondition::KIND => UnlockConditionDto::ImmutableAliasAddress(
465 ImmutableAliasAddressUnlockConditionDto::deserialize(value).map_err(|e| {
466 serde::de::Error::custom(format!(
467 "cannot deserialize immutable alias address unlock condition: {}",
468 e
469 ))
470 })?,
471 ),
472 _ => return Err(serde::de::Error::custom("invalid unlock condition type")),
473 },
474 )
475 }
476 }
477
478 impl Serialize for UnlockConditionDto {
479 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
480 where
481 S: Serializer,
482 {
483 #[derive(Serialize)]
484 #[serde(untagged)]
485 enum UnlockConditionDto_<'a> {
486 T1(&'a AddressUnlockConditionDto),
487 T2(&'a StorageDepositReturnUnlockConditionDto),
488 T3(&'a TimelockUnlockConditionDto),
489 T4(&'a ExpirationUnlockConditionDto),
490 T5(&'a StateControllerAddressUnlockConditionDto),
491 T6(&'a GovernorAddressUnlockConditionDto),
492 T7(&'a ImmutableAliasAddressUnlockConditionDto),
493 }
494 #[derive(Serialize)]
495 struct TypedUnlockCondition<'a> {
496 #[serde(flatten)]
497 unlock_condition: UnlockConditionDto_<'a>,
498 }
499 let unlock_condition = match self {
500 UnlockConditionDto::Address(o) => TypedUnlockCondition {
501 unlock_condition: UnlockConditionDto_::T1(o),
502 },
503 UnlockConditionDto::StorageDepositReturn(o) => TypedUnlockCondition {
504 unlock_condition: UnlockConditionDto_::T2(o),
505 },
506 UnlockConditionDto::Timelock(o) => TypedUnlockCondition {
507 unlock_condition: UnlockConditionDto_::T3(o),
508 },
509 UnlockConditionDto::Expiration(o) => TypedUnlockCondition {
510 unlock_condition: UnlockConditionDto_::T4(o),
511 },
512 UnlockConditionDto::StateControllerAddress(o) => TypedUnlockCondition {
513 unlock_condition: UnlockConditionDto_::T5(o),
514 },
515 UnlockConditionDto::GovernorAddress(o) => TypedUnlockCondition {
516 unlock_condition: UnlockConditionDto_::T6(o),
517 },
518 UnlockConditionDto::ImmutableAliasAddress(o) => TypedUnlockCondition {
519 unlock_condition: UnlockConditionDto_::T7(o),
520 },
521 };
522 unlock_condition.serialize(serializer)
523 }
524 }
525
526 impl From<&UnlockCondition> for UnlockConditionDto {
527 fn from(value: &UnlockCondition) -> Self {
528 match value {
529 UnlockCondition::Address(v) => Self::Address(AddressUnlockConditionDto {
530 kind: AddressUnlockCondition::KIND,
531 address: v.address().into(),
532 }),
533 UnlockCondition::StorageDepositReturn(v) => {
534 Self::StorageDepositReturn(StorageDepositReturnUnlockConditionDto {
535 kind: StorageDepositReturnUnlockCondition::KIND,
536 return_address: AddressDto::from(v.return_address()),
537 amount: v.amount().to_string(),
538 })
539 }
540 UnlockCondition::Timelock(v) => Self::Timelock(TimelockUnlockConditionDto {
541 kind: TimelockUnlockCondition::KIND,
542 timestamp: v.timestamp(),
543 }),
544 UnlockCondition::Expiration(v) => Self::Expiration(ExpirationUnlockConditionDto {
545 kind: ExpirationUnlockCondition::KIND,
546 return_address: v.return_address().into(),
547 timestamp: v.timestamp(),
548 }),
549 UnlockCondition::StateControllerAddress(v) => {
550 Self::StateControllerAddress(StateControllerAddressUnlockConditionDto {
551 kind: StateControllerAddressUnlockCondition::KIND,
552 address: v.address().into(),
553 })
554 }
555 UnlockCondition::GovernorAddress(v) => Self::GovernorAddress(GovernorAddressUnlockConditionDto {
556 kind: GovernorAddressUnlockCondition::KIND,
557 address: v.address().into(),
558 }),
559 UnlockCondition::ImmutableAliasAddress(v) => {
560 Self::ImmutableAliasAddress(ImmutableAliasAddressUnlockConditionDto {
561 kind: ImmutableAliasAddressUnlockCondition::KIND,
562 address: v.address().into(),
563 })
564 }
565 }
566 }
567 }
568
569 impl UnlockCondition {
570 pub fn try_from_dto(value: &UnlockConditionDto, token_supply: u64) -> Result<UnlockCondition, DtoError> {
571 Ok(match value {
572 UnlockConditionDto::Address(v) => UnlockCondition::Address(AddressUnlockCondition::new(
573 (&v.address)
574 .try_into()
575 .map_err(|_e| DtoError::InvalidField("AddressUnlockCondition"))?,
576 )),
577 UnlockConditionDto::StorageDepositReturn(v) => {
578 UnlockCondition::StorageDepositReturn(StorageDepositReturnUnlockCondition::new(
579 Address::try_from(&v.return_address)?,
580 v.amount.parse::<u64>().map_err(|_| DtoError::InvalidField("amount"))?,
581 token_supply,
582 )?)
583 }
584 UnlockConditionDto::Timelock(v) => UnlockCondition::Timelock(
585 TimelockUnlockCondition::new(v.timestamp)
586 .map_err(|_| DtoError::InvalidField("TimelockUnlockCondition"))?,
587 ),
588 UnlockConditionDto::Expiration(v) => UnlockCondition::Expiration(
589 ExpirationUnlockCondition::new(
590 (&v.return_address)
591 .try_into()
592 .map_err(|_e| DtoError::InvalidField("ExpirationUnlockCondition"))?,
593 v.timestamp,
594 )
595 .map_err(|_| DtoError::InvalidField("ExpirationUnlockCondition"))?,
596 ),
597 UnlockConditionDto::StateControllerAddress(v) => {
598 UnlockCondition::StateControllerAddress(StateControllerAddressUnlockCondition::new(
599 (&v.address)
600 .try_into()
601 .map_err(|_e| DtoError::InvalidField("StateControllerAddressUnlockCondition"))?,
602 ))
603 }
604 UnlockConditionDto::GovernorAddress(v) => {
605 UnlockCondition::GovernorAddress(GovernorAddressUnlockCondition::new(
606 (&v.address)
607 .try_into()
608 .map_err(|_e| DtoError::InvalidField("GovernorAddressUnlockCondition"))?,
609 ))
610 }
611 UnlockConditionDto::ImmutableAliasAddress(v) => {
612 let address: Address = (&v.address)
613 .try_into()
614 .map_err(|_e| DtoError::InvalidField("ImmutableAliasAddressUnlockCondition"))?;
615 if let Address::Alias(alias_address) = &address {
617 UnlockCondition::ImmutableAliasAddress(ImmutableAliasAddressUnlockCondition::new(
618 *alias_address,
619 ))
620 } else {
621 return Err(DtoError::InvalidField("ImmutableAliasAddressUnlockCondition"));
622 }
623 }
624 })
625 }
626 }
627
628 impl UnlockConditionDto {
629 pub fn kind(&self) -> u8 {
631 match self {
632 Self::Address(_) => AddressUnlockCondition::KIND,
633 Self::StorageDepositReturn(_) => StorageDepositReturnUnlockCondition::KIND,
634 Self::Timelock(_) => TimelockUnlockCondition::KIND,
635 Self::Expiration(_) => ExpirationUnlockCondition::KIND,
636 Self::StateControllerAddress(_) => StateControllerAddressUnlockCondition::KIND,
637 Self::GovernorAddress(_) => GovernorAddressUnlockCondition::KIND,
638 Self::ImmutableAliasAddress(_) => ImmutableAliasAddressUnlockCondition::KIND,
639 }
640 }
641 }
642}