edjCase / ICP.NET

A library for .NET/C#/Unity to natively communicate with the Internet Computer (ICP)
MIT License
53 stars 5 forks source link

bug: Cannot convert candid type 'Func' to candid type 'Record' #134

Closed witter-deland closed 3 weeks ago

witter-deland commented 1 month ago

@Gekctek test case https://github.com/Deland-Labs/ICP.NET/blob/0afa96059c237bcbdc8d869350ef7042f088f4f6/test/Candid.Tests/QueryResponseTests.cs#L39

Gekctek commented 1 month ago

@witter-deland Sooooo. Ive been looking into this one and its weird On one hand it seems like the simplest thing to just have the raw value CandidFunc to just populate the property, but the way its designed internally, its not so easy, so im trying to figure out the best way to handle this

What information are you looking for/wanting to use for the callback? Do you want to call it? Just the method name/canister id?

Im starting to remember why this doesn't exist in the first place, its just a hard problem to do right, especially if we want to do a callable Func

witter-deland commented 1 month ago

This method is query_blocks from the icp ledger (https://dashboard.internetcomputer.org/canister/ryjl3-tyaaa-aaaaa-aaaba-cai). When retrieving historical transaction records, if the records have been archived, archived records containing a callback will be returned. query_blocks : (GetBlocksArgs) -> (QueryBlocksResponse) query;

Write an extension method for CandidFunc in the EdjCase.ICP.Agent project, such as invoke, which can be called by receiving the ic agent and method parameters? It would be good to decide whether the extension method calls a query request or a call request based on whether the Candid func is a query or a call. Is this feasible?

witter-deland commented 1 month ago

I think you can solve this problem by dividing it into several different goals:

  1. Solve the convert problem.
  2. Solve the problem of direct invocation. For the solution of the first problem, I can obtain the necessary information through the ServiceInfo of CandidFunc, and then I can complete the invocation.

The second problem can be solved in another PR. For example, in EdjCase.ICP.Agent, add an extension method named Invoke for CandidFunc, allowing the invoker to complete the invocation after passing in the Agent and the method's parameters (specifying the reflection type of the return value).

In summary, it can be solved with two PRs. One is to solve the Convert bug problem first, and the second is to add support for direct invocation to CandidFunc.

Gekctek commented 1 month ago

https://github.com/edjCase/ICP.NET/releases/tag/7.0.0-pre.1

Ok why dont you just try this

public class MyRecord
{
    [CandidTypeDefinition("() -> ()")]
    public CandidFunc Callback { get; set; }
}

Put a CandidTypeDefinitionAttribute over the CandidFunc type and for the string value, use the candid definition that can be found in the .did file

Let me know if you have any issues. Had to make some 'technically' breaking changes so im just starting v7 with a pre release just in case i need to tweak a few more things

witter-deland commented 1 month ago

Awesome, all testing has been passed