fuel_gql_client/client/schema/
primitives.rs

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