Skip to main content

ic_query/icrc/model/token_metadata/
mod.rs

1//! Canonical token metadata payload and rows shared by ledger sources and SNS/ICRC reports.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value as JsonValue;
5
6///
7/// IcrcTokenData
8///
9/// Source-layer token metadata returned by an ICRC ledger.
10///
11
12#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
13pub struct IcrcTokenData {
14    /// Native ledger token name.
15    pub token_name: String,
16    /// Native ledger token symbol.
17    pub token_symbol: String,
18    /// Number of decimal places in a base-unit amount.
19    pub decimals: u8,
20    /// Transfer fee as exact base-10 base-unit text.
21    pub transfer_fee: String,
22    /// Total supply as exact base-10 base-unit text.
23    pub total_supply: String,
24    /// Optional minting-account owner in principal text.
25    pub minting_account_owner: Option<String>,
26    /// Optional raw minting subaccount in lowercase hexadecimal.
27    pub minting_account_subaccount_hex: Option<String>,
28    /// Standards advertised by the ledger.
29    pub supported_standards: Vec<IcrcTokenStandardRow>,
30    /// Raw ledger metadata preserving native value kinds.
31    pub metadata: Vec<IcrcTokenMetadataRow>,
32}
33
34///
35/// IcrcTokenStandardRow
36///
37/// Serializable row for one ICRC standard supported by a ledger.
38///
39
40#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
41pub struct IcrcTokenStandardRow {
42    /// Standard name advertised by the ledger.
43    pub name: String,
44    /// Specification URL advertised by the ledger.
45    pub url: String,
46}
47
48///
49/// IcrcTokenMetadataRow
50///
51/// Serializable row for one raw ICRC ledger metadata entry.
52///
53
54#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
55pub struct IcrcTokenMetadataRow {
56    /// Native metadata key.
57    pub key: String,
58    /// Native Candid metadata variant.
59    pub value_type: IcrcMetadataValueKind,
60    /// Lossless decimal, text, or lowercase hexadecimal JSON string.
61    pub value: JsonValue,
62}
63
64///
65/// IcrcMetadataValueKind
66///
67/// Native ICRC-1 metadata value variant represented by a report row.
68///
69
70#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
71#[serde(rename_all = "snake_case")]
72pub enum IcrcMetadataValueKind {
73    /// An arbitrary-precision unsigned integer.
74    Nat,
75    /// An arbitrary-precision signed integer.
76    Int,
77    /// A Unicode text value.
78    Text,
79    /// An opaque byte sequence.
80    Blob,
81}
82
83impl IcrcMetadataValueKind {
84    /// Return the stable JSON and text label.
85    #[must_use]
86    pub const fn as_str(self) -> &'static str {
87        match self {
88            Self::Nat => "nat",
89            Self::Int => "int",
90            Self::Text => "text",
91            Self::Blob => "blob",
92        }
93    }
94}
95
96#[cfg(test)]
97mod tests;
98
99///
100/// IcrcIndexData
101///
102/// ICRC-106 discovery outcome shared by sources and serialized reports.
103///
104
105#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
106#[serde(rename_all = "snake_case")]
107pub enum IcrcIndexData {
108    /// Index principal returned by the ledger.
109    Found(String),
110    /// Index discovery is unavailable; source families own transport-error policy.
111    Unavailable(String),
112}
113
114impl IcrcIndexData {
115    /// Borrow the discovered index principal when discovery succeeded.
116    #[must_use]
117    pub fn canister_id(&self) -> Option<&str> {
118        match self {
119            Self::Found(principal) => Some(principal),
120            Self::Unavailable(_) => None,
121        }
122    }
123
124    /// Borrow the source's explanation when discovery is unavailable.
125    #[must_use]
126    pub fn unavailable_reason(&self) -> Option<&str> {
127        match self {
128            Self::Found(_) => None,
129            Self::Unavailable(reason) => Some(reason),
130        }
131    }
132}