Candid func types as parameters

I’m working on implementing Candid func types in Azle as described here: Candid Reference | Internet Computer Developer Portal

I am able to return funcs from canister methods, but I can never seem to pass funcs in as parameters either through @dfinity/agent or dfx canister call. Is there something I should know about func types as parameters? The documentation seems to hint on some possible limitations with funcs as parameters (“Currently, only public methods of services, which are identified by their principal, are supported:”).

Here’s a simple example in Azle:

import {
    Func,
    Query
} from 'azle';

type BasicFunc = Func<(param1: string) => Query<string>>;

export function basic_func_param(basic_func: BasicFunc): Query<BasicFunc> {
    return basic_func;
}

export function basic_func_return_type(): Query<BasicFunc> {
    return [
        'aaaaa-aa',
        'create_canister'
    ];
}

Here’s the Candid:

type BasicFunc = func (text) -> (text) query;

service: {
    "basic_func_param": (BasicFunc) -> (BasicFunc) query;
    "basic_func_return_type": () -> (BasicFunc) query;
}

When using the JS agent I can successfully call basic_func_return_type. I get errors like below when using the JS agent or dfx canister call with basic_func_param. I also get errors when I use dfx canister call on basic_func_return_type.

 test basic_func_param failed Error: Call failed:en Completed in 2ms
  Canister: rrkah-fqaaa-aaaaa-aaaaq-cai
  Method: basic_func_param (query)
  "Status": "rejected"
  "Code": "CanisterError"
  "Message": "IC0503: Canister rrkah-fqaaa-aaaaa-aaaaq-cai trapped explicitly: Custom(Fail to decode argument 0 from table0 to func () -> ()\n\nCaused by:\n    0: input: 4449444c016a01710171000100_0101000f6372656174655f63616e6973746572\n       table: type table0 = func (text) -> (text)\n       wire_type: table0, expect_type: func () -> ()\n    1: table0 is not a subtype of func () -> ()\n    2: Subtype fails at function input type\n    3: Record field 0: text is only in the expected type and is not of opt or reserved type)"

I think I’m a little confused on how the agent and dfx are handling funcs, and if anyone can shed some light that would be greatly appreciated.

1 Like

I think @chenyan is the right person to ask about this.

1 Like

It’s a known problem with the Rust implementation: Fix ty() for reference · Issue #273 · dfinity/candid · GitHub. Before it gets resolved, there are some workaround, see: fix: workaround for dfinity/candid#273 by Daniel-Bloom-dfinity · Pull Request #323 · dfinity/agent-rs · GitHub

2 Likes