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 tx;
pub mod update;
pub mod value;
pub mod withdrawals;
pub mod witnesses;
@ -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> {

View file

@ -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<babbage::MintedDatumOption> {
pub fn datum(&self) -> Option<conway::MintedDatumOption> {
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<MultiEraPolicyAssets> {
match self {
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 {
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(),