1use fastcrypto::{
22 encoding::{Base58 as FastCryptoBase58, Base64 as FastCryptoBase64},
23 traits::EncodeDecodeBase64,
24};
25use iota_sdk_types::{
26 Digest, Identifier as NativeIdentifier, ObjectId as NativeObjectId,
27 StructTag as NativeStructTag, TypeTag as NativeTypeTag,
28};
29use iota_types::{
30 base_types::{IotaAddress as NativeIotaAddress, SequenceNumber},
31 iota_serde::{to_iota_struct_tag_string, to_iota_type_tag_string},
32 parse_iota_struct_tag, parse_iota_type_tag,
33 signature::GenericSignature as NativeGenericSignature,
34};
35use schemars::{
36 JsonSchema,
37 schema::{InstanceType, Metadata, NumberValidation, SchemaObject},
38};
39use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _};
40use serde_with::{DeserializeAs, DisplayFromStr, SerializeAs, serde_as};
41
42pub struct IotaAddress;
45
46impl JsonSchema for IotaAddress {
47 fn schema_name() -> String {
48 "IotaAddress".to_owned()
49 }
50
51 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
52 SchemaObject {
53 metadata: Some(Box::new(Metadata {
54 description: Some("IOTA address as a hex string".to_owned()),
55 ..Default::default()
56 })),
57 instance_type: Some(InstanceType::String.into()),
58 format: Some("hex".to_owned()),
59 ..Default::default()
60 }
61 .into()
62 }
63}
64
65impl SerializeAs<NativeIotaAddress> for IotaAddress {
66 fn serialize_as<S>(value: &NativeIotaAddress, serializer: S) -> Result<S::Ok, S::Error>
67 where
68 S: Serializer,
69 {
70 DisplayFromStr::serialize_as(value, serializer)
71 }
72}
73
74impl<'de> DeserializeAs<'de, NativeIotaAddress> for IotaAddress {
75 fn deserialize_as<D>(deserializer: D) -> Result<NativeIotaAddress, D::Error>
76 where
77 D: Deserializer<'de>,
78 {
79 DisplayFromStr::deserialize_as(deserializer)
80 }
81}
82
83pub struct ObjectId;
86
87impl JsonSchema for ObjectId {
88 fn schema_name() -> String {
89 "ObjectID".to_owned()
90 }
91
92 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
93 SchemaObject {
94 metadata: Some(Box::new(Metadata {
95 description: Some("Object ID as a hex string".to_owned()),
96 ..Default::default()
97 })),
98 instance_type: Some(InstanceType::String.into()),
99 format: Some("hex".to_owned()),
100 ..Default::default()
101 }
102 .into()
103 }
104}
105
106impl SerializeAs<NativeObjectId> for ObjectId {
107 fn serialize_as<S>(value: &NativeObjectId, serializer: S) -> Result<S::Ok, S::Error>
108 where
109 S: Serializer,
110 {
111 DisplayFromStr::serialize_as(value, serializer)
112 }
113}
114
115impl<'de> DeserializeAs<'de, NativeObjectId> for ObjectId {
116 fn deserialize_as<D>(deserializer: D) -> Result<NativeObjectId, D::Error>
117 where
118 D: Deserializer<'de>,
119 {
120 DisplayFromStr::deserialize_as(deserializer)
121 }
122}
123
124#[serde_as]
128#[derive(Serialize, Deserialize)]
129pub struct SequenceNumberString(#[serde_as(as = "DisplayFromStr")] u64);
130
131impl JsonSchema for SequenceNumberString {
132 fn schema_name() -> String {
133 "SequenceNumberString".to_owned()
134 }
135
136 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
137 SchemaObject {
138 metadata: Some(Box::new(Metadata {
139 description: Some("Sequence number as a string".to_owned()),
140 ..Default::default()
141 })),
142 instance_type: Some(InstanceType::String.into()),
143 ..Default::default()
144 }
145 .into()
146 }
147}
148
149impl SerializeAs<iota_types::base_types::SequenceNumber> for SequenceNumberString {
150 fn serialize_as<S>(
151 source: &iota_types::base_types::SequenceNumber,
152 serializer: S,
153 ) -> Result<S::Ok, S::Error>
154 where
155 S: Serializer,
156 {
157 SequenceNumberString(source.as_u64()).serialize(serializer)
158 }
159}
160
161impl<'de> DeserializeAs<'de, iota_types::base_types::SequenceNumber> for SequenceNumberString {
162 fn deserialize_as<D>(
163 deserializer: D,
164 ) -> Result<iota_types::base_types::SequenceNumber, D::Error>
165 where
166 D: Deserializer<'de>,
167 {
168 let schema = SequenceNumberString::deserialize(deserializer)?;
169 Ok(iota_types::base_types::SequenceNumber::from_u64(schema.0))
170 }
171}
172
173pub struct SequenceNumberU64;
177
178impl JsonSchema for SequenceNumberU64 {
179 fn schema_name() -> String {
180 "SequenceNumberU64".to_owned()
181 }
182
183 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
184 SchemaObject {
185 metadata: Some(Box::new(Metadata {
186 description: Some("Sequence number as a u64 integer".to_owned()),
187 ..Default::default()
188 })),
189 format: Some("uint64".to_owned()),
190 number: Some(Box::new(NumberValidation {
191 minimum: Some(0.0),
192 ..Default::default()
193 })),
194 instance_type: Some(InstanceType::Integer.into()),
195 ..Default::default()
196 }
197 .into()
198 }
199}
200
201impl SerializeAs<SequenceNumber> for SequenceNumberU64 {
202 fn serialize_as<S>(value: &SequenceNumber, serializer: S) -> Result<S::Ok, S::Error>
203 where
204 S: Serializer,
205 {
206 value.as_u64().serialize(serializer)
207 }
208}
209
210impl<'de> DeserializeAs<'de, SequenceNumber> for SequenceNumberU64 {
211 fn deserialize_as<D>(deserializer: D) -> Result<SequenceNumber, D::Error>
212 where
213 D: Deserializer<'de>,
214 {
215 Ok(SequenceNumber::from_u64(u64::deserialize(deserializer)?))
216 }
217}
218
219#[serde_as]
223#[derive(Serialize, Deserialize, JsonSchema)]
224pub struct ProtocolVersion(
225 #[schemars(with = "String")]
226 #[serde_as(as = "DisplayFromStr")]
227 u64,
228);
229
230impl SerializeAs<iota_protocol_config::ProtocolVersion> for ProtocolVersion {
231 fn serialize_as<S>(
232 source: &iota_protocol_config::ProtocolVersion,
233 serializer: S,
234 ) -> Result<S::Ok, S::Error>
235 where
236 S: Serializer,
237 {
238 ProtocolVersion(source.as_u64()).serialize(serializer)
239 }
240}
241
242impl<'de> DeserializeAs<'de, iota_protocol_config::ProtocolVersion> for ProtocolVersion {
243 fn deserialize_as<D>(deserializer: D) -> Result<iota_protocol_config::ProtocolVersion, D::Error>
244 where
245 D: Deserializer<'de>,
246 {
247 let schema = ProtocolVersion::deserialize(deserializer)?;
248 Ok(iota_protocol_config::ProtocolVersion::new(schema.0))
249 }
250}
251
252pub struct Base58;
256
257impl JsonSchema for Base58 {
258 fn schema_name() -> String {
259 "Base58".to_owned()
260 }
261
262 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
263 SchemaObject {
264 metadata: Some(Box::new(Metadata {
265 description: Some("Base58 encoded data".to_owned()),
266 ..Default::default()
267 })),
268 instance_type: Some(InstanceType::String.into()),
269 format: Some("base58".to_owned()),
270 ..Default::default()
271 }
272 .into()
273 }
274}
275
276impl SerializeAs<Digest> for Base58 {
277 fn serialize_as<S>(value: &Digest, serializer: S) -> Result<S::Ok, S::Error>
278 where
279 S: Serializer,
280 {
281 DisplayFromStr::serialize_as(value, serializer)
282 }
283}
284
285impl<'de> DeserializeAs<'de, Digest> for Base58 {
286 fn deserialize_as<D>(deserializer: D) -> Result<Digest, D::Error>
287 where
288 D: Deserializer<'de>,
289 {
290 DisplayFromStr::deserialize_as(deserializer)
291 }
292}
293
294impl SerializeAs<Vec<u8>> for Base58 {
295 fn serialize_as<S>(value: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
296 where
297 S: Serializer,
298 {
299 FastCryptoBase58::serialize_as(value, serializer)
300 }
301}
302
303impl<'de> DeserializeAs<'de, Vec<u8>> for Base58 {
304 fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
305 where
306 D: Deserializer<'de>,
307 {
308 FastCryptoBase58::deserialize_as(deserializer)
309 }
310}
311
312pub struct Base64;
316
317impl JsonSchema for Base64 {
318 fn schema_name() -> String {
319 "Base64".to_owned()
320 }
321
322 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
323 SchemaObject {
324 metadata: Some(Box::new(Metadata {
325 description: Some("Base64 encoded data".to_owned()),
326 ..Default::default()
327 })),
328 instance_type: Some(InstanceType::String.into()),
329 format: Some("base64".to_owned()),
330 ..Default::default()
331 }
332 .into()
333 }
334}
335
336impl SerializeAs<Vec<u8>> for Base64 {
337 fn serialize_as<S>(value: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
338 where
339 S: Serializer,
340 {
341 FastCryptoBase64::serialize_as(value, serializer)
342 }
343}
344
345impl<'de> DeserializeAs<'de, Vec<u8>> for Base64 {
346 fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
347 where
348 D: Deserializer<'de>,
349 {
350 FastCryptoBase64::deserialize_as(deserializer)
351 }
352}
353
354pub struct GenericSignature;
357
358impl JsonSchema for GenericSignature {
359 fn schema_name() -> String {
360 "GenericSignature".to_owned()
361 }
362
363 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
364 SchemaObject {
365 metadata: Some(Box::new(Metadata {
366 description: Some("Base64 encoded signature".to_owned()),
367 ..Default::default()
368 })),
369 instance_type: Some(InstanceType::String.into()),
370 format: Some("base64".to_owned()),
371 ..Default::default()
372 }
373 .into()
374 }
375}
376
377impl SerializeAs<NativeGenericSignature> for GenericSignature {
378 fn serialize_as<S>(value: &NativeGenericSignature, serializer: S) -> Result<S::Ok, S::Error>
379 where
380 S: Serializer,
381 {
382 value.encode_base64().serialize(serializer)
383 }
384}
385
386impl<'de> DeserializeAs<'de, NativeGenericSignature> for GenericSignature {
387 fn deserialize_as<D>(deserializer: D) -> Result<NativeGenericSignature, D::Error>
388 where
389 D: Deserializer<'de>,
390 {
391 let s = String::deserialize(deserializer)?;
392 NativeGenericSignature::decode_base64(&s).map_err(D::Error::custom)
393 }
394}
395
396pub struct StructTag;
400
401impl JsonSchema for StructTag {
402 fn schema_name() -> String {
403 "StructTag".to_owned()
404 }
405
406 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
407 SchemaObject {
408 metadata: Some(Box::new(Metadata {
409 description: Some(
410 "Move struct tag, in the format 'address::module::name<type_params>'"
411 .to_owned(),
412 ),
413 ..Default::default()
414 })),
415 instance_type: Some(InstanceType::String.into()),
416 ..Default::default()
417 }
418 .into()
419 }
420}
421
422impl SerializeAs<NativeStructTag> for StructTag {
423 fn serialize_as<S>(value: &NativeStructTag, serializer: S) -> Result<S::Ok, S::Error>
424 where
425 S: Serializer,
426 {
427 to_iota_struct_tag_string(value)
428 .map_err(S::Error::custom)?
429 .serialize(serializer)
430 }
431}
432
433impl<'de> DeserializeAs<'de, NativeStructTag> for StructTag {
434 fn deserialize_as<D>(deserializer: D) -> Result<NativeStructTag, D::Error>
435 where
436 D: Deserializer<'de>,
437 {
438 let s = String::deserialize(deserializer)?;
439 parse_iota_struct_tag(&s).map_err(D::Error::custom)
440 }
441}
442
443pub struct TypeTag;
447
448impl JsonSchema for TypeTag {
449 fn schema_name() -> String {
450 "TypeTag".to_owned()
451 }
452
453 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
454 SchemaObject {
455 metadata: Some(Box::new(Metadata {
456 description: Some("Move type tag as a string".to_owned()),
457 ..Default::default()
458 })),
459 instance_type: Some(InstanceType::String.into()),
460 ..Default::default()
461 }
462 .into()
463 }
464}
465
466impl SerializeAs<NativeTypeTag> for TypeTag {
467 fn serialize_as<S>(value: &NativeTypeTag, serializer: S) -> Result<S::Ok, S::Error>
468 where
469 S: Serializer,
470 {
471 to_iota_type_tag_string(value)
472 .map_err(S::Error::custom)?
473 .serialize(serializer)
474 }
475}
476
477impl<'de> DeserializeAs<'de, NativeTypeTag> for TypeTag {
478 fn deserialize_as<D>(deserializer: D) -> Result<NativeTypeTag, D::Error>
479 where
480 D: Deserializer<'de>,
481 {
482 let s = String::deserialize(deserializer)?;
483 parse_iota_type_tag(&s).map_err(D::Error::custom)
484 }
485}
486
487pub struct Identifier;
490
491impl JsonSchema for Identifier {
492 fn schema_name() -> String {
493 "Identifier".to_owned()
494 }
495
496 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
497 SchemaObject {
498 metadata: Some(Box::new(Metadata {
499 description: Some("Move identifier".to_owned()),
500 ..Default::default()
501 })),
502 instance_type: Some(InstanceType::String.into()),
503 ..Default::default()
504 }
505 .into()
506 }
507}
508
509impl SerializeAs<NativeIdentifier> for Identifier {
510 fn serialize_as<S>(value: &NativeIdentifier, serializer: S) -> Result<S::Ok, S::Error>
511 where
512 S: Serializer,
513 {
514 DisplayFromStr::serialize_as(value, serializer)
515 }
516}
517
518impl<'de> DeserializeAs<'de, NativeIdentifier> for Identifier {
519 fn deserialize_as<D>(deserializer: D) -> Result<NativeIdentifier, D::Error>
520 where
521 D: Deserializer<'de>,
522 {
523 DisplayFromStr::deserialize_as(deserializer)
524 }
525}