rocklabs-io / ic-py Goto Github PK
View Code? Open in Web Editor NEWPython Agent Library for the DFINITY Internet Computer
License: MIT License
Python Agent Library for the DFINITY Internet Computer
License: MIT License
I have the following ogy.did
candid:
type Account = variant {
account_id : text;
"principal" : principal;
extensible : CandyValue;
};
type BalanceResponse = record {
nfts : vec text;
sales : vec EscrowRecord;
stake : vec StakeRecord;
multi_canister : opt vec principal;
escrow : vec EscrowRecord;
};
type CandyValue = variant {
Int : int;
Nat : nat;
Empty;
Nat16 : nat16;
Nat32 : nat32;
Nat64 : nat64;
Blob : vec nat8;
Bool : bool;
Int8 : int8;
Nat8 : nat8;
Nats : variant { thawed : vec nat; frozen : vec nat };
Text : text;
Bytes : variant { thawed : vec nat8; frozen : vec nat8 };
Int16 : int16;
Int32 : int32;
Int64 : int64;
Option : opt CandyValue;
Floats : variant { thawed : vec float64; frozen : vec float64 };
Float : float64;
Principal : principal;
Array : variant { thawed : vec CandyValue; frozen : vec CandyValue };
Class : vec Property;
};
type Errors = variant {
nyi;
storage_configuration_error;
escrow_withdraw_payment_failed;
token_not_found;
owner_not_found;
content_not_found;
auction_ended;
out_of_range;
sale_id_does_not_match;
sale_not_found;
item_not_owned;
property_not_found;
validate_trx_wrong_host;
withdraw_too_large;
content_not_deserializable;
bid_too_low;
validate_deposit_wrong_amount;
existing_sale_found;
asset_mismatch;
escrow_cannot_be_removed;
deposit_burned;
cannot_restage_minted_token;
cannot_find_status_in_metadata;
receipt_data_mismatch;
validate_deposit_failed;
unauthorized_access;
item_already_minted;
no_escrow_found;
escrow_owner_not_the_owner;
improper_interface;
app_id_not_found;
token_non_transferable;
sale_not_over;
update_class_error;
malformed_metadata;
token_id_mismatch;
id_not_found_in_metadata;
auction_not_started;
library_not_found;
attempt_to_stage_system_data;
validate_deposit_wrong_buyer;
not_enough_storage;
sales_withdraw_payment_failed;
};
type EscrowRecord = record {
token : TokenSpec;
token_id : text;
seller : Account;
lock_to_date : opt int;
buyer : Account;
amount : nat;
sale_id : opt text;
};
type ICTokenSpec = record {
fee : nat;
decimals : nat;
canister : principal;
standard : variant { EXTFungible; DIP20; Ledger };
symbol : text;
};
type OrigynError = record {
"text" : text;
error : Errors;
number : nat32;
flag_point : text;
};
type Principal = principal;
type Property = record {
value : CandyValue;
name : text;
immutable : bool;
};
type Result_19 = variant {
ok : BalanceResponse;
err : OrigynError;
};
type StakeRecord = record {
staker : Account;
token_id : text;
amount : nat;
};
type TokenSpec = variant {
ic : ICTokenSpec;
extensible : CandyValue;
};
service : {
balance_of_nft_origyn : (
Account,
) -> (Result_19) query;
}
I call the canister the following way:
ogy = Canister(agent=agent, canister_id=canister_id,
candid=ogy_candid)
result = ogy.balance_of_nft_origyn({ # type: ignore
'principal': principal,
})
My call fails with the following error
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/discord/ext/tasks/__init__.py", line 239, in _loop
await self.coro(*args, **kwargs)
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/bot.py", line 47, in check_ownership
await verify_ownership_for_guild(guild)
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 32, in verify_ownership_for_guild
if user_has_tokens(
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 66, in user_has_tokens
result = ogy.balance_of_nft_origyn({ # type: ignore
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/canister.py", line 60, in __call__
encode(arguments),
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/candid.py", line 1263, in encode
vals += t.encodeValue(args[i])
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/candid.py", line 770, in encodeValue
raise ValueError("Variant has no data: {}".format(val))
ValueError: Variant has no data: {'principal': 'ci6uj-i7ujw-wrp3j-6nfh6-ux3y4-hym5t-ruodk-flgjh-salcu-6nxa2-cae'}
What am I doing wrong?
I've seen code in JavaScript use a send_dfx method that will allow you to pass in text account addresses and other default values and then will wrap them up and send to the ledger canister to facilitate ICP transfers.
Is this on your roadmap at all?
I'm working on implementing an ICP transfer with the Python Agent and am trying to figure out if I should just interact with the raw canister (encoding all values to appropriate types myself) or if you had any plans to make it really easy. :)
It's not possible to read the response from the ledger archive due to a bug when decoding the response.
Minimum example:
from ic.client import Client
from ic.agent import Agent
from ic.identity import Identity
from ic.common.ledger import Ledger
from ic import Canister
# Identity and Client are dependencies of Agent
iden = Identity() # creates a random keypair
client = Client() # creates a client to talk to the IC
# creates an agent, combination of client and identity
agent = Agent(iden, client)
# creates the ledger canister with the matching interface provided
ledger = Ledger(agent)
ledger_archive_did = open("archive.did").read()
ledger_archive = Canister(agent=agent,
canister_id="qjdve-lqaaa-aaaaa-aaaeq-cai",
candid=ledger_archive_did)
res = ledger_archive.get_blocks({"start": 10, "length": 10})
More info can be found in this thread
for variant type like
variant {
a;
b;
};
use canister.xxx({"a": None})
returns AttributeError: 'NoneType' object has no attribute 'buildTypeTable'
I have the following did
file
type Canister =
service {
tokens: (AccountIdentifier__1) -> (Result_1) query;
};
type CommonError =
variant {
InvalidToken: TokenIdentifier;
Other: text;
};
type AccountIdentifier__1 = text;
type TokenIndex = nat32;
type TokenIdentifier = text;
type Result_1 =
variant {
err: CommonError;
ok: vec TokenIndex;
};
service : () -> Canister
I setup the canister like this
# create agent
iden = Identity()
client = Client()
agent = Agent(iden, client)
ext_did = open("ext.did").read()
ext = Canister(
agent, canister['canisterId'], candid=ext_did)
But making a call to ext.tokens(account)
fails with the error mentioned above. Is this a bug or am I doing something wrong?
when i stringify an account identifier, 0x
is added. i have to manually remove because appliations on the IC don't work with the 0x
prefix. can it be removed by default and added only when explicitly stated?
Hi,
I'm receiving a "cannot find field 'principal' when I run the below code. It seems like the candid did is incorrect, but I've verified it multiple times. Any suggestions on troubleshooting? Thanks!
--------------------------------CODE---------------------------------
from ic.canister import Canister
from ic.client import Client
from ic.agent import Agent
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 = []
params = encode(params)
canister_id = 'zqfso-syaaa-aaaaq-aaafq-cai'
response = agent.query_raw(canister_id,'__get_candid_interface_tmp_hack',params)
canister_did = response[0]['value']
canister = Canister(agent=agent, canister_id=canister_id, candid=canister_did)
---------------------------------------ERROR----------------------------------------------------------
Traceback (most recent call last):
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\SNS\test.py", line 20, in
my_canister.list_neurons({ 'of_principal': [], 'limit': 1000, 'start_page_at': []})
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\canister.py", line 57, in call
res = self.agent.query_raw(
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\agent.py", line 79, in query_raw
return decode(result['reply']['arg'], return_type)
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 1297, in decode
'value': t.decodeValue(b, types[i])
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 671, in decodeValue
x[expectKey] = exceptValue.decodeValue(b, v)
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 552, in decodeValue
rets.append(self._type.decodeValue(b, vec._type))
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 859, in decodeValue
return self._type.decodeValue(b, t)
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 671, in decodeValue
x[expectKey] = exceptValue.decodeValue(b, v)
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 552, in decodeValue
rets.append(self._type.decodeValue(b, vec._type))
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 859, in decodeValue
return self._type.decodeValue(b, t)
File "C:\Users\KyleLangham\PycharmProjects\ICPTransactions\venv\lib\site-packages\ic\candid.py", line 674, in decodeValue
raise ValueError("Cannot find field {}".format(keys[idx]))
ValueError: Cannot find field "principal"
Process finished with exit code 1
test data
4449444c016e68010001011d779590d2cd339802981dfd935d9a3dbb085cafe6ad19b87229a016d602
use didc
>didc.exe decode 4449444c016e68010001011d779590d2cd339802981dfd935d9a3dbb085cafe6ad19b87229a016d602
(
opt principal "expmt-gtxsw-inftj-ttabj-qhp5s-nozup-n3bbo-k7zvn-dg4he-knac3-lae",
)
use ic-py
raise "Cannot decode principal"
TypeError: exceptions must derive from BaseException
version: 0.0.8
Hello! First off, I LOVE this project. I've been waiting for a Python agent for months! So good work!
Next, I pip installed and put together this small example
from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, decode
iden = Identity()
client = Client()
agent = Agent(iden, client)
name = agent.query_raw("hbi4x-wqaaa-aaaaj-aad7a-cai", "getRegistryCount", encode([]))
When I run that I get an error:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_62725/2178616461.py in <module>
8 agent = Agent(iden, client)
9
---> 10 name = agent.query_raw("hbi4x-wqaaa-aaaaj-aad7a-cai", "getRegistryCount", encode([]))
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in query_raw(self, canister_id, method_name, arg)
72 if result['status'] == 'replied':
73 method_type = getType(method_name)
---> 74 arg = decode(method_type, result['reply']['arg'])
75 return arg
76 elif result['status'] == 'rejected':
/opt/anaconda3/lib/python3.9/site-packages/ic/candid.py in decode(retTypes, data)
1147 # outputs[i.name] = i.decodeValue(b, i)
1148 outputs.append({
-> 1149 'type': t.name,
1150 'value': t.decodeValue(b, types[i])
1151 })
AttributeError: 'NoneType' object has no attribute 'name'
Am I encoding empty parameters incorrectly? Or is the canister returning something incorrectly? It should just be querying (no params) to get the total number of NFTs minted, and then return that number.
Thanks, excited to hear back from you all.
from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, decode, Types
#from struct import *
iden = Identity()
client = Client(url = "https://ic0.app")
agent = Agent(iden, client)
canister_id = '3mttv-dqaaa-aaaah-qcn6q-cai'
function_to_call = "getGenes"
params = []
params = encode(params)
res = agent.query_raw(canister_id, function_to_call, encode([]))
print(res)
This gives me either the error Traceback (most recent call last): File "..\traitchecker.py", line 17, in <module> res = agent.query_raw(canister_id, function_to_call, encode([])) File "C:\Python39\lib\site-packages\ic\agent.py", line 73, in query_raw if result['status'] == 'replied': TypeError: byte indices must be integers or slices, not str
Or the correct result (a shitload of data). Probably one out of 4 calls returns correct.
I noticed you're missing the certificate verification and found the draft PR #56.
What's the blocker here?
I'm getting a lot of httpx.ReadTimeout
exceptions, is there anything that can be done to prevent this?
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 130, in _call_sslobject_method
result = func(*args)
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/ssl.py", line 916, in read
v = self._sslobj.read(len)
ssl.SSLWantReadError: The operation did not complete (read) (_ssl.c:2536)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 33, in read
return await self._stream.receive(max_bytes=max_bytes)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 195, in receive
data = await self._call_sslobject_method(self._ssl_object.read, max_bytes)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 137, in _call_sslobject_method
data = await self.transport_stream.receive()
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 1265, in receive
await self._protocol.read_event.wait()
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/asyncio/locks.py", line 213, in wait
await fut
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_exceptions.py", line 8, in map_exceptions
yield
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 31, in read
with anyio.fail_after(timeout):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/_core/_tasks.py", line 118, in __exit__
raise TimeoutError
TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 60, in map_httpcore_exceptions
yield
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 353, in handle_async_request
resp = await self._pool.handle_async_request(req)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 253, in handle_async_request
raise exc
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 237, in handle_async_request
response = await connection.handle_async_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection.py", line 90, in handle_async_request
return await self._connection.handle_async_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/http11.py", line 105, in handle_async_request
raise exc
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/http11.py", line 84, in handle_async_request
) = await self._receive_response_headers(**kwargs)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/http11.py", line 148, in _receive_response_headers
event = await self._receive_event(timeout=timeout)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/http11.py", line 177, in _receive_event
data = await self._network_stream.read(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 30, in read
with map_exceptions(exc_map):
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
raise to_exc(exc)
httpcore.ReadTimeout
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 50, in verify_ownership_for_user
tokens = await user_has_tokens(
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 104, in user_has_tokens
result = await icp_ledger.account_balance_async({'account' : account}) # type: ignore
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/canister.py", line 97, in __call__
res = await self.agent.query_raw_async(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/agent.py", line 93, in query_raw_async
result = await self.query_endpoint_async(canister_id if effective_canister_id is None else effective_canister_id, data)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/agent.py", line 46, in query_endpoint_async
ret = await self.client.query_async(canister_id, data)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/client.py", line 37, in query_async
ret = await client.post(endpoint, data = data, headers=headers)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1842, in post
return await self.request(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1527, in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1614, in send
response = await self._send_handling_auth(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1642, in _send_handling_auth
response = await self._send_handling_redirects(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1679, in _send_handling_redirects
response = await self._send_single_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1716, in _send_single_request
response = await transport.handle_async_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 352, in handle_async_request
with map_httpcore_exceptions():
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions
raise mapped_exc(message) from exc
httpx.ReadTimeout
2022-08-24 15:50:23 INFO discord start
2022-08-24 15:50:28 ERROR discord error checking ownership
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 130, in _call_sslobject_method
result = func(*args)
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/ssl.py", line 974, in do_handshake
self._sslobj.do_handshake()
ssl.SSLWantReadError: The operation did not complete (read) (_ssl.c:997)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 67, in start_tls
ssl_stream = await anyio.streams.tls.TLSStream.wrap(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 122, in wrap
await wrapper._call_sslobject_method(ssl_object.do_handshake)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/streams/tls.py", line 137, in _call_sslobject_method
data = await self.transport_stream.receive()
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 1265, in receive
await self._protocol.read_event.wait()
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/asyncio/locks.py", line 213, in wait
await fut
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_exceptions.py", line 8, in map_exceptions
yield
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 76, in start_tls
raise exc
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 66, in start_tls
with anyio.fail_after(timeout):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/anyio/_core/_tasks.py", line 118, in __exit__
raise TimeoutError
TimeoutError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 60, in map_httpcore_exceptions
yield
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 353, in handle_async_request
resp = await self._pool.handle_async_request(req)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 253, in handle_async_request
raise exc
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection_pool.py", line 237, in handle_async_request
response = await connection.handle_async_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection.py", line 86, in handle_async_request
raise exc
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection.py", line 63, in handle_async_request
stream = await self._connect(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_async/connection.py", line 150, in _connect
stream = await stream.start_tls(**kwargs)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/backends/asyncio.py", line 64, in start_tls
with map_exceptions(exc_map):
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpcore/_exceptions.py", line 12, in map_exceptions
raise to_exc(exc)
httpcore.ConnectTimeout
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 50, in verify_ownership_for_user
tokens = await user_has_tokens(
File "/Users/moritz/projects/ic/glue-org/glue-bot/glue/discord_bot/helpers.py", line 104, in user_has_tokens
result = await icp_ledger.account_balance_async({'account' : account}) # type: ignore
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/canister.py", line 97, in __call__
res = await self.agent.query_raw_async(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/agent.py", line 93, in query_raw_async
result = await self.query_endpoint_async(canister_id if effective_canister_id is None else effective_canister_id, data)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/agent.py", line 46, in query_endpoint_async
ret = await self.client.query_async(canister_id, data)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/ic/client.py", line 37, in query_async
ret = await client.post(endpoint, data = data, headers=headers)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1842, in post
return await self.request(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1527, in request
return await self.send(request, auth=auth, follow_redirects=follow_redirects)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1614, in send
response = await self._send_handling_auth(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1642, in _send_handling_auth
response = await self._send_handling_redirects(
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1679, in _send_handling_redirects
response = await self._send_single_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_client.py", line 1716, in _send_single_request
response = await transport.handle_async_request(request)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 352, in handle_async_request
with map_httpcore_exceptions():
File "/Users/moritz/.pyenv/versions/3.10.2/lib/python3.10/contextlib.py", line 153, in __exit__
self.gen.throw(typ, value, traceback)
File "/Users/moritz/projects/ic/glue-org/glue-bot/.venv/lib/python3.10/site-packages/httpx/_transports/default.py", line 77, in map_httpcore_exceptions
raise mapped_exc(message) from exc
httpx.ConnectTimeout
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!
Maybe I'm doing this wrong, but when calling a method that returns a list such as below, the response comes back as an unstructured list
record = Types.Record({
'include_reward_status':Types.Vec(Types.Int32),
'before_proposal':Types.Null,
'limit':Types.Nat32,
'exclude_topic':Types.Vec(Types.Int32),
'include_status':Types.Vec(Types.Int32),
})
params = [
{
'type': record,
'value':{
'include_reward_status': [],
'before_proposal': None,
'limit': 100,
'exclude_topic': [],
'include_status': [1]
}
}]
res = agent.query_raw("rrkah-fqaaa-aaaaa-aaaaq-cai", "list_proposals", encode(params))
pprint(res)
results in
[{'type': 3871088705,
'value': {'_3720987355': [{'_100394802': 1,
'_1120297033': 1644281103,
'_1138543385': 0,
'_1380048431': [1644626703],
'_1453869204': 0,
'_1659864270': 100000000,
'_2084260468': [{'_24641': 83739340113,
'_338842564': 40551870688681598,
'_4174818006': 1644301268,
'_6039847': 16091166445927}],
'_2139208002': 1,
'_23515': [{'_23515': 43574}],
'_2756235859': 0,
'_3000310834': [{'_2162756390': '## Proposal to '
'Upgrade the '
'Registry '
'Canister\n'
'\n'
'### Proposer: '
'Dfinity '
'Foundation\n'
'### Git Hash: '
'ed721ffdde4b1d4d982d0c843a0b9e293380e05b\n'
'### New Wasm '
'Hash: '
'3cc60f5bee9f555258a5bfb648ff16e7441bc4920383c1127c9bd564eccfc848\n'
'### Target '
'canister: '
'rwlgt-iiaaa-aaaaa-aaaaa-cai\n'
'\n'
'---\n'
'## Release '
'Notes\n'
'\n'
'2c560f3cf2c5e36bdbf5edbd148cb28f72db24b7 '
'Merge branch '
"'egeyar/2022-02-02/Add-removed-fields-back-to-BlessReplicaVersionPayload' "
Is there a way to get this library to return a dictionary with indexed items corresponding to what I see here?
https://bmht6-iiaaa-aaaad-qabeq-cai.raw.ic0.app/principal/rrkah-fqaaa-aaaaa-aaaaq-cai
I want to use ic.identity.Identity, but I have identity.pem only
What are the current limitations of this wonderful WIP Python Agent? I am eager to get things working but am running into a few issues with some canister calls.
This is the error I keep getting
TypeError: getType() missing 2 required positional arguments: 'table' and 't'
When I run
from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, decode
iden = Identity()
client = Client(url = "https://ic0.app")
agent = Agent(iden, client)
result = agent.query_raw("hbi4x-wqaaa-aaaaj-aad7a-cai", "getRegistryCount", encode([]))
It works. The getRegistryCount method works.
However, if I change the last line to:
result = agent.query_raw("hbi4x-wqaaa-aaaaj-aad7a-cai", "getRegistry", encode([]))
just get the registry rather than the count, it appears it has an issue returning a vec or something like that.
I'm assuming this is all known, I'm just exploring what I can and can't do right now. (again, eager to use it as it becomes available)
Hi I have a problem using ic-py library.
I would like to mint canister tokens and send request similar to
dfx canister --network ${NETWORK} call ${CANISTER_ADDRESS} transfer '(record {
memo = 0 : nat64;
amount = record { e8s = 100 : nat64 };
fee = record { e8s = 0 : nat64 };
from_subaccount = null;
to = '${TOKENS_TRANSFER_ACCOUNT_ID_BYTES}' : vec nat8;
created_at_time = null;
})'
But I am not sure how to use ic-py params to fulfill my needs. It would be ideal to do something similar to
params = {
"memo": 0,
"amount": { "e8s": 100 },
"fee": { "e8s": 0 },
"from_subaccount": None,
"to": ["${TOKENS_TRANSFER_ACCOUNT_ID_BYTES}"],
"created_at_time": None,
}
result = agent.update_raw("${CANISTER_ADDRESS}", "transfer", encode(params))
print(result)
If you have any idea what approach could I take, please share.
Library documentation has only few simple examples and so I couldn't get it done yet
The Internet Computer Protocol has deduplication of update calls built into the protocol. This means if you send the same update call to the same canister with the same parameters only one request will process instead of all of them (the rest being deduplicated).
In some cases this is undesirable (for example a payment flow where you request a unique escrow address for each payment and you never want to return the same escrow address more than once).
The nonce and the expiration time are part of the call, so if we vary the nonce or the expiration time on the agent side, then you can prevent deduplication of calls.
Is there an easy way to vary the nonce or expiration time of an update call through ic-py? I saw in the agent creation that there is a nonce_factory parameter, but I couldn't find any documentation on what that is or how to modify it to make it work for me.
Thanks!
Hello, not sure if this is possible, but figured I would ask anyway.
I can find my Internet Identity keys in local storage. If I take the first 32 bytes, then I get a nice ed25519 key that I can import with Identity("ed25519_key_I_took_from_local_storage"). This works and the identity is imported. When I create the agent with the client, I can call agent.get_principal(), but I can't get the agent.get_principal() to match up with the principal that I actually have in an app when I login with Internet Identity. Even if I change the client (to perhaps the domain of the website I was logging in to), the principal I get from agent.get_principal() stays the same.
Am I missing something here? Or am I trying to do something that isn't actually possible? Would love to know how to authenticate with an existing Internet Identity, and perhaps my strategy is flawed somehow.
Thank you!
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!
I'm transferring $ghost token using ic-py.
If I pull candid from the canister and use the canister interface, I get an error: "IDL error: illegal type table"
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_33617/294065910.py in <module>
----> 1 my_canister.transfer(
2 {
3 'amount':int(0.1e8),
4 'from':{'address':'485d6d59c0b58fea568b339dccd63106422c5404f684bcf6d55f4cbccd49ac6d'},
5 'memo':[],
/opt/anaconda3/lib/python3.9/site-packages/ic/canister.py in __call__(self, *args, **kwargs)
63 )
64 else:
---> 65 res = self.agent.update_raw(
66 self.canister_id,
67 self.name,
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in update_raw(self, canister_id, method_name, arg, return_type, effective_canister_id, **kwargs)
114 status, result = self.poll(eid, req_id, **kwargs)
115 if status == 'rejected':
--> 116 raise Exception('Rejected: ' + result.decode())
117 elif status == 'replied':
118 return decode(result, return_type)
Exception: Rejected: Canister fjbi2-fyaaa-aaaan-qanjq-cai trapped explicitly: IDL error: illegal type table
However, if I define the type table myself, it works just fine.
canister_id = 'fjbi2-fyaaa-aaaan-qanjq-cai'
types = Types.Record({
'amount':Types.Nat,
'from':Types.Variant({
'address':Types.Text,
'principal':Types.Principal
}),
'memo':Types.Vec(Types.Nat8),
'nonce':Types.Opt(Types.Nat),
'notify':Types.Bool,
'subaccount':Types.Opt(Types.Vec(Types.Nat8)),
'to':Types.Variant({
'address':Types.Text,
'principal':Types.Principal
}),
'token':Types.Text
})
values = {
'amount':int(0.1e8),
'from':{'address':''},
'memo':[],
'nonce':[],
'notify':False,
'subaccount':[],
'to':{'address':''},
'token':''
}
params = [{'type':types,'value':values}]
params = encode(params)
response = agent.update_raw(canister_id,'transfer',params)
So not sure what is wrong here. Maybe it has to do with the "blob" type that is returned in the candid? I can't figure out why it won't work for me to use the candid I get back from the canister when I run __get_candid_interface_tmp_hack
Would love for you to take a look. Thanks!
This is the correct candid. It was indicated in the error result. My problem is how to handle None.
I wrote params, but I am unsure how to write None
in params.
record {
quoted_resource : variant {
Article : nat64;
None; # This is the point.
Post : nat64;
Comment : nat64;
};
extension : opt variant {
Poll : record {
votes_per_user : nat8;
poll_duration_in_minutes : nat16;
options : vec text;
};
};
}
I used this empty string ' ' as a key for the variable name of type "Types.Null"(None) for the first, but it was not allowed. I have no idea. Could you tell me what key should be set for Types.Null? Tentatively set to 'Null', but it dose not work now.
types = Types.Record({
'quoted_resource':Types.Variant({
'Article':Types.Nat64,
'Null': Types.Null, # This is the point.
'Post' :Types.Nat64,
'Comment':Types.Nat64,
}),
'extension':Types.Opt(Types.Variant({
'Poll':Types.Record({
'votes_per_user' :Types.Nat8,
'poll_duration_in_minutes' :Types.Nat16,
'options': Types.Vec(Types.Text),
})
}))
})
values = {
'quoted_resource': {'Null':None}, # This is the point.
'extension': []
}
params = [
{'type': types, 'value': values}
]
I know I can export PEM from plug and I can import using Identity.from_pem(private_key). But I was wondering if it was possible to import a Stoic identity via seed phrase. Something like Identity.from_seed(mnemonic). I didn't see anything like this when I looked at methods possible with Identity, so wanted to see if this was going to be supported.
Thanks!
Would love to be able to pass in a delegation as a parameter to Identity or Canister or query_raw (or somewhere else) to be able to call on behalf of delegated principal. Is this possible right now?
Thanks for good library. I have some questions about candid interface file.
README.md
- Canister
Create a canister instance with candid interface file and canister id, and call canister method with canister instance:
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?
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?
Which license are you using? I did not see a license file that was selected.
Error
---------------------------------------------------------------------------
CBORDecodeValueError Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_27050/2334640681.py in <module>
44 params = encode(params)
45 print(f'topping up {collection_name}, only has {canister_cycles/1e12}T cycles, adding 15T cycles.')
---> 46 response = agent.update_raw(cycles_wallet_canister_id,'wallet_call',params)
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in update_raw(self, canister_id, method_name, arg, return_type, effective_canister_id, **kwargs)
112 _ = self.call_endpoint(eid, req_id, data)
113 # print('update.req_id:', req_id.hex())
--> 114 status, result = self.poll(eid, req_id, **kwargs)
115 if status == 'rejected':
116 raise Exception('Rejected: ' + result.decode())
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in poll(self, canister_id, req_id, delay, timeout)
200 status = None
201 for _ in wait(delay, timeout):
--> 202 status, cert = self.request_status_raw(canister_id, req_id)
203 if status == 'replied' or status == 'done' or status == 'rejected':
204 break
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in request_status_raw(self, canister_id, req_id)
179 ['request_status'.encode(), req_id],
180 ]
--> 181 cert = self.read_state_raw(canister_id, paths)
182 status = lookup(['request_status'.encode(), req_id, 'status'.encode()], cert)
183 if (status == None):
/opt/anaconda3/lib/python3.9/site-packages/ic/agent.py in read_state_raw(self, canister_id, paths)
154 elif ret == b'Could not parse body as read request: invalid type: byte array, expected a sequence':
155 raise ValueError('Could not parse body as read request: invalid type: byte array, expected a sequence')
--> 156 d = cbor2.loads(ret)
157 cert = cbor2.loads(d['certificate'])
158 return cert
CBORDecodeValueError: unknown unsigned integer subtype 0x1c
And my code:
canister_to_receive_cycles = collection['id']
collection_name = collection['name']
params = encode([])
result = agent.query_raw(canister_to_receive_cycles, 'availableCycles', params)
if 'availableCycles' in result:
continue # no availableCycles method on the canister
else:
canister_cycles = result[0]['value']
if canister_cycles / 1e12 > 20:
continue # don't need to top it up
else:
# TOP UP TIME
# Send cycles from cycles wallet to canister
cycles_wallet_canister_id = 'xxxxx-xxxxx-xxxxx'
cycles_to_send = int(15e12) # 0.3T cycles is 0.3e12
types = Types.Record({
'args': Types.Vec(Types.Nat8),
'cycles': Types.Nat64,
'method_name': Types.Text,
'canister': Types.Principal
})
values = {
'args':encode([
{'type':Types.Record({'canister_id':Types.Principal}),
'value':{'canister_id':canister_to_receive_cycles}}]),
'cycles':cycles_to_send,
'method_name':'deposit_cycles',
'canister':'aaaaa-aa'
}
params = [{'type':types,'value':values}]
params = encode(params)
print(f'topping up {collection_name}, only has {canister_cycles/1e12}T cycles, adding 15T cycles.')
response = agent.update_raw(cycles_wallet_canister_id,'wallet_call',params)
I have the latest version of ic-py (git pulled and pip installed in the git repo). Any ideas why I might be seeing this unsigned int subtype cbor error parsing the response?
This is not really an issue. I tried to use it locally by using: client = Client(url="http://127.0.0.1:8000"), but this does not work. I am writing Motoko and python programs, but I do not fully understand the internals of the ic. I guess it is not sufficient to just change the url of the client. Any hints?
When I run this code
from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, Types
import time
import schedule
import sys
# params is an array, return value is encoded bytes
# params = [{'type': Types.Nat, 'value': 10}]
# data = encode(params)
# Identity and Client are dependencies of Agent
iden = Identity() # creates a random keypair
client = Client() # creates a client to talk to the IC
# creates an agent, combination of client and identity
agent = Agent(iden, client)
def main():
backup(canister_id=sys.argv[1])
schedule.every(5).seconds.do(backup, canister_id=sys.argv[1])
while True:
schedule.run_pending()
time.sleep(1)
def backup(canister_id):
print(f"disburse completed at {time.ctime()}")
# query the NFT canister
# doesnt change after calling `shuffleAssets`
result = agent.update_raw(
canister_id, "disburse", encode([]))
print(result)
get the following error after a couple of iterations:
Traceback (most recent call last):
File "/home/moritz/.venv/bin/backup", line 8, in <module>
sys.exit(main())
File "/home/moritz/.venv/lib/python3.8/site-packages/state_backup/backup.py", line 25, in main
schedule.run_pending()
File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 780, in run_pending
default_scheduler.run_pending()
File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 100, in run_pending
self._run_job(job)
File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 172, in _run_job
ret = job.run()
File "/home/moritz/.venv/lib/python3.8/site-packages/schedule/__init__.py", line 661, in run
ret = self.job_func()
File "/home/moritz/.venv/lib/python3.8/site-packages/state_backup/backup.py", line 33, in backup
result = agent.update_raw(
File "/home/moritz/.venv/lib/python3.8/site-packages/ic/agent.py", line 92, in update_raw
return decode(result)
File "/home/moritz/.venv/lib/python3.8/site-packages/ic/candid.py", line 1123, in decode
b = Pipe(data)
File "/home/moritz/.venv/lib/python3.8/site-packages/ic/candid.py", line 45, in __init__
self._view = buffer[0:len(buffer)]
TypeError: object of type 'NoneType' has no len()
Do you have an example for how to import a pem identity? I have exported a dfx identity from Plug Wallet, which downloaded as identity.pem. Now I am trying to import private key. Here is the error I get:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
/var/folders/yg/mzpfyl291vx30knxqlx43d2r0000gn/T/ipykernel_62451/1169095691.py in <module>
2 private_key_1 = f.read()
3 from ic.identity import Identity
----> 4 i1 = Identity.from_pem(private_key_1)
/opt/anaconda3/lib/python3.9/site-packages/ic/identity.py in from_pem(pem)
34 def from_pem(pem: str):
35 key = load_pem_private_key(pem.encode(), password=None)
---> 36 privkey = key.private_bytes(encoding=Encoding.Raw, format=PrivateFormat.Raw, encryption_algorithm=NoEncryption()).hex()
37 return Identity(privkey=privkey, type='ed25519')
38
/opt/anaconda3/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/ec.py in private_bytes(self, encoding, format, encryption_algorithm)
230 encryption_algorithm: serialization.KeySerializationEncryption,
231 ) -> bytes:
--> 232 return self._backend._private_key_bytes(
233 encoding,
234 format,
/opt/anaconda3/lib/python3.9/site-packages/cryptography/hazmat/backends/openssl/backend.py in _private_key_bytes(self, encoding, format, encryption_algorithm, key, evp_pkey, cdata)
1471 # Anything that key-specific code was supposed to handle earlier,
1472 # like Raw.
-> 1473 raise ValueError("format is invalid with this key")
1474
1475 def _private_key_bytes_via_bio(self, write_bio, evp_pkey, password):
ValueError: format is invalid with this key
And then here is the code I am running.
from ic.identity import Identity
with open('/Users/bob/Downloads/identity.pem','r') as f:
private_key_1 = f.read()
i1 = Identity.from_pem(private_key_1)
I commented this on the old issue thinking it would reopen it, but it didn't open it, so I'm commenting again here. Thanks!
it would be great if i had a way to check wether or not a canister return a result or trapped for example.
if the canister traps, i get a string instead of the expected result. but if both return types are strings, differentiating becomes cumbersome...
ogy IC0503: Canister s32s7-zqaaa-aaaaj-afksa-cai trapped explicitly: IDL error: unexpected variant tag
Attempting to get the details of a proposal
iden = Identity()
client = Client()
agent = Agent(iden, client)
params = [
{'type': Types.Nat64, 'value': 43117}
]
name = agent.query_raw("rrkah-fqaaa-aaaaa-aaaaq-cai", "get_proposal_info", encode(params))
results in the error
candid.py", line 977, in readTypeTable
raise "field id collision or not sorted"
TypeError: exceptions must derive from BaseException
I see that from debugging the IC has returned a response to my request, but the error occurs in decoding.
I'm getting some type errors when using multiple variants in the same request. For example, I have
key_type : variant { platform; seed_phrase; cross_platform; unknown };
purpose : variant { authentication; recovery };
But in the error, it returns the type table, and I only have one type definition that is variant:
type table1 = variant { 1_744_417_459; 3_053_362_247; 3_484_244_626; 3_782_943_626 }
Notice how in the first case, I have two different types of variants (length 4 and length 2 with different values), but in the error, it groups them into a common type of table1, with length 4.
I would have expected two different types for the two different variants, but this is not the case.
Is this user error on my part in defining types incorrectly? Or is there something weird going on with parsing the variant types? Thank you!
Making query and update calls are great, but sometimes I want to make system calls, which requires read_state syntax as can be seen here: https://smartcontracts.org/docs/interface-spec/index.html#http-read-state
Is this interface implemented in the Python agent? I know the JavaScript agent tests supported some read_state calls, but the documentation around it still wasn't very good.
Thanks!
would be nice if i had access to the method available on a canister and their signatures when i define an actor like this:
ogy = Canister(agent=agent, canister_id=canister_id,
candid=ogy_candid)
I have noticed that your candid parser doesn't parse types/values in candid if they are defined inline. So I have had to pull candid files and manually edit (pull out all inline definitions to define them normally) because they aren't pick up by the candid parser.
This is an enhancement that would be awesome to see.
i transferred 19000 coins and 10000 fee with the update_raw function and the given status is replied and there is not any error, but the transaction is not in the network
I tried it many times and checked the balance, do you have any idea?
Hello. Let me ask you a question.I am building a program to automate social networking posts.
However, I'm struggling to understand how to encode the params correctly for a types record.
The picture shows the correct parameters returned in Invalid record error.
These are the parameters I set.
Can you please tell me if there are any mistakes?
types = Types.Record({
'quoted_resource':Types.Nat64,
'user_tags': Types.Vec(Types.Text),
'nft_image_url':Types.Opt(Types.Text),
'hashtags':Types.Vec(Types.Text),
'"text"':Types.Text,
'image':Types.Opt(Types.Record({'canister_id':Types.Principal,'image_id':Types.Text,'timestamp':Types.Nat64,'format':Types.Text})),
}
)
values = {
'quoted_resource':0,
'user_tags':[],
'nft_image_url':"",
'hashtags':[],
'"text"':"Hello.How are you doing?",
'image':[],
}
Thanks for the great library.
Sincerely,
Wrong
I might be doing something wrong here. I'm getting this error with query_raw method. This is how i'm using it:
agent.query_raw(canisterId, "getList", encode([]))
& i'm getting response:
exceptions must derive from BaseException
# Record Test
types = Types.Record({
'to':Types.Text,
'fee': Types.Int,
'memo':Types.Nat64,
'fromsubaccount':Types.Text,
#'created_at_time':Types.Record({'timestamp_nanos':Types.Nat64}),
'amount':Types.Nat64,
}
)
vals = {
'to':wallet_address_to_send_ICP,
'fee': 10000,
'memo':0,
'fromsubaccount':'asdf',#convert_wallet_address_to_bytes_array(purchasing_wallet_address)],
#'created_at_time':[],
'amount':price,
}
params = [
{'type': types, 'value': vals}
]
params = encode(params)
The code above works, but if you include an underscore in "from_subaccount" like so, then it gives you an error. I think the underscore is being parsed incorrectly.
Hello, I'm struggling to understand how to encode the params correctly for a types record. I'm trying to query the list_neurons method of 'rrkah-fqaaa-aaaaa-aaaaq-cai' (canlista). I've tried multiple combinations for the encoding, but receive errors similar to below.
`from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, decode, Types
iden = Identity()
client = Client(url = "https://ic0.app")
agent = Agent(iden, client)
params = [{'type': Types.Record({'name':Types.Text, 'assets': Types.Nat}), 'value': {'name': 'neuron_ids','assets': 4009}},{'type': Types.Bool, 'value': True}]
params = encode(params)
can_id = 'rrkah-fqaaa-aaaaa-aaaaq-cai'
function = 'list_neurons'
response = agent.query_raw(can_id, function, params)
print(response)
`
Error:
IC0503: Canister rrkah-fqaaa-aaaaa-aaaaq-cai trapped explicitly: Panicked at 'Deserialization Failed: "Fail to decode argument 0 from table0 to record { neuron_ids : vec nat64; include_neurons_readable_by_caller : bool }"', /ic/rs/rust_canisters/dfn_core/src/endpoint.rs:34:41
it would be nice if we could verify signatures that were created with the dfinity agent
Currently, query_raw
, update_raw
is a sync function that blocks the process.
Use aiohttp
to perform HTTP requests and change it to async style.
Running name = agent.query_raw("gvbup-jyaaa-aaaah-qcdwa-cai", "name", encode([])) works.
It provides the response:
[{'type': 'text', 'value': 'XTC Test'}]
Changing the method from name to symbol as follows:
name = agent.query_raw("gvbup-jyaaa-aaaah-qcdwa-cai", "symbol, encode([])) works in DFX and returns ("XTC").
In python, it generates an exception:
Exception has occurred: AttributeError
'NoneType' object has no attribute 'name'
File "C:\Users\trrei\py\Untitled-1.py", line 14, in
name = agent.query_raw("gvbup-jyaaa-aaaah-qcdwa-cai", "symbol", encode([]))
Both the name and symbol methods are text fields per the info in ic.rocks.
I have a friend who is able to run this exact code, but it gives me this error. I'm running from Jupiter Notebooks through Anaconda.
This is the code:
canister_id = '3mttv-dqaaa-aaaah-qcn6q-cai'
from ic.client import Client
from ic.identity import Identity
from ic.agent import Agent
from ic.candid import encode, decode, Types
iden = Identity()
client = Client(url = "https://ic0.app")
agent = Agent(iden, client)
params = []
params = encode(params)
result = agent.query_raw(canister_id, "listings", params)
And this is the error trace. Any help would be appreciated!
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-1481165a8320> in <module>
4 params = []
5 params = encode(params)
----> 6 result = agent.query_raw(canister_id, "listings", params)
/opt/anaconda3/lib/python3.7/site-packages/ic/agent.py in query_raw(self, canister_id, method_name, arg)
72 result = self.query_endpoint(canister_id, data)
73 if result['status'] == 'replied':
---> 74 arg = decode(result['reply']['arg'])
75 return arg
76 elif result['status'] == 'rejected':
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decode(data, retTypes)
1149 outputs.append({
1150 'type': t.name,
-> 1151 'value': t.decodeValue(b, types[i])
1152 })
1153
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
870 raise "Recursive type uninitialized"
871 else:
--> 872 return self._type.decodeValue(b, t)
873
874 @property
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
566 rets = []
567 for _ in range(length):
--> 568 rets.append(self._type.decodeValue(b, vec._type))
569 return rets
570
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
870 raise "Recursive type uninitialized"
871 else:
--> 872 return self._type.decodeValue(b, t)
873
874 @property
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
746 wireType.decodeValue(b, wireType)
747 else:
--> 748 res.append(self._components[i].decodeValue(b, wireType))
749 return res
750
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
870 raise "Recursive type uninitialized"
871 else:
--> 872 return self._type.decodeValue(b, t)
873
874 @property
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
685 expectKey = keys[idx]
686 exceptValue = self._fields[expectKey]
--> 687 x[expectKey] = exceptValue.decodeValue(b, v)
688 idx += 1
689 if idx < len(self._fields):
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
870 raise "Recursive type uninitialized"
871 else:
--> 872 return self._type.decodeValue(b, t)
873
874 @property
/opt/anaconda3/lib/python3.7/site-packages/ic/candid.py in decodeValue(self, b, t)
610 return [self._type.decodeValue(b, opt._type)]
611 else:
--> 612 raise "Not an option value"
613
614 @property
TypeError: exceptions must derive from BaseException
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.