Skip to main content

canic_host/canic_metadata/
mod.rs

1//! Module: canic_metadata
2//!
3//! Responsibility: query and decode the maintained Canic metadata endpoint.
4//! Does not own: metadata production, ICP transport, or list rendering.
5//! Boundary: projects the canonical metadata DTO into its reported Canic version.
6
7#[cfg(test)]
8mod tests;
9
10use crate::icp::{IcpCli, IcpCommandError, IcpJsonResponseError, decode_json_response};
11use std::path::Path;
12
13use canic_core::{dto::metadata::CanicMetadataResponse, protocol};
14use thiserror::Error as ThisError;
15
16const ICP_JSON_OUTPUT: &str = "json";
17
18///
19/// CanicMetadataQueryError
20///
21
22#[derive(Debug, ThisError)]
23pub enum CanicMetadataQueryError {
24    #[error(transparent)]
25    Icp(#[from] IcpCommandError),
26
27    #[error(transparent)]
28    Response(#[from] IcpJsonResponseError),
29}
30
31/// Query `canic_metadata` and return the reported Canic framework version.
32pub fn query_canic_metadata_version(
33    icp: &IcpCli,
34    canister_id: &str,
35    candid_path: Option<&Path>,
36) -> Result<String, CanicMetadataQueryError> {
37    let output = icp.canister_query_output_with_candid(
38        canister_id,
39        protocol::CANIC_METADATA,
40        Some(ICP_JSON_OUTPUT),
41        candid_path,
42    )?;
43    parse_canic_metadata_version_response(&output).map_err(Into::into)
44}
45
46/// Parse a Canic framework version from `canic_metadata` command output.
47pub fn parse_canic_metadata_version_response(output: &str) -> Result<String, IcpJsonResponseError> {
48    let metadata = decode_json_response::<CanicMetadataResponse>(output)?;
49    Ok(metadata.canic_version)
50}