ic_cdk/
api.rs

1//! System API bindings.
2//!
3//! This module provides Rust ergonomic bindings to the system APIs.
4//!
5//! Some APIs require more advanced handling and are organized into separate modules:
6//! * For the inter-canister calls API, see the [`call`](mod@crate::call) module.
7//! * For the stable memory management API, see the .
8//!   * The basic bindings are provided in this module including [`stable_size`], [`stable_grow`], [`stable_read`] and [`stable_write`].
9//!   * The [`stable`](crate::stable) module provides more advanced functionalities, e.g. support for `std::io` traits.
10//!
11//! APIs that are only available for `wasm32` are not included.
12//! As a result, system APIs with a numeric postfix (indicating the data bit width) are bound to names without the postfix.
13//! For example, `ic0::msg_cycles_available128` is bound to [`msg_cycles_available`], while `ic0::msg_cycles_available` has no binding.
14//!
15//! Functions that provide bindings for a single system API method share the same name as the system API.
16//! For example, `ic0::msg_reject_code` is bound to [`msg_reject_code`].
17//!
18//! Functions that wrap multiple system API methods are named using the common prefix of the wrapped methods.
19//! For example, [`msg_arg_data`] wraps both `ic0::msg_arg_data_size` and `ic0::msg_arg_data_copy`.
20
21use candid::Principal;
22use std::{convert::TryFrom, num::NonZeroU64};
23
24#[deprecated(
25    since = "0.18.0",
26    note = "The `api::call` module is deprecated. Individual items within this module have their own deprecation notices with specific migration guidance."
27)]
28pub mod call;
29#[deprecated(
30    since = "0.18.0",
31    note = "The `api::management_canister` module is deprecated. Please use the `management_canister` and `bitcoin_canister` modules at the crate root."
32)]
33pub mod management_canister;
34#[deprecated(
35    since = "0.18.0",
36    note = "The `api::stable` module has been moved to `stable` (crate root)."
37)]
38pub mod stable;
39
40/// Gets the message argument data.
41pub fn msg_arg_data() -> Vec<u8> {
42    let len = ic0::msg_arg_data_size();
43    let mut buf = vec![0u8; len];
44    ic0::msg_arg_data_copy(&mut buf, 0);
45    buf
46}
47
48/// Gets the identity of the caller, which may be a canister id or a user id.
49///
50/// During canister installation or upgrade, this is the id of the user or canister requesting the installation or upgrade.
51/// During a system task (heartbeat or global timer), this is the id of the management canister.
52pub fn msg_caller() -> Principal {
53    let len = ic0::msg_caller_size();
54    let mut buf = vec![0u8; len];
55    ic0::msg_caller_copy(&mut buf, 0);
56    // Trust that the system always returns a valid principal.
57    Principal::try_from(&buf).unwrap()
58}
59
60/// Returns the reject code, if the current function is invoked as a reject callback.
61pub fn msg_reject_code() -> u32 {
62    ic0::msg_reject_code()
63}
64
65/// Gets the reject message.
66///
67/// This function can only be called in the reject callback.
68///
69/// Traps if:
70/// - There is no reject message (i.e. if `reject_code` is 0).
71/// - The message is not valid UTF-8.
72pub fn msg_reject_msg() -> String {
73    let len = ic0::msg_reject_msg_size();
74    let mut buf = vec![0u8; len];
75    ic0::msg_reject_msg_copy(&mut buf, 0);
76    String::from_utf8(buf).expect("reject message is not valid UTF-8")
77}
78
79/// Gets the deadline, in nanoseconds since 1970-01-01, after which the caller might stop waiting for a response.
80///
81/// For calls to update methods with best-effort responses and their callbacks,
82/// the deadline is computed based on the time the call was made,
83/// and the `timeout_seconds` parameter provided by the caller.
84/// In such cases, the deadline value will be converted to `NonZeroU64` and wrapped in `Some`.
85/// To get the deadline value as a `u64`, call `get()` on the `NonZeroU64` value.
86///
87/// ```rust,no_run
88/// use ic_cdk::api::msg_deadline;
89/// if let Some(deadline) = msg_deadline() {
90///     let deadline_value : u64 = deadline.get();
91/// }
92/// ```
93///
94/// For other calls (ingress messages and all calls to query and composite query methods,
95/// including calls in replicated mode), a `None` is returned.
96/// Please note that the raw `msg_deadline` system API returns 0 in such cases.
97/// This function is a wrapper around the raw system API that provides more semantic information through the return type.
98pub fn msg_deadline() -> Option<NonZeroU64> {
99    let nano_seconds = ic0::msg_deadline();
100    match nano_seconds {
101        0 => None,
102        _ => Some(NonZeroU64::new(nano_seconds).unwrap()),
103    }
104}
105
106/// Replies to the sender with the data.
107pub fn msg_reply<T: AsRef<[u8]>>(data: T) {
108    let buf = data.as_ref();
109    if !buf.is_empty() {
110        ic0::msg_reply_data_append(buf);
111    }
112    ic0::msg_reply();
113}
114
115/// Rejects the call with a diagnostic message.
116pub fn msg_reject<T: AsRef<str>>(message: T) {
117    let message = message.as_ref();
118    ic0::msg_reject(message.as_bytes());
119}
120
121/// Gets the number of cycles transferred by the caller of the current call, still available in this message.
122pub fn msg_cycles_available() -> u128 {
123    ic0::msg_cycles_available128()
124}
125
126/// Gets the amount of cycles that came back with the response as a refund
127///
128/// This function can only be used in a callback handler (reply or reject).
129/// The refund has already been added to the canister balance automatically.
130pub fn msg_cycles_refunded() -> u128 {
131    ic0::msg_cycles_refunded128()
132}
133
134/// Moves cycles from the call to the canister balance.
135///
136/// The actual amount moved will be returned.
137pub fn msg_cycles_accept(max_amount: u128) -> u128 {
138    ic0::msg_cycles_accept128(max_amount)
139}
140
141/// Burns cycles from the canister.
142///
143/// Returns the amount of cycles that were actually burned.
144pub fn cycles_burn(amount: u128) -> u128 {
145    ic0::cycles_burn128(amount)
146}
147
148/// Gets canister's own identity.
149pub fn canister_self() -> Principal {
150    let len = ic0::canister_self_size();
151    let mut buf = vec![0u8; len];
152    ic0::canister_self_copy(&mut buf, 0);
153    // Trust that the system always returns a valid principal.
154    Principal::try_from(&buf).unwrap()
155}
156
157/// Gets the current cycle balance of the canister.
158pub fn canister_cycle_balance() -> u128 {
159    ic0::canister_cycle_balance128()
160}
161
162/// Gets the current amount of cycles that is available for spending in calls and execution.
163pub fn canister_liquid_cycle_balance() -> u128 {
164    ic0::canister_liquid_cycle_balance128()
165}
166
167/// Gets the status of the canister.
168///
169/// The status is one of the following:
170///.- 1: Running
171///.- 2: Stopping
172///.- 3: Stopped
173pub fn canister_status() -> CanisterStatusCode {
174    ic0::canister_status().into()
175}
176
177/// The status of a canister.
178///
179/// See [Canister status](https://internetcomputer.org/docs/current/references/ic-interface-spec/#system-api-canister-status).
180#[derive(Debug, PartialEq, Eq, Clone, Copy)]
181#[repr(u32)]
182pub enum CanisterStatusCode {
183    /// Running.
184    Running = 1,
185    /// Stopping.
186    Stopping = 2,
187    /// Stopped.
188    Stopped = 3,
189    /// A status code that is not recognized by this library.
190    Unrecognized(u32),
191}
192
193impl From<u32> for CanisterStatusCode {
194    fn from(value: u32) -> Self {
195        match value {
196            1 => Self::Running,
197            2 => Self::Stopping,
198            3 => Self::Stopped,
199            _ => Self::Unrecognized(value),
200        }
201    }
202}
203
204impl From<CanisterStatusCode> for u32 {
205    fn from(value: CanisterStatusCode) -> Self {
206        match value {
207            CanisterStatusCode::Running => 1,
208            CanisterStatusCode::Stopping => 2,
209            CanisterStatusCode::Stopped => 3,
210            CanisterStatusCode::Unrecognized(value) => value,
211        }
212    }
213}
214
215impl PartialEq<u32> for CanisterStatusCode {
216    fn eq(&self, other: &u32) -> bool {
217        let self_as_u32: u32 = (*self).into();
218        self_as_u32 == *other
219    }
220}
221
222/// Gets the canister version.
223///
224/// See [Canister version](https://internetcomputer.org/docs/current/references/ic-interface-spec/#system-api-canister-version).
225pub fn canister_version() -> u64 {
226    ic0::canister_version()
227}
228
229/// Gets the ID of the subnet on which the canister is running.
230pub fn subnet_self() -> Principal {
231    let len = ic0::subnet_self_size();
232    let mut buf = vec![0u8; len];
233    ic0::subnet_self_copy(&mut buf, 0);
234    // Trust that the system always returns a valid principal.
235    Principal::try_from(&buf).unwrap()
236}
237
238/// Gets the name of the method to be inspected.
239///
240/// This function is only available in the `canister_inspect_message` context.
241///
242/// Traps if the method name is not valid UTF-8.
243pub fn msg_method_name() -> String {
244    let len = ic0::msg_method_name_size();
245    let mut buf = vec![0u8; len];
246    ic0::msg_method_name_copy(&mut buf, 0);
247    String::from_utf8(buf).expect("msg_method_name is not valid UTF-8")
248}
249
250/// Accepts the message in `canister_inspect_message`.
251///
252/// This function is only available in the `canister_inspect_message` context.
253/// This function traps if invoked twice.
254pub fn accept_message() {
255    ic0::accept_message();
256}
257
258/// Gets the current size of the stable memory (in WebAssembly pages).
259///
260/// One WebAssembly page is 64KiB.
261pub fn stable_size() -> u64 {
262    ic0::stable64_size()
263}
264
265/// Attempts to grow the stable memory by `new_pages` many pages containing zeroes.
266///
267/// One WebAssembly page is 64KiB.
268///
269/// If successful, returns the previous size of the memory (in pages).
270/// Otherwise, returns `u64::MAX`.
271pub fn stable_grow(new_pages: u64) -> u64 {
272    ic0::stable64_grow(new_pages)
273}
274
275/// Writes data to the stable memory location specified by an offset.
276///
277/// # Warning
278/// This will panic if `offset + buf.len()` exceeds the current size of stable memory.
279/// Call [`stable_grow`] to request more stable memory if needed.
280pub fn stable_write(offset: u64, buf: &[u8]) {
281    ic0::stable64_write(buf, offset);
282}
283
284/// Reads data from the stable memory location specified by an offset.
285///
286/// # Warning
287/// This will panic if `offset + buf.len()` exceeds the current size of stable memory.
288pub fn stable_read(offset: u64, buf: &mut [u8]) {
289    ic0::stable64_read(buf, offset);
290}
291
292/// Gets the public key (a DER-encoded BLS key) of the root key of this instance of the Internet Computer Protocol.
293///
294/// # Note
295///
296/// This traps in non-replicated mode.
297pub fn root_key() -> Vec<u8> {
298    let len = ic0::root_key_size();
299    let mut buf = vec![0u8; len];
300    ic0::root_key_copy(&mut buf, 0);
301    buf
302}
303
304/// Sets the certified data of this canister.
305///
306/// Canisters can store up to 32 bytes of data that is certified by
307/// the system on a regular basis.  One can call [`data_certificate`]
308/// function from a query call to get a certificate authenticating the
309/// value set by calling this function.
310///
311/// This function can only be called from the following contexts:
312/// - `canister_init`, `canister_pre_upgrade` and `canister_post_upgrade`
313///   hooks.
314/// - `canister_update` calls.
315/// - reply or reject callbacks.
316///
317/// # Panics
318///
319/// - This function traps if `data.len() > 32`.
320/// - This function traps if it's called from an illegal context
321///   (e.g., from a query call).
322pub fn certified_data_set<T: AsRef<[u8]>>(data: T) {
323    let buf = data.as_ref();
324    ic0::certified_data_set(buf);
325}
326
327/// When called from a query call, returns the data certificate authenticating
328/// certified data set by this canister.
329///
330/// Returns `None` if called not from a query call.
331pub fn data_certificate() -> Option<Vec<u8>> {
332    if ic0::data_certificate_present() == 0 {
333        return None;
334    }
335    let n = ic0::data_certificate_size();
336    let mut buf = vec![0u8; n];
337    ic0::data_certificate_copy(&mut buf, 0);
338    Some(buf)
339}
340
341/// Gets current timestamp, in nanoseconds since the epoch (1970-01-01)
342pub fn time() -> u64 {
343    ic0::time()
344}
345
346/// Sets global timer.
347///
348/// The canister can set a global timer to make the system
349/// schedule a call to the exported `canister_global_timer`
350/// Wasm method after the specified time.
351/// The time must be provided as nanoseconds since 1970-01-01.
352///
353/// The function returns the previous value of the timer.
354/// If no timer is set before invoking the function, then the function returns zero.
355///
356/// Passing zero as an argument to the function deactivates the timer and thus
357/// prevents the system from scheduling calls to the canister's `canister_global_timer` Wasm method.
358pub fn global_timer_set(timestamp: u64) -> u64 {
359    ic0::global_timer_set(timestamp)
360}
361
362/// Gets the value of specified performance counter.
363///
364/// See [`PerformanceCounterType`] for available counter types.
365#[inline]
366pub fn performance_counter(counter_type: impl Into<PerformanceCounterType>) -> u64 {
367    let counter_type: u32 = counter_type.into().into();
368    ic0::performance_counter(counter_type)
369}
370
371/// The type of performance counter.
372#[derive(Debug, PartialEq, Eq, Clone, Copy)]
373#[repr(u32)]
374pub enum PerformanceCounterType {
375    /// Current execution instruction counter.
376    ///
377    /// The number of WebAssembly instructions the canister has executed
378    /// since the beginning of the current Message execution.
379    InstructionCounter,
380    /// Call context instruction counter
381    ///
382    /// The number of WebAssembly instructions the canister has executed
383    /// within the call context of the current Message execution
384    /// since Call context creation.
385    /// The counter monotonically increases across all message executions
386    /// in the call context until the corresponding call context is removed.
387    CallContextInstructionCounter,
388    /// A performance counter type that is not recognized by this library.
389    Unrecognized(u32),
390}
391
392impl From<u32> for PerformanceCounterType {
393    fn from(value: u32) -> Self {
394        match value {
395            0 => Self::InstructionCounter,
396            1 => Self::CallContextInstructionCounter,
397            _ => Self::Unrecognized(value),
398        }
399    }
400}
401
402impl From<PerformanceCounterType> for u32 {
403    fn from(value: PerformanceCounterType) -> Self {
404        match value {
405            PerformanceCounterType::InstructionCounter => 0,
406            PerformanceCounterType::CallContextInstructionCounter => 1,
407            PerformanceCounterType::Unrecognized(value) => value,
408        }
409    }
410}
411
412impl PartialEq<u32> for PerformanceCounterType {
413    fn eq(&self, other: &u32) -> bool {
414        let self_as_u32: u32 = (*self).into();
415        self_as_u32 == *other
416    }
417}
418
419/// Returns the number of instructions that the canister executed since the last [entry
420/// point](https://internetcomputer.org/docs/current/references/ic-interface-spec/#entry-points).
421#[inline]
422pub fn instruction_counter() -> u64 {
423    performance_counter(0)
424}
425
426/// Returns the number of WebAssembly instructions the canister has executed
427/// within the call context of the current Message execution since
428/// Call context creation.
429///
430/// The counter monotonically increases across all message executions
431/// in the call context until the corresponding call context is removed.
432#[inline]
433pub fn call_context_instruction_counter() -> u64 {
434    performance_counter(1)
435}
436
437/// Determines if a Principal is a controller of the canister.
438pub fn is_controller(principal: &Principal) -> bool {
439    let slice = principal.as_slice();
440    match ic0::is_controller(slice) {
441        0 => false,
442        1 => true,
443        n => panic!("unexpected return value from is_controller: {n}"),
444    }
445}
446
447/// Checks if in replicated execution.
448///
449/// The canister can check whether it is currently running in replicated or non replicated execution.
450pub fn in_replicated_execution() -> bool {
451    match ic0::in_replicated_execution() {
452        0 => false,
453        1 => true,
454        n => panic!("unexpected return value from in_replicated_execution: {n}"),
455    }
456}
457
458/// Gets the amount of cycles that a canister needs to be above the freezing threshold in order to successfully make an inter-canister call.
459pub fn cost_call(method_name_size: u64, payload_size: u64) -> u128 {
460    ic0::cost_call(method_name_size, payload_size)
461}
462
463/// Gets the cycle cost of the Management canister method [`creating_canister`](https://internetcomputer.org/docs/references/ic-interface-spec#ic-create_canister).
464///
465/// # Note
466///
467/// [`create_canister`](crate::management_canister::create_canister) and
468/// [`create_canister_with_extra_cycles`](crate::management_canister::create_canister_with_extra_cycles)
469/// invoke this function inside and attach the required cycles to the call.
470pub fn cost_create_canister() -> u128 {
471    ic0::cost_create_canister()
472}
473
474/// Gets the cycle cost of the Management canister method [`http_request`](https://internetcomputer.org/docs/references/ic-interface-spec#ic-http_request).
475///
476/// # Note
477///
478/// [`http_request`](crate::management_canister::http_request) and [`http_request_with_closure`](crate::management_canister::http_request_with_closure)
479/// invoke this function inside and attach the required cycles to the call.
480pub fn cost_http_request(request_size: u64, max_res_bytes: u64) -> u128 {
481    ic0::cost_http_request(request_size, max_res_bytes)
482}
483
484/// The error type for [`cost_sign_with_ecdsa`] and [`cost_sign_with_schnorr`].
485#[derive(thiserror::Error, Debug, Clone)]
486pub enum SignCostError {
487    /// The ECDSA/vetKD curve or Schnorr algorithm is invalid.
488    #[error("invalid curve or algorithm")]
489    InvalidCurveOrAlgorithm,
490
491    /// The key name is invalid for the provided curve or algorithm.
492    #[error("invalid key name")]
493    InvalidKeyName,
494    /// Unrecognized error.
495    ///
496    /// This error is returned when the System API returns an unrecognized error code.
497    /// Please report to ic-cdk maintainers.
498    #[error("unrecognized error: {0}")]
499    UnrecognizedError(u32),
500}
501
502/// Helper function to handle the result of a signature cost function.
503fn sign_cost_result(dst: u128, code: u32) -> Result<u128, SignCostError> {
504    match code {
505        0 => Ok(dst),
506        1 => Err(SignCostError::InvalidCurveOrAlgorithm),
507        2 => Err(SignCostError::InvalidKeyName),
508        _ => Err(SignCostError::UnrecognizedError(code)),
509    }
510}
511
512/// Gets the cycle cost of the Management canister method [`sign_with_ecdsa`](https://internetcomputer.org/docs/references/ic-interface-spec#ic-sign_with_ecdsa).
513///
514/// # Note
515///
516/// Alternatively, [`management_canister::cost_sign_with_ecdsa`](crate::management_canister::cost_sign_with_ecdsa) provides a higher-level API that wraps this function.
517///
518/// # Errors
519///
520/// This function will return an error if the `key_name` or the `ecdsa_curve` is invalid.
521/// The error type [`SignCostError`] provides more information about the reason of the error.
522pub fn cost_sign_with_ecdsa<T: AsRef<str>>(
523    key_name: T,
524    ecdsa_curve: u32,
525) -> Result<u128, SignCostError> {
526    let key_name = key_name.as_ref();
527    let (cost, code) = ic0::cost_sign_with_ecdsa(key_name, ecdsa_curve);
528    sign_cost_result(cost, code)
529}
530
531/// Gets the cycle cost of the Management canister method [`sign_with_schnorr`](https://internetcomputer.org/docs/references/ic-interface-spec#ic-sign_with_schnorr).
532///
533/// # Note
534///
535/// Alternatively, [`management_canister::cost_sign_with_schnorr`](crate::management_canister::cost_sign_with_schnorr) provides a higher-level API that wraps this function.
536///
537/// # Errors
538///
539/// This function will return an error if the `key_name` or the `algorithm` is invalid.
540/// The error type [`SignCostError`] provides more information about the reason of the error.
541pub fn cost_sign_with_schnorr<T: AsRef<str>>(
542    key_name: T,
543    algorithm: u32,
544) -> Result<u128, SignCostError> {
545    let key_name = key_name.as_ref();
546    let (dst, code) = ic0::cost_sign_with_schnorr(key_name, algorithm);
547    sign_cost_result(dst, code)
548}
549
550/// Gets the cycle cost of the Management canister method [`vetkd_derive_key`](https://github.com/dfinity/portal/pull/3763).
551///
552/// Later, the description will be available in [the interface spec](https://internetcomputer.org/docs/current/references/ic-interface-spec/#ic-vetkd_derive_key).
553///
554/// # Note
555///
556/// Alternatively, [`management_canister::cost_vetkd_derive_key`](crate::management_canister::cost_vetkd_derive_key) provides a higher-level API that wraps this function.
557///
558/// # Errors
559///
560/// This function will return an error if the `key_name` or the `vetkd_curve` is invalid.
561/// The error type [`SignCostError`] provides more information about the reason of the error.
562pub fn cost_vetkd_derive_key<T: AsRef<str>>(
563    key_name: T,
564    vetkd_curve: u32,
565) -> Result<u128, SignCostError> {
566    let key_name = key_name.as_ref();
567    let (cost, code) = ic0::cost_vetkd_derive_key(key_name, vetkd_curve);
568    sign_cost_result(cost, code)
569}
570
571/// Gets the number of environment variables available in the canister.
572pub fn env_var_count() -> usize {
573    ic0::env_var_count()
574}
575
576/// Gets the size of the name of the environment variable at the given index.
577///
578/// # Panics
579///
580/// This function traps if:
581/// - The index is out of bounds (>= than value provided by [`env_var_count`])
582/// - The name is not valid UTF-8.
583pub fn env_var_name(index: usize) -> String {
584    let len = ic0::env_var_name_size(index);
585    let mut buf = vec![0u8; len];
586    ic0::env_var_name_copy(index, &mut buf, 0);
587    String::from_utf8(buf).expect("env_var_name is not valid UTF-8")
588}
589
590/// Checks if the environment variable with the given name exists.
591///
592/// # Panics
593///
594/// This function traps if the length of `name` exceeds `MAX_ENV_VAR_NAME_LENGTH`.
595pub fn env_var_name_exists<T: AsRef<str>>(name: T) -> bool {
596    match ic0::env_var_name_exists(name.as_ref()) {
597        0 => false,
598        1 => true,
599        n => panic!("unexpected return value from env_var_name_exists: {n}"),
600    }
601}
602
603/// Gets the value of the environment variable with the given name.
604///
605/// It's recommended to use [`env_var_name_exists`] to check if the variable exists before calling this function.
606///
607/// # Panics
608///
609/// This function traps if:
610/// - The length of `name` exceeds `MAX_ENV_VAR_NAME_LENGTH`.
611/// - The name does not match any existing environment variable.
612/// - The value is not valid UTF-8.
613pub fn env_var_value<T: AsRef<str>>(name: T) -> String {
614    let name = name.as_ref();
615    let len = ic0::env_var_value_size(name);
616    let mut buf = vec![0u8; len];
617    ic0::env_var_value_copy(name, &mut buf, 0);
618    String::from_utf8(buf).expect("env_var_value is not valid UTF-8")
619}
620
621/// Emits textual trace messages.
622///
623/// On the "real" network, these do not do anything.
624///
625/// When executing in an environment that supports debugging, this copies out the data
626/// and logs, prints or stores it in an environment-appropriate way.
627pub fn debug_print<T: AsRef<str>>(data: T) {
628    let buf = data.as_ref();
629    ic0::debug_print(buf.as_bytes());
630}
631
632/// Traps with the given message.
633///
634/// The environment may copy out the data and log, print or store it in an environment-appropriate way,
635/// or include it in system-generated reject messages where appropriate.
636pub fn trap<T: AsRef<str>>(data: T) -> ! {
637    let buf = data.as_ref();
638    ic0::trap(buf.as_bytes());
639}
640
641// # Deprecated API bindings
642//
643// The following functions are deprecated and will be removed in the future.
644// They are kept here for compatibility with existing code.
645
646/// Prints the given message.
647#[deprecated(since = "0.18.0", note = "Use `debug_print` instead")]
648pub fn print<S: std::convert::AsRef<str>>(s: S) {
649    let s = s.as_ref();
650    ic0::debug_print(s.as_bytes());
651}
652
653/// Returns the caller of the current call.
654#[deprecated(since = "0.18.0", note = "Use `msg_caller` instead")]
655pub fn caller() -> Principal {
656    let len = ic0::msg_caller_size();
657    let mut bytes = vec![0u8; len];
658    ic0::msg_caller_copy(&mut bytes, 0);
659    Principal::try_from(&bytes).unwrap()
660}
661
662/// Returns the canister id as a blob.
663#[deprecated(since = "0.18.0", note = "Use `canister_self` instead")]
664pub fn id() -> Principal {
665    let len = ic0::canister_self_size();
666    let mut bytes = vec![0u8; len];
667    ic0::canister_self_copy(&mut bytes, 0);
668    Principal::try_from(&bytes).unwrap()
669}
670
671/// Gets the amount of funds available in the canister.
672///
673/// # Panic
674///
675/// When the cycle balance is greater than `u64::MAX`, this function will panic.
676/// As this function is deprecated, it is recommended to use [`canister_cycle_balance`].
677#[deprecated(since = "0.18.0", note = "Use `canister_cycle_balance` instead")]
678pub fn canister_balance() -> u64 {
679    // ic0 no longer provides `ic0.canister_cycle_balance` which returns a u64,
680    // so we use the u128 version and convert it to u64.
681    // When the cycle balance is greater than `u64::MAX`, `ic0.canister_cycle_balance` also panics.
682    canister_cycle_balance()
683        .try_into()
684        .expect("the cycle balance is greater than u64::MAX, please use canister_cycle_balance which returns u128")
685}
686
687/// Gets the amount of funds available in the canister.
688#[deprecated(since = "0.18.0", note = "Use `canister_cycle_balance` instead")]
689pub fn canister_balance128() -> u128 {
690    canister_cycle_balance()
691}
692
693/// Sets the certified data of this canister.
694///
695/// Canisters can store up to 32 bytes of data that is certified by
696/// the system on a regular basis.  One can call [`data_certificate`]
697/// function from a query call to get a certificate authenticating the
698/// value set by calling this function.
699///
700/// This function can only be called from the following contexts:
701/// - `canister_init`, `canister_pre_upgrade` and `canister_post_upgrade`
702///   hooks.
703/// - `canister_update` calls.
704/// - reply or reject callbacks.
705///
706/// # Panics
707///
708/// - This function traps if `data.len() > 32`.
709/// - This function traps if it's called from an illegal context
710///   (e.g., from a query call).
711#[deprecated(since = "0.18.0", note = "Use `certified_data_set` instead")]
712pub fn set_certified_data(data: &[u8]) {
713    ic0::certified_data_set(data);
714}
715
716/// Sets global timer.
717///
718/// The canister can set a global timer to make the system
719/// schedule a call to the exported `canister_global_timer`
720/// Wasm method after the specified time.
721/// The time must be provided as nanoseconds since 1970-01-01.
722///
723/// The function returns the previous value of the timer.
724/// If no timer is set before invoking the function, then the function returns zero.
725///
726/// Passing zero as an argument to the function deactivates the timer and thus
727/// prevents the system from scheduling calls to the canister's `canister_global_timer` Wasm method.
728#[deprecated(since = "0.18.0", note = "Use `global_timer_set` instead")]
729pub fn set_global_timer(timestamp: u64) -> u64 {
730    ic0::global_timer_set(timestamp)
731}