diff --git a/pallas-traverse/src/lib.rs b/pallas-traverse/src/lib.rs index e18054b..7a9c3ca 100644 --- a/pallas-traverse/src/lib.rs +++ b/pallas-traverse/src/lib.rs @@ -31,6 +31,7 @@ pub mod size; pub mod time; pub mod tx; pub mod update; +pub mod value; pub mod withdrawals; pub mod witnesses; @@ -89,6 +90,14 @@ pub enum MultiEraTx<'b> { Conway(Box>>), } +#[derive(Debug, Clone)] +#[non_exhaustive] +pub enum MultiEraValue<'b> { + Byron(u64), + AlonzoCompatible(Cow<'b, alonzo::Value>), + Conway(Cow<'b, conway::Value>), +} + #[derive(Debug, Clone, PartialEq, Eq)] #[non_exhaustive] pub enum MultiEraOutput<'b> { diff --git a/pallas-traverse/src/output.rs b/pallas-traverse/src/output.rs index 70d4ed5..9202188 100644 --- a/pallas-traverse/src/output.rs +++ b/pallas-traverse/src/output.rs @@ -4,7 +4,7 @@ use pallas_addresses::{Address, ByronAddress, Error as AddressError}; use pallas_codec::minicbor; use pallas_primitives::{alonzo, babbage, byron, conway}; -use crate::{Era, MultiEraOutput, MultiEraPolicyAssets}; +use crate::{Era, MultiEraOutput, MultiEraPolicyAssets, MultiEraValue}; impl<'b> MultiEraOutput<'b> { pub fn from_byron(output: &'b byron::TxOut) -> Self { @@ -23,7 +23,7 @@ impl<'b> MultiEraOutput<'b> { Self::Conway(Box::new(Cow::Borrowed(output))) } - pub fn datum(&self) -> Option { + pub fn datum(&self) -> Option { match self { MultiEraOutput::AlonzoCompatible(x, _) => { x.datum_hash.map(babbage::MintedDatumOption::Hash) @@ -160,46 +160,37 @@ impl<'b> MultiEraOutput<'b> { } } - /// The amount of ADA asset expressed in Lovelace unit - /// - /// The value returned provides the amount of the ADA in a particular - /// output. The value is expressed in 'lovelace' (1 ADA = 1,000,000 - /// lovelace). - pub fn lovelace_amount(&self) -> u64 { + pub fn value(&self) -> MultiEraValue<'_> { match self { - MultiEraOutput::AlonzoCompatible(x, _) => match x.amount { - alonzo::Value::Coin(c) => c, - alonzo::Value::Multiasset(c, _) => c, - }, + MultiEraOutput::Byron(x) => MultiEraValue::Byron(x.amount), + MultiEraOutput::AlonzoCompatible(x, _) => { + MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount)) + } MultiEraOutput::Babbage(x) => match x.deref().deref() { - babbage::MintedTransactionOutput::Legacy(x) => match x.amount { - babbage::Value::Coin(c) => c, - babbage::Value::Multiasset(c, _) => c, - }, - babbage::MintedTransactionOutput::PostAlonzo(x) => match x.value { - babbage::Value::Coin(c) => c, - babbage::Value::Multiasset(c, _) => c, - }, + babbage::MintedTransactionOutput::Legacy(x) => { + MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount)) + } + babbage::MintedTransactionOutput::PostAlonzo(x) => { + MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.value)) + } }, - MultiEraOutput::Byron(x) => x.amount, MultiEraOutput::Conway(x) => match x.deref().deref() { - conway::MintedTransactionOutput::Legacy(x) => match x.amount { - babbage::Value::Coin(c) => c, - babbage::Value::Multiasset(c, _) => c, - }, - conway::MintedTransactionOutput::PostAlonzo(x) => match x.value { - conway::Value::Coin(c) => c, - conway::Value::Multiasset(c, _) => c, - }, + conway::MintedTransactionOutput::Legacy(x) => { + MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount)) + } + conway::MintedTransactionOutput::PostAlonzo(x) => { + MultiEraValue::Conway(Cow::Borrowed(&x.value)) + } }, } } - /// List of native assets in the output - /// - /// Returns a list of Asset structs where each one represent a native asset - /// present in the output of the tx. ADA assets are not included in this - /// list. + #[deprecated(note = "Use `value().coin()` instead")] + pub fn lovelace_amount(&self) -> u64 { + self.value().coin() + } + + #[deprecated(note = "Use `value().assets()` instead")] pub fn non_ada_assets(&self) -> Vec { match self { MultiEraOutput::AlonzoCompatible(x, _) => match &x.amount { diff --git a/pallas-traverse/src/value.rs b/pallas-traverse/src/value.rs new file mode 100644 index 0000000..7c0342c --- /dev/null +++ b/pallas-traverse/src/value.rs @@ -0,0 +1,73 @@ +use std::ops::Deref; + +use pallas_primitives::{alonzo, conway}; + +use crate::{MultiEraPolicyAssets, MultiEraValue}; + +impl MultiEraValue<'_> { + pub fn into_alonzo(&self) -> alonzo::Value { + match self { + Self::Byron(x) => alonzo::Value::Coin(*x), + Self::AlonzoCompatible(x) => x.deref().clone(), + Self::Conway(x) => match x.deref() { + conway::Value::Coin(x) => alonzo::Value::Coin(*x), + conway::Value::Multiasset(x, assets) => { + let coin = *x; + let assets = assets + .iter() + .map(|(k, v)| { + let v = v.iter().map(|(k, v)| (k.clone(), v.into())).collect(); + (*k, v) + }) + .collect(); + + alonzo::Value::Multiasset(coin, assets) + } + }, + } + } + + /// The amount of ADA asset expressed in Lovelace unit + /// + /// The value returned provides the amount of the ADA in a particular + /// output. The value is expressed in 'lovelace' (1 ADA = 1,000,000 + /// lovelace). + pub fn coin(&self) -> u64 { + match self { + Self::Byron(x) => *x, + Self::AlonzoCompatible(x) => match x.deref() { + alonzo::Value::Coin(c) => *c, + alonzo::Value::Multiasset(c, _) => *c, + }, + Self::Conway(x) => match x.deref() { + conway::Value::Coin(c) => *c, + conway::Value::Multiasset(c, _) => *c, + }, + } + } + + /// List of native assets in the output + /// + /// Returns a list of Asset structs where each one represent a native asset + /// present in the output of the tx. ADA assets are not included in this + /// list. + pub fn assets(&self) -> Vec> { + match self { + Self::Byron(_) => vec![], + Self::AlonzoCompatible(x) => match x.deref() { + alonzo::Value::Coin(_) => vec![], + alonzo::Value::Multiasset(_, x) => x + .iter() + .map(|(k, v)| MultiEraPolicyAssets::AlonzoCompatibleOutput(k, v)) + .collect(), + }, + Self::Conway(x) => match x.deref() { + conway::Value::Coin(_) => vec![], + conway::Value::Multiasset(_, x) => x + .iter() + .map(|(k, v)| MultiEraPolicyAssets::ConwayOutput(k, v)) + .collect(), + }, + } + } +} diff --git a/pallas-utxorpc/src/lib.rs b/pallas-utxorpc/src/lib.rs index fe973b4..995ea85 100644 --- a/pallas-utxorpc/src/lib.rs +++ b/pallas-utxorpc/src/lib.rs @@ -147,12 +147,13 @@ impl Mapper { pub fn map_tx_output(&self, x: &trv::MultiEraOutput) -> u5c::TxOutput { u5c::TxOutput { address: x.address().map(|a| a.to_vec()).unwrap_or_default().into(), - coin: x.lovelace_amount(), + coin: x.value().coin(), // TODO: this is wrong, we're crating a new item for each asset even if they share // the same policy id. We need to adjust Pallas' interface to make this mapping more // ergonomic. assets: x - .non_ada_assets() + .value() + .assets() .iter() .map(|x| self.map_policy_assets(x)) .collect(),