# Candid

- text
- blob
- nat
- nat8
- nat16
- nat32
- nat64
- int
- int8
- int16
- int32
- int64
- float32
- float64
- bool
- null
- vec
- opt
- record
- variant
- func
- service
- principal
- reserved
- empty

Candid is an interface description language created by DFINITY. It can be used to define interfaces between services (canisters), allowing canisters and clients written in various languages to easily interact with each other. This interaction occurs through the serialization/encoding and deserialization/decoding of runtime values to and from Candid bytes.

Azle performs automatic encoding and decoding of JavaScript values to and from Candid bytes through the use of various `CandidType` objects. For example, `CandidType` objects are used when defining the parameter and return types of your query and update methods. They are also used to define the keys and values of a `StableBTreeMap`.

It's important to note that the `CandidType` objects decode Candid bytes into specific JavaScript runtime data structures that may differ in behavior from the description of the actual Candid type. For example, a `float32` Candid type is a JavaScript Number, a `nat64` is a JavaScript BigInt, and an `int` is also a JavaScript BigInt.

Keep this in mind as it may result in unexpected behavior. Each `CandidType` object and its equivalent JavaScript runtime value is explained in more detail in The Azle Book Candid reference.

A more canonical reference of all Candid types available on the Internet Computer (IC) can be found here.

The following is a simple example showing how to import and use many of the `CandidType` objects available in Azle:

    import {
        blob,
        bool,
        Canister,
        float32,
        float64,
        Func,
        int,
        int16,
        int32,
        int64,
        int8,
        nat,
        nat16,
        nat32,
        nat64,
        nat8,
        None,
        Null,
        Opt,
        Principal,
        query,
        Record,
        Recursive,
        text,
        update,
        Variant,
        Vec
    } from 'azle';

    const MyCanister = Canister({
        query: query([], bool),
        update: update([], text)
    });

    const Candid = Record({
        text: text,
        blob: blob,
        nat: nat,
        nat64: nat64,
        nat32: nat32,
        nat16: nat16,
        nat8: nat8,
        int: int,
        int64: int64,
        int32: int32,
        int16: int16,
        int8: int8,
        float64: float64,
        float32: float32,
        bool: bool,
        null: Null,
        vec: Vec(text),
        opt: Opt(nat),
        record: Record({
            firstName: text,
            lastName: text,
            age: nat8
        }),
        variant: Variant({
            Tag1: Null,
            Tag2: Null,
            Tag3: int
        }),
        func: Recursive(() => Func([], Candid, 'query')),
        canister: Canister({
            query: query([], bool),
            update: update([], text)
        }),
        principal: Principal
    });

    export default Canister({
        candidTypes: query([], Candid, () => {
            return {
                text: 'text',
                blob: Uint8Array.from([]),
                nat: 340_282_366_920_938_463_463_374_607_431_768_211_455n,
                nat64: 18_446_744_073_709_551_615n,
                nat32: 4_294_967_295,
                nat16: 65_535,
                nat8: 255,
                int: 170_141_183_460_469_231_731_687_303_715_884_105_727n,
                int64: 9_223_372_036_854_775_807n,
                int32: 2_147_483_647,
                int16: 32_767,
                int8: 127,
                float64: Math.E,
                float32: Math.PI,
                bool: true,
                null: null,
                vec: ['has one element'],
                opt: None,
                record: {
                    firstName: 'John',
                    lastName: 'Doe',
                    age: 35
                },
                variant: {
                    Tag1: null
                },
                func: [
                    Principal.fromText('rrkah-fqaaa-aaaaa-aaaaq-cai'),
                    'candidTypes'
                ],
                canister: MyCanister(Principal.fromText('aaaaa-aa')),
                principal: Principal.fromText('ryjl3-tyaaa-aaaaa-aaaba-cai')
            };
        })
    });

Calling `candidTypes` with `dfx` will return:

    (
      record {
        func = func "rrkah-fqaaa-aaaaa-aaaaq-cai".candidTypes;
        text = "text";
        nat16 = 65_535 : nat16;
        nat32 = 4_294_967_295 : nat32;
        nat64 = 18_446_744_073_709_551_615 : nat64;
        record = record { age = 35 : nat8; lastName = "Doe"; firstName = "John" };
        int = 170_141_183_460_469_231_731_687_303_715_884_105_727 : int;
        nat = 340_282_366_920_938_463_463_374_607_431_768_211_455 : nat;
        opt = null;
        vec = vec { "has one element" };
        variant = variant { Tag1 };
        nat8 = 255 : nat8;
        canister = service "aaaaa-aa";
        int16 = 32_767 : int16;
        int32 = 2_147_483_647 : int32;
        int64 = 9_223_372_036_854_775_807 : int64;
        null = null : null;
        blob = vec {};
        bool = true;
        principal = principal "ryjl3-tyaaa-aaaaa-aaaba-cai";
        int8 = 127 : int8;
        float32 = 3.1415927 : float32;
        float64 = 2.718281828459045 : float64;
      },
    )