A Rebel Candid Format

As well as a binary format, Candid possesses a textual presentation, a human-friendly format. We’ve caught glimpses of this format in the input and output of the dfx tool.

But the format is not friendly enough for me:

  • I get confused that some type-related words like record appear before the value, while others like nat8 appear after, and with a colon separator.

  • The sane way to use dfx is to declare Candid interface files in dfx.json, and the textual presentation seems to assume this. However, I like to tinker, and craft messages in the absence of these files.

  • I’m uncertain how Candid’s type inference works. Perhaps I run into trouble because I often neglect to declare Candid interfaces?

  • At times I experiment with messages where most fields have preset values and only a few have varying values. I could use a tool that dumps the hex for the fixed parts.

I devised a rebel textual presentation to address these issues. Thanks to Candid’s elegant design, this is easy to do, especially since I’m only adding features as I need them, rather than supporting the entire spec.

Examples

Types go before the value.

nat32 314159

becomes:

4449444c0001792fcb0400

For principal values, use human friendly strings. For example:

principal "fxa77-fiaaa-aaaae-aaana-cai"

encodes to:

4449444c000168010a000000000080001a0101

Instead of a value, we can place a dollar sign followed by an identifier.

record
  { memo = nat64 0
  ; amount = record { e8s = nat64 $AMT }
  ; fee = record { e8s = nat64 10000 }
  ; to = blob $TGT
  ; from_subaccount = opt blob $SUB
  }

These variables are enclosed in double quotes and passed through:

4449444c046d7b6c01e0a9b302786e006c05fbca0100c6fcb60201ba89e5c20478a2de94eb0602d8a38ca80d010103"$TGT"10270000000000000000000000000000"$SUB""$AMT"

Our tool can infer a vector’s type from item values. For example:

record
  { minting_account = text $MINT_ACC
  ; initial_values = vec
    { record
      { text $ALICE_ACC
      ; record { e8s=nat64 100_000_000_000 }
      }
    }
  ; send_whitelist = vec principal {}
  }

produces:

4449444c056d686c01e0a9b302786c02007101016d026c0390c5a3a90100aecbeb880471fdbacfcc0d03010400"$MINT_ACC"01"$ALICE_ACC"00e8764817000000

💡