@@ -377,6 +377,14 @@ CLIENT VERIFICATION:
377377**Cargo.toml:**
378378
379379```toml
380+ [package]
381+ name = "certified_vars_backend"
382+ version = "0.1.0"
383+ edition = "2021"
384+
385+ [lib]
386+ crate-type = ["cdylib"]
387+
380388[dependencies]
381389candid = "0.10"
382390ic-cdk = "0.18"
@@ -496,12 +504,22 @@ For canisters serving HTTP responses directly (not through the asset canister),
496504**Additional Cargo.toml dependency:**
497505
498506```toml
507+ [package]
508+ name = "http_certified_backend"
509+ version = "0.1.0"
510+ edition = "2021"
511+
512+ [lib]
513+ crate-type = ["cdylib"]
514+
499515[dependencies]
500516ic-http-certification = "2.6"
501517```
502518
503519**Certifying HTTP responses:**
504520
521+ > **Note:** The HTTP certification API is evolving rapidly. Verify these examples against the latest [ic-http-certification docs](https://docs.rs/ic-http-certification) before use.
522+
505523```rust
506524use ic_http_certification::{
507525 HttpCertification, HttpCertificationTree, HttpCertificationTreeEntry,
@@ -2431,7 +2449,6 @@ import Blob "mo:core/Blob";
24312449import Nat64 "mo:core/Nat64";
24322450import Text "mo:core/Text";
24332451import Runtime "mo:core/Runtime";
2434- import Iter "mo:core/Iter";
24352452
24362453persistent actor {
24372454
@@ -2502,7 +2519,7 @@ persistent actor {
25022519 method = #get;
25032520 transform = ?{
25042521 function = transform;
2505- context = Blob.fromIter(Iter. empty() );
2522+ context = Blob.empty();
25062523 };
25072524 };
25082525
@@ -2511,7 +2528,7 @@ persistent actor {
25112528 let response = await (with cycles = 200_000_000) ic.http_request(request);
25122529
25132530 // Decode the response body
2514- let bodyBlob = Blob.fromIter(Iter. fromArray(response.body) );
2531+ let bodyBlob = Blob.fromArray(response.body);
25152532 let body = Text.decodeUtf8(bodyBlob);
25162533 switch (body) {
25172534 case (?text) { text };
@@ -2523,7 +2540,7 @@ persistent actor {
25232540 public func postData(jsonPayload : Text) : async Text {
25242541 let url = "https://httpbin.org/post";
25252542
2526- let bodyBytes = Iter .toArray(Blob.values( Text.encodeUtf8(jsonPayload) ));
2543+ let bodyBytes = Blob .toArray(Text.encodeUtf8(jsonPayload));
25272544
25282545 let request : HttpRequestArgs = {
25292546 url = url;
@@ -2538,14 +2555,14 @@ persistent actor {
25382555 method = #post;
25392556 transform = ?{
25402557 function = transform;
2541- context = Blob.fromIter(Iter. empty() );
2558+ context = Blob.empty();
25422559 };
25432560 };
25442561
25452562 // POST may cost more due to request body size
25462563 let response = await (with cycles = 300_000_000) ic.http_request(request);
25472564
2548- let bodyBlob = Blob.fromIter(Iter. fromArray(response.body) );
2565+ let bodyBlob = Blob.fromArray(response.body);
25492566 let body = Text.decodeUtf8(bodyBlob);
25502567 switch (body) {
25512568 case (?text) { text };
@@ -2575,7 +2592,7 @@ serde_json = "1"
25752592```
25762593
25772594```rust
2578- use ic_cdk::management_canister::http_request::{
2595+ use ic_cdk::api:: management_canister::http_request::{
25792596 http_request, CanisterHttpRequestArgument, HttpHeader, HttpMethod, HttpResponse,
25802597 TransformArgs, TransformContext, TransformFunc,
25812598};
@@ -2973,7 +2990,7 @@ persistent actor {
29732990 };
29742991
29752992 // Remote ledger actor reference (ICP ledger shown; swap canister ID for other tokens)
2976- let icpLedger = actor ("ryjl3-tyaaa-aaaaa-aaaba-cai") : actor {
2993+ transient let icpLedger = actor ("ryjl3-tyaaa-aaaaa-aaaba-cai") : actor {
29772994 icrc1_balance_of : shared query (Account) -> async Nat;
29782995 icrc1_transfer : shared (TransferArg) -> async { #Ok : Nat; #Err : TransferError };
29792996 icrc2_approve : shared (ApproveArg) -> async { #Ok : Nat; #Err : ApproveError };
@@ -3214,13 +3231,15 @@ async fn transfer_from(from: Principal, to: Principal, amount: Nat) -> Result<Na
32143231
32153232Add to `icp.json`:
32163233
3234+ Pin the release hash before deploying: get the latest hash from https://dashboard.internetcomputer.org/releases, then substitute it for `<RELEASE_HASH>` in both URLs below.
3235+
32173236```json
32183237{
32193238 "canisters": {
32203239 "icrc1_ledger": {
32213240 "type": "custom",
3222- "candid": "https://raw.githubusercontent.com/dfinity/ic/master /rs/ledger_suite/icrc1/ledger/ledger.did",
3223- "wasm": "https://download.dfinity.systems/ic/master /canisters/ic-icrc1-ledger.wasm.gz",
3241+ "candid": "https://raw.githubusercontent.com/dfinity/ic/<RELEASE_HASH> /rs/ledger_suite/icrc1/ledger/ledger.did",
3242+ "wasm": "https://download.dfinity.systems/ic/<RELEASE_HASH> /canisters/ic-icrc1-ledger.wasm.gz",
32243243 "init_arg_file": "icrc1_ledger_init.args"
32253244 }
32263245 }
@@ -3628,7 +3647,7 @@ fn init_owner() -> String {
36283647 let mut cell = owner.borrow_mut();
36293648 match cell.get() {
36303649 None => {
3631- cell.set(Some(caller)).unwrap() ;
3650+ cell.set(Some(caller));
36323651 format!("Owner set to {}", caller)
36333652 }
36343653 Some(_) => "Owner already initialized".to_string(),
@@ -4177,19 +4196,17 @@ fn register(username: String) -> Result<UserProfile, String> {
41774196
41784197 let key = principal_to_key(&caller);
41794198 USERS.with(|users| {
4180- let users = users.borrow();
4181- if users.contains_key(&key) {
4199+ if users.borrow().contains_key(&key) {
41824200 return Err("Already exists".to_string());
41834201 }
4184- drop(users);
41854202
41864203 let profile = UserProfile {
41874204 id: caller,
41884205 username,
41894206 created: ic_cdk::api::time() as i64,
41904207 };
41914208 let bytes = serialize_profile(&profile);
4192- USERS.with(|u| u. borrow_mut().insert(key, bytes) );
4209+ users. borrow_mut().insert(key, bytes);
41934210 Ok(profile)
41944211 })
41954212}
@@ -4493,9 +4510,9 @@ persistent actor Self {
44934510
44944511```rust
44954512use candid::{CandidType, Deserialize, Principal, encode_one};
4496- use ic_cdk::management_canister::main:: {
4513+ use ic_cdk::management_canister::{
44974514 create_canister, install_code,
4498- CreateCanisterArgument, InstallCodeArgument , CanisterInstallMode, CanisterSettings,
4515+ CreateCanisterArgs, InstallCodeArgs , CanisterInstallMode, CanisterSettings,
44994516};
45004517use ic_cdk::update;
45014518use ic_stable_structures::memory_manager::{MemoryId, MemoryManager, VirtualMemory};
@@ -4522,7 +4539,7 @@ async fn create_child_canister(wasm_module: Vec<u8>) -> Principal {
45224539 assert_ne!(caller, Principal::anonymous(), "Auth required");
45234540
45244541 // Create canister
4525- let create_args = CreateCanisterArgument {
4542+ let create_args = CreateCanisterArgs {
45264543 settings: Some(CanisterSettings {
45274544 controllers: Some(vec![ic_cdk::id(), caller]),
45284545 compute_allocation: None,
@@ -4535,21 +4552,21 @@ async fn create_child_canister(wasm_module: Vec<u8>) -> Principal {
45354552 };
45364553
45374554 // Attach 1T cycles for the new canister
4538- let ( create_result,) = create_canister(create_args, 1_000_000_000_000u128)
4555+ let create_result = create_canister(& create_args, 1_000_000_000_000u128)
45394556 .await
45404557 .expect("Failed to create canister");
45414558
45424559 let canister_id = create_result.canister_id;
45434560
45444561 // Install code
4545- let install_args = InstallCodeArgument {
4562+ let install_args = InstallCodeArgs {
45464563 mode: CanisterInstallMode::Install,
45474564 canister_id,
45484565 wasm_module,
45494566 arg: encode_one(&caller).unwrap(), // Pass owner as init arg
45504567 };
45514568
4552- install_code(install_args)
4569+ install_code(& install_args)
45534570 .await
45544571 .expect("Failed to install code");
45554572
@@ -4725,7 +4742,7 @@ dependencies: [icrc-ledger, multi-canister]
47254742---
47264743
47274744# SNS DAO Launch
4728- > version: 1.8.0 | requires: [icp-cli >= 0.1.0, quill CLI , NNS neuron with stake]
4745+ > version: 1.8.0 | requires: [icp-cli >= 0.1.0, dfx sns extension , NNS neuron with stake]
47294746
47304747## What This Is
47314748
@@ -4734,7 +4751,7 @@ Service Nervous System (SNS) is the DAO framework for decentralizing individual
47344751## Prerequisites
47354752
47364753- `icp-cli` >= 0.1.0 (`brew install dfinity/tap/icp-cli`)
4737- - `quill` CLI for proposal submission (`quill sns make-proposal` is the recommended approach)
4754+ - `dfx` with the sns extension (`dfx extension install sns`) for prepare-canisters, validate, and propose
47384755- An NNS neuron with sufficient stake to submit proposals (mainnet)
47394756- Dapp canisters already deployed and working on mainnet
47404757- `sns_init.yaml` configuration file with all parameters defined
@@ -4891,7 +4908,7 @@ Swap:
48914908```
48924909Stage 1: Developer defines parameters in sns_init.yaml
48934910Stage 2: Developer adds NNS Root as co-controller of dapp canisters
4894- Stage 3: Developer submits NNS proposal using `quill sns make-proposal `
4911+ Stage 3: Developer submits NNS proposal using `dfx sns propose `
48954912Stage 4: NNS community votes on the proposal
48964913Stage 5: (If adopted) SNS-W deploys uninitialized SNS canisters
48974914Stage 6: SNS Root becomes sole controller of dapp canisters
@@ -5058,17 +5075,17 @@ icp deploy my_frontend
50585075
50595076```bash
50605077# Step 1: Add NNS Root as co-controller of each dapp canister
5061- # Use quill to add NNS Root as co-controller:
5062- quill sns prepare-canisters add-nns-root BACKEND_CANISTER_ID --network ic
5063- quill sns prepare-canisters add-nns-root FRONTEND_CANISTER_ID --network ic
5078+ # Requires dfx sns extension: `dfx extension install sns`
5079+ dfx sns prepare-canisters add-nns-root BACKEND_CANISTER_ID --network ic
5080+ dfx sns prepare-canisters add-nns-root FRONTEND_CANISTER_ID --network ic
50645081
50655082# Step 2: Validate your config locally before submitting
5066- sns-cli validate -- init-config-file sns_init.yaml
5083+ dfx sns init-config-file validate
50675084# Or review the rendered proposal by inspecting the yaml output carefully.
50685085# You can also test the full flow on a local replica first (see Local Testing above).
50695086
50705087# Step 3: Submit the proposal (THIS IS IRREVERSIBLE — double-check your config)
5071- quill sns make-proposal --network ic --neuron-id NEURON_ID sns_init.yaml
5088+ dfx sns propose --network ic --neuron $ NEURON_ID sns_init.yaml
50725089```
50735090
50745091## Verify It Works
@@ -5622,9 +5639,9 @@ serde_bytes = "0.11"
56225639
56235640# Option A: Use the high-level ic-vetkeys library (if available on crates.io)
56245641# ⚠ Verify this crate exists before adding. If not published, use a git dependency:
5625- # ic-vetkeys = { git = "https://github.com/dfinity/examples", branch = "master " }
5642+ # ic-vetkeys = { git = "https://github.com/dfinity/ic-vetkeys " }
56265643# Or use Option B (raw canister calls) which has no extra dependency.
5627- ic-vetkeys = "0.1 "
5644+ ic-vetkeys = "0.6.0 "
56285645
56295646# Option B: Call management canister directly (lower level, always works)
56305647# No extra dependency -- use ic_cdk::api::call::call_with_payment128
@@ -5918,9 +5935,10 @@ icp canister call backend getPublicKey '()'
59185935icp canister call backend deriveKey '(blob "\00\01...")'
59195936# Expected: (blob "\12\34\56...") -- encrypted key material
59205937
5921- # 3. Verify determinism: same inputs produce same output
5922- # Call deriveKey twice with identical transport key
5923- # Expected: identical encrypted_key blobs both times
5938+ # 3. Note: vetkd_derive_key uses randomized encryption — the encrypted blobs DIFFER each call.
5939+ # The underlying derived key is deterministic (same canister/context/input always produces the same key),
5940+ # but the encrypted_key blob varies because a fresh random nonce is used each time.
5941+ # To verify the underlying key is correct, decrypt both blobs with the transport secret and confirm they match.
59245942
59255943# 4. Verify isolation: different callers get different keys
59265944icp identity new test-user-1 --storage-mode=plaintext
@@ -6139,8 +6157,8 @@ use candid::{CandidType, Deserialize, Nat, Principal};
61396157use ic_cdk::update;
61406158use ic_cdk::management_canister::{
61416159 create_canister, canister_status, deposit_cycles, stop_canister, delete_canister,
6142- CreateCanisterArgument, CanisterIdRecord ,
6143- CanisterSettings, CanisterStatusResponse ,
6160+ CreateCanisterArgs, CanisterStatusArgs, DepositCyclesArgs, StopCanisterArgs, DeleteCanisterArgs ,
6161+ CanisterSettings, CanisterStatusResult ,
61446162};
61456163
61466164#[update]
@@ -6157,40 +6175,39 @@ async fn create_new_canister() -> Principal {
61576175 wasm_memory_limit: None,
61586176 };
61596177
6160- let arg = CreateCanisterArgument {
6178+ let arg = CreateCanisterArgs {
61616179 settings: Some(settings),
61626180 };
61636181
61646182 // Send 1T cycles with the create call
6165- let ( result,) = create_canister(arg, 1_000_000_000_000u128)
6183+ let result = create_canister(& arg, 1_000_000_000_000u128)
61666184 .await
61676185 .expect("Failed to create canister");
61686186
61696187 result.canister_id
61706188}
61716189
61726190#[update]
6173- async fn check_status(canister_id: Principal) -> CanisterStatusResponse {
6174- let (status,) = canister_status(CanisterIdRecord { canister_id })
6191+ async fn check_status(canister_id: Principal) -> CanisterStatusResult {
6192+ canister_status(&CanisterStatusArgs { canister_id })
61756193 .await
6176- .expect("Failed to get canister status");
6177- status
6194+ .expect("Failed to get canister status")
61786195}
61796196
61806197#[update]
61816198async fn top_up(canister_id: Principal, amount: u128) {
6182- deposit_cycles(CanisterIdRecord { canister_id }, amount)
6199+ deposit_cycles(&DepositCyclesArgs { canister_id }, amount)
61836200 .await
61846201 .expect("Failed to deposit cycles");
61856202}
61866203
61876204#[update]
61886205async fn stop_and_delete(canister_id: Principal) {
6189- stop_canister(CanisterIdRecord { canister_id })
6206+ stop_canister(&StopCanisterArgs { canister_id })
61906207 .await
61916208 .expect("Failed to stop canister");
61926209
6193- delete_canister(CanisterIdRecord { canister_id })
6210+ delete_canister(&DeleteCanisterArgs { canister_id })
61946211 .await
61956212 .expect("Failed to delete canister");
61966213}
0 commit comments