Skip to main content

Calling canisters

Beginner
Concept

To interact with a canister's methods, there are two primary types of calls that can be used: update calls and query calls.

Update calls can make modifications to a canister's state, while query calls cannot.

A query method can be called as both an update and a query, whereas update methods can be called only as an update.

Update callsQuery Calls
Slow (1-2s)Fast (200-400ms)
Can modify stateCan't modify state
Goes through consensusDoes not go through consensus
Synchronous responseSynchronous response
Executed on all nodes of a subnetExecuted on a single node
Cost cyclesFree

See the reference on ingress messages for a more technical discussion of this topic.

Update calls

Update calls are executed on all nodes of the subnet that the canister is deployed on since the result of the call must go through consensus. This makes them slower than query calls. They are submitted asynchronously and answered synchronously.

Update calls do not go through consensus on the local replica.

Making update calls

To make a update call to a canister, use the dfx canister call command with the --update flag:

  • dfx canister call --update <canister-name> <method_name> : Make an update call to a canister deployed locally. The local replica must be running to create a canister locally. Start it with dfx start --background.

  • dfx canister call --update <canister-name> <method_name> --network=playground: Make an update call to a canister deployed on the playground. Making update calls to canisters deployed on the playground is free, but canisters are temporary and will be removed after 20 minutes.

  • dfx canister call --update <canister-name> <method_name> --network=ic: Make an update call to a canister deployed on the mainnet. Update calls will cost cycles.

Using update calls from within canisters

  // Set the value of the counter.
public func set(n : Nat) : async () {
counter := n;
};

Query calls

Query calls, also referred to as non-replicated queries, are executed on a single node and return a synchronous response. Since they execute on a single node, they do not go through consensus and can be much faster than update calls.

Making query calls

To make a query call to a canister, use the dfx canister call command with the --query flag:

  • dfx canister call --query <canister-name> <method_name>: Make a query call to a canister deployed locally. The local replica must be running to create a canister locally. Start it with dfx start --background.

  • dfx canister call --query <canister-name> <method_name> --network=playground: Make a query call to a canister deployed on the playground. Query calls are free, but canisters are temporary and will be removed after 20 minutes.

  • dfx canister call --query <canister-name> <method_name> --network=ic: Make a query call to a canister deployed on the mainnet. Query calls are free.

The downside of query calls is that the response is not trusted since it's coming from a single node. An update call or a certified query should be used for security-critical calls.

Using query calls from within canisters

  // Get the value of the counter.
public query func get() : async Nat {
return counter;
};

ICP message executions

Calls to canisters can be initiated by end users or other canisters. A call is processed by the canister in one or more message executions. A message execution is a set of consecutive instructions that ICP executes on behalf of the canister.

Typically, a call is processed within a single message execution unless there are calls to other canisters involved, in which case the call will be split across several message executions.

Learn more about the properties of ICP message executions.

Other types of calls

Composite queries

Composite queries are query calls that can call other queries on the same subnet. They can only be invoked by end users and not by other canisters.

Certified queries

Certified queries use certified variables to prove the authenticity of a piece of data that comes along with the query's response. Certified variables can be set via an update call, then read via a query call.

Replicated queries

Replicated queries, also referred to as the "query-as-update" execution model, are query calls executed as updates. The query still discards the state changes, but execution happens on all subnet nodes and the results go through consensus.

Inter-canister calls

Inter-canister calls are used to make calls between different canisters. An inter-canister call involves two messages: a request from the caller to the callee along with a response that the callee will return to the caller.

Authorized calls

An authorized call on ICP refers to a call to a canister that can only be made by a principal (a user or another canister) that has the necessary permissions to perform the call. For example, only a controller of a canister can call the canister's install_code function.

Authorized calls that return a value of () indicate that the function was successful, but may not take an argument or return a meaningful value. If an authorized call is unsuccessful, it will return an error.

Making calls with IDLs

On the protocol level, calls on ICP use blobs to describe arguments and results passed to and returned from canisters. It's typically easier to use an interface description language (IDL) to define a canister's interfaces that can be called by end users or other canisters.

While any IDL can be used for this purpose, most canisters on ICP use Candid, a specialized IDL that is developed for ICP.

Common errors related to calling canisters include: