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