use crate::address::{Address, RewardAddress};
use crate::cert::Cert;
use crate::plutus::{PlutusData, Redeemer};
use crate::primitives::{
AssetName, DataHash, Hash32, KeyHash, Lovelace, MintQuantity, PolicyId, Slot, TxHash,
};
use crate::script::Script;
use crate::value::Value;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TxInput {
pub tx_hash: TxHash,
pub index: u32,
pub address: Address,
pub value: Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub datum: Option<DatumOption>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub redeemer: Option<Redeemer>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script_ref: Option<Script>,
}
impl TxInput {
pub fn new(
tx_hash: impl Into<TxHash>,
index: u32,
address: impl Into<Address>,
value: Value,
) -> Self {
Self {
tx_hash: tx_hash.into(),
index,
address: address.into(),
value,
datum: None,
redeemer: None,
script_ref: None,
}
}
pub fn with_datum(mut self, d: DatumOption) -> Self { self.datum = Some(d); self }
pub fn with_inline_datum(mut self, d: PlutusData) -> Self {
self.datum = Some(DatumOption::Inline { data: d });
self
}
pub fn with_datum_hash(mut self, h: impl Into<DataHash>) -> Self {
self.datum = Some(DatumOption::Hash { hash: h.into() });
self
}
pub fn with_redeemer(mut self, r: Redeemer) -> Self { self.redeemer = Some(r); self }
pub fn with_script_ref(mut self, s: Script) -> Self { self.script_ref = Some(s); self }
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum DatumOption {
Hash { hash: DataHash },
Inline { data: PlutusData },
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TxOutput {
pub address: Address,
pub value: Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub datum: Option<DatumOption>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script_ref: Option<Script>,
}
impl TxOutput {
pub fn new(address: impl Into<Address>, value: Value) -> Self {
Self { address: address.into(), value, datum: None, script_ref: None }
}
pub fn with_inline_datum(mut self, d: PlutusData) -> Self {
self.datum = Some(DatumOption::Inline { data: d });
self
}
pub fn with_datum_hash(mut self, h: impl Into<DataHash>) -> Self {
self.datum = Some(DatumOption::Hash { hash: h.into() });
self
}
pub fn with_script_ref(mut self, s: Script) -> Self {
self.script_ref = Some(s);
self
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct MintPolicy {
pub assets: BTreeMap<AssetName, MintQuantity>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script: Option<Script>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub redeemer: Option<Redeemer>,
}
impl MintPolicy {
pub fn new() -> Self { Self::default() }
pub fn mint(mut self, asset: impl Into<AssetName>, qty: i128) -> Self {
self.assets.insert(asset.into(), MintQuantity(qty));
self
}
pub fn with_script(mut self, s: Script) -> Self { self.script = Some(s); self }
pub fn with_redeemer(mut self, r: Redeemer) -> Self { self.redeemer = Some(r); self }
}
pub type Mint = BTreeMap<PolicyId, MintPolicy>;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Withdrawal {
pub amount: Lovelace,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script: Option<Script>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub redeemer: Option<Redeemer>,
}
impl Withdrawal {
pub fn new(amount: Lovelace) -> Self {
Self { amount, script: None, redeemer: None }
}
pub fn with_script(mut self, s: Script) -> Self { self.script = Some(s); self }
pub fn with_redeemer(mut self, r: Redeemer) -> Self { self.redeemer = Some(r); self }
}
pub type Withdrawals = BTreeMap<RewardAddress, Withdrawal>;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct CertEntry {
pub cert: Cert,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script: Option<Script>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub redeemer: Option<Redeemer>,
}
impl CertEntry {
pub fn new(cert: Cert) -> Self {
Self { cert, script: None, redeemer: None }
}
pub fn with_script(mut self, s: Script) -> Self { self.script = Some(s); self }
pub fn with_redeemer(mut self, r: Redeemer) -> Self { self.redeemer = Some(r); self }
}
impl From<Cert> for CertEntry {
fn from(cert: Cert) -> Self { Self::new(cert) }
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TxBody {
pub inputs: Vec<TxInput>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub reference_inputs: Vec<TxInput>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub collateral_inputs: Vec<TxInput>,
pub outputs: Vec<TxOutput>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub collateral_return: Option<TxOutput>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub total_collateral: Option<Lovelace>,
pub fee: Lovelace,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub ttl: Option<Slot>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub validity_start: Option<Slot>,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub certs: Vec<CertEntry>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub withdrawals: Withdrawals,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub mint: Mint,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub required_signers: Vec<KeyHash>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub network_id: Option<u8>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub auxiliary_data_hash: Option<Hash32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub script_data_hash: Option<Hash32>,
}
impl TxBody {
pub fn new() -> Self { Self::default() }
}