1#[cfg(feature = "diesel")]
2use diesel::sql_types::{Array, Bytea, Nullable};
3use num_bigint::BigInt;
4use pla::csl::pla_to_csl::TryToCSL;
5use plutus_ledger_api as pla;
6use thiserror::Error;
7use plutus_ledger_api::csl::{
8 lib as csl,
9 csl_to_pla::{TryFromCSLError, TryToPLA},
10 pla_to_csl::TryFromPLAError,
11};
12
13#[derive(Error, Debug)]
14pub enum DBTypeConversionError {
15 #[error("Couldn't parse DB type, because some invariants weren't valid: {0}")]
16 InvariantBroken(String),
17
18 #[error("Cannot represent BigInt as PostgreSQL BIGINT type: {0}")]
19 BigIntConversion(num_bigint::TryFromBigIntError<BigInt>),
20
21 #[error(transparent)]
22 PlutusDataEncodingError(#[from] PlutusDataEncodingError),
23}
24
25#[cfg(feature = "diesel")]
26pub mod sql_types {
27
28 #[derive(diesel::QueryId, diesel::SqlType)]
29 #[diesel(postgres_type(name = "address", schema = "plutus"))]
30 pub struct Address;
31
32 #[derive(diesel::QueryId, diesel::SqlType)]
33 #[diesel(postgres_type(name = "asset_quantity", schema = "plutus"))]
34 pub struct AssetQuantity;
35
36 #[derive(diesel::QueryId, diesel::SqlType)]
37 #[diesel(postgres_type(name = "chain_pointer", schema = "plutus"))]
38 pub struct ChainPointer;
39
40 #[derive(diesel::QueryId, diesel::SqlType)]
41 #[diesel(postgres_type(name = "credential", schema = "plutus"))]
42 pub struct Credential;
43
44 #[derive(diesel::QueryId, diesel::SqlType)]
45 #[diesel(postgres_type(name = "currency_symbol", schema = "plutus"))]
46 pub struct CurrencySymbol;
47
48 #[derive(diesel::QueryId, diesel::SqlType)]
49 #[diesel(postgres_type(name = "datum_hash", schema = "plutus"))]
50 pub struct DatumHash;
51
52 #[derive(diesel::QueryId, diesel::SqlType)]
53 #[diesel(postgres_type(name = "ed25519_pub_key_hash", schema = "plutus"))]
54 pub struct Ed25519PubKeyHash;
55
56 #[derive(diesel::QueryId, diesel::SqlType)]
57 #[diesel(postgres_type(name = "hash28", schema = "plutus"))]
58 pub struct Hash28;
59
60 #[derive(diesel::QueryId, diesel::SqlType)]
61 #[diesel(postgres_type(name = "hash32", schema = "plutus"))]
62 pub struct Hash32;
63
64 #[derive(diesel::QueryId, diesel::SqlType)]
65 #[diesel(postgres_type(name = "output_datum", schema = "plutus"))]
66 pub struct OutputDatum;
67
68 #[derive(diesel::QueryId, diesel::SqlType)]
69 #[diesel(postgres_type(name = "plutus_data", schema = "plutus"))]
70 pub struct PlutusData;
71
72 #[derive(diesel::QueryId, diesel::SqlType)]
73 #[diesel(postgres_type(name = "script_hash", schema = "plutus"))]
74 pub struct ScriptHash;
75
76 #[derive(diesel::QueryId, diesel::SqlType)]
77 #[diesel(postgres_type(name = "slot", schema = "plutus"))]
78 pub struct Slot;
79
80 #[derive(diesel::QueryId, diesel::SqlType)]
81 #[diesel(postgres_type(name = "staking_credential", schema = "plutus"))]
82 pub struct StakingCredential;
83
84 #[derive(diesel::QueryId, diesel::SqlType)]
85 #[diesel(postgres_type(name = "token_name", schema = "plutus"))]
86 pub struct TokenName;
87
88 #[derive(diesel::QueryId, diesel::SqlType)]
89 #[diesel(postgres_type(name = "transaction_hash", schema = "plutus"))]
90 pub struct TransactionHash;
91
92 #[derive(diesel::QueryId, diesel::SqlType)]
93 #[diesel(postgres_type(name = "transaction_input", schema = "plutus"))]
94 pub struct TransactionInput;
95
96 #[derive(diesel::QueryId, diesel::SqlType)]
97 #[diesel(postgres_type(name = "transaction_output", schema = "plutus"))]
98 pub struct TransactionOutput;
99
100 #[derive(diesel::QueryId, diesel::SqlType)]
101 #[diesel(postgres_type(name = "tx_in_info", schema = "plutus"))]
102 pub struct TxInInfo;
103
104 #[derive(diesel::QueryId, diesel::SqlType)]
105 #[diesel(postgres_type(name = "value", schema = "plutus"))]
106 pub struct Value;
107}
108
109#[derive(Clone, Debug, PartialEq, Eq)]
114#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
115#[cfg_attr(
116 feature = "diesel",
117 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
118 diesel(sql_type = sql_types::Hash28),
119 diesel_derive_pg(sql_type = sql_types::Hash28)
120)]
121pub struct Hash28(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Bytea))] pub Vec<u8>);
122
123impl From<pla::v3::crypto::LedgerBytes> for Hash28 {
124 fn from(item: pla::v3::crypto::LedgerBytes) -> Self {
125 Hash28(item.0)
126 }
127}
128
129impl From<Hash28> for pla::v3::crypto::LedgerBytes {
130 fn from(item: Hash28) -> Self {
131 pla::v3::crypto::LedgerBytes(item.0)
132 }
133}
134
135#[cfg(feature = "sqlx")]
136impl ::sqlx::Type<::sqlx::postgres::Postgres> for Hash28 {
137 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
138 ::sqlx::postgres::PgTypeInfo::with_name("plutus.hash28")
139 }
140 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
141 Self::type_info() == *ty || <Vec<u8> as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
142 }
143}
144
145#[derive(Clone, Debug, PartialEq, Eq)]
150#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
151#[cfg_attr(
152 feature = "diesel",
153 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
154 diesel(sql_type = sql_types::Hash32),
155 diesel_derive_pg(sql_type = sql_types::Hash32)
156)]
157pub struct Hash32(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Bytea))] pub Vec<u8>);
158
159impl From<pla::v3::crypto::LedgerBytes> for Hash32 {
160 fn from(item: pla::v3::crypto::LedgerBytes) -> Self {
161 Hash32(item.0)
162 }
163}
164
165impl From<Hash32> for pla::v3::crypto::LedgerBytes {
166 fn from(item: Hash32) -> Self {
167 pla::v3::crypto::LedgerBytes(item.0)
168 }
169}
170
171#[cfg(feature = "sqlx")]
172impl ::sqlx::Type<::sqlx::postgres::Postgres> for Hash32 {
173 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
174 ::sqlx::postgres::PgTypeInfo::with_name("plutus.hash32")
175 }
176 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
177 Self::type_info() == *ty || <Vec<u8> as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
178 }
179}
180
181#[derive(Clone, Debug, PartialEq, Eq)]
186#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
187#[cfg_attr(
188 feature = "diesel",
189 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
190 diesel(sql_type = sql_types::CurrencySymbol),
191 diesel_derive_pg(sql_type = sql_types::CurrencySymbol)
192)]
193pub struct CurrencySymbol(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Bytea))] pub Vec<u8>);
194
195impl From<pla::v3::value::CurrencySymbol> for CurrencySymbol {
196 fn from(item: pla::v3::value::CurrencySymbol) -> Self {
197 match item {
198 pla::v3::value::CurrencySymbol::Ada => CurrencySymbol(Vec::with_capacity(0)),
199 pla::v3::value::CurrencySymbol::NativeToken(pla::v3::script::MintingPolicyHash(
200 pla::v3::script::ScriptHash(pla::v3::crypto::LedgerBytes(bytes)),
201 )) => CurrencySymbol(bytes),
202 }
203 }
204}
205
206impl From<CurrencySymbol> for pla::v3::value::CurrencySymbol {
207 fn from(item: CurrencySymbol) -> Self {
208 let CurrencySymbol(bytes) = item;
209 if bytes.is_empty() {
210 pla::v3::value::CurrencySymbol::Ada
211 } else {
212 pla::v3::value::CurrencySymbol::NativeToken(pla::v3::script::MintingPolicyHash(
213 pla::v3::script::ScriptHash(pla::v3::crypto::LedgerBytes(bytes)),
214 ))
215 }
216 }
217}
218
219#[cfg(feature = "sqlx")]
220impl ::sqlx::Type<::sqlx::postgres::Postgres> for CurrencySymbol {
221 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
222 ::sqlx::postgres::PgTypeInfo::with_name("plutus.currency_symbol")
223 }
224 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
225 Self::type_info() == *ty || <Vec<u8> as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
226 }
227}
228
229#[derive(Clone, Debug, PartialEq, Eq)]
234#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
235#[cfg_attr(
236 feature = "diesel",
237 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
238 diesel(sql_type = sql_types::TokenName),
239 diesel_derive_pg(sql_type = sql_types::TokenName)
240)]
241pub struct TokenName(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Bytea))] pub Vec<u8>);
242
243impl From<pla::v3::value::TokenName> for TokenName {
244 fn from(item: pla::v3::value::TokenName) -> Self {
245 TokenName(item.0 .0)
246 }
247}
248
249impl From<TokenName> for pla::v3::value::TokenName {
250 fn from(item: TokenName) -> Self {
251 pla::v3::value::TokenName(pla::v3::crypto::LedgerBytes(item.0))
252 }
253}
254
255#[cfg(feature = "sqlx")]
256impl ::sqlx::Type<::sqlx::postgres::Postgres> for TokenName {
257 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
258 ::sqlx::postgres::PgTypeInfo::with_name("plutus.token_name")
259 }
260 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
261 Self::type_info() == *ty || <Vec<u8> as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
262 }
263}
264
265#[derive(Clone, Debug, PartialEq, Eq)]
270#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
271#[cfg_attr(
272 feature = "diesel",
273 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
274 diesel(sql_type = sql_types::TransactionHash),
275 diesel_derive_pg(sql_type = sql_types::TransactionHash)
276)]
277pub struct TransactionHash(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Hash32))] pub Hash32);
278
279impl From<pla::v3::transaction::TransactionHash> for TransactionHash {
280 fn from(item: pla::v3::transaction::TransactionHash) -> Self {
281 TransactionHash(item.0.into())
282 }
283}
284
285impl From<TransactionHash> for pla::v3::transaction::TransactionHash {
286 fn from(item: TransactionHash) -> Self {
287 pla::v3::transaction::TransactionHash(item.0.into())
288 }
289}
290
291#[cfg(feature = "sqlx")]
292impl ::sqlx::Type<::sqlx::postgres::Postgres> for TransactionHash {
293 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
294 ::sqlx::postgres::PgTypeInfo::with_name("plutus.transaction_hash")
295 }
296 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
297 Self::type_info() == *ty || <Hash32 as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
298 }
299}
300
301#[derive(Clone, Debug, PartialEq, Eq)]
306#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
307#[cfg_attr(
308 feature = "diesel",
309 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
310 diesel(sql_type = sql_types::Ed25519PubKeyHash),
311 diesel_derive_pg(sql_type = sql_types::Ed25519PubKeyHash)
312)]
313pub struct Ed25519PubKeyHash(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Hash28))] pub Hash28);
314
315impl From<pla::v3::crypto::Ed25519PubKeyHash> for Ed25519PubKeyHash {
316 fn from(item: pla::v3::crypto::Ed25519PubKeyHash) -> Self {
317 Ed25519PubKeyHash(item.0.into())
318 }
319}
320
321impl From<Ed25519PubKeyHash> for pla::v3::crypto::Ed25519PubKeyHash {
322 fn from(item: Ed25519PubKeyHash) -> Self {
323 pla::v3::crypto::Ed25519PubKeyHash(item.0.into())
324 }
325}
326
327#[cfg(feature = "sqlx")]
328impl ::sqlx::Type<::sqlx::postgres::Postgres> for Ed25519PubKeyHash {
329 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
330 ::sqlx::postgres::PgTypeInfo::with_name("plutus.ed25519_pub_key_hash")
331 }
332 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
333 Self::type_info() == *ty || <Hash28 as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
334 }
335}
336
337#[derive(Clone, Debug, PartialEq, Eq)]
342#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
343#[cfg_attr(
344 feature = "diesel",
345 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
346 diesel(sql_type = sql_types::ScriptHash),
347 diesel_derive_pg(sql_type = sql_types::ScriptHash)
348)]
349pub struct ScriptHash(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Hash28))] pub Hash28);
350
351impl From<pla::v3::script::ScriptHash> for ScriptHash {
352 fn from(item: pla::v3::script::ScriptHash) -> Self {
353 ScriptHash(item.0.into())
354 }
355}
356
357impl From<ScriptHash> for pla::v3::script::ScriptHash {
358 fn from(item: ScriptHash) -> Self {
359 pla::v3::script::ScriptHash(item.0.into())
360 }
361}
362
363#[cfg(feature = "sqlx")]
364impl ::sqlx::Type<::sqlx::postgres::Postgres> for ScriptHash {
365 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
366 ::sqlx::postgres::PgTypeInfo::with_name("plutus.script_hash")
367 }
368 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
369 Self::type_info() == *ty || <Hash28 as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
370 }
371}
372
373#[derive(Clone, Debug, PartialEq, Eq)]
378#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
379#[cfg_attr(
380 feature = "diesel",
381 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
382 diesel(sql_type = sql_types::DatumHash),
383 diesel_derive_pg(sql_type = sql_types::DatumHash)
384 )]
385pub struct DatumHash(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Hash32))] pub Hash32);
386
387impl From<pla::v3::datum::DatumHash> for DatumHash {
388 fn from(item: pla::v3::datum::DatumHash) -> Self {
389 DatumHash(item.0.into())
390 }
391}
392
393impl From<DatumHash> for pla::v3::datum::DatumHash {
394 fn from(item: DatumHash) -> Self {
395 pla::v3::datum::DatumHash(item.0.into())
396 }
397}
398
399#[cfg(feature = "sqlx")]
400impl ::sqlx::Type<::sqlx::postgres::Postgres> for DatumHash {
401 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
402 ::sqlx::postgres::PgTypeInfo::with_name("plutus.datum_hash")
403 }
404 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
405 Self::type_info() == *ty || <Hash32 as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
406 }
407}
408
409#[derive(Clone, Debug, PartialEq, Eq)]
414#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
415#[cfg_attr(
416 feature = "diesel",
417 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
418 diesel(sql_type = sql_types::Slot),
419 diesel_derive_pg(sql_type = sql_types::Slot)
420)]
421pub struct Slot(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))] pub i64);
422
423impl From<u64> for Slot {
424 fn from(item: u64) -> Self {
425 Slot(item as i64)
426 }
427}
428
429impl From<&Slot> for u64 {
430 fn from(item: &Slot) -> Self {
431 item.0 as u64
432 }
433}
434
435#[cfg(feature = "sqlx")]
436impl ::sqlx::Type<::sqlx::postgres::Postgres> for Slot {
437 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
438 ::sqlx::postgres::PgTypeInfo::with_name("plutus.slot")
439 }
440 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
441 Self::type_info() == *ty || <i64 as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
442 }
443}
444
445
446#[derive(Error, Debug)]
451pub enum PlutusDataEncodingError {
452 #[error(transparent)]
453 CSLConversionError(#[from] csl::JsError),
454
455 #[error(transparent)]
456 TryFromPLAError(#[from] TryFromPLAError),
457
458 #[error(transparent)]
459 TryFromCSLError(#[from] TryFromCSLError),
460}
461
462#[derive(Clone, Debug, PartialEq, Eq)]
463#[cfg_attr(feature = "sqlx", derive(sqlx::Encode, sqlx::Decode))]
464#[cfg_attr(
465 feature = "diesel",
466 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
467 diesel(sql_type = sql_types::PlutusData),
468 diesel_derive_pg(sql_type = sql_types::PlutusData)
469)]
470pub struct PlutusData(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::Jsonb))] pub serde_json::Value);
471
472impl TryFrom<pla::plutus_data::PlutusData> for PlutusData {
473 type Error = DBTypeConversionError;
474
475 fn try_from(item: pla::plutus_data::PlutusData) -> Result<Self, Self::Error> {
476 Ok(PlutusData(
477 csl::decode_plutus_datum_to_json_value(
478 &item
479 .try_to_csl()
480 .map_err(PlutusDataEncodingError::TryFromPLAError)?,
481 csl::PlutusDatumSchema::DetailedSchema,
482 )
483 .map_err(PlutusDataEncodingError::CSLConversionError)?,
484 ))
485 }
486}
487
488impl TryFrom<PlutusData> for pla::plutus_data::PlutusData {
489 type Error = DBTypeConversionError;
490
491 fn try_from(item: PlutusData) -> Result<Self, Self::Error> {
492 Ok(
493 csl::encode_json_value_to_plutus_datum(item.0, csl::PlutusDatumSchema::DetailedSchema)
494 .map_err(PlutusDataEncodingError::CSLConversionError)?
495 .try_to_pla()
496 .map_err(PlutusDataEncodingError::TryFromCSLError)?,
497 )
498 }
499}
500
501#[cfg(feature = "sqlx")]
502impl ::sqlx::Type<::sqlx::postgres::Postgres> for PlutusData {
503 fn type_info() -> ::sqlx::postgres::PgTypeInfo {
504 ::sqlx::postgres::PgTypeInfo::with_name("plutus.plutus_data")
505 }
506 fn compatible(ty: &sqlx::postgres::PgTypeInfo) -> ::std::primitive::bool {
507 Self::type_info() == *ty
508 || <serde_json::Value as ::sqlx::Type<::sqlx::Postgres>>::compatible(ty)
509 }
510}
511
512#[derive(Clone, Debug, PartialEq, Eq)]
517#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
518#[cfg_attr(feature = "sqlx", sqlx(type_name = "plutus.credential"))]
519#[cfg_attr(
520 feature = "diesel",
521 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
522 diesel(sql_type = sql_types::Credential),
523 diesel_derive_pg(sql_type = sql_types::Credential)
524)]
525pub struct Credential {
526 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::Ed25519PubKeyHash>))]
527 pub_key_hash: Option<Ed25519PubKeyHash>,
528
529 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::ScriptHash>))]
530 script_hash: Option<ScriptHash>,
531}
532
533impl From<pla::v3::address::Credential> for Credential {
534 fn from(item: pla::v3::address::Credential) -> Self {
535 match item {
536 pla::v3::address::Credential::PubKey(pkh) => Credential {
537 pub_key_hash: Some(pkh.into()),
538 script_hash: None,
539 },
540 pla::v3::address::Credential::Script(pla::v3::script::ValidatorHash(sh)) => {
541 Credential {
542 pub_key_hash: None,
543 script_hash: Some(sh.into()),
544 }
545 }
546 }
547 }
548}
549
550impl TryFrom<Credential> for pla::v3::address::Credential {
551 type Error = DBTypeConversionError;
552
553 fn try_from(item: Credential) -> Result<Self, Self::Error> {
554 Ok(match item {
555 Credential {
556 pub_key_hash: Some(pkh_db),
557 script_hash: None,
558 } => pla::v3::address::Credential::PubKey(pkh_db.into()),
559 Credential {
560 pub_key_hash: None,
561 script_hash: Some(sh_db),
562 } => pla::v3::address::Credential::Script(pla::v3::script::ValidatorHash(sh_db.into())),
563 _ => Err(DBTypeConversionError::InvariantBroken(
564 "DB Credential must have either 'pub_key_hash' or 'script_hash'".to_string(),
565 ))?,
566 })
567 }
568}
569
570#[derive(Clone, Debug, PartialEq, Eq)]
575#[cfg_attr(feature = "sqlx", derive(sqlx::Type))]
576#[cfg_attr(feature = "sqlx", sqlx(type_name = "plutus.chain_pointer"))]
577#[cfg_attr(
578 feature = "diesel",
579 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
580 diesel(sql_type = sql_types::ChainPointer),
581 diesel_derive_pg(sql_type = sql_types::ChainPointer)
582)]
583pub struct ChainPointer {
584 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))]
585 slot_num: i64,
586
587 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))]
588 tx_idx: i64,
589
590 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))]
591 cert_idx: i64,
592}
593
594impl TryFrom<pla::v3::address::ChainPointer> for ChainPointer {
595 type Error = DBTypeConversionError;
596
597 fn try_from(item: pla::v3::address::ChainPointer) -> Result<Self, Self::Error> {
598 Ok(ChainPointer {
599 slot_num: item
600 .slot_number
601 .0
602 .try_into()
603 .map_err(DBTypeConversionError::BigIntConversion)?,
604 tx_idx: item
605 .transaction_index
606 .0
607 .try_into()
608 .map_err(DBTypeConversionError::BigIntConversion)?,
609 cert_idx: item
610 .certificate_index
611 .0
612 .try_into()
613 .map_err(DBTypeConversionError::BigIntConversion)?,
614 })
615 }
616}
617
618impl From<ChainPointer> for pla::v3::address::ChainPointer {
619 fn from(item: ChainPointer) -> Self {
620 pla::v3::address::ChainPointer {
621 slot_number: pla::v3::address::Slot(BigInt::from(item.slot_num)),
622 transaction_index: pla::v3::address::TransactionIndex(BigInt::from(item.tx_idx)),
623 certificate_index: pla::v3::address::CertificateIndex(BigInt::from(item.cert_idx)),
624 }
625 }
626}
627
628#[derive(Clone, Debug, PartialEq, Eq)]
633#[cfg_attr(feature = "sqlx", derive(sqlx::Type), sqlx(type_name = "plutus.staking_credential"))]
634#[cfg_attr(
635 feature = "diesel",
636 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
637 diesel(sql_type = sql_types::StakingCredential),
638 diesel_derive_pg(sql_type = sql_types::StakingCredential)
639)]
640pub struct StakingCredential {
641 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::Credential>))]
642 staking_hash: Option<Credential>,
643
644 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::ChainPointer>))]
645 staking_ptr: Option<ChainPointer>,
646}
647
648impl TryFrom<pla::v3::address::StakingCredential> for StakingCredential {
649 type Error = DBTypeConversionError;
650
651 fn try_from(item: pla::v3::address::StakingCredential) -> Result<Self, Self::Error> {
652 Ok(match item {
653 pla::v3::address::StakingCredential::Hash(cred) => StakingCredential {
654 staking_hash: Some(cred.into()),
655 staking_ptr: None,
656 },
657 pla::v3::address::StakingCredential::Pointer(ptr) => StakingCredential {
658 staking_hash: None,
659 staking_ptr: Some(ptr.try_into()?),
660 },
661 })
662 }
663}
664
665impl TryFrom<StakingCredential> for pla::v3::address::StakingCredential {
666 type Error = DBTypeConversionError;
667
668 fn try_from(item: StakingCredential) -> Result<Self, Self::Error> {
669 Ok(match item {
670 StakingCredential {
671 staking_hash: Some(cred),
672 staking_ptr: None,
673 } => pla::v3::address::StakingCredential::Hash(cred.try_into()?),
674 StakingCredential {
675 staking_hash: None,
676 staking_ptr: Some(ptr),
677 } => pla::v3::address::StakingCredential::Pointer(ptr.into()),
678
679 _ => Err(DBTypeConversionError::InvariantBroken(
680 "DB StakingCredential must have either 'staking_hash' or 'staking_ptr'".to_string(),
681 ))?,
682 })
683 }
684}
685
686#[derive(Clone, Debug, PartialEq, Eq)]
691#[cfg_attr(
692 feature = "sqlx",
693 derive(sqlx::Type),
694 sqlx(type_name = "plutus.address")
695)]
696#[cfg_attr(
697 feature = "diesel",
698 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
699 diesel(sql_type = sql_types::Address),
700 diesel_derive_pg(sql_type = sql_types::Address)
701)]
702pub struct Address {
703 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Credential))]
704 credential: Credential,
705
706 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::StakingCredential>))]
707 staking_credential: Option<StakingCredential>,
708}
709
710impl TryFrom<pla::v3::address::Address> for Address {
711 type Error = DBTypeConversionError;
712
713 fn try_from(item: pla::v3::address::Address) -> Result<Self, Self::Error> {
714 Ok(Address {
715 credential: item.credential.into(),
716 staking_credential: item
717 .staking_credential
718 .map(StakingCredential::try_from)
719 .transpose()?,
720 })
721 }
722}
723
724impl TryFrom<Address> for pla::v3::address::Address {
725 type Error = DBTypeConversionError;
726
727 fn try_from(item: Address) -> Result<Self, Self::Error> {
728 Ok(pla::v3::address::Address {
729 credential: item.credential.try_into()?,
730 staking_credential: item
731 .staking_credential
732 .map(pla::v3::address::StakingCredential::try_from)
733 .transpose()?,
734 })
735 }
736}
737
738#[derive(Clone, Debug, PartialEq, Eq)]
743#[cfg_attr(
744 feature = "sqlx", derive(sqlx::Type),
745 sqlx(type_name = "plutus.asset_quantity")
746)]
747#[cfg_attr(
748 feature = "diesel",
749 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
750 diesel(sql_type = sql_types::AssetQuantity),
751 diesel_derive_pg(sql_type = sql_types::AssetQuantity)
752)]
753pub struct AssetQuantity {
754 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::CurrencySymbol))]
755 currency_symbol: CurrencySymbol,
756
757 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::TokenName))]
758 token_name: TokenName,
759
760 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))]
761 amount: i64,
762}
763
764impl
765 TryFrom<(
766 pla::v3::value::CurrencySymbol,
767 pla::v3::value::TokenName,
768 BigInt,
769 )> for AssetQuantity
770{
771 type Error = DBTypeConversionError;
772
773 fn try_from(
774 item: (
775 pla::v3::value::CurrencySymbol,
776 pla::v3::value::TokenName,
777 BigInt,
778 ),
779 ) -> Result<Self, Self::Error> {
780 Ok(AssetQuantity {
781 currency_symbol: item.0.into(),
782 token_name: item.1.into(),
783 amount: item
784 .2
785 .try_into()
786 .map_err(DBTypeConversionError::BigIntConversion)?,
787 })
788 }
789}
790
791impl From<AssetQuantity>
792 for (
793 pla::v3::value::CurrencySymbol,
794 pla::v3::value::TokenName,
795 BigInt,
796 )
797{
798 fn from(item: AssetQuantity) -> Self {
799 (
800 item.currency_symbol.into(),
801 item.token_name.into(),
802 item.amount.into(),
803 )
804 }
805}
806
807#[derive(Clone, Debug, PartialEq, Eq)]
812#[cfg_attr(
813 feature = "sqlx",
814 derive(sqlx::Type),
815 sqlx(type_name = "plutus.asset_quantity[]")
816)]
817#[cfg_attr(
818 feature = "diesel",
819 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
820 diesel(sql_type = sql_types::Value),
821 diesel_derive_pg(sql_type = sql_types::Value)
822)]
823pub struct Value(#[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Array<sql_types::AssetQuantity>))] pub Vec<AssetQuantity>);
824
825impl TryFrom<pla::v3::value::Value> for Value {
826 type Error = DBTypeConversionError;
827
828 fn try_from(item: pla::v3::value::Value) -> Result<Self, Self::Error> {
829 let assets = item
830 .0
831 .iter()
832 .flat_map(|(cs, assets)| {
833 assets
834 .iter()
835 .map(|(tn, amount)| {
836 AssetQuantity::try_from((cs.to_owned(), tn.to_owned(), amount.to_owned()))
837 })
838 .collect::<Vec<_>>()
839 })
840 .collect::<Result<Vec<AssetQuantity>, DBTypeConversionError>>()?;
841
842 Ok(Value(assets))
843 }
844}
845
846impl From<Value> for pla::v3::value::Value {
847 fn from(item: Value) -> Self {
848 item.0.into_iter().fold(
849 pla::v3::value::Value::new(),
850 |value,
851 AssetQuantity {
852 currency_symbol,
853 token_name,
854 amount,
855 }| {
856 value.insert_token(¤cy_symbol.into(), &token_name.into(), &amount.into())
857 },
858 )
859 }
860}
861
862#[derive(Clone, Debug, PartialEq, Eq)]
867#[cfg_attr(
868 feature = "sqlx",
869 derive(sqlx::Type),
870 sqlx(type_name = "plutus.transaction_input")
871)]
872#[cfg_attr(
873 feature = "diesel",
874 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
875 diesel(sql_type = sql_types::TransactionInput),
876 diesel_derive_pg(sql_type = sql_types::TransactionInput)
877)]
878pub struct TransactionInput {
879 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::TransactionHash))]
880 tx_id: TransactionHash,
881
882 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = diesel::sql_types::BigInt))]
883 tx_idx: i64,
884}
885
886impl TryFrom<pla::v3::transaction::TransactionInput> for TransactionInput {
887 type Error = DBTypeConversionError;
888
889 fn try_from(item: pla::v3::transaction::TransactionInput) -> Result<Self, Self::Error> {
890 Ok(TransactionInput {
891 tx_id: item.transaction_id.into(),
892 tx_idx: item
893 .index
894 .try_into()
895 .map_err(DBTypeConversionError::BigIntConversion)?,
896 })
897 }
898}
899
900impl From<TransactionInput> for pla::v3::transaction::TransactionInput {
901 fn from(item: TransactionInput) -> Self {
902 pla::v3::transaction::TransactionInput {
903 transaction_id: item.tx_id.into(),
904 index: item.tx_idx.into(),
905 }
906 }
907}
908
909#[derive(Clone, Debug, PartialEq, Eq)]
914#[cfg_attr(
915 feature = "sqlx",
916 derive(sqlx::Type),
917 sqlx(type_name = "plutus.output_datum")
918)]
919#[cfg_attr(
920 feature = "diesel",
921 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
922 diesel(sql_type = sql_types::OutputDatum),
923 diesel_derive_pg(sql_type = sql_types::OutputDatum)
924)]
925pub struct OutputDatum {
926 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::DatumHash>))]
927 datum_hash: Option<DatumHash>,
928
929 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::PlutusData>))]
930 inline_datum: Option<PlutusData>,
931}
932
933impl TryFrom<pla::v3::datum::OutputDatum> for OutputDatum {
934 type Error = DBTypeConversionError;
935
936 fn try_from(item: pla::v3::datum::OutputDatum) -> Result<Self, Self::Error> {
937 Ok(match item {
938 pla::v3::datum::OutputDatum::DatumHash(dh) => OutputDatum {
939 datum_hash: Some(dh.into()),
940 inline_datum: None,
941 },
942 pla::v3::datum::OutputDatum::InlineDatum(pla::v3::datum::Datum(datum)) => OutputDatum {
943 datum_hash: None,
944 inline_datum: Some(datum.try_into()?),
945 },
946 pla::v3::datum::OutputDatum::None => OutputDatum {
947 datum_hash: None,
948 inline_datum: None,
949 },
950 })
951 }
952}
953
954impl TryFrom<OutputDatum> for pla::v3::datum::OutputDatum {
955 type Error = DBTypeConversionError;
956
957 fn try_from(item: OutputDatum) -> Result<Self, Self::Error> {
958 Ok(match item {
959 OutputDatum {
960 datum_hash: Some(dh_db),
961 ..
962 } => pla::v3::datum::OutputDatum::DatumHash(dh_db.into()),
963 OutputDatum {
964 inline_datum: Some(datum_db),
965 ..
966 } => pla::v3::datum::OutputDatum::InlineDatum(pla::v3::datum::Datum(
967 datum_db.try_into()?,
968 )),
969 _ => pla::v3::datum::OutputDatum::None,
970 })
971 }
972}
973
974#[derive(Clone, Debug, PartialEq, Eq)]
979#[cfg_attr(
980 feature = "sqlx",
981 derive(sqlx::Type),
982 sqlx(type_name = "plutus.transaction_output")
983)]
984#[cfg_attr(
985 feature = "diesel",
986 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
987 diesel(sql_type = sql_types::TransactionOutput),
988 diesel_derive_pg(sql_type = sql_types::TransactionOutput)
989)]
990pub struct TransactionOutput {
991 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Address))]
992 address: Address,
993
994 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::Value))]
995 assets: Value,
996
997 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::OutputDatum))]
998 datum: OutputDatum,
999
1000 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = Nullable<sql_types::ScriptHash>))]
1001 reference_script: Option<ScriptHash>,
1002}
1003
1004impl TryFrom<pla::v3::transaction::TransactionOutput> for TransactionOutput {
1005 type Error = DBTypeConversionError;
1006
1007 fn try_from(item: pla::v3::transaction::TransactionOutput) -> Result<Self, Self::Error> {
1008 Ok(TransactionOutput {
1009 address: item.address.try_into()?,
1010 assets: item.value.try_into()?,
1011 datum: item.datum.try_into()?,
1012 reference_script: item.reference_script.map(ScriptHash::from),
1013 })
1014 }
1015}
1016
1017impl TryFrom<TransactionOutput> for pla::v3::transaction::TransactionOutput {
1018 type Error = DBTypeConversionError;
1019
1020 fn try_from(item: TransactionOutput) -> Result<Self, Self::Error> {
1021 Ok(pla::v3::transaction::TransactionOutput {
1022 address: item.address.try_into()?,
1023 value: item.assets.into(),
1024 datum: item.datum.try_into()?,
1025 reference_script: item.reference_script.map(pla::v3::script::ScriptHash::from),
1026 })
1027 }
1028}
1029
1030#[derive(Clone, Debug, PartialEq, Eq)]
1035#[cfg_attr(
1036 feature = "sqlx",
1037 derive(sqlx::Type),
1038 sqlx(type_name = "plutus.tx_in_info")
1039)]
1040#[cfg_attr(
1041 feature = "diesel",
1042 derive(diesel::AsExpression, diesel::FromSqlRow, diesel_derive_pg::PgCustomType),
1043 diesel(sql_type = sql_types::TxInInfo),
1044 diesel_derive_pg(sql_type = sql_types::TxInInfo)
1045)]
1046pub struct TxInInfo {
1047 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::TransactionInput))]
1048 reference: TransactionInput,
1049
1050 #[cfg_attr(feature = "diesel", diesel_derive_pg(sql_type = sql_types::TransactionOutput))]
1051 output: TransactionOutput,
1052}
1053
1054impl TryFrom<pla::v3::transaction::TxInInfo> for TxInInfo {
1055 type Error = DBTypeConversionError;
1056
1057 fn try_from(item: pla::v3::transaction::TxInInfo) -> Result<Self, Self::Error> {
1058 Ok(TxInInfo {
1059 reference: item.reference.try_into()?,
1060 output: item.output.try_into()?,
1061 })
1062 }
1063}
1064
1065impl TryFrom<TxInInfo> for pla::v3::transaction::TxInInfo {
1066 type Error = DBTypeConversionError;
1067
1068 fn try_from(item: TxInInfo) -> Result<Self, Self::Error> {
1069 Ok(pla::v3::transaction::TxInInfo {
1070 reference: item.reference.into(),
1071 output: item.output.try_into()?,
1072 })
1073 }
1074}
1075