1use num_traits::ToPrimitive;
16use sidechain_domain::*;
17use sqlx::database::Database;
18use sqlx::encode::IsNull;
19use sqlx::error::BoxDynError;
20use sqlx::postgres::PgTypeInfo;
21use sqlx::*;
22
23#[macro_export]
35macro_rules! sqlx_implementations_for_wrapper {
36 ($WRAPPED:ty, $DBTYPE:expr, $NAME:ty, $DOMAIN:ty) => {
37 impl sqlx::Type<Postgres> for $NAME {
38 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
39 PgTypeInfo::with_name($DBTYPE)
40 }
41 }
42
43 impl<'r> Decode<'r, Postgres> for $NAME
44 where
45 $WRAPPED: Decode<'r, Postgres>,
46 {
47 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
48 let decoded: $WRAPPED = <$WRAPPED as Decode<Postgres>>::decode(value)?;
49 Ok(Self(decoded.try_into()?))
50 }
51 }
52
53 #[cfg(test)]
54 impl From<$WRAPPED> for $NAME {
55 fn from(value: $WRAPPED) -> Self {
56 Self(value.try_into().expect("value from domain fits in type db type"))
57 }
58 }
59
60 impl<'q> Encode<'q, Postgres> for $NAME {
61 fn encode_by_ref(
62 &self,
63 buf: &mut <Postgres as Database>::ArgumentBuffer<'q>,
64 ) -> std::result::Result<IsNull, BoxDynError> {
65 buf.extend(&self.0.to_be_bytes());
66 Ok(IsNull::No)
67 }
68 }
69
70 impl From<$NAME> for $DOMAIN {
71 fn from(value: $NAME) -> Self {
72 Self(value.0)
73 }
74 }
75
76 impl From<$DOMAIN> for $NAME {
77 fn from(value: $DOMAIN) -> Self {
78 Self(value.0)
79 }
80 }
81 };
82}
83
84#[derive(Debug, Copy, Ord, PartialOrd, Clone, PartialEq, Eq, Default)]
86pub struct BlockNumber(pub u32);
87sqlx_implementations_for_wrapper!(i32, "INT4", BlockNumber, McBlockNumber);
88
89impl BlockNumber {
90 pub fn saturating_add<Rhs: Into<u32>>(self, rhs: Rhs) -> Self {
91 Self(self.0.saturating_add(rhs.into()))
92 }
93
94 pub fn saturating_sub<Rhs: Into<u32>>(self, rhs: Rhs) -> Self {
95 Self(self.0.saturating_sub(rhs.into()))
96 }
97}
98
99#[derive(Debug, Copy, Clone, PartialEq)]
101pub struct EpochNumber(pub u32);
102sqlx_implementations_for_wrapper!(i32, "INT4", EpochNumber, McEpochNumber);
103
104#[derive(Debug, Copy, Clone, PartialEq)]
106pub struct SlotNumber(pub u64);
107sqlx_implementations_for_wrapper!(i64, "INT8", SlotNumber, McSlotNumber);
108
109#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
116pub struct TxIndex(pub u16);
117sqlx_implementations_for_wrapper!(i16, "INT2", TxIndex, UtxoIndex);
118
119#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
121pub struct TxIndexInBlock(pub u32);
122sqlx_implementations_for_wrapper!(i32, "INT4", TxIndexInBlock, McTxIndexInBlock);
123
124#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
125pub struct TxHash(pub [u8; 32]);
126
127impl sqlx::Type<Postgres> for TxHash {
128 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
129 PgTypeInfo::with_name("bytea")
130 }
131}
132
133impl<'r> Decode<'r, Postgres> for TxHash {
134 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
135 let decoded = <[u8; 32]>::decode(value)?;
136 Ok(Self(decoded))
137 }
138}
139
140impl<'r> Encode<'r, Postgres> for TxHash {
141 fn encode_by_ref(
142 &self,
143 buf: &mut <Postgres as Database>::ArgumentBuffer<'r>,
144 ) -> std::result::Result<IsNull, BoxDynError> {
145 buf.extend(self.0.iter());
146 Ok(IsNull::No)
147 }
148}
149
150impl From<TxHash> for McTxHash {
151 fn from(hash: TxHash) -> Self {
152 Self(hash.0)
153 }
154}
155impl From<McTxHash> for TxHash {
156 fn from(hash: McTxHash) -> Self {
157 Self(hash.0)
158 }
159}
160
161#[derive(Debug, Clone, PartialEq)]
168pub struct TxValue(pub i128);
169
170impl sqlx::Type<Postgres> for TxValue {
171 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
172 PgTypeInfo::with_name("NUMERIC")
173 }
174}
175
176impl<'r> Decode<'r, Postgres> for TxValue {
177 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
178 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
179 let i = decoded.to_i128().ok_or("TxValue is always an integer".to_string())?;
180 Ok(Self(i))
181 }
182}
183
184#[derive(Debug, Clone, PartialEq)]
191pub struct StakeDelegation(pub u64);
192
193impl sqlx::Type<Postgres> for StakeDelegation {
194 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
195 PgTypeInfo::with_name("NUMERIC")
196 }
197}
198
199impl<'r> Decode<'r, Postgres> for StakeDelegation {
200 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
201 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
202 let i = decoded.to_u64().ok_or("StakeDelegation is always a u64".to_string())?;
203 Ok(Self(i))
204 }
205}
206
207#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
209pub struct AssetName(pub Vec<u8>);
210
211impl From<sidechain_domain::AssetName> for AssetName {
212 fn from(name: sidechain_domain::AssetName) -> Self {
213 Self(name.0.to_vec())
214 }
215}
216
217#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
219pub struct PolicyId(pub Vec<u8>);
220
221impl From<sidechain_domain::PolicyId> for PolicyId {
222 fn from(id: sidechain_domain::PolicyId) -> Self {
223 Self(id.0.to_vec())
224 }
225}
226
227#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
229pub struct Asset {
230 pub policy_id: PolicyId,
232 pub asset_name: AssetName,
234}
235
236impl Asset {
237 pub fn new(policy_id: sidechain_domain::PolicyId) -> Self {
239 Self { policy_id: PolicyId(policy_id.0.to_vec()), asset_name: AssetName(vec![]) }
240 }
241}
242
243impl From<sidechain_domain::AssetId> for Asset {
244 fn from(asset: AssetId) -> Self {
245 Self { policy_id: asset.policy_id.into(), asset_name: asset.asset_name.into() }
246 }
247}
248
249#[allow(deprecated)]
251mod epoch_number_row {
252 use super::*;
253 #[deprecated(
254 since = "1.7.0",
255 note = "Deprecated due to not being either a primitive type or a complete Db-Sync table row."
256 )]
257 #[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
258 pub struct EpochNumberRow(pub EpochNumber);
259
260 #[allow(deprecated)]
261 impl From<EpochNumberRow> for EpochNumber {
262 fn from(r: EpochNumberRow) -> Self {
263 r.0
264 }
265 }
266}
267pub use epoch_number_row::*;
268
269#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
271pub struct Address(pub String);
272
273impl From<MainchainAddress> for Address {
274 fn from(addr: MainchainAddress) -> Self {
275 Self(addr.to_string())
276 }
277}
278
279#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
283pub struct MainchainEpochNonce(pub Vec<u8>);