Call

Struct Call 

Source
pub struct Call<'m, 'a> { /* private fields */ }
Expand description

Inter-canister Call.

This type enables the configuration and execution of inter-canister calls using a builder pattern.

§Constructors

Call has two constructors that differentiate whether the call’s response is waited for an unbounded amount of time or not.

§Configuration

Before execution, a Call can be configured in following aspects:

  • Arguments:
    • with_arg: single CandidType value that will be encoded.
    • with_args: a tuple of multiple CandidType values that will be encoded.
    • with_raw_args: raw bytes that won’t be encoded.
    • Note: If no methods in this category are invoked, the Call defaults to sending a Candid empty tuple ().
  • Cycles:
  • Response waiting timeout:

Please note that all the configuration methods are chainable and can be called multiple times. For each aspect of the call, the last configuration takes effect.

§Example

let call = Call::bounded_wait(canister_id, method)
    .with_raw_args(&[1,0])
    .with_cycles(1000)
    .change_timeout(5)
    .with_arg(42)
    .with_cycles(2000);

The call above will have the following configuration in effect:

  • Arguments: 42 encoded as Candid bytes.
  • Attach 2000 cycles.
  • Boundedly waiting for response with a 5-second timeout.

§Execution

A Call can be executed in two ways:

  • Asynchronously: Convert to a CallFuture and await the response.
    • Direct approach: Use .await on the call (e.g., call.await).
    • Collective approach: Use IntoFuture::into_future to obtain futures explicitly, then combine them with join!, select!, or other combinators.
  • One-way: Send a call with oneway when you don’t need a response.

§Example

let response = Call::bounded_wait(canister_id, method).await;
let calls = vec![
  Call::bounded_wait(canister_id1, method1).into_future(),
  Call::bounded_wait(canister_id2, method2).into_future(),
];
let responses = futures::future::join_all(calls).await;
Call::bounded_wait(canister_id, method).oneway().unwrap();

§Decoding the response

If an asynchronous Call succeeds, the response can be decoded in two ways:

  • candid: decode the response as a single Candid type.
  • candid_tuple: decode the response as a tuple of Candid types.

§Example

let res: Response = Call::bounded_wait(canister_id, method).await.unwrap();
let result: u32 = res.candid().unwrap();
let result_tuple: (u32,) = res.candid_tuple().unwrap();

Using an inter-canister call creates the possibility that your async function will be canceled partway through. Read the futures module docs for why and how this happens.

Implementations§

Source§

impl<'m> Call<'m, '_>

Source

pub fn bounded_wait(canister_id: Principal, method: &'m str) -> Call<'m, '_>

Constructs a Call which will boundedly wait for response.

§Note

The bounded waiting is set with a default 300-second timeout. It aligns with the MAX_CALL_TIMEOUT constant in the current IC implementation. The timeout can be changed using the change_timeout method.

To unboundedly wait for response, use the Call::unbounded_wait constructor instead.

Source

pub fn unbounded_wait(canister_id: Principal, method: &'m str) -> Call<'m, '_>

Constructs a Call which will unboundedly wait for response.

To boundedly wait for response, use the Call::bounded_wait constructor instead.

Source§

impl<'a> Call<'_, 'a>

Source

pub fn with_arg<A>(self, arg: A) -> Call<'_, 'a>
where A: CandidType,

Sets the argument for the call.

The argument must implement CandidType.

Source

pub fn with_args<A>(self, args: &A) -> Call<'_, 'a>
where A: ArgumentEncoder,

Sets the arguments for the call.

The arguments are a tuple of types, each implementing CandidType.

Source

pub fn with_raw_args(self, raw_args: &'a [u8]) -> Call<'_, 'a>

Sets the arguments for the call as raw bytes.

§Note

This method just borrows the bytes, so it is useful when making multiple calls with the same argument data.

The Call object will be tied to the lifetime of the argument bytes, which may prevent storing the call in collections or returning it from functions if the arguments don’t live long enough.

For cases where you need to transfer ownership of the arguments bytes consider using Self::take_raw_args instead.

Source

pub fn take_raw_args(self, raw_args: Vec<u8>) -> Call<'_, 'a>

Sets the arguments for the call as raw bytes and consumes the bytes.

§Note

This method takes ownership of the arguments bytes, so it is useful when you want to store the call in collections or return a Call from functions.

For cases where you want to make multiple calls with the same argument data, consider using Self::with_raw_args instead to avoid unnecessary cloning.

Source

pub fn with_cycles(self, cycles: u128) -> Call<'_, 'a>

Sets the cycles payment for the call.

§Note

The behavior of this method when invoked multiple times is as follows:

  • Overrides any previously set cycle value
  • Last invocation determines the final cycles amount
  • Does not accumulate cycles across multiple invocations
Source

pub fn change_timeout(self, timeout_seconds: u32) -> Call<'_, 'a>

Changes the timeout for bounded response waiting.

If invoked multiple times, the last value takes effect.

The timeout value is silently capped by the MAX_CALL_TIMEOUT constant which is currently set to 300 seconds. Therefore, setting a timeout greater than 300 seconds will actually result in a 300-second timeout.

§Panics

This method will panic if invoked on an unbounded response waiting call constructed by Call::unbounded_wait .

§Note

A timeout of 0 second DOES NOT mean unbounded response waiting. The call would most likely time out (result in a SysUnknown reject). Unless it’s a call to the canister on the same subnet, and the execution manages to schedule both the request and the response in the same round.

To unboundedly wait for response, use the Call::unbounded_wait constructor instead.

Source

pub fn get_cost(&self) -> u128

Returns the amount of cycles a canister needs to be above the freezing threshold in order to successfully perform this call. Takes into account the attached cycles (with_cycles) as well as

  • the method name byte length
  • the payload length
  • the cost of transmitting the request
  • the cost for the reservation of response transmission (may be partially refunded)
  • the cost for the reservation of callback execution (may be partially refunded).
Source§

impl Call<'_, '_>

Source

pub fn oneway(&self) -> Result<(), OnewayError>

Sends the call and ignores the reply.

Trait Implementations§

Source§

impl<'m, 'a> Clone for Call<'m, 'a>

Source§

fn clone(&self) -> Call<'m, 'a>

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<'m, 'a> Debug for Call<'m, 'a>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl<'m, 'a> IntoFuture for Call<'m, 'a>

Source§

type Output = Result<Response, CallFailed>

The output that the future will produce on completion.
Source§

type IntoFuture = CallFuture<'m, 'a>

Which kind of future are we turning this into?
Source§

fn into_future(self) -> <Call<'m, 'a> as IntoFuture>::IntoFuture

Creates a future from a value. Read more

Auto Trait Implementations§

§

impl<'m, 'a> Freeze for Call<'m, 'a>

§

impl<'m, 'a> RefUnwindSafe for Call<'m, 'a>

§

impl<'m, 'a> Send for Call<'m, 'a>

§

impl<'m, 'a> Sync for Call<'m, 'a>

§

impl<'m, 'a> Unpin for Call<'m, 'a>

§

impl<'m, 'a> UnwindSafe for Call<'m, 'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.