concordium_rust_sdk/protocol_level_tokens/
mod.rs

1//! Types and functions for working with Protocol Level Tokens (PLT).
2
3use crate::v2::{generated, Require};
4use concordium_base::protocol_level_tokens;
5
6mod token_account_info;
7pub mod token_client;
8mod token_info;
9
10pub use protocol_level_tokens::*;
11pub use token_account_info::*;
12pub use token_info::*;
13
14// gRPC type conversions for the types which are define as part of
15// the `concordium-base` crate.
16
17impl TryFrom<generated::plt::TokenId> for TokenId {
18    type Error = tonic::Status;
19
20    fn try_from(token_id: generated::plt::TokenId) -> Result<Self, Self::Error> {
21        Self::try_from(token_id.value)
22            .map_err(|err| tonic::Status::internal(format!("Unexpected token identifier: {}", err)))
23    }
24}
25
26impl From<TokenId> for generated::plt::TokenId {
27    fn from(value: protocol_level_tokens::TokenId) -> Self {
28        Self {
29            value: value.into(),
30        }
31    }
32}
33
34impl TryFrom<generated::plt::TokenAmount> for TokenAmount {
35    type Error = tonic::Status;
36
37    fn try_from(value: generated::plt::TokenAmount) -> Result<Self, Self::Error> {
38        Ok(Self::from_raw(
39            value.value,
40            value
41                .decimals
42                .try_into()
43                .map_err(|_| tonic::Status::internal("Unexpected token decimals"))?,
44        ))
45    }
46}
47
48impl TryFrom<generated::plt::TokenModuleRef> for TokenModuleRef {
49    type Error = tonic::Status;
50
51    fn try_from(value: generated::plt::TokenModuleRef) -> Result<Self, Self::Error> {
52        let bytes = value
53            .value
54            .try_into()
55            .map_err(|_| tonic::Status::internal("Unexpected module reference format."))?;
56        Ok(Self::new(bytes))
57    }
58}
59
60impl From<generated::plt::CBor> for RawCbor {
61    fn from(wrapper: generated::plt::CBor) -> Self {
62        wrapper.value.into()
63    }
64}
65
66impl TryFrom<generated::plt::TokenEvent> for TokenEvent {
67    type Error = tonic::Status;
68
69    fn try_from(token_event: generated::plt::TokenEvent) -> Result<Self, Self::Error> {
70        Ok(Self {
71            token_id: token_event.token_id.require()?.try_into()?,
72            event: token_event.event.require()?.try_into()?,
73        })
74    }
75}
76
77impl TryFrom<generated::plt::token_event::Event> for TokenEventDetails {
78    type Error = tonic::Status;
79
80    fn try_from(event: generated::plt::token_event::Event) -> Result<Self, Self::Error> {
81        use generated::plt::token_event::Event as GenEvent;
82        let out = match event {
83            GenEvent::ModuleEvent(token_module_event) => {
84                TokenEventDetails::Module(token_module_event.try_into()?)
85            }
86            GenEvent::TransferEvent(token_transfer_event) => {
87                TokenEventDetails::Transfer(token_transfer_event.try_into()?)
88            }
89            GenEvent::MintEvent(token_supply_update_event) => {
90                TokenEventDetails::Mint(token_supply_update_event.try_into()?)
91            }
92            GenEvent::BurnEvent(token_supply_update_event) => {
93                TokenEventDetails::Burn(token_supply_update_event.try_into()?)
94            }
95        };
96        Ok(out)
97    }
98}
99
100impl TryFrom<generated::plt::TokenModuleEvent> for TokenModuleEvent {
101    type Error = tonic::Status;
102
103    fn try_from(event: generated::plt::TokenModuleEvent) -> Result<Self, Self::Error> {
104        Ok(Self {
105            event_type: protocol_level_tokens::TokenModuleCborTypeDiscriminator::try_from(
106                event.r#type,
107            )
108            .map_err(|err| tonic::Status::internal(err.to_string()))?,
109            details: event.details.require()?.into(),
110        })
111    }
112}
113
114impl TryFrom<generated::plt::TokenTransferEvent> for TokenTransferEvent {
115    type Error = tonic::Status;
116
117    fn try_from(event: generated::plt::TokenTransferEvent) -> Result<Self, Self::Error> {
118        Ok(Self {
119            from: event.from.require()?.try_into()?,
120            to: event.to.require()?.try_into()?,
121            amount: event.amount.require()?.try_into()?,
122            memo: event
123                .memo
124                .map(concordium_base::transactions::Memo::try_from)
125                .transpose()?,
126        })
127    }
128}
129
130impl TryFrom<generated::plt::TokenSupplyUpdateEvent> for TokenSupplyUpdateEvent {
131    type Error = tonic::Status;
132
133    fn try_from(event: generated::plt::TokenSupplyUpdateEvent) -> Result<Self, Self::Error> {
134        Ok(Self {
135            target: event.target.require()?.try_into()?,
136            amount: event.amount.require()?.try_into()?,
137        })
138    }
139}
140
141impl TryFrom<generated::plt::TokenHolder> for TokenHolder {
142    type Error = tonic::Status;
143
144    fn try_from(holder: generated::plt::TokenHolder) -> Result<Self, Self::Error> {
145        use generated::plt::token_holder::Address as HolderAddress;
146        match holder.address.require()? {
147            HolderAddress::Account(account_address) => Ok(TokenHolder::Account {
148                address: account_address.try_into()?,
149            }),
150        }
151    }
152}
153
154impl TryFrom<generated::plt::TokenModuleRejectReason> for TokenModuleRejectReason {
155    type Error = tonic::Status;
156
157    fn try_from(value: generated::plt::TokenModuleRejectReason) -> Result<Self, Self::Error> {
158        Ok(Self {
159            token_id: value.token_id.require()?.try_into()?,
160            reason_type: protocol_level_tokens::TokenModuleCborTypeDiscriminator::try_from(
161                value.r#type,
162            )
163            .map_err(|err| tonic::Status::internal(err.to_string()))?,
164            details: value.details.map(|d| d.into()),
165        })
166    }
167}