-
Notifications
You must be signed in to change notification settings - Fork 97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
doc: candid serialization and raw calls #4662
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,135 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
--- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sidebar_position: 28 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
--- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# Candid | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Candid is an interface description language and serialization format designed specifically for the Internet Computer platform. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It's a crucial component that enables seamless communication between different services and canister smart contracts on the IC, regardless of the programming languages they're implemented in. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
At its core, Candid provides a language-agnostic way to describe and transmit data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It ensures strong typing, which means data is correctly interpreted across different services and languages. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This type safety is complemented by an efficient binary format for encoding data, making it ideal for network transmission. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In the context of Motoko, Candid is deeply integrated into the language. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Motoko automatically generates Candid interfaces for canister smart contracts, and provides built-in functions like `to_candid` and `from_candid` for easy serialization and | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deserialization of data to and from Candid format. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+10
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
On the broader Internet Computer platform, Candid serves as the standard communication protocol between canisters. When one canister calls another, the arguments are serialized to Candid, transmitted, and then deserialized by the receiving canister. This standardization enables developers to create frontends in languages like JavaScript that can easily interact with backend canisters written in Motoko or Rust. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The IC SDK includes various tools for working with Candid, such as utilities for generating interface files and creating TypeScript bindings from Candid definitions. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
These tools further enhance the developer experience and promote interoperability. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Importantly, Candid's design allows for backwards-compatible upgrades of canister interfaces. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
This feature facilitates the evolution of services over time, a critical aspect for long-lived applications | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
on the Internet Computer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In essence, Candid forms a fundamental part of the IC ecosystem. It provides a standardized way to describe, serialize, and communicate data between different parts of the platform. Its seamless integration with Motoko and other languages makes it easier for developers to create interoperable and type-safe services on the Internet Computer. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
## Explicit Candid serialization | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Motoko's `to_candid` and `from_candid` operators allow you to work with Candid-encoded data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`to_candid (<exp1>, ..., <expn>)` serializes a sequence of Motoko values into a `Blob` containing a Candid binary encoding of the data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
For example, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` motoko no-repl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let encoding : Blob = to_candid ("dogs", #are, ['g', 'r', 'e', 'a', 't']); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`from_candid <exp>` deserializes a blob that contains Candid data back into a Motoko value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` motoko no-repl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let ?(t, v, cs) = from_candid encoding : ?(Text, {#are; #are_not}, [Char]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`from_candid` will trap if its arguments is a blob that does not contain valid Candid data. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Because deserialization can fail if the encoded value does not have the expected Candid type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`from_candid` returns a value of option type, with `null` indicated the encoding is well-formed but of the wrong Candid type or some value `?v` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
where `v` is the decoded value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
`from_candid` can only be used in the context of other code that determines its optinal result type, for which a type annotation may be required. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+47
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
For example, this code that underspecifies the expected type of the decoded value, is rejected by the compiler: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` motoko no-repl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let ?(t, v, cs) = from_candid encoding; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `to_candid` and `from_candid` operators are keywords, built into the language and handle most common use cases automatically. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The operators ensure type safety and proper data encoding without requiring developers to manually handle the intricacies of Candid serialization. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
:::danger | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Although `to_candid` will return a valid Candid encoding of its argument, there are actually many different Candid encodings, and thus blobs, for the same value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There is no guarantee that `to_candid` will always return the same `blob`, given the same argument. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
That means that you should never use these blobs to compare values for equality, or be tempted to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
compute a hash for a value, by hashing its Candid encoding. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The hash of a value should be unique, but if you compute it from one of several Candid encodings, it may not be. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
::: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
See the language manual for more details on [`Candid serialization`](../reference/language-manual#candid_serialization). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+58
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
## Dynamic calls | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Most users will should never need to use `to_candid` and `from_candid`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
One scenario in which the operations are useful is when calling canister methods dynamically using the `call` function from | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
the `ExperimentalInternetComputer` base library. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Although most canisters on the Internet Computer speak Candid, this isn't mandated by the Internet Computer Protocol. At the protocol level, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
canisters communicate in raw binary data. Candid is just a common interpretation of that data that allows canisters written in different languages to interoperate. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The `call` function take a canister principal, the name of a method as text, and a raw binary blob and returns a future containing the result of the call, also | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
as a raw binary blob. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+77
to
+84
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Dynamic calls are particularly useful when working with canisters or services that have complex or non-standard interfaces, or when you | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
need fine-grained control over the calling process. However, they require manual handling of binary encoding and decoding, which is | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
more error-prone than using the high-level abstractions provided by Motoko. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
When the service does speak Candid, and you know the types of the method you want to invoke, you can use `to_candid` and `from_candid` to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
deal with the binary format. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Typically, you might use `to_candid` to prepare the argument of a call, and `from_candid` to process its result. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In this example, we use the imported `call` function to make a (silly) dynamic call on the actor: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+86
to
+95
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` motoko no-repl | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import Principal "mo:base/Principal"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import {call} "mo:base/ExperimentalInternetComputer"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
actor This { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public func concat(ts : [Text]) : async Text { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
var r = ""; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (t in ts.vals()) { r #= t }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
r | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public func test() : async Text { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let arguments = to_candid (["a", "b", "c"]); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let results = await call(Principal.fromActor(This), "concat", arguments); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let ?t = from_candid(results) : ?Text; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
t | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
While dynamic calls offer more flexibility, they should be used judiciously. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
In most cases, the standard inter-canister call mechanisms and automatic Candid handling in Motoko provide a safer and more convenient approach to canister interactions. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
## Links | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
For further information on Candid, check out the documentation here: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- [Candid UI](/docs/current/developer-docs/smart-contracts/candid). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- [What is Candid?](/docs/current/developer-docs/smart-contracts/candid/candid-concepts). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- [Using Candid](/docs/current/developer-docs/smart-contracts/candid/candid-howto). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
- [Candid specification](https://github.com/dfinity/candid/blob/master/spec/Candid.md). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<img src="https://github.com/user-attachments/assets/844ca364-4d71-42b3-aaec-4a6c3509ee2e" alt="Logo" width="150" height="150" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.