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