From a536f4c77e8f55a6751b39e29c9f7fa5e40494fd Mon Sep 17 00:00:00 2001 From: Dan Steren Date: Mon, 2 Oct 2023 10:51:20 -0600 Subject: [PATCH 1/4] Add stubs for stableGrow and stableGrow64 --- src/lib_new/ic.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib_new/ic.ts b/src/lib_new/ic.ts index 385d46f185..353bb5fdc6 100644 --- a/src/lib_new/ic.ts +++ b/src/lib_new/ic.ts @@ -929,9 +929,11 @@ export const ic: Ic = globalThis._azleIc replyRaw: () => {}, setCertifiedData: () => {}, stableBytes: () => {}, + stableGrow: () => {}, stableRead: () => {}, stableSize: () => {}, stableWrite: () => {}, + stable64Grow: () => {}, stable64Read: () => {}, stable64Size: () => {}, stable64Write: () => {}, From 0256f492b9a458b6eebfb444f3762876555d283c Mon Sep 17 00:00:00 2001 From: Dan Steren Date: Mon, 2 Oct 2023 11:31:15 -0600 Subject: [PATCH 2/4] Add TS types for canister_info API --- canisters/management/canister_info.ts | 131 ++++++++++++++++++++ canisters/management/canister_management.ts | 14 +++ canisters/management/index.ts | 4 + 3 files changed, 149 insertions(+) create mode 100644 canisters/management/canister_info.ts diff --git a/canisters/management/canister_info.ts b/canisters/management/canister_info.ts new file mode 100644 index 0000000000..00fc38b262 --- /dev/null +++ b/canisters/management/canister_info.ts @@ -0,0 +1,131 @@ +import { + Record, + Opt, + Vec, + Principal, + Variant, + nat64, + nat8, + Null +} from '../../src/lib_functional'; +import { managementCanister } from '.'; + +/** Argument type of {@link managementCanister.canister_info}. */ +export const CanisterInfoArgs = Record({ + /** Principle of the canister. */ + canister_id: Principal, + /** + * Number of most recent changes requested to be retrieved from canister + * history. No changes are retrieved if this field is `None`. + */ + num_requested_changes: Opt(nat64) +}); + +/** Details about a canister creation. */ +export const CreationRecord = Record({ + /** Initial set of canister controllers. */ + controllers: Vec(Principal) +}); + +/** The mode with which a canister is installed. */ +export const CanisterInstallMode = Variant({ + /** A fresh install of a new canister. */ + install: Null, + /** Reinstalling a canister that was already installed. */ + reinstall: Null, + /** Upgrade an existing canister. */ + upgrade: Null +}); + +/** Details about a canister code deployment. */ +export const CodeDeploymentRecord = Record({ + /** See {@link CanisterInstallMode}. */ + mode: CanisterInstallMode, + /** A SHA256 hash of the new module installed on the canister. */ + module_hash: Vec(nat8) +}); + +/** Details about updating canister controllers. */ +export const ControllersChangeRecord = Record({ + /** The full new set of canister controllers. */ + controllers: Vec(Principal) +}); + +/** Provides details on the respective canister change. */ +export const CanisterChangeDetails = Variant({ + /** See {@link CreationRecord}. */ + creation: CreationRecord, + /** Uninstalling canister's module */ + code_uninstall: Null, + /** See {@link CodeDeploymentRecord}. */ + code_deployment: CodeDeploymentRecord, + /** See {@link ControllersChangeRecord}. */ + controllers_change: ControllersChangeRecord +}); + +/** Details about a canister change initiated by a user. */ +export const FromUserRecord = Record({ + /** Principle of the user. */ + user_id: Principal +}); + +/** + * Details about a canister change initiated by a canister (called *originator*). + */ +export const FromCanisterRecord = Record({ + /** Principle of the originator. */ + canister_id: Principal, + /** + * Canister version of the originator when the originator initiated the + * change. This is `None` if the original does not include its canister + * version in the field `sender_canister_version` of the management canister + * payload. + */ + canister_version: Opt(nat64) +}); + +/** Provides details on who initiated a canister change. */ +export const CanisterChangeOrigin = Variant({ + /** See {@link FromUserRecord}. */ + from_user: FromUserRecord, + /** See {@link FromCanisterRecord}. */ + from_canister: FromCanisterRecord +}); + +/** Represents a canister change as stored in the canister history. */ +export const CanisterChange = Record({ + /** + * The system timestamp (in nanoseconds since Unix Epoch) at which the + * change was performed + */ + timestamp_nanos: nat64, + /** The canister version after performing the change. */ + canister_version: nat64, + /** The change’s origin (a user or a canister). */ + origin: CanisterChangeOrigin, + /** The change’s details. */ + details: CanisterChangeDetails +}); + +/** Return type of {@link managementCanister.canister_info}. */ +export const CanisterInfoResult = Record({ + /** + * Total number of changes ever recorded in canister history. This might be + * higher than the number of canister changes in recent_changes because the + * IC might drop old canister changes from its history (with 20 most recent + * canister changes to always remain in the list). + */ + total_num_changes: nat64, + /** + * The canister changes stored in the order from the oldest to the most + * recent. + */ + recent_changes: Vec(CanisterChange), + /** + * A SHA256 hash of the module installed on the canister. This is null if + * the canister is empty. + */ + module_hash: Opt(Vec(nat8)), + /** Controllers of the canister. */ + controllers: Vec(Principal) +}); diff --git a/canisters/management/canister_management.ts b/canisters/management/canister_management.ts index 87b8dc771b..757c38883f 100644 --- a/canisters/management/canister_management.ts +++ b/canisters/management/canister_management.ts @@ -9,6 +9,20 @@ import { blob } from '../../src/lib_functional'; +export { + CanisterInfoArgs, + CreationRecord, + CanisterInstallMode, + CodeDeploymentRecord, + ControllersChangeRecord, + CanisterChangeDetails, + FromUserRecord, + FromCanisterRecord, + CanisterChangeOrigin, + CanisterChange, + CanisterInfoResult +} from './canister_info'; + export const CanisterId = Principal; export const UserId = Principal; export const WasmModule = blob; diff --git a/canisters/management/index.ts b/canisters/management/index.ts index 4202551d9c..36d2aba4fc 100644 --- a/canisters/management/index.ts +++ b/canisters/management/index.ts @@ -16,6 +16,8 @@ import { SendTransactionArgs } from './bitcoin'; import { + CanisterInfoArgs, + CanisterInfoResult, CanisterStatusArgs, CanisterStatusResult, CreateCanisterArgs, @@ -60,6 +62,8 @@ export const managementCanister = Canister({ uninstall_code: update([UninstallCodeArgs], Void), start_canister: update([StartCanisterArgs], Void), stop_canister: update([StopCanisterArgs], Void), + /** Get public information about the canister. */ + canister_info: update([CanisterInfoArgs], CanisterInfoResult), canister_status: update([CanisterStatusArgs], CanisterStatusResult), delete_canister: update([DeleteCanisterArgs], Void), deposit_cycles: update([DepositCyclesArgs], Void), From 10017916dcb06027f5f866673b38d1b5f97f0485 Mon Sep 17 00:00:00 2001 From: Dan Steren Date: Mon, 2 Oct 2023 13:24:12 -0600 Subject: [PATCH 3/4] Update management canister example --- examples/management_canister/src/index.did | 1 + examples/management_canister/src/index.ts | 17 +++++++++++++++++ examples/management_canister/test/tests.ts | 22 +++++++++++++++++++++- 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/examples/management_canister/src/index.did b/examples/management_canister/src/index.did index 1c11a82a54..ba311bf24e 100644 --- a/examples/management_canister/src/index.did +++ b/examples/management_canister/src/index.did @@ -7,6 +7,7 @@ service: () -> { executeStopCanister: (principal) -> (bool); executeUninstallCode: (principal) -> (bool); executeUpdateSettings: (principal) -> (bool); + getCanisterInfo: (record {canister_id:principal; num_requested_changes:opt nat64}) -> (record {controllers:vec principal; module_hash:opt vec nat8; recent_changes:vec record {timestamp_nanos:nat64; canister_version:nat64; origin:variant {from_user:record {user_id:principal}; from_canister:record {canister_version:opt nat64; canister_id:principal}}; details:variant {creation:record {controllers:vec principal}; code_deployment:record {mode:variant {reinstall; upgrade; install}; module_hash:vec nat8}; controllers_change:record {controllers:vec principal}; code_uninstall}}; total_num_changes:nat64}); getCanisterStatus: (record {canister_id:principal}) -> (record {status:variant {stopped; stopping; running}; memory_size:nat; cycles:nat; settings:record {freezing_threshold:nat; controllers:vec principal; memory_allocation:nat; compute_allocation:nat}; module_hash:opt vec nat8}); getCreatedCanisterId: () -> (principal) query; getRawRand: () -> (vec nat8); diff --git a/examples/management_canister/src/index.ts b/examples/management_canister/src/index.ts index 4e7027998c..9f534bb565 100644 --- a/examples/management_canister/src/index.ts +++ b/examples/management_canister/src/index.ts @@ -13,6 +13,8 @@ import { update } from 'azle'; import { + CanisterInfoArgs, + CanisterInfoResult, CanisterStatusArgs, CanisterStatusResult, CreateCanisterResult, @@ -113,6 +115,21 @@ export default Canister({ return true; }), + getCanisterInfo: update( + [CanisterInfoArgs], + CanisterInfoResult, + async (args) => { + const result = await ic.call(managementCanister.canister_info, { + args: [ + { + canister_id: args.canister_id, + num_requested_changes: args.num_requested_changes + } + ] + }); + return result; + } + ), getCanisterStatus: update( [CanisterStatusArgs], CanisterStatusResult, diff --git a/examples/management_canister/test/tests.ts b/examples/management_canister/test/tests.ts index 33a1c3b044..ad06213c6e 100644 --- a/examples/management_canister/test/tests.ts +++ b/examples/management_canister/test/tests.ts @@ -1,5 +1,5 @@ import { ActorSubclass } from '@dfinity/agent'; -import { ok, Test } from 'azle/test'; +import { Test } from 'azle/test'; import { _SERVICE } from './dfx_generated/management_canister/management_canister.did'; import { readFileSync } from 'fs'; @@ -192,6 +192,26 @@ export function getTests(managementCanister: ActorSubclass<_SERVICE>): Test[] { }; } }, + { + name: 'getCanisterInfo', + test: async () => { + const canisterId = + await managementCanister.getCreatedCanisterId(); + + const canisterInfo = await managementCanister.getCanisterInfo({ + canister_id: canisterId, + num_requested_changes: [50n] + }); + + return { + Ok: + canisterInfo.total_num_changes === 3n && + canisterInfo.recent_changes.length === 3 && + canisterInfo.module_hash.length === 0 && + canisterInfo.controllers.length === 1 + }; + } + }, { name: 'executeDeleteCanister', test: async () => { From fe85181622d1c71ee0b8dd7023b5efeadc0b4cc7 Mon Sep 17 00:00:00 2001 From: Dan Steren Date: Mon, 2 Oct 2023 15:13:57 -0600 Subject: [PATCH 4/4] Implement code review suggestions --- canisters/management/canister_info.ts | 6 ++++++ canisters/management/canister_management.ts | 14 -------------- canisters/management/index.ts | 10 ++++++++-- examples/management_canister/src/index.ts | 13 ++----------- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/canisters/management/canister_info.ts b/canisters/management/canister_info.ts index 00fc38b262..ef82839764 100644 --- a/canisters/management/canister_info.ts +++ b/canisters/management/canister_info.ts @@ -1,3 +1,9 @@ +// JS docs licensed under: +// +// - https://github.com/dfinity/cdk-rs/blob/main/LICENSE +// +// Some documentation changed from original work. + import { Record, Opt, diff --git a/canisters/management/canister_management.ts b/canisters/management/canister_management.ts index 757c38883f..87b8dc771b 100644 --- a/canisters/management/canister_management.ts +++ b/canisters/management/canister_management.ts @@ -9,20 +9,6 @@ import { blob } from '../../src/lib_functional'; -export { - CanisterInfoArgs, - CreationRecord, - CanisterInstallMode, - CodeDeploymentRecord, - ControllersChangeRecord, - CanisterChangeDetails, - FromUserRecord, - FromCanisterRecord, - CanisterChangeOrigin, - CanisterChange, - CanisterInfoResult -} from './canister_info'; - export const CanisterId = Principal; export const UserId = Principal; export const WasmModule = blob; diff --git a/canisters/management/index.ts b/canisters/management/index.ts index 36d2aba4fc..33a44e0b82 100644 --- a/canisters/management/index.ts +++ b/canisters/management/index.ts @@ -1,3 +1,9 @@ +// Some JS docs licensed under: +// +// - https://github.com/dfinity/cdk-rs/blob/main/LICENSE +// +// Some documentation changed from original work. + import { blob, Canister, @@ -15,9 +21,8 @@ import { Satoshi, SendTransactionArgs } from './bitcoin'; +import { CanisterInfoArgs, CanisterInfoResult } from './canister_info'; import { - CanisterInfoArgs, - CanisterInfoResult, CanisterStatusArgs, CanisterStatusResult, CreateCanisterArgs, @@ -42,6 +47,7 @@ import { } from './t_ecdsa'; export * from './bitcoin'; +export * from './canister_info'; export * from './canister_management'; export * from './http_request'; export * from './t_ecdsa'; diff --git a/examples/management_canister/src/index.ts b/examples/management_canister/src/index.ts index 9f534bb565..f4680ad64c 100644 --- a/examples/management_canister/src/index.ts +++ b/examples/management_canister/src/index.ts @@ -120,12 +120,7 @@ export default Canister({ CanisterInfoResult, async (args) => { const result = await ic.call(managementCanister.canister_info, { - args: [ - { - canister_id: args.canister_id, - num_requested_changes: args.num_requested_changes - } - ] + args: [args] }); return result; } @@ -135,11 +130,7 @@ export default Canister({ CanisterStatusResult, async (args) => { return await ic.call(managementCanister.canister_status, { - args: [ - { - canister_id: args.canister_id - } - ] + args: [args] }); } ),