1use borsh::{BorshDeserialize, BorshSerialize};
2use ibc::apps::nft_transfer::context::{NftClassContext, NftContext};
3use ibc::apps::nft_transfer::types::{
4 ClassData, ClassId, ClassUri, PrefixedClassId, TokenData, TokenId, TokenUri,
5};
6use ibc::core::host::types::error::DecodingError;
7
8#[derive(Clone, Debug)]
10pub struct NftClass {
11 pub class_id: PrefixedClassId,
13 pub class_uri: Option<ClassUri>,
15 pub class_data: Option<ClassData>,
17}
18
19impl BorshSerialize for NftClass {
20 fn serialize<W: std::io::Write>(
21 &self,
22 writer: &mut W,
23 ) -> std::io::Result<()> {
24 BorshSerialize::serialize(&self.class_id.to_string(), writer)?;
25 match &self.class_uri {
26 Some(uri) => {
27 BorshSerialize::serialize(&true, writer)?;
28 BorshSerialize::serialize(&uri.to_string(), writer)?;
29 }
30 None => BorshSerialize::serialize(&false, writer)?,
31 }
32 match &self.class_data {
33 Some(data) => {
34 BorshSerialize::serialize(&true, writer)?;
35 BorshSerialize::serialize(&data.to_string(), writer)
36 }
37 None => BorshSerialize::serialize(&false, writer),
38 }
39 }
40}
41
42impl BorshDeserialize for NftClass {
43 fn deserialize_reader<R: std::io::Read>(
44 reader: &mut R,
45 ) -> std::io::Result<Self> {
46 use std::io::{Error, ErrorKind};
47 let class_id: String = BorshDeserialize::deserialize_reader(reader)?;
48 let class_id = class_id.parse().map_err(|e: DecodingError| {
49 Error::new(ErrorKind::InvalidData, e.to_string())
50 })?;
51
52 let is_uri: bool = BorshDeserialize::deserialize_reader(reader)?;
53 let class_uri = if is_uri {
54 let uri_str: String = BorshDeserialize::deserialize_reader(reader)?;
55 Some(uri_str.parse().map_err(|e: DecodingError| {
56 Error::new(ErrorKind::InvalidData, e.to_string())
57 })?)
58 } else {
59 None
60 };
61
62 let is_data: bool = BorshDeserialize::deserialize_reader(reader)?;
63 let class_data = if is_data {
64 let data_str: String =
65 BorshDeserialize::deserialize_reader(reader)?;
66 Some(data_str.parse().map_err(|e: DecodingError| {
67 Error::new(ErrorKind::InvalidData, e.to_string())
68 })?)
69 } else {
70 None
71 };
72
73 Ok(Self {
74 class_id,
75 class_uri,
76 class_data,
77 })
78 }
79}
80
81impl NftClassContext for NftClass {
82 fn get_id(&self) -> &ClassId {
83 &self.class_id.base_class_id
84 }
85
86 fn get_uri(&self) -> Option<&ClassUri> {
87 self.class_uri.as_ref()
88 }
89
90 fn get_data(&self) -> Option<&ClassData> {
91 self.class_data.as_ref()
92 }
93}
94
95#[derive(Clone, Debug)]
97pub struct NftMetadata {
98 pub class_id: PrefixedClassId,
100 pub token_id: TokenId,
102 pub token_uri: Option<TokenUri>,
104 pub token_data: Option<TokenData>,
106}
107
108impl BorshSerialize for NftMetadata {
109 fn serialize<W: std::io::Write>(
110 &self,
111 writer: &mut W,
112 ) -> std::io::Result<()> {
113 BorshSerialize::serialize(&self.class_id.to_string(), writer)?;
114 BorshSerialize::serialize(&self.token_id.to_string(), writer)?;
115 match &self.token_uri {
116 Some(uri) => {
117 BorshSerialize::serialize(&true, writer)?;
118 BorshSerialize::serialize(&uri.to_string(), writer)?;
119 }
120 None => BorshSerialize::serialize(&false, writer)?,
121 }
122 match &self.token_data {
123 Some(data) => {
124 BorshSerialize::serialize(&true, writer)?;
125 BorshSerialize::serialize(&data.to_string(), writer)
126 }
127 None => BorshSerialize::serialize(&false, writer),
128 }
129 }
130}
131
132impl BorshDeserialize for NftMetadata {
133 fn deserialize_reader<R: std::io::Read>(
134 reader: &mut R,
135 ) -> std::io::Result<Self> {
136 use std::io::{Error, ErrorKind};
137 let class_id: String = BorshDeserialize::deserialize_reader(reader)?;
138 let class_id = class_id.parse().map_err(|e: DecodingError| {
139 Error::new(ErrorKind::InvalidData, e.to_string())
140 })?;
141
142 let token_id: String = BorshDeserialize::deserialize_reader(reader)?;
143 let token_id = token_id.parse().map_err(|e: DecodingError| {
144 Error::new(ErrorKind::InvalidData, e.to_string())
145 })?;
146
147 let is_uri: bool = BorshDeserialize::deserialize_reader(reader)?;
148 let token_uri = if is_uri {
149 let uri_str: String = BorshDeserialize::deserialize_reader(reader)?;
150 Some(uri_str.parse().map_err(|e: DecodingError| {
151 Error::new(ErrorKind::InvalidData, e.to_string())
152 })?)
153 } else {
154 None
155 };
156
157 let is_data: bool = BorshDeserialize::deserialize_reader(reader)?;
158 let token_data = if is_data {
159 let data_str: String =
160 BorshDeserialize::deserialize_reader(reader)?;
161 Some(data_str.parse().map_err(|e: DecodingError| {
162 Error::new(ErrorKind::InvalidData, e.to_string())
163 })?)
164 } else {
165 None
166 };
167
168 Ok(Self {
169 class_id,
170 token_id,
171 token_uri,
172 token_data,
173 })
174 }
175}
176
177impl NftContext for NftMetadata {
178 fn get_class_id(&self) -> &ClassId {
179 &self.class_id.base_class_id
180 }
181
182 fn get_id(&self) -> &TokenId {
183 &self.token_id
184 }
185
186 fn get_uri(&self) -> Option<&TokenUri> {
187 self.token_uri.as_ref()
188 }
189
190 fn get_data(&self) -> Option<&TokenData> {
191 self.token_data.as_ref()
192 }
193}