partner_chains_plutus_data/
bridge.rs1use crate::*;
4use cardano_serialization_lib::{PlutusData, traits::NoneOrEmpty};
5use sidechain_domain::byte_string::ByteString;
6
7#[derive(Clone, Debug, PartialEq)]
9pub enum TokenTransferDatum {
10 V1(TokenTransferDatumV1),
12}
13
14#[derive(Clone, Debug, PartialEq)]
16pub enum TokenTransferDatumV1 {
17 UserTransfer {
19 receiver: ByteString,
21 },
22 ReserveTransfer,
24}
25
26impl From<TokenTransferDatumV1> for PlutusData {
27 fn from(datum: TokenTransferDatumV1) -> Self {
28 VersionedGenericDatum {
29 version: 1,
30 datum: PlutusData::new_empty_constr_plutus_data(&0u64.into()),
31 appendix: {
32 match datum {
33 TokenTransferDatumV1::UserTransfer { receiver } => {
34 PlutusData::new_single_value_constr_plutus_data(
35 &0u64.into(),
36 &PlutusData::new_bytes(receiver.0),
37 )
38 },
39 TokenTransferDatumV1::ReserveTransfer => {
40 PlutusData::new_empty_constr_plutus_data(&1u64.into())
41 },
42 }
43 },
44 }
45 .into()
46 }
47}
48
49impl From<TokenTransferDatum> for PlutusData {
50 fn from(datum: TokenTransferDatum) -> Self {
51 match datum {
52 TokenTransferDatum::V1(datum) => datum.into(),
53 }
54 }
55}
56
57impl TryFrom<PlutusData> for TokenTransferDatum {
58 type Error = DataDecodingError;
59 fn try_from(data: PlutusData) -> Result<Self, Self::Error> {
60 Self::decode(&data)
61 }
62}
63
64impl VersionedDatum for TokenTransferDatum {
65 fn decode(data: &PlutusData) -> crate::DecodingResult<Self> {
66 match plutus_data_version_and_payload(data) {
67 None => Err(decoding_error_and_log(data, "TokenTransferDatum", "unversioned datum")),
68 Some(VersionedGenericDatum { appendix, version: 1, .. }) => {
69 decode_v1_token_transfer_datum(&appendix).ok_or_else(|| {
70 decoding_error_and_log(&appendix, "TokenTransferDatum", "malformed appendix")
71 })
72 },
73 Some(_) => Err(decoding_error_and_log(data, "TokenTransferDatum", "invalid version")),
74 }
75 }
76}
77
78fn decode_v1_token_transfer_datum(appendix: &PlutusData) -> Option<TokenTransferDatum> {
79 let constr = appendix.as_constr_plutus_data()?;
80 let alternative = u64::from(constr.alternative());
81 let data = constr.data();
82
83 match alternative {
84 0 if data.len() == 1 => {
85 let receiver = data.get(0).as_bytes()?.into();
86 Some(TokenTransferDatum::V1(TokenTransferDatumV1::UserTransfer { receiver }))
87 },
88 1 if data.is_none_or_empty() => {
89 Some(TokenTransferDatum::V1(TokenTransferDatumV1::ReserveTransfer))
90 },
91 _ => None,
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98 use crate::test_helpers::test_plutus_data;
99
100 fn reserve_transfer_data() -> PlutusData {
101 test_plutus_data!({
102 "list": [
103 { "constructor": 0, "fields": [] },
104 { "constructor": 1, "fields": [] },
105 { "int":1 },
106
107 ]
108 })
109 }
110
111 fn user_transfer_data(addr: &[u8]) -> PlutusData {
112 test_plutus_data!({
113 "list": [
114 { "constructor": 0, "fields": [] },
115 { "constructor": 0, "fields": [{ "bytes": hex::encode(addr) }] },
116 { "int":1 },
117
118 ]
119 })
120 }
121
122 mod decode {
123 use super::*;
124 use hex_literal::hex;
125 use pretty_assertions::assert_eq;
126
127 #[test]
128 fn user_transfer_v1() {
129 let datum = TokenTransferDatum::decode(&user_transfer_data(&hex!("abcd")))
130 .expect("Should decode successfully");
131 assert_eq!(
132 datum,
133 TokenTransferDatum::V1(TokenTransferDatumV1::UserTransfer {
134 receiver: ByteString(hex!("abcd").into())
135 })
136 )
137 }
138
139 #[test]
140 fn reserve_transfer_v1() {
141 let datum = TokenTransferDatum::decode(&reserve_transfer_data())
142 .expect("Should decode successfully");
143 assert_eq!(datum, TokenTransferDatum::V1(TokenTransferDatumV1::ReserveTransfer))
144 }
145 }
146
147 mod encode {
148 use super::*;
149 use hex_literal::hex;
150 use pretty_assertions::assert_eq;
151
152 #[test]
153 fn user_transfer_v1() {
154 let data: PlutusData = TokenTransferDatum::V1(TokenTransferDatumV1::UserTransfer {
155 receiver: ByteString::from_hex_unsafe("abcd"),
156 })
157 .into();
158
159 assert_eq!(data, user_transfer_data(&hex!("abcd")))
160 }
161
162 #[test]
163 fn reserve_transfer_v1() {
164 let data: PlutusData =
165 TokenTransferDatum::V1(TokenTransferDatumV1::ReserveTransfer).into();
166
167 assert_eq!(data, reserve_transfer_data())
168 }
169 }
170}