feat(traverse): Add helper methods to Asset data (#195)
This commit is contained in:
parent
2f7bfc8551
commit
47a5c52a9b
3 changed files with 123 additions and 135 deletions
110
pallas-traverse/src/assets.rs
Normal file
110
pallas-traverse/src/assets.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use pallas_codec::utils::{Bytes, KeyValuePairs};
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{alonzo, babbage};
|
||||
|
||||
use crate::{Asset, MultiEraOutput};
|
||||
|
||||
fn iter_policy_assets<'b>(
|
||||
policy: &'b Hash<28>,
|
||||
assets: &'b KeyValuePairs<Bytes, u64>,
|
||||
) -> impl Iterator<Item = Asset> + 'b {
|
||||
assets
|
||||
.iter()
|
||||
.map(|(name, amount)| Asset::NativeAsset(*policy, Vec::<u8>::clone(name), *amount))
|
||||
}
|
||||
|
||||
fn collect_multiassets(multiassets: &alonzo::Multiasset<alonzo::Coin>) -> Vec<Asset> {
|
||||
multiassets
|
||||
.iter()
|
||||
.flat_map(|(p, a)| iter_policy_assets(p, a))
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
impl Asset {
|
||||
pub fn subject(&self) -> String {
|
||||
match self {
|
||||
Self::Ada(_) => String::from("ada"),
|
||||
Self::NativeAsset(p, n, _) => format!("{p}.{}", hex::encode(n)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ascii_name(&self) -> Option<String> {
|
||||
match self {
|
||||
Self::Ada(_) => None,
|
||||
Self::NativeAsset(_, n, _) => String::from_utf8(n.clone()).ok(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn policy_hex(&self) -> Option<String> {
|
||||
match self {
|
||||
Asset::Ada(_) => None,
|
||||
Asset::NativeAsset(p, _, _) => Some(p.to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
match self {
|
||||
MultiEraOutput::Byron(x) => x.amount,
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => match x.amount {
|
||||
babbage::Value::Coin(c) => c,
|
||||
babbage::Value::Multiasset(c, _) => c,
|
||||
},
|
||||
babbage::TransactionOutput::PostAlonzo(x) => match x.value {
|
||||
babbage::Value::Coin(c) => c,
|
||||
babbage::Value::Multiasset(c, _) => c,
|
||||
},
|
||||
},
|
||||
MultiEraOutput::AlonzoCompatible(x) => match x.amount {
|
||||
alonzo::Value::Coin(c) => c,
|
||||
alonzo::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 non_ada_assets(&self) -> Vec<Asset> {
|
||||
match self {
|
||||
MultiEraOutput::Byron(_) => vec![],
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => match &x.amount {
|
||||
babbage::Value::Coin(_) => vec![],
|
||||
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
||||
},
|
||||
babbage::TransactionOutput::PostAlonzo(x) => match &x.value {
|
||||
babbage::Value::Coin(_) => vec![],
|
||||
babbage::Value::Multiasset(_, x) => collect_multiassets(x),
|
||||
},
|
||||
},
|
||||
MultiEraOutput::AlonzoCompatible(x) => match &x.amount {
|
||||
alonzo::Value::Coin(_) => vec![],
|
||||
alonzo::Value::Multiasset(_, x) => collect_multiassets(x),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// List of all assets in the output
|
||||
///
|
||||
/// Returns a list of Asset structs where each one represent either ADA or a
|
||||
/// native asset present in the output of the tx.
|
||||
pub fn assets(&self) -> Vec<Asset> {
|
||||
[
|
||||
vec![Asset::Ada(self.lovelace_amount())],
|
||||
self.non_ada_assets(),
|
||||
]
|
||||
.concat()
|
||||
}
|
||||
}
|
||||
|
|
@ -7,12 +7,9 @@ use thiserror::Error;
|
|||
|
||||
use pallas_codec::utils::KeepRaw;
|
||||
use pallas_crypto::hash::Hash;
|
||||
use pallas_primitives::{
|
||||
alonzo,
|
||||
babbage::{self, AssetName, PolicyId},
|
||||
byron,
|
||||
};
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
|
||||
pub mod assets;
|
||||
pub mod block;
|
||||
pub mod cert;
|
||||
pub mod era;
|
||||
|
|
@ -137,24 +134,9 @@ pub enum MultiEraSigners<'b> {
|
|||
pub struct OutputRef(Hash<32>, u64);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Asset {
|
||||
pub subject: Subject,
|
||||
pub quantity: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Subject {
|
||||
Lovelace,
|
||||
NativeAsset(PolicyId, AssetName),
|
||||
}
|
||||
|
||||
impl ToString for Subject {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
Self::Lovelace => String::from("lovelace"),
|
||||
Self::NativeAsset(p, n) => format!("{p}.{n}"),
|
||||
}
|
||||
}
|
||||
pub enum Asset {
|
||||
Ada(u64),
|
||||
NativeAsset(Hash<28>, Vec<u8>, u64),
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
|
|
|||
|
|
@ -2,13 +2,9 @@ use std::{borrow::Cow, ops::Deref};
|
|||
|
||||
use pallas_addresses::{Address, ByronAddress, Error as AddressError};
|
||||
use pallas_codec::minicbor;
|
||||
use pallas_primitives::{
|
||||
alonzo,
|
||||
babbage::{self, Coin, DatumOption, ScriptRef},
|
||||
byron,
|
||||
};
|
||||
use pallas_primitives::{alonzo, babbage, byron};
|
||||
|
||||
use crate::{Asset, Era, MultiEraOutput, Subject};
|
||||
use crate::{Era, MultiEraOutput};
|
||||
|
||||
impl<'b> MultiEraOutput<'b> {
|
||||
pub fn from_byron(output: &'b byron::TxOut) -> Self {
|
||||
|
|
@ -23,18 +19,20 @@ impl<'b> MultiEraOutput<'b> {
|
|||
Self::Babbage(Box::new(Cow::Borrowed(output)))
|
||||
}
|
||||
|
||||
pub fn datum(&self) -> Option<DatumOption> {
|
||||
pub fn datum(&self) -> Option<babbage::DatumOption> {
|
||||
match self {
|
||||
MultiEraOutput::AlonzoCompatible(x) => x.datum_hash.map(DatumOption::Hash),
|
||||
MultiEraOutput::AlonzoCompatible(x) => x.datum_hash.map(babbage::DatumOption::Hash),
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => x.datum_hash.map(DatumOption::Hash),
|
||||
babbage::TransactionOutput::Legacy(x) => {
|
||||
x.datum_hash.map(babbage::DatumOption::Hash)
|
||||
}
|
||||
babbage::TransactionOutput::PostAlonzo(x) => x.datum_option.clone(),
|
||||
},
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn script_ref(&self) -> Option<&ScriptRef> {
|
||||
pub fn script_ref(&self) -> Option<&babbage::ScriptRef> {
|
||||
match &self {
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(_) => None,
|
||||
|
|
@ -57,70 +55,6 @@ impl<'b> MultiEraOutput<'b> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn ada_amount(&self) -> u64 {
|
||||
match self {
|
||||
MultiEraOutput::Byron(x) => x.amount,
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => match x.amount {
|
||||
babbage::Value::Coin(c) => c,
|
||||
babbage::Value::Multiasset(c, _) => c,
|
||||
},
|
||||
babbage::TransactionOutput::PostAlonzo(x) => match x.value {
|
||||
babbage::Value::Coin(c) => c,
|
||||
babbage::Value::Multiasset(c, _) => c,
|
||||
},
|
||||
},
|
||||
MultiEraOutput::AlonzoCompatible(x) => match x.amount {
|
||||
alonzo::Value::Coin(c) => c,
|
||||
alonzo::Value::Multiasset(c, _) => c,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assets(&self) -> Vec<Asset> {
|
||||
let mut assets = Vec::new();
|
||||
|
||||
match self {
|
||||
MultiEraOutput::Byron(x) => {
|
||||
push_lovelace(&mut assets, x.amount);
|
||||
}
|
||||
MultiEraOutput::Babbage(x) => match x.deref().deref() {
|
||||
babbage::TransactionOutput::Legacy(x) => match &x.amount {
|
||||
babbage::Value::Coin(c) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
}
|
||||
babbage::Value::Multiasset(c, multi_asset) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
|
||||
push_native_asset(&mut assets, multi_asset);
|
||||
}
|
||||
},
|
||||
babbage::TransactionOutput::PostAlonzo(x) => match &x.value {
|
||||
babbage::Value::Coin(c) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
}
|
||||
babbage::Value::Multiasset(c, multi_asset) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
|
||||
push_native_asset(&mut assets, multi_asset);
|
||||
}
|
||||
},
|
||||
},
|
||||
MultiEraOutput::AlonzoCompatible(x) => match &x.amount {
|
||||
alonzo::Value::Coin(c) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
}
|
||||
alonzo::Value::Multiasset(c, multi_asset) => {
|
||||
push_lovelace(&mut assets, *c);
|
||||
|
||||
push_native_asset(&mut assets, multi_asset);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
assets
|
||||
}
|
||||
|
||||
pub fn as_babbage(&self) -> Option<&babbage::TransactionOutput> {
|
||||
match self {
|
||||
MultiEraOutput::AlonzoCompatible(_) => None,
|
||||
|
|
@ -174,41 +108,3 @@ impl<'b> MultiEraOutput<'b> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn push_lovelace(assets: &mut Vec<Asset>, quantity: u64) {
|
||||
assets.push(Asset {
|
||||
subject: Subject::Lovelace,
|
||||
quantity,
|
||||
})
|
||||
}
|
||||
|
||||
fn push_native_asset(assets: &mut Vec<Asset>, multi_asset: &alonzo::Multiasset<Coin>) {
|
||||
for (policy_id, names) in multi_asset.iter() {
|
||||
for (asset_name, quantity) in names.iter() {
|
||||
assets.push(Asset {
|
||||
subject: Subject::NativeAsset(*policy_id, asset_name.clone()),
|
||||
quantity: *quantity,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::MultiEraBlock;
|
||||
|
||||
#[test]
|
||||
fn traverse_block_with_varied_outputs() {
|
||||
let str = include_str!("../../test_data/alonzo24.block");
|
||||
let bytes = hex::decode(str).unwrap();
|
||||
let block = MultiEraBlock::decode(&bytes).unwrap();
|
||||
|
||||
for tx in block.txs() {
|
||||
for output in tx.outputs() {
|
||||
assert_ne!(output.assets()[0].quantity, 0);
|
||||
assert_ne!(output.ada_amount(), 0);
|
||||
assert!(matches!(output.address(), Ok(_)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue