rocklabs-io / ic-py

Python Agent Library for the DFINITY Internet Computer
MIT License
128 stars 27 forks source link

candid interface file #94

Closed yugocabrio closed 1 year ago

yugocabrio commented 1 year ago

Thanks for good library. I have some questions about candid interface file. README.md

  1. Canister Create a canister instance with candid interface file and canister id, and call canister method with canister instance:
  1. How is creating an instance from a candid file and calling canister different from other common a query_call or update_call that does not use candid files?

  2. In the case that a Dapp has no candid file, is there any solution? If ic-py can't do it, can an agent in another language do it?

Myse1f commented 1 year ago

How is creating an instance from a candid file and calling canister different from other common a query_call or update_call that does not use candid files?

By calling through canister, you don't need to handle encoding parameters and decoding return values. query_raw and call_raw are lower level api. You must provide the struct of parameter and return value.

In the case that a Dapp has no candid file, is there any solution?

If you don't provide the candid, it will try to call __get_candid_interface_tmp_hack to get the candid result. Otherwise, it will fail to initialize the canister.

If ic-py can't do it, can an agent in another language do it?

I don't think so. I think candid desciption is a must for Internet Computer Canister. Without it, we don't know what api the canister are exposing. Something like ABI in Ethereum contract.

yugocabrio commented 1 year ago

I appreciate your response. I tried to use __get_candid_interface_tmp_hack to get the candid result from Rust canister, which doesn't have a candid file, but I received the below error. What is the cause of this error?

from ic.canister import Canister
from ic.client import Client
from ic.agent import Agent
from ic import Principal
from ic.candid import encode, decode, Types
from ic.identity import Identity

i1 = Identity()
client = Client(url = "https://ic0.app")
agent = Agent(i1, client)
params = encode([])

canister_id = 'cea4l-ryaaa-aaaae-aaa6a-cai'

response = agent.query_raw(canister_id,'__get_candid_interface_tmp_hack',params)
canister_did = response[0]['value']
my_canister = Canister(agent=agent, canister_id=canister_id, candid=canister_did)

result = my_canister.method_you_want_to_call()
--------------------------------------
TypeError                                 Traceback (most recent call last)
[<ipython-input-14-0fc7a45863c3>](https://localhost:8080/#) in <module>
     14 
     15 response = agent.query_raw(canister_id,'__get_candid_interface_tmp_hack',params)
---> 16 canister_did = response[0]['value']
     17 my_canister = Canister(agent=agent, canister_id=canister_id, candid=canister_did)
     18 

TypeError: string indices must be integers
Myse1f commented 1 year ago

Motoko written canister will implement the __get_candid_interface_tmp_hack automatically, while Rust one need to implement manually.

For canister that doesn't expose such method, you need to define the did manually. Otherwise, use the query_raw and update_raw.