feat(traverse): introduce MultiEraValue (#516)

This commit is contained in:
Santiago Carmuega 2024-10-01 09:46:58 -03:00 committed by GitHub
parent 80d121d13a
commit de88df1986
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 110 additions and 36 deletions

View file

@ -31,6 +31,7 @@ pub mod size;
pub mod time; pub mod time;
pub mod tx; pub mod tx;
pub mod update; pub mod update;
pub mod value;
pub mod withdrawals; pub mod withdrawals;
pub mod witnesses; pub mod witnesses;
@ -89,6 +90,14 @@ pub enum MultiEraTx<'b> {
Conway(Box<Cow<'b, conway::MintedTx<'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)] #[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
pub enum MultiEraOutput<'b> { pub enum MultiEraOutput<'b> {

View file

@ -4,7 +4,7 @@ use pallas_addresses::{Address, ByronAddress, Error as AddressError};
use pallas_codec::minicbor; use pallas_codec::minicbor;
use pallas_primitives::{alonzo, babbage, byron, conway}; use pallas_primitives::{alonzo, babbage, byron, conway};
use crate::{Era, MultiEraOutput, MultiEraPolicyAssets}; use crate::{Era, MultiEraOutput, MultiEraPolicyAssets, MultiEraValue};
impl<'b> MultiEraOutput<'b> { impl<'b> MultiEraOutput<'b> {
pub fn from_byron(output: &'b byron::TxOut) -> Self { pub fn from_byron(output: &'b byron::TxOut) -> Self {
@ -23,7 +23,7 @@ impl<'b> MultiEraOutput<'b> {
Self::Conway(Box::new(Cow::Borrowed(output))) Self::Conway(Box::new(Cow::Borrowed(output)))
} }
pub fn datum(&self) -> Option<babbage::MintedDatumOption> { pub fn datum(&self) -> Option<conway::MintedDatumOption> {
match self { match self {
MultiEraOutput::AlonzoCompatible(x, _) => { MultiEraOutput::AlonzoCompatible(x, _) => {
x.datum_hash.map(babbage::MintedDatumOption::Hash) x.datum_hash.map(babbage::MintedDatumOption::Hash)
@ -160,46 +160,37 @@ impl<'b> MultiEraOutput<'b> {
} }
} }
/// The amount of ADA asset expressed in Lovelace unit pub fn value(&self) -> MultiEraValue<'_> {
///
/// 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 {
match self { match self {
MultiEraOutput::AlonzoCompatible(x, _) => match x.amount { MultiEraOutput::Byron(x) => MultiEraValue::Byron(x.amount),
alonzo::Value::Coin(c) => c, MultiEraOutput::AlonzoCompatible(x, _) => {
alonzo::Value::Multiasset(c, _) => c, MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount))
}, }
MultiEraOutput::Babbage(x) => match x.deref().deref() { MultiEraOutput::Babbage(x) => match x.deref().deref() {
babbage::MintedTransactionOutput::Legacy(x) => match x.amount { babbage::MintedTransactionOutput::Legacy(x) => {
babbage::Value::Coin(c) => c, MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount))
babbage::Value::Multiasset(c, _) => c, }
}, babbage::MintedTransactionOutput::PostAlonzo(x) => {
babbage::MintedTransactionOutput::PostAlonzo(x) => match x.value { MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.value))
babbage::Value::Coin(c) => c, }
babbage::Value::Multiasset(c, _) => c,
},
}, },
MultiEraOutput::Byron(x) => x.amount,
MultiEraOutput::Conway(x) => match x.deref().deref() { MultiEraOutput::Conway(x) => match x.deref().deref() {
conway::MintedTransactionOutput::Legacy(x) => match x.amount { conway::MintedTransactionOutput::Legacy(x) => {
babbage::Value::Coin(c) => c, MultiEraValue::AlonzoCompatible(Cow::Borrowed(&x.amount))
babbage::Value::Multiasset(c, _) => c, }
}, conway::MintedTransactionOutput::PostAlonzo(x) => {
conway::MintedTransactionOutput::PostAlonzo(x) => match x.value { MultiEraValue::Conway(Cow::Borrowed(&x.value))
conway::Value::Coin(c) => c, }
conway::Value::Multiasset(c, _) => c,
},
}, },
} }
} }
/// List of native assets in the output #[deprecated(note = "Use `value().coin()` instead")]
/// pub fn lovelace_amount(&self) -> u64 {
/// Returns a list of Asset structs where each one represent a native asset self.value().coin()
/// present in the output of the tx. ADA assets are not included in this }
/// list.
#[deprecated(note = "Use `value().assets()` instead")]
pub fn non_ada_assets(&self) -> Vec<MultiEraPolicyAssets> { pub fn non_ada_assets(&self) -> Vec<MultiEraPolicyAssets> {
match self { match self {
MultiEraOutput::AlonzoCompatible(x, _) => match &x.amount { MultiEraOutput::AlonzoCompatible(x, _) => match &x.amount {

View file

@ -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(),
},
}
}
}

View file

@ -147,12 +147,13 @@ impl<C: LedgerContext> Mapper<C> {
pub fn map_tx_output(&self, x: &trv::MultiEraOutput) -> u5c::TxOutput { pub fn map_tx_output(&self, x: &trv::MultiEraOutput) -> u5c::TxOutput {
u5c::TxOutput { u5c::TxOutput {
address: x.address().map(|a| a.to_vec()).unwrap_or_default().into(), 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 // 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 // the same policy id. We need to adjust Pallas' interface to make this mapping more
// ergonomic. // ergonomic.
assets: x assets: x
.non_ada_assets() .value()
.assets()
.iter() .iter()
.map(|x| self.map_policy_assets(x)) .map(|x| self.map_policy_assets(x))
.collect(), .collect(),