canic_host/cycle_balance/
mod.rs1use crate::{
2 icp::{IcpCli, IcpCommandError},
3 replica_query,
4 response_parse::parse_cycle_balance_response,
5};
6use canic_core::protocol;
7use std::{error::Error, fmt, path::Path};
8
9const ICP_JSON_OUTPUT: &str = "json";
10
11#[derive(Debug)]
16pub enum CycleBalanceQueryError {
17 Icp(IcpCommandError),
18 Parse { canister: String, output: String },
19}
20
21impl fmt::Display for CycleBalanceQueryError {
22 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
23 match self {
24 Self::Icp(err) => write!(formatter, "{err}"),
25 Self::Parse { canister, output } => write!(
26 formatter,
27 "could not parse {canister} {} response: {output}",
28 protocol::CANIC_CYCLE_BALANCE
29 ),
30 }
31 }
32}
33
34impl Error for CycleBalanceQueryError {
35 fn source(&self) -> Option<&(dyn Error + 'static)> {
36 match self {
37 Self::Icp(err) => Some(err),
38 Self::Parse { .. } => None,
39 }
40 }
41}
42
43impl From<IcpCommandError> for CycleBalanceQueryError {
44 fn from(err: IcpCommandError) -> Self {
45 Self::Icp(err)
46 }
47}
48
49pub fn query_cycle_balance(
51 icp: &IcpCli,
52 canister_id: &str,
53 network: &str,
54 icp_root: Option<&Path>,
55 candid_path: Option<&Path>,
56) -> Result<u128, CycleBalanceQueryError> {
57 if replica_query::should_use_local_replica_query(Some(network))
58 && let Some(root) = icp_root
59 && let Ok(cycles) =
60 replica_query::query_cycle_balance_from_root(Some(network), canister_id, root)
61 {
62 return Ok(cycles);
63 }
64
65 let output = icp.canister_query_output_with_candid(
66 canister_id,
67 protocol::CANIC_CYCLE_BALANCE,
68 Some(ICP_JSON_OUTPUT),
69 candid_path,
70 )?;
71 parse_cycle_balance_response(&output).ok_or_else(|| CycleBalanceQueryError::Parse {
72 canister: canister_id.to_string(),
73 output,
74 })
75}
76
77#[must_use]
79pub fn query_cycle_balance_optional(
80 icp: &IcpCli,
81 canister_id: &str,
82 network: &str,
83 icp_root: Option<&Path>,
84 candid_path: Option<&Path>,
85) -> Option<u128> {
86 query_cycle_balance(icp, canister_id, network, icp_root, candid_path).ok()
87}