You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: doc/md/writing-motoko/intercanister-calls.md
+65-31
Original file line number
Diff line number
Diff line change
@@ -4,76 +4,99 @@ sidebar_position: 12
4
4
5
5
# Inter-canister calls
6
6
7
-
8
-
9
7
One of the most important features of ICP for developers is the ability to call functions in one canister from another canister. This capability to make calls between canisters, also sometimes referred to as **inter-canister calls**, enables you to reuse and share functionality in multiple dapps.
10
8
11
9
For example, you might want to create a dapp for professional networking, organizing community events, or hosting fundraising activities. Each of these dapps might have a social component that enables users to identify social relationships based on some criteria or shared interest, such as friends and family or current and former colleagues.
12
10
13
11
To address this social component, you might want to create a single canister for storing user relationships then write your professional networking, community organizing, or fundraising application to import and call functions that are defined in the canister for social connections. You could then build additional applications to use the social connections canister or extend the features provided by the social connections canister to make it useful to an even broader community of other developers.
14
12
15
-
This example will showcase a simple way to configure inter-canister calls that can be used as the foundation for more elaborate projects and use-cases such as those mentioned above.
13
+
## Basic usage
14
+
15
+
A simple way to set up inter-canister calls is through your project's `dfx.json` file.
16
+
17
+
For example, let's say that you want to build a canister named `foo` which calls the canister `bar`.
18
+
Here is the `dfx.json` file:
19
+
20
+
```json
21
+
{
22
+
"canisters": {
23
+
"foo": {
24
+
"dependencies": ["bar"],
25
+
"type": "motoko",
26
+
"main": "src/Foo.mo"
27
+
},
28
+
"bar": {
29
+
"type": "motoko",
30
+
"main": "src/Bar.mo"
31
+
}
32
+
}
33
+
}
34
+
```
16
35
17
-
## Example
36
+
Notice that `foo` includes `bar` as a canister dependency.
18
37
19
-
Consider the following code for `Canister1`:
38
+
Below is an example implementation of `foo` (`src/Foo.mo`) which calls the `bar` canister:
20
39
21
40
```motoko no-repl
22
-
import Canister2 "canister:canister2";
41
+
import Bar "canister:bar";
23
42
24
-
persistent actor Canister1 {
43
+
persistent actor Foo {
25
44
26
45
public func main() : async Nat {
27
-
return await Canister2.getValue();
46
+
let value = await Bar.getValue(); // Call a method on the `bar` canister
47
+
value;
28
48
};
29
49
30
50
};
31
51
```
32
52
33
-
Then, consider the following code for `Canister2`:
53
+
Below is an implementation for `bar` (`src/Bar.mo`):
34
54
35
55
```motoko
36
56
import Debug "mo:base/Debug";
37
57
38
-
persistent actor Canister2 {
58
+
persistent actor Bar {
59
+
39
60
public func getValue() : async Nat {
40
-
Debug.print("Hello from canister 2!");
41
-
return 10;
61
+
Debug.print("Hello from the `bar` canister!");
62
+
123;
42
63
};
64
+
43
65
};
44
66
```
45
67
68
+
To run this example, you can use the `dfx canister call` subcommand (after deploying the canisters with `dfx deploy`):
46
69
47
-
To make an inter-canister call from `canister1` to `canister2`, you can use the `dfx` command:
48
-
49
-
```
50
-
dfx canister call canister1 main
70
+
```bash
71
+
dfx canister call foo main
51
72
```
52
73
53
74
The output should resemble the following:
54
75
55
-
```
56
-
2023-06-15 15:53:39.567801 UTC: [Canister ajuq4-ruaaa-aaaaa-qaaga-cai] Hello from canister 2!
57
-
(10 : nat)
76
+
```bash
77
+
2025-02-21 15:53:39.567801 UTC: [Canister ajuq4-ruaaa-aaaaa-qaaga-cai] Hello from the `bar` canister!
78
+
(123: nat)
58
79
```
59
80
60
-
Alternatively, you can also use a canister id to access a previously deployed canister by using the following piece of code in `canister1`:
81
+
You can also use a canister ID to access a previously deployed canister as shown in this alternate implementation of `foo`:
61
82
62
83
```motoko
63
-
persistent actor {
64
-
84
+
persistent actor Foo {
65
85
public func main(canisterId: Text) : async Nat {
66
-
let canister2 = actor(canisterId): actor { getValue: () -> async Nat };
@@ -117,4 +141,14 @@ persistent actor AdvancedCanister2 {
117
141
};
118
142
```
119
143
144
+
In some situations, it may be useful to reference a canister by ID. This is possible with the following import syntax:
145
+
146
+
```motoko
147
+
import Canister "ic:7hfb6-caaaa-aaaar-qadga-cai";
148
+
```
149
+
150
+
If you do this, double check that the referenced canister is available and has the same canister ID in all intended runtime environments (usually the local replica and ICP mainnet).
151
+
152
+
In addition, a corresponding `.did` file with name `7hfb6-caaaa-aaaar-qadga-cai.did`, containing the Candid interface of the imported canister, must be available on the `moc` compiler's `actor-idl` path.
0 commit comments