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)]
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, Copy, PartialOrd, Ord, PartialEq, Eq)]
115pub struct TxHash(pub [u8; 32]);
116
117impl sqlx::Type<Postgres> for TxHash {
118 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
119 PgTypeInfo::with_name("bytea")
120 }
121}
122
123impl<'r> Decode<'r, Postgres> for TxHash {
124 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
125 let decoded = <[u8; 32]>::decode(value)?;
126 Ok(Self(decoded))
127 }
128}
129
130impl<'r> Encode<'r, Postgres> for TxHash {
131 fn encode_by_ref(
132 &self,
133 buf: &mut <Postgres as Database>::ArgumentBuffer<'r>,
134 ) -> std::result::Result<IsNull, BoxDynError> {
135 buf.extend(self.0.iter());
136 Ok(IsNull::No)
137 }
138}
139
140impl From<TxHash> for McTxHash {
141 fn from(hash: TxHash) -> Self {
142 Self(hash.0)
143 }
144}
145impl From<McTxHash> for TxHash {
146 fn from(hash: McTxHash) -> Self {
147 Self(hash.0)
148 }
149}
150
151#[derive(Debug, Clone, PartialEq)]
158pub struct TxValue(pub i128);
159
160impl sqlx::Type<Postgres> for TxValue {
161 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
162 PgTypeInfo::with_name("NUMERIC")
163 }
164}
165
166impl<'r> Decode<'r, Postgres> for TxValue {
167 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
168 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
169 let i = decoded.to_i128().ok_or("TxValue is always an integer".to_string())?;
170 Ok(Self(i))
171 }
172}
173
174#[derive(Debug, Clone, PartialEq)]
181pub struct StakeDelegation(pub u64);
182
183impl sqlx::Type<Postgres> for StakeDelegation {
184 fn type_info() -> <Postgres as sqlx::Database>::TypeInfo {
185 PgTypeInfo::with_name("NUMERIC")
186 }
187}
188
189impl<'r> Decode<'r, Postgres> for StakeDelegation {
190 fn decode(value: <Postgres as Database>::ValueRef<'r>) -> Result<Self, BoxDynError> {
191 let decoded = <sqlx::types::BigDecimal as Decode<Postgres>>::decode(value)?;
192 let i = decoded.to_u64().ok_or("StakeDelegation is always a u64".to_string())?;
193 Ok(Self(i))
194 }
195}
196
197#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
199pub struct AssetName(pub Vec<u8>);
200
201impl From<sidechain_domain::AssetName> for AssetName {
202 fn from(name: sidechain_domain::AssetName) -> Self {
203 Self(name.0.to_vec())
204 }
205}
206
207#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
209pub struct PolicyId(pub Vec<u8>);
210
211impl From<sidechain_domain::PolicyId> for PolicyId {
212 fn from(id: sidechain_domain::PolicyId) -> Self {
213 Self(id.0.to_vec())
214 }
215}
216
217#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
219pub struct Asset {
220 pub policy_id: PolicyId,
222 pub asset_name: AssetName,
224}
225
226impl Asset {
227 pub fn new(policy_id: sidechain_domain::PolicyId) -> Self {
229 Self { policy_id: PolicyId(policy_id.0.to_vec()), asset_name: AssetName(vec![]) }
230 }
231}
232
233impl From<sidechain_domain::AssetId> for Asset {
234 fn from(asset: AssetId) -> Self {
235 Self { policy_id: asset.policy_id.into(), asset_name: asset.asset_name.into() }
236 }
237}
238
239#[allow(deprecated)]
241mod epoch_number_row {
242 use super::*;
243 #[deprecated(
244 since = "1.7.0",
245 note = "Deprecated due to not being either a primitive type or a complete Db-Sync table row."
246 )]
247 #[derive(Debug, Copy, Clone, sqlx::FromRow, PartialEq)]
248 pub struct EpochNumberRow(pub EpochNumber);
249
250 #[allow(deprecated)]
251 impl From<EpochNumberRow> for EpochNumber {
252 fn from(r: EpochNumberRow) -> Self {
253 r.0
254 }
255 }
256}
257pub use epoch_number_row::*;
258
259#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
261pub struct Address(pub String);
262
263impl From<MainchainAddress> for Address {
264 fn from(addr: MainchainAddress) -> Self {
265 Self(addr.to_string())
266 }
267}
268
269#[derive(Debug, Clone, sqlx::FromRow, PartialEq)]
273pub struct MainchainEpochNonce(pub Vec<u8>);