Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
03154a5
feat(icrc-ledger-types): add MetadataKey type
mducroux Jan 5, 2026
08378c6
refactor: replace hardcoded metadata keys with const
mducroux Jan 5, 2026
c3edc99
refactor: icrc1_metadata returns MetadataKey instead of String
mducroux Jan 5, 2026
db89279
Automatically fixing code for linting and formatting issues
Jan 5, 2026
2d82842
fix build
mducroux Jan 5, 2026
cb406ef
add ICRC-106 key
mducroux Jan 5, 2026
7a78d5b
Merge branch 'mducroux/DEFI-1010-add-metadata-keys-icrc-ledger-types'…
mducroux Jan 5, 2026
e82af09
use explicit MetadataKey in hashmaps
mducroux Jan 5, 2026
a04776e
fix build
mducroux Jan 7, 2026
314af8b
Automatically fixing code for linting and formatting issues
Jan 7, 2026
6bb1d01
fix build
mducroux Jan 7, 2026
eda1eec
Update mod.rs
mducroux Jan 7, 2026
78ce22f
fix build
mducroux Jan 7, 2026
b3ba885
fix build
mducroux Jan 7, 2026
70d47d3
Automatically fixing code for linting and formatting issues
Jan 7, 2026
1d3c0b2
clippy
mducroux Jan 7, 2026
d552e5c
remove unused imports
mducroux Jan 7, 2026
b93e6ea
Merge branch 'master' into mducroux/DEFI-1010-add-metadata-keys-icrc-…
mducroux Jan 8, 2026
26261b0
improve doc
mducroux Jan 8, 2026
0b7dfe5
use type-state pattern to store checked/unchecked metadata keys
mducroux Jan 8, 2026
fbfe50e
revert: remove MetadataKey<Unchecked> and use string in init and upgr…
mducroux Jan 8, 2026
02334de
Automatically fixing code for linting and formatting issues
Jan 8, 2026
4b391f0
use candid encode in tests
mducroux Jan 8, 2026
18a7317
revert changes to legacy UpgradeArgs/InitArgs
mducroux Jan 9, 2026
1fb91e8
fix build
mducroux Jan 9, 2026
238a135
add setting metadata key tests during init/upgrade icrc1 ledger
mducroux Jan 9, 2026
4ce4c5b
Automatically fixing code for linting and formatting issues
Jan 9, 2026
f3d9799
Update lib.rs
mducroux Jan 9, 2026
3c22c9c
Automatically fixing code for linting and formatting issues
Jan 9, 2026
e1d5fe7
make entry err instead of panic
mducroux Jan 9, 2026
3b98373
Automatically fixing code for linting and formatting issues
Jan 9, 2026
b37f351
make key and namespace return an Option
mducroux Jan 9, 2026
03e86a0
Update Cargo.toml
mducroux Jan 13, 2026
3415b80
Update metadata_key.rs
mducroux Jan 13, 2026
3239802
remove unused dep
mducroux Jan 21, 2026
4461bf7
Automatically updated Cargo*.lock
Jan 21, 2026
2d5f324
remove reference to ISO-4217
mducroux Jan 21, 2026
771238f
inline CONST metadata values
mducroux Jan 21, 2026
af7d83e
Automatically fixing code for linting and formatting issues
Jan 21, 2026
b837851
add logs when accepting invalid metadata key during upgrades
mducroux Jan 21, 2026
0e8a0c9
Automatically fixing code for linting and formatting issues
Jan 21, 2026
10284c7
Update lib.rs
mducroux Jan 21, 2026
59bffda
Automatically fixing code for linting and formatting issues
Jan 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions packages/icrc-ledger-agent/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use icrc_ledger_types::icrc3::archive::{ArchivedRange, QueryBlockArchiveFn};
use icrc_ledger_types::icrc3::blocks::ICRC3DataCertificate;
use icrc_ledger_types::icrc3::blocks::{GetBlocksRequest, GetBlocksResponse};
use icrc_ledger_types::{
icrc::generic_metadata_value::MetadataValue as Value, icrc3::blocks::BlockRange,
icrc::generic_metadata_value::MetadataValue as Value, icrc::metadata_key::MetadataKey,
icrc3::blocks::BlockRange,
};

#[derive(Debug)]
Expand Down Expand Up @@ -126,15 +127,18 @@ impl Icrc1Agent {
}

/// Returns the list of metadata entries for this ledger
pub async fn metadata(&self, mode: CallMode) -> Result<Vec<(String, Value)>, Icrc1AgentError> {
pub async fn metadata(
&self,
mode: CallMode,
) -> Result<Vec<(MetadataKey, Value)>, Icrc1AgentError> {
Ok(match mode {
CallMode::Query => Decode!(
&self.query("icrc1_metadata", &Encode!()?).await?,
Vec<(String, Value)>
Vec<(MetadataKey, Value)>
)?,
CallMode::Update => Decode!(
&self.update("icrc1_metadata", &Encode!()?).await?,
Vec<(String, Value)>
Vec<(MetadataKey, Value)>
)?,
})
}
Expand Down
3 changes: 2 additions & 1 deletion packages/icrc-ledger-client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use candid::Principal;
use candid::types::number::Nat;
use candid::utils::{ArgumentDecoder, ArgumentEncoder};
use icrc_ledger_types::icrc::generic_metadata_value::MetadataValue as Value;
use icrc_ledger_types::icrc::metadata_key::MetadataKey;
use icrc_ledger_types::icrc1::account::Account;
use icrc_ledger_types::icrc1::transfer::{BlockIndex, TransferArg, TransferError};
use icrc_ledger_types::icrc2::approve::{ApproveArgs, ApproveError};
Expand Down Expand Up @@ -55,7 +56,7 @@ impl<R: Runtime> ICRC1Client<R> {
.map(untuple)
}

pub async fn metadata(&self) -> Result<Vec<(String, Value)>, (i32, String)> {
pub async fn metadata(&self) -> Result<Vec<(MetadataKey, Value)>, (i32, String)> {
self.runtime
.call(self.ledger_canister_id, "icrc1_metadata", ())
.await
Expand Down
37 changes: 34 additions & 3 deletions packages/icrc-ledger-types/src/icrc/generic_metadata_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use candid::{CandidType, Deserialize, Int, Nat};
use serde::Serialize;
use serde_bytes::ByteBuf;

pub use crate::icrc::metadata_key::{MetadataKey, MetadataKeyError};

/// Variant type for the `icrc1_metadata` endpoint values. The corresponding metadata keys are
/// arbitrary Unicode strings and must follow the pattern `<namespace>:<key>`, where `<namespace>`
/// is a string not containing colons. The namespace `icrc1` is reserved for keys defined in the
Expand All @@ -17,9 +19,20 @@ pub enum MetadataValue {
}

impl MetadataValue {
/// Create a `(String, MetadataValue)` tuple for use in metadata maps.
pub fn entry(key: impl ToString, val: impl Into<MetadataValue>) -> (String, Self) {
(key.to_string(), val.into())
/// Create a `(MetadataKey, MetadataValue)` tuple for use in metadata maps.
///
/// The key must be a valid metadata key in the format `<namespace>:<key>`.
/// This is typically used with the predefined constants like `MetadataKey::ICRC1_NAME`.
///
/// # Errors
///
/// Returns an error if the key is not a valid metadata key format.
pub fn entry(
key: &str,
val: impl Into<MetadataValue>,
) -> Result<(MetadataKey, Self), MetadataKeyError> {
let metadata_key = MetadataKey::parse(key)?;
Ok((metadata_key, val.into()))
}
}

Expand Down Expand Up @@ -76,3 +89,21 @@ impl<'a> From<&'a [u8]> for MetadataValue {
MetadataValue::Blob(ByteBuf::from(bytes.to_vec()))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_metadata_value_entry() {
let entry = MetadataValue::entry(MetadataKey::ICRC1_NAME, "My Token").unwrap();
assert_eq!(entry.0.as_str(), "icrc1:name");
assert_eq!(entry.1, MetadataValue::Text("My Token".to_string()));
}

#[test]
fn test_metadata_value_entry_invalid_key() {
let result = MetadataValue::entry("invalid_no_colon", "value");
assert!(result.is_err());
}
}
Loading
Loading