canic_core/spec/icrc/icrc21/
mod.rs

1//! The [ICRC-21](https://github.com/dfinity/wg-identity-authentication/blob/main/topics/ICRC-21/icrc_21_consent_msg.md)
2//! Canister Call Consent Messages standard.
3
4///
5/// NOTE: We're using the code directly as importing the icrc-ledger-types is not
6/// currently a good idea.  It's got a lot of bloated dependencies and an older version
7/// of ic-stable-structures
8///
9mod errors;
10
11pub use errors::*;
12
13use crate::spec::prelude::*;
14
15///
16/// ConsentResult
17/// added here so we can manage ? in error flow
18///
19
20pub type ConsentResult = Result<ConsentInfo, Icrc21Error>;
21
22///
23/// ConsentInfo
24///
25
26#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
27pub struct ConsentInfo {
28    pub consent_message: ConsentMessage,
29    pub metadata: ConsentMessageMetadata,
30}
31
32///
33/// ConsentMessage
34///
35
36#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
37pub enum ConsentMessage {
38    GenericDisplayMessage(String),
39    FieldsDisplayMessage(FieldsDisplay),
40}
41
42///
43/// ConsentMessageMetadata
44///
45
46#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
47pub struct ConsentMessageMetadata {
48    pub language: String,
49    pub utc_offset_minutes: Option<i16>,
50}
51
52///
53/// ConsentMessageRequest
54///
55
56#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
57pub struct ConsentMessageRequest {
58    pub method: String,
59    pub arg: Vec<u8>,
60    pub user_preferences: ConsentMessageSpec,
61}
62
63///
64/// ConsentMessageResponse
65/// Wrapper capturing the ok/error variants from an ICRC-21 consent request.
66///
67
68#[derive(CandidType, Deserialize)]
69pub enum ConsentMessageResponse {
70    Ok(ConsentInfo),
71    Err(Icrc21Error),
72}
73
74impl From<ConsentResult> for ConsentMessageResponse {
75    fn from(result: ConsentResult) -> Self {
76        match result {
77            Ok(info) => Self::Ok(info),
78            Err(err) => Self::Err(err),
79        }
80    }
81}
82
83impl From<Icrc21Error> for ConsentMessageResponse {
84    fn from(err: Icrc21Error) -> Self {
85        Self::Err(err)
86    }
87}
88
89///
90/// ConsentMessageSpec
91///
92
93#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
94pub struct ConsentMessageSpec {
95    pub metadata: ConsentMessageMetadata,
96    pub device_spec: Option<DisplayMessageType>,
97}
98
99///
100/// DisplayMessageType
101///
102
103#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
104pub enum DisplayMessageType {
105    GenericDisplay,
106    FieldsDisplay,
107}
108
109///
110/// FieldsDisplay
111///
112
113#[derive(CandidType, Clone, Debug, Default, Deserialize, Eq, PartialEq)]
114pub struct FieldsDisplay {
115    pub intent: String,
116    pub fields: Vec<(String, Value)>,
117}
118
119///
120/// Value
121///
122
123#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
124pub enum Value {
125    TokenAmount {
126        decimals: u8,
127        amount: u64,
128        symbol: String,
129    },
130    TimestampSeconds {
131        amount: u64,
132    },
133    DurationSeconds {
134        amount: u64,
135    },
136    Text {
137        content: String,
138    },
139}