1use num_traits::ToPrimitive;
15use sidechain_domain::*;
16use sqlx::database::Database;
17use sqlx::encode::IsNull;
18use sqlx::error::BoxDynError;
19use sqlx::postgres::PgTypeInfo;
20use sqlx::*;
21
22#[macro_export]
34macro_rules! sqlx_implementations_for_wrapper {
35 ($WRAPPED:ty, $DBTYPE:expr, $NAME:ty, $DOMAIN:ty) => {
36 impl sqlx::Type<Postgres> for $NAME {
37 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
38 PgTypeInfo::with_name($DBTYPE)
39 }
40 }
41
42 impl<'r> Decode<'r, Postgres> for $NAME
43 where
44 $WRAPPED: Decode<'r, Postgres>,
45 {
46 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
47 let decoded: $WRAPPED = <$WRAPPED as Decode<Postgres>>::decode(value)?;
48 Ok(Self(decoded.try_into()?))
49 }
50 }
51
52 #[cfg(test)]
53 impl From<$WRAPPED> for $NAME {
54 fn from(value: $WRAPPED) -> Self {
55 Self(value.try_into().expect("value from domain fits in type db type"))
56 }
57 }
58
59 impl<'q> Encode<'q, Postgres> for $NAME {
60 fn encode_by_ref(
61 &self,
62 buf: &mut <Postgres as Database>::ArgumentBuffer<'q>,
63 ) -> std::result::Result<IsNull, Box<(dyn std::error::Error + Send + Sync + 'static)>>
64 {
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)]
86pub struct BlockNumber(pub u32);
87sqlx_implementations_for_wrapper!(i32, "INT4", BlockNumber, McBlockNumber);
88
89#[derive(Debug, Copy, Clone, PartialEq)]
91pub struct EpochNumber(pub u32);
92sqlx_implementations_for_wrapper!(i32, "INT4", EpochNumber, McEpochNumber);
93
94#[derive(Debug, Copy, Clone, PartialEq)]
96pub struct SlotNumber(pub u64);
97sqlx_implementations_for_wrapper!(i64, "INT8", SlotNumber, McSlotNumber);
98
99#[derive(Debug, Clone, PartialEq)]
106pub struct TxIndex(pub u16);
107sqlx_implementations_for_wrapper!(i16, "INT2", TxIndex, UtxoIndex);
108
109#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
111pub struct TxIndexInBlock(pub u32);
112sqlx_implementations_for_wrapper!(i32, "INT4", TxIndexInBlock, McTxIndexInBlock);
113
114#[derive(Debug, Clone, PartialEq)]
121pub struct TxValue(pub i128);
122
123impl sqlx::Type<Postgres> for TxValue {
124 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
125 PgTypeInfo::with_name("NUMERIC")
126 }
127}
128
129impl<'r> Decode<'r, Postgres> for TxValue {
130 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
131 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
132 let i = decoded.to_i128().ok_or("TxValue is always an integer".to_string())?;
133 Ok(Self(i))
134 }
135}
136
137#[derive(Debug, Clone, PartialEq)]
144pub struct StakeDelegation(pub u64);
145
146impl sqlx::Type<Postgres> for StakeDelegation {
147 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
148 PgTypeInfo::with_name("NUMERIC")
149 }
150}
151
152impl<'r> Decode<'r, Postgres> for StakeDelegation {
153 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
154 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
155 let i = decoded.to_u64().ok_or("StakeDelegation is always a u64".to_string())?;
156 Ok(Self(i))
157 }
158}
159
160#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
162pub struct AssetName(pub Vec<u8>);
163
164impl From<sidechain_domain::AssetName> for AssetName {
165 fn from(name: sidechain_domain::AssetName) -> Self {
166 Self(name.0.to_vec())
167 }
168}
169
170#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
172pub struct PolicyId(pub Vec<u8>);
173
174impl From<sidechain_domain::PolicyId> for PolicyId {
175 fn from(id: sidechain_domain::PolicyId) -> Self {
176 Self(id.0.to_vec())
177 }
178}
179
180#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
182pub struct Asset {
183 pub policy_id: PolicyId,
185 pub asset_name: AssetName,
187}
188
189impl Asset {
190 pub fn new(policy_id: sidechain_domain::PolicyId) -> Self {
192 Self { policy_id: PolicyId(policy_id.0.to_vec()), asset_name: AssetName(vec![]) }
193 }
194}
195
196impl From<sidechain_domain::AssetId> for Asset {
197 fn from(asset: AssetId) -> Self {
198 Self { policy_id: asset.policy_id.into(), asset_name: asset.asset_name.into() }
199 }
200}
201
202#[allow(deprecated)]
204mod epoch_number_row {
205 use super::*;
206 #[deprecated(
207 since = "1.7.0",
208 note = "Deprecated due to not being either a primitive type or a complete Db-Sync table row."
209 )]
210 #[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
211 pub struct EpochNumberRow(pub EpochNumber);
212
213 #[allow(deprecated)]
214 impl From<EpochNumberRow> for EpochNumber {
215 fn from(r: EpochNumberRow) -> Self {
216 r.0
217 }
218 }
219}
220pub use epoch_number_row::*;
221
222#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
224pub struct Address(pub String);
225
226impl From<MainchainAddress> for Address {
227 fn from(addr: MainchainAddress) -> Self {
228 Self(addr.to_string())
229 }
230}
231
232#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
236pub struct MainchainEpochNonce(pub Vec<u8>);