Skip to main content

miden_objects/conversion/
asset.rs

1use alloc::format;
2
3use miden_protocol::asset::{Asset, AssetClass, AssetComposition, AssetId};
4
5use super::{MessageDecodeExt, required};
6use crate::{ConversionError, ConversionResultExt, proto};
7
8impl From<&AssetClass> for proto::asset::AssetClass {
9    fn from(asset_class: &AssetClass) -> Self {
10        Self {
11            suffix: Some(asset_class.suffix().into()),
12            prefix: Some(asset_class.prefix().into()),
13        }
14    }
15}
16
17impl From<AssetClass> for proto::asset::AssetClass {
18    fn from(asset_class: AssetClass) -> Self {
19        Self::from(&asset_class)
20    }
21}
22
23impl TryFrom<proto::asset::AssetClass> for AssetClass {
24    type Error = ConversionError;
25
26    fn try_from(message: proto::asset::AssetClass) -> Result<Self, Self::Error> {
27        let decoder = message.decoder();
28        let suffix = required!(decoder, message.suffix)?;
29        let prefix = required!(decoder, message.prefix)?;
30
31        Ok(Self::new(suffix, prefix))
32    }
33}
34
35fn decode_asset_composition(composition: i32) -> Result<AssetComposition, ConversionError> {
36    match proto::asset::AssetComposition::try_from(composition) {
37        Ok(proto::asset::AssetComposition::None) => Ok(AssetComposition::None),
38        Ok(proto::asset::AssetComposition::Fungible) => Ok(AssetComposition::Fungible),
39        Ok(proto::asset::AssetComposition::Custom) => Ok(AssetComposition::Custom),
40        Ok(proto::asset::AssetComposition::Unspecified) => {
41            Err(ConversionError::message("asset composition is unspecified"))
42        },
43        Err(error) => Err(ConversionError::with_source(
44            format!("unknown asset composition {composition}"),
45            error,
46        )),
47    }
48}
49
50fn decode_asset_version(version: i32) -> Result<(), ConversionError> {
51    match proto::asset::AssetVersion::try_from(version) {
52        Ok(proto::asset::AssetVersion::V1) => Ok(()),
53        Ok(proto::asset::AssetVersion::Unspecified) => {
54            Err(ConversionError::message("asset id version is unspecified"))
55        },
56        Err(error) => Err(ConversionError::with_source(
57            format!("unknown asset id version {version}"),
58            error,
59        )),
60    }
61}
62
63fn encode_asset_composition(composition: AssetComposition) -> i32 {
64    match composition {
65        AssetComposition::None => proto::asset::AssetComposition::None as i32,
66        AssetComposition::Fungible => proto::asset::AssetComposition::Fungible as i32,
67        AssetComposition::Custom => proto::asset::AssetComposition::Custom as i32,
68    }
69}
70
71impl From<&AssetId> for proto::asset::AssetId {
72    fn from(asset_id: &AssetId) -> Self {
73        Self {
74            version: proto::asset::AssetVersion::V1 as i32,
75            asset_class: Some(asset_id.asset_class().into()),
76            composition: encode_asset_composition(asset_id.composition()),
77            faucet_id: Some(asset_id.faucet_id().into()),
78        }
79    }
80}
81
82impl From<AssetId> for proto::asset::AssetId {
83    fn from(asset_id: AssetId) -> Self {
84        Self::from(&asset_id)
85    }
86}
87
88impl TryFrom<proto::asset::AssetId> for AssetId {
89    type Error = ConversionError;
90
91    fn try_from(message: proto::asset::AssetId) -> Result<Self, Self::Error> {
92        decode_asset_version(message.version).context("version")?;
93
94        let decoder = message.decoder();
95        let asset_class = required!(decoder, message.asset_class)?;
96        let composition = decode_asset_composition(message.composition).context("composition")?;
97        let faucet_id = required!(decoder, message.faucet_id)?;
98
99        Self::new(asset_class, faucet_id, composition).map_err(ConversionError::new)
100    }
101}
102
103impl From<&Asset> for proto::asset::Asset {
104    fn from(asset: &Asset) -> Self {
105        Self {
106            asset_id: Some(asset.id().into()),
107            value: Some(asset.to_value_word().into()),
108        }
109    }
110}
111
112impl From<Asset> for proto::asset::Asset {
113    fn from(asset: Asset) -> Self {
114        Self::from(&asset)
115    }
116}
117
118impl TryFrom<proto::asset::Asset> for Asset {
119    type Error = ConversionError;
120
121    fn try_from(message: proto::asset::Asset) -> Result<Self, Self::Error> {
122        let decoder = message.decoder();
123        let asset_id = required!(decoder, message.asset_id)?;
124        let value = required!(decoder, message.value)?;
125
126        Self::new(asset_id, value).map_err(ConversionError::new)
127    }
128}