rocklabs-io/ic-py

When I get a response the keys are underscored numbers, not values

Closed this issue · 5 comments

For example, in a response, instead of a nice candid value, I get an underscored prefixed number. Like this:

{
'_220804107': 'https://web.whatsapp.com/',
'_272465847': 1648359818507890360,
'_509026302': 'Japan'
}

Is there a way to automatically parse those key values as part of the Python agent? Is there some functionality with decode that I am missing? Is there a way to manually decode these key values?

Thank you!

update and query can receive a parameter to parse as return type. Refer to #29

However, I recommend to use the new function of ic-py that can parse candid automatically. Refer to readme example. (pls update the version to current main branch).

Hope this help.

zkung commented

I usually prefer Canister to Agent, it is more convenient

class Canister:
    def __init__(self, agent, canister_id, candid=None):

Ah, yeah. I was hoping the return types would come with the response, but I suppose needing the candid makes sense. Thanks!

IC serializes the key using an irreversible hash function,so you need to provide candid interface to parse the return type.

As I know, Motoko canister export __get_candid_interface_tmp_hack method automatically to get the canister interface. But you need to export this method manually in Rust canister.

When instantiating Canister, you can omit the candid parameter and it would try to fetch the interface through __get_candid_interface_tmp_hack.

I'm closing this issue. Here is my best solution so far:

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 = XYZ

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()

This will pull down the candid for all Motoko canisters (not Rust canisters) and pass it into the Canister declaration so that you don't have to specify Types of objects in request or response.