Using Candid
Overview
Candid provides a language-agnostic way to interact with canisters.
While Candid is a robust, type-safe, and future-proof way to facilitate communication between canisters, it is not required. Arbitrary bytes can be exchanged if all canisters that are part of the communication stream are designed to understand them (such that they are using the same underlying protocol, written in the same language, etc.).
By using Candid, you can specify input argument values and display return values from canister methods regardless of whether you interact with ICP from a terminal using the IC SDK, through a web browser, or from a program written in JavaScript, Motoko, Rust, or any other language.
The .did
file
Candid types can be used to describe a service via a Candid service description file (.did
file), which can either be manually written or generated from a service implementation.
Auto-generated .did
files
If you write a canister in Motoko, the compiler automatically generates a Candid description when you compile the program. If you use dfx
, you will typically see the auto-generated .did
files in the /declarations
directory of your project. Since these files are auto-generated, it is recommended that you do not manually edit them; they will be overwritten in the next dfx build
.
For canisters written in Rust, the Candid extractor tool can be used with the Rust IC CDK versions 0.11.0
and newer. View the full instructions for using the Candid extractor.
Writing .did
files
For other languages, you will have to write the Candid interface description manually. Define a service, then add a public method's name, followed by the data types that the method accepts and returns:
Here is an example that defines the public method greet
, which accepts type text
and returns type text
using a query call.
service : {
"greet" : (text) -> (text) query;
};
Learn more about supported data types in the Candid reference documentation.
Splitting interface descriptions across multiple files (Motoko)
In some workflows, it may be beneficial to split interface descriptions across multiple .did
files. For example, one file may be used to define type definitions that are used by several canisters, while another file is used to define the main service for one of those canisters.
This workflow is for Motoko projects.
You can import both interface descriptions into your canister with two import statements:
import A "a.did"; // Imports only type definitions
import service B "b.did"; // Imports both type definitions and main service
Interact with a service
Command line
To interact with a service, use dfx canister call
To pass Candid arguments to the dfx canister call
command, please refer to the Candid reference, or, for Candid arguments too long to fit the command line, please use the --argument-file
flag.
You can also omit the arguments and let the IC SDK generate a random value that matches the method type.
Browser
The Candid interface description language provides a common language for specifying the signature of a canister. Based on the type signature of the service offered by the smart contract, Candid provides a web interface (the Candid UI) that allows you to call canister functions for testing and debugging from a web browser without writing any frontend code.
When a canister is deployed, it will return a Candid UI URL as part of the output, indicated as the "backend canister URL." The full URL should look similar to the following, but with the canister_id
reflecting your project's canister ID.
http://127.0.0.1:4943/?canisterId=<canister_id> // Local URL
https://a4gq6-oaaaa-aaaab-qaa4q-cai.icp0.io/?id=ts425-saaaa-aaaab-qbksq-cai // Playground or Mainnet URL
For more information about the tool that creates a web interface from the Candid interface of any canister, see the Candid UI repository.
At this time, it is not possible to disable the Candid UI from being installed and deployed for your canister.
Interact with a service from a Motoko canister
If you are writing a canister in Motoko, the Motoko compiler automatically translates the signature of your canister’s top-level actor
or actor class
into a Candid description, and the dfx build
command ensures that the service description is properly referenced where it needs to be. It ensures that the canister identifier and the Candid description are passed to the Motoko compiler correctly. The Motoko compiler then translates the Candid type into the appropriate native Motoko type. This translation enables you to call the canister's method natively. For additional information on the type mapping between Candid and Motoko, you can consult the supported types reference section.
Motoko canisters auto-generate a Candid description file, located in your project build directory at .dfx/local/canisters/hello/hello.did
.
Interact with a service from a Rust canister
If you write a canister in Rust, the dfx build
command ensures that the service description is properly referenced where it needs to be. However, you need to write the Candid service description manually, following the conventions described in the Candid specification.
The Rust CDK then translates the Candid type into the appropriate native Rust type. This translation enables you to call the canister's method natively. For additional information on the type mapping between Candid and Rust, you can consult the supported types reference section.
There is also an experimental feature to generate a Candid service description automatically; see this test case as an example.
For additional information and libraries to help you create Candid services or canisters in Rust, see the documentation for the Candid crate, Rust CDK examples and the Rust tutorials.
Interact with a service from JavaScript
The dfinity/agent npm package includes support for importing canisters using Candid.
When the import dependency of a canister is processed by the dfx build
command and the webpack
configuration, this processing ensures that the canister identifier and the Candid description are passed to the JavaScript program correctly. Behind the scenes, the Candid service description is translated into a JavaScript module, located at .dfx/local/canister/counter/counter.did.js
by dfx build
. The dfinity/agent
package then translates the Candid type into native JavaScript values and enables you to call the canister's method natively. For additional information on the type mapping between Candid and JavaScript, you can consult the supported types reference section.
Publish Candid interfaces privately
By default, dfx
makes the candid:service
metadata information public to promote interoperability and make it convenient to use the Candid UI. The Candid UI reads this metadata to determine the interface of your canister. It doesn’t publish any more information than what is already public. This metadata can be returned through the dfx canister metadata
command:
dfx canister metadata <canister_id> candid:service
However, you can make this metadata information private so that it is only readable by the controllers of your canister. To do this, add the following configuration information to your canister's definition in the project's dfx.json
file:
"metadata": [
{
"name": "candid:service",
"visibility": "private"
}
]
Then, redeploy your canister and confirm that the interface is no longer public.
Create a new Candid implementation
There are community-supported Candid libraries for the following host languages:
If you want to create a Candid implementation to support a language or tool for which an implementation is not currently available, you should consult the Candid specification.
If you add a Candid implementation for a new language or tool, you can use the official Candid test data to test and verify that your implementation is compatible with Candid, even in slightly more obscure corner cases.