-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Report from building a production application using ic-vetkeys (EncryptedMaps, KeyManager) with a React frontend. Covers skills used, issues encountered, and suggestions for new skills.
Issues already reported in #96 (Illegal invocation fetch fix, SDK version/import issues, local II deployment, ic_env cookie issues) are excluded here — this report focuses on new findings only.
1. vetkd skill: Rust API mismatches
The skill's Rust code shows types imported from ic_vetkeys::types that actually live in ic_cdk::management_canister:
// Skill shows:
use ic_vetkeys::types::{VetKDCurve, VetKDKeyId};
// Actual:
use ic_cdk::management_canister::{VetKDCurve, VetKDKeyId};The enum variant name is also wrong:
// Skill shows:
VetKDCurve::Bls12381G2
// Actual (ic-cdk 0.19):
VetKDCurve::Bls12_381_G2These cause immediate compilation failures.
2. vetkd skill: TypeScript API doesn't match @dfinity/vetkeys v0.4.0
The skill's frontend examples use an API that doesn't exist in the current npm package:
| Skill shows | Actual @dfinity/vetkeys v0.4.0 API |
|---|---|
TransportSecretKey.fromSeed(seed) |
TransportSecretKey.random() |
tsk.publicKey() |
tsk.publicKeyBytes() |
vetKey.toDerivedKeyMaterial() |
vetKey.asDerivedKeyMaterial() (returns Promise) |
Manual crypto.subtle.importKey("raw", material.data.slice(0,32), ...) |
keyMaterial.deriveAesGcmCryptoKey(domainSep) |
The DerivedKeyMaterial class has a much richer API than documented — encryptMessage(), decryptMessage(), and deriveAesGcmCryptoKey() handle IV generation and key derivation internally. The skill's manual crypto.subtle approach works but is unnecessary and error-prone.
3. vetkd skill: EncryptedMaps not documented
The ic-vetkeys crate's EncryptedMaps<T: AccessControl> is the primary abstraction most developers will want — it wraps KeyManager + StableBTreeMap into a single struct with integrated encrypted storage and access control. It's not mentioned in the skill at all.
Key API details discovered by reading crate source:
EncryptedMaps::init()takes 4 memory regions (not 3 likeKeyManager): config, ACL, shared keys, and data storageKeyId = (Principal, Blob<32>)— owner principal + 32-byte map nameMapKey = Blob<32>— entries within a map use 32-byte keysEncryptedMapValue = ByteBuf— the crate's ownByteBuftype (notVec<u8>; hasFrom/Intoconversions)- Owner automatically gets
ReadWriteManagerights set_user_rights()/remove_user()for granting/revoking accessget_encrypted_values_for_map()checks ACL before returning ciphertextget_encrypted_vetkey()also checks ACL — access control and encryption are coupled (two independent locks)get_accessible_shared_map_names()for discovering what's been shared with youget_all_accessible_encrypted_maps()for bulk retrieval
Example init (not in any skill):
use ic_vetkeys::encrypted_maps::EncryptedMaps;
use ic_vetkeys::types::AccessRights;
ENCRYPTED_MAPS.with(|em| {
*em.borrow_mut() = Some(EncryptedMaps::init(
"my_app_v1", // domain separator
key_id, // VetKDKeyId
mm.get(MemoryId::new(0)), // config memory
mm.get(MemoryId::new(1)), // ACL memory
mm.get(MemoryId::new(2)), // shared keys memory
mm.get(MemoryId::new(3)), // encrypted data memory
));
});4. vetkd skill: Missing getrandom dependency for WASM
Building ic-vetkeys for wasm32-unknown-unknown fails without:
getrandom = { version = "0.2", features = ["custom"] }The error is:
error: the wasm*-unknown-unknown targets are not supported by default,
you may need to enable the "js" feature.
This is a hard build failure that every Rust vetKeys project will hit. Should be in the skill's Cargo.toml example.
5. stable-memory skill: Missing into_bytes in Storable example
The Rust Storable trait in ic-stable-structures v0.7 requires into_bytes(self) -> Vec<u8> in addition to to_bytes(&self) -> Cow<[u8]>. The skill's example omits into_bytes, causing a compilation error:
error[E0046]: not all trait items implemented, missing: `into_bytes`
6. icp-cli skill: No documentation for custom gateway port
When running multiple ICP projects simultaneously, they all default to port 8000 and conflict. The gateway.port configuration option exists (confirmed via icp-yaml-schema.json) but is not documented in any skill:
networks:
- name: local
mode: managed
gateway:
port: 80017. icp-cli skill: candid-extractor workflow not documented
The workflow for generating .did files from Rust canisters using export_candid!() is not covered by any skill. The process:
- Add
ic_cdk::export_candid!();to lib.rs - Build:
cargo build --target wasm32-unknown-unknown --release - Extract:
candid-extractor target/wasm32-unknown-unknown/release/<name>.wasm > <name>.did - Use with
@icp-sdk/bindgenfor TypeScript bindings
candid-extractor must be installed separately (cargo install candid-extractor). Without this workflow documented, developers have no clear path from export_candid!() to TypeScript bindings.
Suggested new skills
encrypted-maps
A skill covering ic-vetkeys's EncryptedMaps — the primary abstraction for building encrypted storage applications. Should cover:
- Init with 4 memory regions
- Type system:
KeyId,MapKey,EncryptedMapValue,ByteBuf - CRUD operations on encrypted values
- Access control: grant, revoke, list shared users
- Frontend pattern: deriving key material for another user's map (shared data decryption)
- Complete working example
candid-generation
A skill covering .did file generation and TypeScript binding creation:
export_candid!()macro usagecandid-extractortool@icp-sdk/bindgenVite plugin configuration- The full pipeline: Rust → WASM → .did → TypeScript bindings → frontend actor
Version matrix
All working together as of March 2026:
| Dependency | Version |
|---|---|
ic-cdk |
0.19 |
ic-stable-structures |
0.7 |
ic-vetkeys |
0.6 |
candid |
0.10 |
getrandom |
0.2 (features = ["custom"]) |
@icp-sdk/core |
5.1.0 |
@icp-sdk/bindgen |
0.2.3 |
@dfinity/vetkeys |
0.4.0 |
| Rust | 1.93.0 |
| Node.js | 24.8.0 |