Candid file(s) structure - can I have multiple services or import other .did files

I am trying to handcraft a .did file for a custom canister with multiple services from multiple C functions.

  • Is it possible to import .did files into another .did file?
  • Or alternatively, can you have multiple services in a single candid file ?

For example, using the examples I found for counter.c & reverse.c, who have a counter.did and a reverse.did.

I would love to be able to just import these into a main my_services.did for my canister, like:

# file: my_services.did
<...somehow import file counter.did...>
<...somehow import file reverse.did...>
# file: counter.did
service counter: {
  get : () -> (int) query;
  set : (int) -> ();
  inc : () -> ();
  dec : () -> ();
}
# file: reverse.did
service reverse: {
  "go": (text) -> (text) query;
}

If importing is not possible, another good alternative would be to have multiple services, like:

# file: my_services.did
service counter: {
  get : () -> (int) query;
  set : (int) -> ();
  inc : () -> ();
  dec : () -> ();
}
service reverse: {
  "go": (text) -> (text) query;
}

I could not figure out either of those approaches.
It works to just create a single service, but I would have to update the C code & rename the functions to distinguish between the counter & reverse service:

# file: my_services.did
service : {
  "go": (text) -> (text) query;
  get : () -> (int) query;
  set : (int) -> ();
  inc : () -> ();
  dec : () -> ();
}
1 Like

I did find a way to group things within a single service:

# file: my_services.did
service: {
  "counter.get" : () -> (int) query;
  "counter.set" : (int) -> ();
  "counter.inc" : () -> ();
  "counter.dec" : () -> ();
  "reverse.go": (text) -> (text) query;
}

And then in the C code, use this:

void go() WASM_EXPORT("canister_query reverse.go");
void go() {
 ...
}

And after deployment, you call this from the command line:

$ dfx canister call myCanister reverse.go reward
("drawer")

Candid is really flexible. Even spaces are allowed. For example, Instead of reverse.go, it works as well to use reverse: go.

I will go with this approach for now.

1 Like

You can use import "a.did"; to import the type declaration of did file, but the main service will not be imported. Each did file can only contain a single main service. So you can import all your did files, and manually write the combined main service interface. The method name can be unicode as well, but some host language doesn’t support unicode function names.