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 { wrapper.value.into() }
62}
63
64impl TryFrom<generated::plt::TokenEvent> for TokenEvent {
65    type Error = tonic::Status;
66
67    fn try_from(token_event: generated::plt::TokenEvent) -> Result<Self, Self::Error> {
68        Ok(Self {
69            token_id: token_event.token_id.require()?.try_into()?,
70            event:    token_event.event.require()?.try_into()?,
71        })
72    }
73}
74
75impl TryFrom<generated::plt::token_event::Event> for TokenEventDetails {
76    type Error = tonic::Status;
77
78    fn try_from(event: generated::plt::token_event::Event) -> Result<Self, Self::Error> {
79        use generated::plt::token_event::Event as GenEvent;
80        let out = match event {
81            GenEvent::ModuleEvent(token_module_event) => {
82                TokenEventDetails::Module(token_module_event.try_into()?)
83            }
84            GenEvent::TransferEvent(token_transfer_event) => {
85                TokenEventDetails::Transfer(token_transfer_event.try_into()?)
86            }
87            GenEvent::MintEvent(token_supply_update_event) => {
88                TokenEventDetails::Mint(token_supply_update_event.try_into()?)
89            }
90            GenEvent::BurnEvent(token_supply_update_event) => {
91                TokenEventDetails::Burn(token_supply_update_event.try_into()?)
92            }
93        };
94        Ok(out)
95    }
96}
97
98impl TryFrom<generated::plt::TokenModuleEvent> for TokenModuleEvent {
99    type Error = tonic::Status;
100
101    fn try_from(event: generated::plt::TokenModuleEvent) -> Result<Self, Self::Error> {
102        Ok(Self {
103            event_type: protocol_level_tokens::TokenModuleCborTypeDiscriminator::try_from(
104                event.r#type,
105            )
106            .map_err(|err| tonic::Status::internal(err.to_string()))?,
107            details:    event.details.require()?.into(),
108        })
109    }
110}
111
112impl TryFrom<generated::plt::TokenTransferEvent> for TokenTransferEvent {
113    type Error = tonic::Status;
114
115    fn try_from(event: generated::plt::TokenTransferEvent) -> Result<Self, Self::Error> {
116        Ok(Self {
117            from:   event.from.require()?.try_into()?,
118            to:     event.to.require()?.try_into()?,
119            amount: event.amount.require()?.try_into()?,
120            memo:   event
121                .memo
122                .map(concordium_base::transactions::Memo::try_from)
123                .transpose()?,
124        })
125    }
126}
127
128impl TryFrom<generated::plt::TokenSupplyUpdateEvent> for TokenSupplyUpdateEvent {
129    type Error = tonic::Status;
130
131    fn try_from(event: generated::plt::TokenSupplyUpdateEvent) -> Result<Self, Self::Error> {
132        Ok(Self {
133            target: event.target.require()?.try_into()?,
134            amount: event.amount.require()?.try_into()?,
135        })
136    }
137}
138
139impl TryFrom<generated::plt::TokenHolder> for TokenHolder {
140    type Error = tonic::Status;
141
142    fn try_from(holder: generated::plt::TokenHolder) -> Result<Self, Self::Error> {
143        use generated::plt::token_holder::Address as HolderAddress;
144        match holder.address.require()? {
145            HolderAddress::Account(account_address) => Ok(TokenHolder::Account {
146                address: account_address.try_into()?,
147            }),
148        }
149    }
150}
151
152impl TryFrom<generated::plt::TokenModuleRejectReason> for TokenModuleRejectReason {
153    type Error = tonic::Status;
154
155    fn try_from(value: generated::plt::TokenModuleRejectReason) -> Result<Self, Self::Error> {
156        Ok(Self {
157            token_id:    value.token_id.require()?.try_into()?,
158            reason_type: protocol_level_tokens::TokenModuleCborTypeDiscriminator::try_from(
159                value.r#type,
160            )
161            .map_err(|err| tonic::Status::internal(err.to_string()))?,
162            details:     value.details.map(|d| d.into()),
163        })
164    }
165}