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, BoxDynError> {
64 buf.extend(&self.0.to_be_bytes());
65 Ok(IsNull::No)
66 }
67 }
68
69 impl From<$NAME> for $DOMAIN {
70 fn from(value: $NAME) -> Self {
71 Self(value.0)
72 }
73 }
74
75 impl From<$DOMAIN> for $NAME {
76 fn from(value: $DOMAIN) -> Self {
77 Self(value.0)
78 }
79 }
80 };
81}
82
83#[derive(Debug, Copy, Ord, PartialOrd, Clone, PartialEq, Eq)]
85pub struct BlockNumber(pub u32);
86sqlx_implementations_for_wrapper!(i32, "INT4", BlockNumber, McBlockNumber);
87
88#[derive(Debug, Copy, Clone, PartialEq)]
90pub struct EpochNumber(pub u32);
91sqlx_implementations_for_wrapper!(i32, "INT4", EpochNumber, McEpochNumber);
92
93#[derive(Debug, Copy, Clone, PartialEq)]
95pub struct SlotNumber(pub u64);
96sqlx_implementations_for_wrapper!(i64, "INT8", SlotNumber, McSlotNumber);
97
98#[derive(Debug, Clone, PartialEq)]
105pub struct TxIndex(pub u16);
106sqlx_implementations_for_wrapper!(i16, "INT2", TxIndex, UtxoIndex);
107
108#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
110pub struct TxIndexInBlock(pub u32);
111sqlx_implementations_for_wrapper!(i32, "INT4", TxIndexInBlock, McTxIndexInBlock);
112
113#[derive(Debug, Clone, PartialEq)]
120pub struct TxValue(pub i128);
121
122impl sqlx::Type<Postgres> for TxValue {
123 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
124 PgTypeInfo::with_name("NUMERIC")
125 }
126}
127
128impl<'r> Decode<'r, Postgres> for TxValue {
129 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
130 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
131 let i = decoded.to_i128().ok_or("TxValue is always an integer".to_string())?;
132 Ok(Self(i))
133 }
134}
135
136#[derive(Debug, Clone, PartialEq)]
143pub struct StakeDelegation(pub u64);
144
145impl sqlx::Type<Postgres> for StakeDelegation {
146 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
147 PgTypeInfo::with_name("NUMERIC")
148 }
149}
150
151impl<'r> Decode<'r, Postgres> for StakeDelegation {
152 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
153 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
154 let i = decoded.to_u64().ok_or("StakeDelegation is always a u64".to_string())?;
155 Ok(Self(i))
156 }
157}
158
159#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
161pub struct AssetName(pub Vec<u8>);
162
163impl From<sidechain_domain::AssetName> for AssetName {
164 fn from(name: sidechain_domain::AssetName) -> Self {
165 Self(name.0.to_vec())
166 }
167}
168
169#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
171pub struct PolicyId(pub Vec<u8>);
172
173impl From<sidechain_domain::PolicyId> for PolicyId {
174 fn from(id: sidechain_domain::PolicyId) -> Self {
175 Self(id.0.to_vec())
176 }
177}
178
179#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
181pub struct Asset {
182 pub policy_id: PolicyId,
184 pub asset_name: AssetName,
186}
187
188impl Asset {
189 pub fn new(policy_id: sidechain_domain::PolicyId) -> Self {
191 Self { policy_id: PolicyId(policy_id.0.to_vec()), asset_name: AssetName(vec![]) }
192 }
193}
194
195impl From<sidechain_domain::AssetId> for Asset {
196 fn from(asset: AssetId) -> Self {
197 Self { policy_id: asset.policy_id.into(), asset_name: asset.asset_name.into() }
198 }
199}
200
201#[allow(deprecated)]
203mod epoch_number_row {
204 use super::*;
205 #[deprecated(
206 since = "1.7.0",
207 note = "Deprecated due to not being either a primitive type or a complete Db-Sync table row."
208 )]
209 #[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
210 pub struct EpochNumberRow(pub EpochNumber);
211
212 #[allow(deprecated)]
213 impl From<EpochNumberRow> for EpochNumber {
214 fn from(r: EpochNumberRow) -> Self {
215 r.0
216 }
217 }
218}
219pub use epoch_number_row::*;
220
221#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
223pub struct Address(pub String);
224
225impl From<MainchainAddress> for Address {
226 fn from(addr: MainchainAddress) -> Self {
227 Self(addr.to_string())
228 }
229}
230
231#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
235pub struct MainchainEpochNonce(pub Vec<u8>);