Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(traverse): introduce MultiEraValue #516

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pallas-traverse/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -89,6 +90,14 @@ pub enum MultiEraTx<'b> {
Conway(Box<Cow<'b, conway::MintedTx<'b>>>),
}

#[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> {
Expand Down
59 changes: 25 additions & 34 deletions pallas-traverse/src/output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -23,7 +23,7 @@ impl<'b> MultiEraOutput<'b> {
Self::Conway(Box::new(Cow::Borrowed(output)))
}

pub fn datum(&self) -> Option<babbage::MintedDatumOption> {
pub fn datum(&self) -> Option<conway::MintedDatumOption> {
match self {
MultiEraOutput::AlonzoCompatible(x, _) => {
x.datum_hash.map(babbage::MintedDatumOption::Hash)
Expand Down Expand Up @@ -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<MultiEraPolicyAssets> {
match self {
MultiEraOutput::AlonzoCompatible(x, _) => match &x.amount {
Expand Down
73 changes: 73 additions & 0 deletions pallas-traverse/src/value.rs
Original file line number Diff line number Diff line change
@@ -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<MultiEraPolicyAssets<'_>> {
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(),
},
}
}
}
5 changes: 3 additions & 2 deletions pallas-utxorpc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,12 +147,13 @@ impl<C: LedgerContext> Mapper<C> {
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(),
Expand Down
Loading