Motoko candid encodings using candid.mo

I am working with the Motoko candid encoding package, It’s great that we have this in Motoko and it’s come in very helpful. But, i’m finding it very verbose to declare large records with multiple variants. Both the type RecordFieldType and value RecordFieldValue need to be declared for the encoding to work - it results in repeated code ? Is there a better / cleaner way to format this? Example:

        // candid formatting:
        let commandArgType : CandidType.RecordFieldType = {
            tag = #name("command");
            type_ = #opt(
                #variant([{
                    tag = #name("Configure");
                    type_ = #record([{
                        tag = #name("operation");
                        type_ = #opt(
                            #variant([{
                                tag = #name("AddHotKey");
                                type_ = #record([{
                                    tag = #name("new_hot_key");
                                    type_ = #opt(#principal);
                                }]);
                            }])
                        );
                    }]);
                }])
            );
        };

        let commandArgValue : CandidValue.RecordFieldValue = {
            tag = #name("command");
            value = #opt(
                #variant({
                    tag = #name("Configure");
                    value = #record([{
                        tag = #name("operation");
                        value = #opt(
                            #variant({
                                tag = #name("AddHotKey");
                                value = #record([{
                                    tag = #name("new_hot_key");
                                    value = #opt(#principal(hotkey));
                                }]);
                            })
                        );
                    }]);
                })
            );
        };

I was thinking of expanding on this in my own project with some helper functions but maybe I am doing something wrong or there is a tool already in the package I am unaware of?

Tagging @Gekctek (creator of this particular package)

For context the equivalent Motoko code is:

        let command = #Configure({
            operation = ? #AddHotKey({ new_hot_key = ?hotkey });
        });

Unfortunately, not that Im aware of. I have written this and one in C# and I have the same issue with verboseness. In some cases its possible to imply type from value, but not all cases, so the type definition is required with the redundant value. There might be a way to shortcut some cases, but nothing like that is implemented right now

Ideally what would happen is Motoko has some macro/reflection added to it so that this doesn’t have to be done manually, but it can create it from a Motoko type definition/value. But Motoko doesn’t have anything like that yet.

I have heard there are some other ways like using Mops⠀•⠀Motoko Package Manager by @tomijaga with candid ↔ JSON but it depends on what you are trying to do

1 Like

Ok, it’s not a bad idea to leave it up to the developer anyway to abstract some of it into helper functions - maybe I can shortcut some cases, like you said.

I’m not sure if that would really reduce the lines of code, probably will add some confusion. Overall i’m liking the candid.mo package and it’s come in very handy so far.

Thanks for the response.

1 Like

Motoko now has the built-in to_candid and from_candid primitives: https://internetcomputer.org/docs/current/motoko/main/language-manual/#candid-serialization. I think it should work for most use cases where you can transform between native Motoko value and Candid binary format.

3 Likes

I just tested it and it works great! That’s exactly what I was looking for - thanks!