Sorry, I just returned from a long trip. I’ll look into this issue and fix it over the next couple of days, and then I’ll release a new version shortly afterward. Thanks for pointing out the issue.
icp-py-core v2.3.1 Released
I have released icp-py-core v2.3.1 with bug fixes for IC spec compliance and new ECDSA P-256 (secp256r1) support. Upgrade with:
pip install --upgrade icp-py-core
This is a drop-in upgrade — no API changes; existing code continues to work.
New features
ECDSA P-256 (secp256r1) identity
Identity now supports P-256 alongside Ed25519 and secp256k1. Useful for WebAuthn / passkey integrations.
from icp_identity.identity import Identity
iden = Identity(type="p256") # or "secp256r1"
Bug fixes
These are silent correctness issues — your code didn’t change, but it now behaves correctly per the IC interface spec.
reject_code now reports the real value
Previously, update calls rejected via the polling / async path silently reported reject_code = 0. You now get the actual reject code (e.g. 5 for
CANISTER_REJECT).
Principal.from_str is case-insensitive
Principal.from_str("AAAAA-AA") and "aaaaa-aa" both work now, per spec.
Principal.self_authenticating accepts more key types
Previously rejected valid BLS subnet keys (including the IC root key) and P-256 keys. Now accepts any well-formed DER public key.
update_raw_async uses the v4 synchronous response
The async path was always polling, even when /call returned the result inline. Now matches the sync fast path — one fewer round-trip in the common case.
Request ID encoding fix
to_request_id was using Signed LEB128 for natural numbers instead of Unsigned LEB128 as the spec mandates. Latent bug fixed before it could bite.
cbor2 6.x compatibility
Closes #14. cbor2 6.0+ returns frozendict for tagged maps; the library now accepts both dict (5.x) and
frozendict (6.x). You can use the latest cbor2 without pinning.
@marc0olo @icpp
Candid composite_query round-trip
Loading a DID file that declares composite_query methods now works end-to-end.