2.3 Using third-party canisters
Overview
Third-party canisters are canisters that provide a public service at a static canister ID. Some examples are the DFINITY NNS and Internet Identity canisters, but third-party canisters can also be made by community developers. Using third-party canisters can be a good way to add additional functionalities to your dapp. For example, by integrating the Internet Identity canister into your dapp, you can enable identity and authentication for the users of your application.
dfx
enables a dependency workflow, where a canister can be configured to pull third-party canisters that it depends on into the local environment. This can be useful for developers who are looking to test the accuracy of their integration with the third-party canister and perform tests without paying cycles or using production environments. It also drastically simplifies the local deployment of canisters like the II canister, since you don't need to obtain the Wasm and Candid files for the canisters yourself - dfx
takes care of it in the background for you.
In this tutorial, you'll be focusing on pulling third-party canisters. If you're interested in developing third-party canisters that can be pulled by other developers, check out the documentation on dfx deps
.
Pulling third-party canister dependencies
Let's take a look at a basic example of pulling a third-party canister as a dependency. To do this, you'll use the dfx deps
command, which is the dfx
subcommand responsible for pulling canisters that are listed as dependencies of another canister in the project's dfx.json
file.
Prerequisites
Before you start, verify that you have set up your developer environment according to the instructions in 0.3 Developer environment setup.
Creating a new project
To get started, create a new project in your working directory. Open a terminal window, navigate into your working directory (developer_journey
), then use the following commands to start dfx
and create a new project:
Use dfx new <project_name>
to create a new project:
dfx start --clean --background
dfx new dependencies
You will be prompted to select the language that your backend canister will use. Select 'Motoko':
? Select a backend language: ›
❯ Motoko
Rust
TypeScript (Azle)
Python (Kybra)
dfx
versions v0.17.0
and newer support this dfx new
interactive prompt. Learn more about dfx v0.17.0
.
Then, select a frontend framework for your frontend canister. Select 'No frontend canister':
? Select a frontend framework: ›
SvelteKit
React
Vue
Vanilla JS
No JS template
❯ No frontend canister
Lastly, you can include extra features to be added to your project:
? Add extra features (space to select, enter to confirm) ›
⬚ Internet Identity
⬚ Bitcoin (Regtest)
⬚ Frontend tests
Then, navigate into the new project directory:
cd dependencies
You'll use the default 'Hello world' project in this example, then you'll pull the Internet Identity canister as a dependency of our dependencies_backend
canister.
First, open the dfx.json
file in your project's directory. You need to configure your dependencies_backend
canister to have the dependencies of internet_identity
, with canister ID rdmx6-jaaaa-aaaaa-aaadq-cai
on the mainnet. This is the canister ID of the DFINITY canister used to interact with ICP's identity and authentication product called Internet Identity. The developer journey will dive deeper into II in a later tutorial; for now, you'll just use it to demonstrate how third-party canisters can be used. You can do so by editing our dfx.json
file to reflect the following configuration:
{
"canisters": {
"dependencies_backend": {
"type": "motoko",
"main": "src/dependencies_backend/main.mo",
"dependencies": [
"internet_identity"
]
},
"internet_identity": {
"type": "pull",
"id": "rdmx6-jaaaa-aaaaa-aaadq-cai"
}
},
"defaults": {
"build": {
"args": "",
"packtool": ""
}
},
"output_env_file": ".env",
"version": 1
}
Next, run the dfx deps pull
command:
dfx deps pull
By running this command, the following steps are executed:
First, the dependency canister is fetched and the Wasm for it is downloaded.
Then, the hash of the downloaded Wasm is verified against the hash of the deployed canister on the mainnet.
Next, a series of information is extracted from the downloaded Wasm file, such as the
dfx
metadata and Candid information.
The deps/
folder is also created in your project's root folder. The deps/pulled.json
file will contain all major information regarding the project's dependencies. In this example, the deps/pulled.json
file should resemble the following:
{
"canisters": {
"rdmx6-jaaaa-aaaaa-aaadq-cai": {
"name": "internet_identity",
"wasm_hash": "07869792e0841765e24014a2cb23e4a53d3147be6051bfc4966565017cd5fb2c",
"init_guide": "Use '(null)' for sensible defaults. See the candid interface for more details.",
"candid_args": "(opt InternetIdentityInit)",
"gzip": true
}
}
}%
Using dfx deps
Next, you'll set the init
arguments for the dependency canisters using the dfx deps init
command. An init
argument is an argument that will be passed to the canister when it is deployed. This command will iterate over all listed dependencies in the pulled.json
file and set an empty argument for any that do not require an init
argument. For those that require an init
argument, they will be returned so that they can be set manually. Run the command:
dfx deps init
This will show that our II canister requires an init
argument:
WARN: The following canister(s) require an init argument. Please run `dfx deps init <NAME/PRINCIPAL>` to set them individually:
rdmx6-jaaaa-aaaaa-aaadq-cai (internet_identity)
This output shows you that the Internet Identity canister requires an init
argument, but it doesn't give you any additional information. For more information, run the command dfx deps init rdmx6-jaaaa-aaaaa-aaadq-cai
, which will provide an error message that shows you more details:
Error: Canister rdmx6-jaaaa-aaaaa-aaadq-cai (internet_identity) requires an init argument. The following info might be helpful:
init => Use '(null)' for sensible defaults. See the candid interface for more details.
candid:args => (opt InternetIdentityInit)
In this error, you can see that to use the canister's defaults, you can use a null
value as the init
argument. To pass this value as an init
argument, run the command:
dfx deps init rdmx6-jaaaa-aaaaa-aaadq-cai --argument null
Now it's time to deploy our pulled dependency canister. Run the command:
dfx deps deploy
Lastly, let's deploy our project all together with the dfx deploy
command:
dfx deploy
The output will include a local Candid UI URL for both the dependencies_backend
canister, which has the default 'Hello world' code, and the local Candid UI URL for the Internet Identity canister.
Installing code for canister dependencies_backend, with canister ID bkyz2-fmaaa-aaaaa-qaaaq-cai
Deployed canisters.
URLs:
Backend canister via Candid interface:
dependencies_backend: http://127.0.0.1:4943/?canisterId=bd3sg-teaaa-aaaaa-qaaba-cai&id=bkyz2-fmaaa-aaaaa-qaaaq-cai
internet_identity: http://127.0.0.1:4943/?canisterId=bd3sg-teaaa-aaaaa-qaaba-cai&id=rdmx6-jaaaa-aaaaa-aaadq-cai
Now, you can interact with the II canister locally using the CLI or the Candid UI. In a future tutorial you'll integrate your backend canister with the II canister. For now, that'll wrap up this module.
Need help?
Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The ICP community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out:
Developer Discord, which is a large chatroom for ICP developers to ask questions, get help, or chat with other developers asynchronously via text chat.
Motoko Bootcamp - The DAO Adventure - Discover the Motoko language in this 7 day adventure and learn to build a DAO on the Internet Computer.
Motoko Bootcamp - Discord community - A community for and by Motoko developers to ask for advice, showcase projects and participate in collaborative events.
Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on the Discord server.
Submit your feedback to the ICP Developer feedback board.
Next steps
Next, let's take a deeper dive into an introduction of Candid and the role that it plays in development on ICP.