rocklabs-io / ic-py

Python Agent Library for the DFINITY Internet Computer
MIT License
127 stars 26 forks source link

Trying to call "lock" method on canister and getting typeTable error #15

Closed bodily11 closed 2 years ago

bodily11 commented 2 years ago

I am trying to execute the "lock" method of an NFT canister (a marketplace method). Here is my code so far:

canister_id = 'tde7l-3qaaa-aaaah-qansa-cai'
function_to_call = 'lock'
price = int(0.01E8)
params = [
    {'type':Types.Text,'value':'kw6gv-vykor-uwiaa-aaaaa-b4adm-qaqca-aau3d-a'}, #tokenId
    {'type':Types.Nat64,'value':price}, #price
    {'type':Types.Text,'value':'485d6d59c0b58fea568b339dccd63106422c5404f684bcf6d55f4cbccd49ac6d'}, #wallet address
    {'type':Types.Vec,'value':[0]}
]
params = encode(params)

result = agent.update_raw(canister_id, function_to_call, params)

And then when I run that, I get a really quick error about the function object not having an attribute "buildTypeTable". Error below.

AttributeError                            Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_72643/2348097593.py in <module>
     10     {'type':Types.Vec,'value':[0]}
     11 ]
---> 12 params = encode(params)
     13 
     14 result = agent.update_raw(canister_id, function_to_call, params)

/opt/anaconda3/lib/python3.9/site-packages/ic/candid.py in encode(params)
   1101     typetable = TypeTable()
   1102     for item in argTypes:
-> 1103         item.buildTypeTable(typetable)
   1104 
   1105     pre = prefix.encode()

AttributeError: 'function' object has no attribute 'buildTypeTable'

I'm assuming the Vec encoding class hasn't been implemented yet for sending update calls? This is just a guess. I'm sure you know better than I do.

I also tried running the request without the vec option (read somewhere that it was optional), but then I run into a response decode error. So I'm back with more questions.

Thank you!

ccyanxyz commented 2 years ago

Thanks for reporting this, we're looking into it now

mircial commented 2 years ago

Sorry for the trouble caused! I have fixed the Vec issue. Please note that the right way to ues Vec type is that you have to specific the array value's type, such as {'type': Types.Vec(Types.Nat), 'value': [0]}, which means the type of value 0 is Nat. In addition, you also could use {'type': Types.Vec(Types.Nat64), 'value': [0, 1, 2, 3]}, which means the whole array [0, 1, 2, 3 ] is Nat64 type. BTW, thanks for your support! we hope ic-py can help you!

bodily11 commented 2 years ago

Ok, I reinstalled by cloning repo and adjusted syntax. I'm getting a new error:

#lock: (TokenIdentifier__1, nat64, AccountIdentifier__1, SubAccount__1) ->
#   (Result_5);
canister_id = 'tde7l-3qaaa-aaaah-qansa-cai'
function_to_call = 'lock'
price = int(0.01E8)
params = [
    {'type':Types.Text,'value':'kw6gv-vykor-uwiaa-aaaaa-b4adm-qaqca-aau3d-a'}, #tokenId
    {'type':Types.Nat64,'value':price}, #price
    {'type':Types.Text,'value':'485d6d59c0b58fea568b339dccd63106422c5404f684bcf6d55f4cbccd49ac6d'}, #wallet address
    {'type':Types.Vec(Types.Nat8),'value':[0]}
]
params = encode(params)

result = agent.update_raw(canister_id, function_to_call, params)

Maybe I don't understand what a Nat8 type is? The error I'm getting is:

TypeError                                 Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_73760/201057501.py in <module>
     10     {'type':Types.Vec(Types.Nat8),'value':[0]}
     11 ]
---> 12 params = encode(params)
     13 
     14 result = agent.update_raw(canister_id, function_to_call, params)

/opt/anaconda3/lib/python3.9/site-packages/ic/candid.py in encode(params)
   1115         if not t.covariant(args[i]):
   1116             raise "Invalid {} argument: {}".format(t.display(), str(args[i]))
-> 1117         vals += t.encodeValue(args[i])
   1118     return pre + table + length + typs + vals
   1119 

/opt/anaconda3/lib/python3.9/site-packages/ic/candid.py in encodeValue(self, val)
    547         length = leb128.u.encode(len(val))
    548         if self._blobOptimization:
--> 549             return length + b''.join(val)
    550         vec = list(map(self._type.encodeValue, val))
    551         return length + b''.join(vec)

TypeError: sequence item 0: expected a bytes-like object, int found

And when I try to do a bytes-like object instead, I get a: TypeError: '>=' not supported between instances of 'bytes' and 'int'

It is likely I'm just using types wrong here. Can I not pass in 0 as a Nat8?

mircial commented 2 years ago

sorry, it's ok now, please try again.

bodily11 commented 2 years ago

Yep. That did it. Thank you!