AsyncCall

Trait AsyncCall 

Source
pub trait AsyncCall: CallIntoFuture<Output = Result<Self::Value, AgentError>> {
    type Value: for<'de> ArgumentDecoder<'de> + Send;

    // Required methods
    fn call<'async_trait>(
        self,
    ) -> Pin<Box<dyn Future<Output = Result<CallResponse<Self::Value>, AgentError>> + 'async_trait>>
       where Self: 'async_trait;
    fn call_and_wait<'async_trait>(
        self,
    ) -> Pin<Box<dyn Future<Output = Result<Self::Value, AgentError>> + 'async_trait>>
       where Self: 'async_trait;

    // Provided methods
    fn and_then<'a, Out2, R, AndThen>(
        self,
        and_then: AndThen,
    ) -> AndThenAsyncCaller<'a, Self::Value, Out2, Self, R, AndThen>
       where Self: Sized + Send + 'a,
             Out2: for<'de> ArgumentDecoder<'de> + Send + 'a,
             R: Future<Output = Result<Out2, AgentError>> + Send + 'a,
             AndThen: Send + Fn(Self::Value) -> R + 'a { ... }
    fn map<'a, Out, Map>(
        self,
        map: Map,
    ) -> MappedAsyncCaller<'a, Self::Value, Out, Self, Map>
       where Self: Sized + Send + 'a,
             Out: for<'de> ArgumentDecoder<'de> + Send + 'a,
             Map: Send + Fn(Self::Value) -> Out + 'a { ... }
}
Expand description

A type that implements asynchronous calls (ie. ‘update’ calls). This can call synchronous and return a RequestId, or it can wait for the result by polling the agent, and return a type.

The return type must be a tuple type that represents all the values the return call should be returning.

Required Associated Types§

Source

type Value: for<'de> ArgumentDecoder<'de> + Send

The return type of the Candid function being called.

Required Methods§

Source

fn call<'async_trait>( self, ) -> Pin<Box<dyn Future<Output = Result<CallResponse<Self::Value>, AgentError>> + 'async_trait>>
where Self: 'async_trait,

Execute the call, but returns the RequestId. Waiting on the request Id must be managed by the caller using the Agent directly.

Since the return type is encoded in the trait itself, this can lead to types that are not compatible to Out when getting the result from the Request Id. For example, you might hold a AsyncCall<u8>, use call() and poll for the result, and try to deserialize it as a String. This would be caught by Rust type system, but in this case it will be checked at runtime (as RequestId does not have a type associated with it).

Source

fn call_and_wait<'async_trait>( self, ) -> Pin<Box<dyn Future<Output = Result<Self::Value, AgentError>> + 'async_trait>>
where Self: 'async_trait,

Execute the call, and wait for an answer using an exponential-backoff strategy. The return type is encoded in the trait.

Provided Methods§

Source

fn and_then<'a, Out2, R, AndThen>( self, and_then: AndThen, ) -> AndThenAsyncCaller<'a, Self::Value, Out2, Self, R, AndThen>
where Self: Sized + Send + 'a, Out2: for<'de> ArgumentDecoder<'de> + Send + 'a, R: Future<Output = Result<Out2, AgentError>> + Send + 'a, AndThen: Send + Fn(Self::Value) -> R + 'a,

Apply a transformation function after the call has been successful. The transformation is applied with the result.

use ic_agent::Agent;
use ic_utils::{Canister, interfaces, call::AsyncCall};
use candid::{Encode, Decode, CandidType, Principal};

async fn create_a_canister() -> Result<Principal, Box<dyn std::error::Error>> {
  let agent = Agent::builder()
    .with_url(url)
    .with_identity(create_identity())
    .build()?;
  agent.fetch_root_key().await?;
  let management_canister = interfaces::ManagementCanister::create(&agent);
  let management_canister = &management_canister; // needed for `async move`

  // Create a canister, then call the management canister to install a base canister
  // WASM. This is to show how this API would be used, but is probably not a good
  // real use case.
  let (canister_id,) = management_canister
    .create_canister()
    .as_provisional_create_with_amount(None)
    .with_effective_canister_id(effective_id)
    .and_then(|(canister_id,)| async move {
      management_canister
        .install_code(&canister_id, canister_wasm)
        .build()
        .unwrap()
        .await?;
      Ok((canister_id,))
    })
    .await?;

  Ok(canister_id)
}

let canister_id = create_a_canister().await.unwrap();
eprintln!("{}", canister_id);
Source

fn map<'a, Out, Map>( self, map: Map, ) -> MappedAsyncCaller<'a, Self::Value, Out, Self, Map>
where Self: Sized + Send + 'a, Out: for<'de> ArgumentDecoder<'de> + Send + 'a, Map: Send + Fn(Self::Value) -> Out + 'a,

Apply a transformation function after the call has been successful. Equivalent to .and_then(|x| async { map(x) }).

Implementors§

Source§

impl<'a, Out, Out2, Inner, Map> AsyncCall for MappedAsyncCaller<'a, Out, Out2, Inner, Map>
where Out: for<'de> ArgumentDecoder<'de> + Send + 'a, Out2: for<'de> ArgumentDecoder<'de> + Send + 'a, Inner: AsyncCall<Value = Out> + Send + 'a, Map: Send + Fn(Out) -> Out2 + 'a,

Source§

type Value = Out2

Source§

impl<'a, Out, Out2, Inner, R, AndThen> AsyncCall for AndThenAsyncCaller<'a, Out, Out2, Inner, R, AndThen>
where Out: for<'de> ArgumentDecoder<'de> + Send + 'a, Out2: for<'de> ArgumentDecoder<'de> + Send + 'a, Inner: AsyncCall<Value = Out> + Send + 'a, R: Future<Output = Result<Out2, AgentError>> + Send + 'a, AndThen: Send + Fn(Out) -> R + 'a,

Source§

type Value = Out2

Source§

impl<'agent, 'canister: 'agent> AsyncCall for CreateCanisterBuilder<'agent, 'canister>

Source§

impl<'agent, 'canister: 'agent> AsyncCall for InstallChunkedCodeBuilder<'agent, 'canister>

Source§

impl<'agent, 'canister: 'agent> AsyncCall for InstallCodeBuilder<'agent, 'canister>

Source§

impl<'agent, 'canister: 'agent> AsyncCall for UpdateCanisterBuilder<'agent, 'canister>

Source§

impl<'agent, Out> AsyncCall for AsyncCaller<'agent, Out>
where Out: for<'de> ArgumentDecoder<'de> + Send + 'agent,

Source§

type Value = Out

Source§

impl<'agent: 'canister, 'canister, Out> AsyncCall for CallForwarder<'agent, 'canister, Out>
where Out: for<'de> ArgumentDecoder<'de> + Send + Sync + 'agent,

Source§

type Value = Out