Skip to content

Conversation

@bitdivine
Copy link
Collaborator

@bitdivine bitdivine commented Sep 25, 2025

Motivation

A newer ICP runtime is available. A new ic_cdk i needed to use the updated canister API, and the runtimes (pocketic and dfx) need to be updated to provide that new API.

This necessarily requires some fairly deep incisions, so thorough testing is advised.

Changes

  • Update pocket-ic from version 5.0.0 to version 10.0.0
  • Update dfx from version 0.25.0 to 0.29.1
  • Update ic_cdk from version 0.17.2 to 0.18.7
  • Update code to work with this new runtime.
    • Update the ledger canister bindings to use the new Call::unbounded_wait builder instead of the deprecated ic_cdk::call.
      • Note: We should probably switch to bounded wait calls. Unbounded wait is used now to minimize the already substantial changes in this PR.

Tests

Functionality should not have changed, so existing tests should suffice.

@bitdivine bitdivine changed the title Bump ic cdk chore(rust): Bump ic cdk Sep 25, 2025
Copy link
Collaborator Author

@bitdivine bitdivine Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes here are from the formatter.

@@ -21,15 +21,15 @@ The following cryptocurrencies are currently supported:
| ICP Cycles | XDR | The native utility token of the Internet Computer, tied in price to the IMF XDR basket of currencies. |
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes here are from the formatter.


[didc.rust]
target = "custom"
template = "didc.hbs"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

didc still generates bindings for the old ic_cdk API. We need our own template to generate bindings for the new API.

"package": "example_paid_service",
"type": "rust",
"optimize": "cycles",
"gzip": true,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatter at work.

@@ -1,15 +1,13 @@
{
"dfx": "0.25.0",
"dfx": "0.29.1",
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This updates dfx so that it provides the new runtime.

"method": "curl",
"version": "0.5.1",
"url": "https://github.com/dfinity/candid/releases/download/2025-08-04/didc-linux64"
},
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This installs the latest didc, used to generate bindings.

@bitdivine bitdivine marked this pull request as ready for review September 25, 2025 19:38
@@ -112,7 +112,6 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just the formatter at work.

}

pub type TokenAmount = u64;
pub type TokenAmount = u128;
Copy link
Collaborator Author

@bitdivine bitdivine Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the new cdk, cycle amounts are u128 instead of u64.

target="$HOME/.local/bin/$tool"
mkdir -p "$(dirname "$target")"
curl -Lf "$url" | "$pipe" | install -m 755 /dev/stdin "$target"
;;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the install mechanism for didc, used to generate the updated code.

.await
.unwrap();
ans
Call::unbounded_wait(canister_id, &method)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I picked unbounded_wait to minimize changes, but we should think hard about switching to bounded_wait almost immediately. E.g. in the very next PR.


use candid::{self, CandidType, Deserialize, Principal};
use ic_cdk::api::call::CallResult as Result;
use ic_cdk::call::{Call, CallResult as Result};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ic_cdk::api::call::CallResult is now deprecated.

/// The ID of this canister.
fn canister_id(&self) -> Principal {
self.canister_id.clone()
self.canister_id
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clippy: Principal implements the Copy trait.

use ic_cdk::api::call::CallResult;
use pocket_ic::{PocketIc, WasmResult};
use ic_cdk::call::{Call, CallResult};
use pocket_ic::PocketIc;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stop using deprecated types & methods.

Blob(serde_bytes::ByteBuf),
Text(String),
Array(Vec<Box<Value>>),
Array(Vec<Value>),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clippy: The Vec is already on the heap, so the box is pointless.

Ok(Call::unbounded_wait(self.0, "create_canister")
.with_args(&(arg0,))
.await?
.candid()?)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New bindings generated with didc.

.candid()?)
}
pub async fn icrc_2_transfer_from(
pub async fn icrc2_transfer_from(
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: The canister method is icrc2_transfer_from but the old autogenerated bindings inserted an underscore before numbers.

format!(
"Update call error. RejectionCode: {:?}, Error: {}",
e.code, e.description
e.reject_code, e.reject_message
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cdk has a new error type, so we have to update to use the equivalent fields in the new type.

self.wasm_path
))
fs::read(self.wasm_path.clone())
.unwrap_or_else(|_| panic!("Could not find the backend wasm: {}", self.wasm_path))
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clippy complained about a function in expect().

.expect("Failed to approve the paid service to spend the user's ICRC-2 tokens");
}
/// Calls a paid service.
#[allow(clippy::result_large_err)]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error type is 144 bytes. I'm not sure there is much we can do about that. It is an enum of all the different error types that can occur in the payment process, such as the canister call to the ledger failing.

fn inter_canister_call_succeeds_with_sufficient_cycles_only() {
let setup = AttachedCyclesTestSetup::default();
for cycles in 995u64..1005 {
for cycles in 995u128..1005 {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cycles are u128 in the new runtime.

caller.to_string(),
patron.to_string(),
caller,
patron,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clippy

@@ -1,5 +1,5 @@
use super::{PaymentError, PaymentGuardTrait};
use ic_cdk::api::call::{msg_cycles_accept, msg_cycles_available};
use ic_cdk::api::{msg_cycles_accept, msg_cycles_available};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the new methods, not the deprecated ones.

[dependencies]
candid = { workspace = true }
ic-cdk = "0.17.2"
ic-cdk = { workspace = true }
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sure that the ic-cdk version here stays in sync with that used elsewhere in this workspace.

edition = "2021"
publish = true
version = "0.1.1"
version = "0.2.0-alpha.1.1"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump version, as this code is definitely not compatible with version 0.1.1

Copy link

@DecentAgeCoder DecentAgeCoder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants