1use fastcrypto::{
22 encoding::{Base58 as FastCryptoBase58, Base64 as FastCryptoBase64},
23 traits::EncodeDecodeBase64,
24};
25use iota_sdk_types::{
26 Address as NativeAddress, CertificateDigest, CheckpointContentsDigest, CheckpointDigest,
27 ConsensusCommitDigest, Digest, EffectsAuxDataDigest, Identifier as NativeIdentifier,
28 MisbehaviorReportDigest, MoveAuthenticatorDigest, ObjectDigest, ObjectId as NativeObjectId,
29 SenderSignedDataDigest, StructTag as NativeStructTag, TransactionDigest,
30 TransactionEffectsDigest, TransactionEventsDigest, TypeTag as NativeTypeTag, Version,
31};
32use iota_types::{
33 iota_serde::{to_iota_struct_tag_string, to_iota_type_tag_string},
34 parse_iota_struct_tag, parse_iota_type_tag,
35 signature::GenericSignature as NativeGenericSignature,
36};
37use schemars::{
38 JsonSchema,
39 schema::{InstanceType, Metadata, NumberValidation, SchemaObject},
40};
41use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error as _, ser::Error as _};
42use serde_with::{DeserializeAs, DisplayFromStr, SerializeAs, serde_as};
43
44pub struct Address;
47
48impl JsonSchema for Address {
49 fn schema_name() -> String {
50 "Address".to_owned()
51 }
52
53 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
54 SchemaObject {
55 metadata: Some(Box::new(Metadata {
56 description: Some("IOTA address as a hex string".to_owned()),
57 ..Default::default()
58 })),
59 instance_type: Some(InstanceType::String.into()),
60 format: Some("hex".to_owned()),
61 ..Default::default()
62 }
63 .into()
64 }
65}
66
67impl SerializeAs<NativeAddress> for Address {
68 fn serialize_as<S>(value: &NativeAddress, serializer: S) -> Result<S::Ok, S::Error>
69 where
70 S: Serializer,
71 {
72 DisplayFromStr::serialize_as(value, serializer)
73 }
74}
75
76impl<'de> DeserializeAs<'de, NativeAddress> for Address {
77 fn deserialize_as<D>(deserializer: D) -> Result<NativeAddress, D::Error>
78 where
79 D: Deserializer<'de>,
80 {
81 DisplayFromStr::deserialize_as(deserializer)
82 }
83}
84
85pub struct ObjectId;
88
89impl JsonSchema for ObjectId {
90 fn schema_name() -> String {
91 "ObjectID".to_owned()
92 }
93
94 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
95 SchemaObject {
96 metadata: Some(Box::new(Metadata {
97 description: Some("Object ID as a hex string".to_owned()),
98 ..Default::default()
99 })),
100 instance_type: Some(InstanceType::String.into()),
101 format: Some("hex".to_owned()),
102 ..Default::default()
103 }
104 .into()
105 }
106}
107
108impl SerializeAs<NativeObjectId> for ObjectId {
109 fn serialize_as<S>(value: &NativeObjectId, serializer: S) -> Result<S::Ok, S::Error>
110 where
111 S: Serializer,
112 {
113 DisplayFromStr::serialize_as(value, serializer)
114 }
115}
116
117impl<'de> DeserializeAs<'de, NativeObjectId> for ObjectId {
118 fn deserialize_as<D>(deserializer: D) -> Result<NativeObjectId, D::Error>
119 where
120 D: Deserializer<'de>,
121 {
122 DisplayFromStr::deserialize_as(deserializer)
123 }
124}
125
126#[serde_as]
130#[derive(Serialize, Deserialize)]
131pub struct SequenceNumberString(#[serde_as(as = "DisplayFromStr")] u64);
132
133impl JsonSchema for SequenceNumberString {
134 fn schema_name() -> String {
135 "SequenceNumberString".to_owned()
136 }
137
138 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
139 SchemaObject {
140 metadata: Some(Box::new(Metadata {
141 description: Some("Sequence number as a string".to_owned()),
142 ..Default::default()
143 })),
144 instance_type: Some(InstanceType::String.into()),
145 ..Default::default()
146 }
147 .into()
148 }
149}
150
151impl SerializeAs<Version> for SequenceNumberString {
152 fn serialize_as<S>(source: &Version, serializer: S) -> Result<S::Ok, S::Error>
153 where
154 S: Serializer,
155 {
156 SequenceNumberString(source.as_u64()).serialize(serializer)
157 }
158}
159
160impl<'de> DeserializeAs<'de, Version> for SequenceNumberString {
161 fn deserialize_as<D>(deserializer: D) -> Result<Version, D::Error>
162 where
163 D: Deserializer<'de>,
164 {
165 let schema = SequenceNumberString::deserialize(deserializer)?;
166 Ok(Version::from_u64(schema.0))
167 }
168}
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
175pub struct SequenceNumberU64(Version);
176
177impl From<Version> for SequenceNumberU64 {
178 fn from(value: Version) -> Self {
179 Self(value)
180 }
181}
182
183impl From<SequenceNumberU64> for Version {
184 fn from(value: SequenceNumberU64) -> Self {
185 value.0
186 }
187}
188
189impl std::fmt::Display for SequenceNumberU64 {
190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
191 self.0.fmt(f)
192 }
193}
194
195impl Serialize for SequenceNumberU64 {
196 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
197 where
198 S: Serializer,
199 {
200 self.0.as_u64().serialize(serializer)
201 }
202}
203
204impl<'de> Deserialize<'de> for SequenceNumberU64 {
205 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
206 where
207 D: Deserializer<'de>,
208 {
209 Ok(Self(Version::from_u64(u64::deserialize(deserializer)?)))
210 }
211}
212
213impl JsonSchema for SequenceNumberU64 {
214 fn schema_name() -> String {
215 "SequenceNumberU64".to_owned()
216 }
217
218 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
219 SchemaObject {
220 metadata: Some(Box::new(Metadata {
221 description: Some("Sequence number as a u64 integer".to_owned()),
222 ..Default::default()
223 })),
224 format: Some("uint64".to_owned()),
225 number: Some(Box::new(NumberValidation {
226 minimum: Some(0.0),
227 ..Default::default()
228 })),
229 instance_type: Some(InstanceType::Integer.into()),
230 ..Default::default()
231 }
232 .into()
233 }
234}
235
236#[serde_as]
240#[derive(Serialize, Deserialize, JsonSchema)]
241pub struct ProtocolVersion(
242 #[schemars(with = "String")]
243 #[serde_as(as = "DisplayFromStr")]
244 u64,
245);
246
247impl SerializeAs<iota_protocol_config::ProtocolVersion> for ProtocolVersion {
248 fn serialize_as<S>(
249 source: &iota_protocol_config::ProtocolVersion,
250 serializer: S,
251 ) -> Result<S::Ok, S::Error>
252 where
253 S: Serializer,
254 {
255 ProtocolVersion(source.as_u64()).serialize(serializer)
256 }
257}
258
259impl<'de> DeserializeAs<'de, iota_protocol_config::ProtocolVersion> for ProtocolVersion {
260 fn deserialize_as<D>(deserializer: D) -> Result<iota_protocol_config::ProtocolVersion, D::Error>
261 where
262 D: Deserializer<'de>,
263 {
264 let schema = ProtocolVersion::deserialize(deserializer)?;
265 Ok(iota_protocol_config::ProtocolVersion::new(schema.0))
266 }
267}
268
269pub struct Base58;
273
274impl JsonSchema for Base58 {
275 fn schema_name() -> String {
276 "Base58".to_owned()
277 }
278
279 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
280 SchemaObject {
281 metadata: Some(Box::new(Metadata {
282 description: Some("Base58 encoded data".to_owned()),
283 ..Default::default()
284 })),
285 instance_type: Some(InstanceType::String.into()),
286 format: Some("base58".to_owned()),
287 ..Default::default()
288 }
289 .into()
290 }
291}
292
293macro_rules! impl_base58_for_digest {
296 ($($t:ty),* $(,)?) => {
297 $(
298 impl SerializeAs<$t> for Base58 {
299 fn serialize_as<S>(value: &$t, serializer: S) -> Result<S::Ok, S::Error>
300 where
301 S: Serializer,
302 {
303 DisplayFromStr::serialize_as(value, serializer)
304 }
305 }
306
307 impl<'de> DeserializeAs<'de, $t> for Base58 {
308 fn deserialize_as<D>(deserializer: D) -> Result<$t, D::Error>
309 where
310 D: Deserializer<'de>,
311 {
312 DisplayFromStr::deserialize_as(deserializer)
313 }
314 }
315 )*
316 };
317}
318
319impl_base58_for_digest!(
320 Digest,
321 CheckpointDigest,
322 CheckpointContentsDigest,
323 CertificateDigest,
324 SenderSignedDataDigest,
325 TransactionDigest,
326 TransactionEffectsDigest,
327 TransactionEventsDigest,
328 EffectsAuxDataDigest,
329 ObjectDigest,
330 ConsensusCommitDigest,
331 MoveAuthenticatorDigest,
332 MisbehaviorReportDigest,
333);
334
335impl SerializeAs<Vec<u8>> for Base58 {
336 fn serialize_as<S>(value: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
337 where
338 S: Serializer,
339 {
340 FastCryptoBase58::serialize_as(value, serializer)
341 }
342}
343
344impl<'de> DeserializeAs<'de, Vec<u8>> for Base58 {
345 fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
346 where
347 D: Deserializer<'de>,
348 {
349 FastCryptoBase58::deserialize_as(deserializer)
350 }
351}
352
353pub struct Base64;
357
358impl JsonSchema for Base64 {
359 fn schema_name() -> String {
360 "Base64".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 data".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<Vec<u8>> for Base64 {
378 fn serialize_as<S>(value: &Vec<u8>, serializer: S) -> Result<S::Ok, S::Error>
379 where
380 S: Serializer,
381 {
382 FastCryptoBase64::serialize_as(value, serializer)
383 }
384}
385
386impl<'de> DeserializeAs<'de, Vec<u8>> for Base64 {
387 fn deserialize_as<D>(deserializer: D) -> Result<Vec<u8>, D::Error>
388 where
389 D: Deserializer<'de>,
390 {
391 FastCryptoBase64::deserialize_as(deserializer)
392 }
393}
394
395pub struct GenericSignature;
398
399impl JsonSchema for GenericSignature {
400 fn schema_name() -> String {
401 "GenericSignature".to_owned()
402 }
403
404 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
405 SchemaObject {
406 metadata: Some(Box::new(Metadata {
407 description: Some("Base64 encoded signature".to_owned()),
408 ..Default::default()
409 })),
410 instance_type: Some(InstanceType::String.into()),
411 format: Some("base64".to_owned()),
412 ..Default::default()
413 }
414 .into()
415 }
416}
417
418impl SerializeAs<NativeGenericSignature> for GenericSignature {
419 fn serialize_as<S>(value: &NativeGenericSignature, serializer: S) -> Result<S::Ok, S::Error>
420 where
421 S: Serializer,
422 {
423 value.encode_base64().serialize(serializer)
424 }
425}
426
427impl<'de> DeserializeAs<'de, NativeGenericSignature> for GenericSignature {
428 fn deserialize_as<D>(deserializer: D) -> Result<NativeGenericSignature, D::Error>
429 where
430 D: Deserializer<'de>,
431 {
432 let s = String::deserialize(deserializer)?;
433 NativeGenericSignature::decode_base64(&s).map_err(D::Error::custom)
434 }
435}
436
437pub struct StructTag;
441
442impl JsonSchema for StructTag {
443 fn schema_name() -> String {
444 "StructTag".to_owned()
445 }
446
447 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
448 SchemaObject {
449 metadata: Some(Box::new(Metadata {
450 description: Some(
451 "Move struct tag, in the format 'address::module::name<type_params>'"
452 .to_owned(),
453 ),
454 ..Default::default()
455 })),
456 instance_type: Some(InstanceType::String.into()),
457 ..Default::default()
458 }
459 .into()
460 }
461}
462
463impl SerializeAs<NativeStructTag> for StructTag {
464 fn serialize_as<S>(value: &NativeStructTag, serializer: S) -> Result<S::Ok, S::Error>
465 where
466 S: Serializer,
467 {
468 to_iota_struct_tag_string(value)
469 .map_err(S::Error::custom)?
470 .serialize(serializer)
471 }
472}
473
474impl<'de> DeserializeAs<'de, NativeStructTag> for StructTag {
475 fn deserialize_as<D>(deserializer: D) -> Result<NativeStructTag, D::Error>
476 where
477 D: Deserializer<'de>,
478 {
479 let s = String::deserialize(deserializer)?;
480 parse_iota_struct_tag(&s).map_err(D::Error::custom)
481 }
482}
483
484pub struct TypeTag;
488
489impl JsonSchema for TypeTag {
490 fn schema_name() -> String {
491 "TypeTag".to_owned()
492 }
493
494 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
495 SchemaObject {
496 metadata: Some(Box::new(Metadata {
497 description: Some("Move type tag as a string".to_owned()),
498 ..Default::default()
499 })),
500 instance_type: Some(InstanceType::String.into()),
501 ..Default::default()
502 }
503 .into()
504 }
505}
506
507impl SerializeAs<NativeTypeTag> for TypeTag {
508 fn serialize_as<S>(value: &NativeTypeTag, serializer: S) -> Result<S::Ok, S::Error>
509 where
510 S: Serializer,
511 {
512 to_iota_type_tag_string(value)
513 .map_err(S::Error::custom)?
514 .serialize(serializer)
515 }
516}
517
518impl<'de> DeserializeAs<'de, NativeTypeTag> for TypeTag {
519 fn deserialize_as<D>(deserializer: D) -> Result<NativeTypeTag, D::Error>
520 where
521 D: Deserializer<'de>,
522 {
523 let s = String::deserialize(deserializer)?;
524 parse_iota_type_tag(&s).map_err(D::Error::custom)
525 }
526}
527
528pub struct Identifier;
531
532impl JsonSchema for Identifier {
533 fn schema_name() -> String {
534 "Identifier".to_owned()
535 }
536
537 fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> schemars::schema::Schema {
538 SchemaObject {
539 metadata: Some(Box::new(Metadata {
540 description: Some("Move identifier".to_owned()),
541 ..Default::default()
542 })),
543 instance_type: Some(InstanceType::String.into()),
544 ..Default::default()
545 }
546 .into()
547 }
548}
549
550impl SerializeAs<NativeIdentifier> for Identifier {
551 fn serialize_as<S>(value: &NativeIdentifier, serializer: S) -> Result<S::Ok, S::Error>
552 where
553 S: Serializer,
554 {
555 DisplayFromStr::serialize_as(value, serializer)
556 }
557}
558
559impl<'de> DeserializeAs<'de, NativeIdentifier> for Identifier {
560 fn deserialize_as<D>(deserializer: D) -> Result<NativeIdentifier, D::Error>
561 where
562 D: Deserializer<'de>,
563 {
564 DisplayFromStr::deserialize_as(deserializer)
565 }
566}