Note that if you don’t add the \ to specify the byte sequence, e7 for example will be interpreted as 65 37 – the respective byte encoding of the chars – instead of 231 – the hex encoding.
I have started to use your IC-PY python package. I would like to use it to query the ledger canister, but I don’t know how to encode the ‘account’ parameters when calling account_balance. Could you please indicate me below what I am doing wrong?
First, you can just import the Ledger canister interface from ic-py directly.
from ic.client import Client
from ic.agent import Agent
from ic.identity import Identity
from ic.common.ledger import Ledger
# 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)
def convert_wallet_address_to_bytes_array(wallet_address):
final_text = list(bytes.fromhex(wallet_address))
return final_text
result = ledger.account_balance({ # type: ignore
"account":
convert_wallet_address_to_bytes_array(
"a40c72396b11001b235b6fba8ec879defeafd7e53f2ff967c118bdb7b767d045")
})
e8s = result[0]['e8s']
icp = e8s / 100000000
print(icp)
The call to the archive canister doesn’t seem to work due to a bug either in Candid or both the JS and Python agents when decoding the response
I’m able to get the response decoded correctly with the following dfx command
❯ dfx canister --network ic call qjdve-lqaaa-aaaaa-aaaeq-cai get_blocks '(record { start = 10 : nat64; length = 1 : nat64 })' --candid cron/archive.did
dfx.json not found, using default.
(
variant {
Ok = record {
blocks = vec {
record {
transaction = record {
memo = 0 : nat64;
operation = opt variant {
Mint = record {
to = blob ">\eb\e1e\bcqS!+z\bf \27\fd\f4d\ae\b3\c8\7f\c9K\ba\b5\a6\d2R\8c \12\e4\f1";
amount = record { e8s = 2_124_797_959_183 : nat64 };
}
};
created_at_time = record {
timestamp_nanos = 1_620_328_630_192_468_691 : nat64;
};
};
timestamp = record {
timestamp_nanos = 1_620_328_630_192_468_691 : nat64;
};
parent_hash = opt blob "\d7\b9\baf~\b7\b0\d1}\81]*\ea\8f9w=\d4\f8\b6p\12\00\04?\89o2\94!\5cv";
};
};
}
},
)
The archive.did is the same used in the ic-py call where the decoding fails with ValueError: Not an option type. The same call using candid ui also fails with Not an option type.
Ok, so if the Candid file is correct and should be parsed correctly, then the agent.js either is buggy for the subtypes case or an old version is used for candid ui.
agent.js hasn’t implemented the full subtyping check yet. As a workaround, it’s best to use the exact did file in JS (the ones that removes the opt type).
The reason is Candid, the language/encoding we use to make the interface. It can do some automatic conversions (e.g. from a naked string to ("text") or choosing the right number type), but some things are more than what is possible (or reasonable) automatically. It is also a matter of tradeoff between what it does automagically and how likely it is to do something wrong when the user makes an input error.
The content is the same, but in different encoding. The first is hex, the second a candid vector
id is short for identifier, these two are the same
The error message is accurate. Candid tuples take commas to separate the values, not semicolons. It wants you to either close the (unary) tuple or to continue with a new value (i.e. put a comma and then the next value. So it should look like this:
(record { to = vec {...} }, memo = 1:nat64, amount = record {e8s = 17_000 }, fee = record { e8s = 10_000 })
In that case the only error was one too many closing braces here: 122; 169} }; memo = 1:nat64. If you change this to 122; 169}; memo = 1:nat64 then the record will continue until the end, and in a record ; is correct to separate the fields. Then it also makes sense why you had an extra closing brace at the end