fuel_core_client/client/schema/
primitives.rs1use super::schema;
2use crate::client::schema::{
3 ConversionError,
4 ConversionError::HexStringPrefixError,
5};
6use core::fmt;
7use cynic::impl_scalar;
8use fuel_core_types::{
9 fuel_tx::PanicInstruction,
10 fuel_types::BlockHeight,
11};
12use serde::{
13 Deserialize,
14 Deserializer,
15 Serialize,
16 Serializer,
17 de::Error,
18};
19use std::{
20 fmt::{
21 Debug,
22 Display,
23 Formatter,
24 LowerHex,
25 },
26 ops::Deref,
27 str::FromStr,
28};
29use tai64::Tai64;
30
31#[derive(Debug, Clone, Default)]
32pub struct HexFormatted<T: Debug + Clone + Default>(pub T);
33
34impl<T: LowerHex + Debug + Clone + Default> Serialize for HexFormatted<T> {
35 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
36 where
37 S: Serializer,
38 {
39 serializer.serialize_str(format!("{:#x}", self.0).as_str())
40 }
41}
42
43impl<'de, T: FromStr<Err = E> + Debug + Clone + Default, E: Display> Deserialize<'de>
44 for HexFormatted<T>
45{
46 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
47 where
48 D: Deserializer<'de>,
49 {
50 let s: String = Deserialize::deserialize(deserializer)?;
51 T::from_str(s.as_str()).map_err(D::Error::custom).map(Self)
52 }
53}
54
55impl<T: FromStr<Err = E> + Debug + Clone + Default, E: Display> FromStr
56 for HexFormatted<T>
57{
58 type Err = ConversionError;
59
60 fn from_str(s: &str) -> Result<Self, Self::Err> {
61 T::from_str(s)
62 .map_err(|e| ConversionError::HexError(format!("{e}")))
63 .map(Self)
64 }
65}
66
67impl<T: LowerHex + Debug + Clone + Default> Display for HexFormatted<T> {
68 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
69 write!(f, "0x{:x}", self.0)
70 }
71}
72
73macro_rules! fuel_type_scalar {
74 ($id:ident, $ft_id:ident) => {
75 #[derive(cynic::Scalar, Debug, Clone, Default)]
76 pub struct $id(pub HexFormatted<::fuel_core_types::fuel_types::$ft_id>);
77
78 impl FromStr for $id {
79 type Err = ConversionError;
80
81 fn from_str(s: &str) -> Result<Self, Self::Err> {
82 let b =
83 HexFormatted::<::fuel_core_types::fuel_types::$ft_id>::from_str(s)?;
84 Ok($id(b))
85 }
86 }
87
88 impl From<$id> for ::fuel_core_types::fuel_types::$ft_id {
89 fn from(s: $id) -> Self {
90 ::fuel_core_types::fuel_types::$ft_id::new(s.0.0.into())
91 }
92 }
93
94 impl From<::fuel_core_types::fuel_types::$ft_id> for $id {
95 fn from(s: ::fuel_core_types::fuel_types::$ft_id) -> Self {
96 $id(HexFormatted::<::fuel_core_types::fuel_types::$ft_id>(s))
97 }
98 }
99
100 impl Display for $id {
101 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
102 Display::fmt(&self.0, f)
103 }
104 }
105 };
106}
107
108fuel_type_scalar!(Bytes32, Bytes32);
109fuel_type_scalar!(Address, Address);
110fuel_type_scalar!(BlockId, Bytes32);
111fuel_type_scalar!(AssetId, AssetId);
112fuel_type_scalar!(BlobId, BlobId);
113fuel_type_scalar!(ContractId, ContractId);
114fuel_type_scalar!(SubId, SubAssetId);
115fuel_type_scalar!(Salt, Salt);
116fuel_type_scalar!(TransactionId, Bytes32);
117fuel_type_scalar!(RelayedTransactionId, Bytes32);
118fuel_type_scalar!(Signature, Bytes64);
119fuel_type_scalar!(Nonce, Nonce);
120
121impl LowerHex for Nonce {
122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123 LowerHex::fmt(&self.0.0, f)
124 }
125}
126
127#[derive(cynic::Scalar, Debug, Clone, Default)]
128pub struct UtxoId(pub HexFormatted<::fuel_core_types::fuel_tx::UtxoId>);
129
130impl FromStr for UtxoId {
131 type Err = ConversionError;
132
133 fn from_str(s: &str) -> Result<Self, Self::Err> {
134 let b = HexFormatted::<::fuel_core_types::fuel_tx::UtxoId>::from_str(s)?;
135 Ok(UtxoId(b))
136 }
137}
138
139impl From<UtxoId> for ::fuel_core_types::fuel_tx::UtxoId {
140 fn from(s: UtxoId) -> Self {
141 s.0.0
142 }
143}
144
145impl From<fuel_core_types::fuel_tx::UtxoId> for UtxoId {
146 fn from(value: fuel_core_types::fuel_tx::UtxoId) -> Self {
147 Self(HexFormatted(value))
148 }
149}
150
151impl LowerHex for UtxoId {
152 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
153 LowerHex::fmt(&self.0.0, f)
154 }
155}
156
157#[derive(cynic::Scalar, Debug, Clone, Default)]
158pub struct TxPointer(pub HexFormatted<::fuel_core_types::fuel_tx::TxPointer>);
159
160impl FromStr for TxPointer {
161 type Err = ConversionError;
162
163 fn from_str(s: &str) -> Result<Self, Self::Err> {
164 let b = HexFormatted::<::fuel_core_types::fuel_tx::TxPointer>::from_str(s)?;
165 Ok(TxPointer(b))
166 }
167}
168
169impl From<TxPointer> for ::fuel_core_types::fuel_tx::TxPointer {
170 fn from(s: TxPointer) -> Self {
171 s.0.0
172 }
173}
174
175impl LowerHex for TxPointer {
176 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
177 LowerHex::fmt(&self.0.0, f)
178 }
179}
180
181#[derive(cynic::Scalar, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
182pub struct HexString(pub Bytes);
183
184impl From<HexString> for Vec<u8> {
185 fn from(s: HexString) -> Self {
186 s.0.0
187 }
188}
189
190impl From<HexString> for fuel_core_types::fuel_types::bytes::Bytes {
191 fn from(s: HexString) -> Self {
192 s.0.0.into()
193 }
194}
195
196impl From<Vec<u8>> for HexString {
197 fn from(s: Vec<u8>) -> Self {
198 HexString(Bytes(s))
199 }
200}
201
202impl Deref for HexString {
203 type Target = Bytes;
204
205 fn deref(&self) -> &Self::Target {
206 &self.0
207 }
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
211pub struct Bytes(pub Vec<u8>);
212
213impl FromStr for Bytes {
214 type Err = ConversionError;
215
216 fn from_str(s: &str) -> Result<Self, Self::Err> {
217 let value = s.strip_prefix("0x").ok_or(HexStringPrefixError)?;
219 Ok(Bytes(hex::decode(value)?))
221 }
222}
223
224impl Serialize for Bytes {
225 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
226 where
227 S: Serializer,
228 {
229 let hex = format!("0x{}", hex::encode(&self.0));
230 serializer.serialize_str(hex.as_str())
231 }
232}
233
234impl<'de> Deserialize<'de> for Bytes {
235 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
236 where
237 D: Deserializer<'de>,
238 {
239 let s: String = Deserialize::deserialize(deserializer)?;
240 Self::from_str(s.as_str()).map_err(D::Error::custom)
241 }
242}
243
244impl Display for Bytes {
245 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246 write!(f, "0x{}", hex::encode(&self.0))
247 }
248}
249
250impl Deref for Bytes {
251 type Target = [u8];
252
253 fn deref(&self) -> &Self::Target {
254 &self.0
255 }
256}
257
258macro_rules! number_scalar {
259 ($i:ident, $t:ty) => {
260 #[derive(
261 Debug, Clone, derive_more::Into, derive_more::From, PartialOrd, Eq, PartialEq,
262 )]
263 pub struct $i(pub $t);
264 impl_scalar!($i, schema::$i);
265
266 impl Serialize for $i {
267 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
268 where
269 S: Serializer,
270 {
271 let s = self.0.to_string();
272 serializer.serialize_str(s.as_str())
273 }
274 }
275
276 impl<'de> Deserialize<'de> for $i {
277 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
278 where
279 D: Deserializer<'de>,
280 {
281 let s: String = Deserialize::deserialize(deserializer)?;
282 Ok(Self(s.parse().map_err(D::Error::custom)?))
283 }
284 }
285 };
286}
287
288number_scalar!(U128, u128);
289number_scalar!(U64, u64);
290number_scalar!(U32, u32);
291number_scalar!(U16, u16);
292
293impl TryFrom<U64> for PanicInstruction {
294 type Error = ConversionError;
295
296 fn try_from(s: U64) -> Result<Self, Self::Error> {
297 Ok(s.0.into())
298 }
299}
300
301impl From<usize> for U64 {
302 fn from(i: usize) -> Self {
303 U64(i as u64)
304 }
305}
306
307impl From<U32> for BlockHeight {
308 fn from(s: U32) -> Self {
309 s.0.into()
310 }
311}
312
313impl From<BlockHeight> for U32 {
314 fn from(s: BlockHeight) -> U32 {
315 (*s).into()
316 }
317}
318
319#[derive(
320 Debug, Clone, derive_more::Into, derive_more::From, PartialOrd, Eq, PartialEq,
321)]
322pub struct Tai64Timestamp(pub Tai64);
323impl_scalar!(Tai64Timestamp, schema::Tai64Timestamp);
324
325impl Tai64Timestamp {
326 pub fn from_unix(secs: i64) -> Self {
328 Tai64Timestamp(Tai64::from_unix(secs))
329 }
330
331 pub fn to_unix(self) -> i64 {
333 self.0.to_unix()
334 }
335}
336
337impl Serialize for Tai64Timestamp {
338 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
339 where
340 S: Serializer,
341 {
342 let s = self.0.0.to_string();
343 serializer.serialize_str(s.as_str())
344 }
345}
346
347impl<'de> Deserialize<'de> for Tai64Timestamp {
348 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
349 where
350 D: Deserializer<'de>,
351 {
352 let s: String = Deserialize::deserialize(deserializer)?;
353 Ok(Self(Tai64(s.parse().map_err(D::Error::custom)?)))
354 }
355}
356
357impl BlockId {
358 pub fn into_message(self) -> fuel_core_types::fuel_crypto::Message {
360 let bytes: fuel_core_types::fuel_types::Bytes32 = self.into();
361 fuel_core_types::fuel_crypto::Message::from_bytes(*bytes)
362 }
363}
364
365impl Signature {
366 pub fn into_signature(self) -> fuel_core_types::fuel_crypto::Signature {
367 let bytes: fuel_core_types::fuel_types::Bytes64 = self.into();
368 fuel_core_types::fuel_crypto::Signature::from_bytes(*bytes)
369 }
370}