diff --git a/canisters/management/canister_management.ts b/canisters/management/canister_management.ts index c1c2b8e5e9..026116d93c 100644 --- a/canisters/management/canister_management.ts +++ b/canisters/management/canister_management.ts @@ -35,6 +35,11 @@ export const CanisterSettings = Record({ }); export type CanisterSettings = typeof CanisterSettings.tsType; +export const ChunkHash = Record({ + hash: blob +}); +export type ChunkHash = typeof ChunkHash.tsType; + /** * The arguments to provide to the management canister's create_canister * method @@ -89,6 +94,28 @@ export const UpdateSettingsArgs = Record({ }); export type UpdateSettingsArgs = typeof UpdateSettingsArgs.tsType; +export const UploadChunkArgs = Record({ + canister_id: CanisterId, + chunk: blob +}); +export type UploadChunkArgs = typeof UploadChunkArgs.tsType; + +export const UploadChunkResult = ChunkHash; +export type UploadChunkResult = typeof UploadChunkResult.tsType; + +export const ClearChunkStoreArgs = Record({ + canister_id: CanisterId +}); +export type ClearChunkStoreArgs = typeof ClearChunkStoreArgs.tsType; + +export const StoredChunksArgs = Record({ + canister_id: CanisterId +}); +export type StoredChunksArgs = typeof StoredChunksArgs.tsType; + +export const StoredChunksResult = Vec(ChunkHash); +export type StoredChunksResult = typeof StoredChunksResult.tsType; + export const InstallCodeMode = Variant({ install: Null, reinstall: Null, @@ -105,6 +132,17 @@ export const InstallCodeArgs = Record({ }); export type InstallCodeArgs = typeof InstallCodeArgs.tsType; +export const InstallChunkedCodeArgs = Record({ + mode: InstallCodeMode, + target_canister: CanisterId, + store_canister: Opt(CanisterId), + chunk_hashes_list: Vec(ChunkHash), + wasm_module_hash: blob, + arg: blob, + sender_canister_version: Opt(nat64) +}); +export type InstallChunkedCodeArgs = typeof InstallChunkedCodeArgs.tsType; + export const UninstallCodeArgs = Record({ canister_id: CanisterId, sender_canister_version: Opt(nat64) diff --git a/canisters/management/ic.did b/canisters/management/ic.did index 7eab9045b0..28b974ffa1 100644 --- a/canisters/management/ic.did +++ b/canisters/management/ic.did @@ -1,4 +1,4 @@ -// Taken from: https://github.com/dfinity/interface-spec/blob/d04e0dd12956d7b7f52ea01e1bba24479deffa00/spec/_attachments/ic.did +// Taken from: https://github.com/dfinity/interface-spec/blob/6e00887946b612a1169964fc75ee14f57c0ce65d/spec/_attachments/ic.did // Copyright 2021 DFINITY Foundation // @@ -18,70 +18,77 @@ type canister_id = principal; type wasm_module = blob; type canister_settings = record { - controllers : opt vec principal; - compute_allocation : opt nat; - memory_allocation : opt nat; - freezing_threshold : opt nat; - reserved_cycles_limit : opt nat; + controllers : opt vec principal; + compute_allocation : opt nat; + memory_allocation : opt nat; + freezing_threshold : opt nat; + reserved_cycles_limit : opt nat; }; type definite_canister_settings = record { - controllers : vec principal; - compute_allocation : nat; - memory_allocation : nat; - freezing_threshold : nat; - reserved_cycles_limit : nat; + controllers : vec principal; + compute_allocation : nat; + memory_allocation : nat; + freezing_threshold : nat; + reserved_cycles_limit : nat; }; type change_origin = variant { - from_user : record { - user_id : principal; - }; - from_canister : record { - canister_id : principal; - canister_version : opt nat64; - }; + from_user : record { + user_id : principal; + }; + from_canister : record { + canister_id : principal; + canister_version : opt nat64; + }; }; type change_details = variant { - creation : record { - controllers : vec principal; - }; - code_uninstall; - code_deployment : record { - mode : variant {install; reinstall; upgrade}; - module_hash : blob; - }; - controllers_change : record { - controllers : vec principal; - }; + creation : record { + controllers : vec principal; + }; + code_uninstall; + code_deployment : record { + mode : variant { install; reinstall; upgrade }; + module_hash : blob; + }; + controllers_change : record { + controllers : vec principal; + }; }; type change = record { - timestamp_nanos : nat64; - canister_version : nat64; - origin : change_origin; - details : change_details; + timestamp_nanos : nat64; + canister_version : nat64; + origin : change_origin; + details : change_details; }; -type chunk_hash = blob; +type chunk_hash = record { + hash : blob; +}; -type http_header = record { name: text; value: text }; +type http_header = record { + name : text; + value : text; +}; -type http_response = record { - status: nat; - headers: vec http_header; - body: blob; +type http_request_result = record { + status : nat; + headers : vec http_header; + body : blob; }; -type ecdsa_curve = variant { secp256k1; }; +type ecdsa_curve = variant { + secp256k1; +}; type satoshi = nat64; type bitcoin_network = variant { - mainnet; - testnet; - regtest; + mainnet; + testnet; + regtest; }; type bitcoin_address = text; @@ -89,45 +96,67 @@ type bitcoin_address = text; type block_hash = blob; type outpoint = record { - txid : blob; - vout : nat32 + txid : blob; + vout : nat32; }; type utxo = record { - outpoint: outpoint; - value: satoshi; - height: nat32; + outpoint : outpoint; + value : satoshi; + height : nat32; }; -type get_utxos_request = record { - address : bitcoin_address; - network: bitcoin_network; - filter: opt variant { - min_confirmations: nat32; - page: blob; - }; +type bitcoin_get_utxos_args = record { + address : bitcoin_address; + network : bitcoin_network; + filter : opt variant { + min_confirmations : nat32; + page : blob; + }; +}; + +type bitcoin_get_utxos_query_args = record { + address : bitcoin_address; + network : bitcoin_network; + filter : opt variant { + min_confirmations : nat32; + page : blob; + }; +}; + +type bitcoin_get_current_fee_percentiles_args = record { + network : bitcoin_network; }; -type get_current_fee_percentiles_request = record { - network: bitcoin_network; +type bitcoin_get_utxos_result = record { + utxos : vec utxo; + tip_block_hash : block_hash; + tip_height : nat32; + next_page : opt blob; }; -type get_utxos_response = record { - utxos: vec utxo; - tip_block_hash: block_hash; - tip_height: nat32; - next_page: opt blob; +type bitcoin_get_utxos_query_result = record { + utxos : vec utxo; + tip_block_hash : block_hash; + tip_height : nat32; + next_page : opt blob; }; -type get_balance_request = record { - address : bitcoin_address; - network: bitcoin_network; - min_confirmations: opt nat32; +type bitcoin_get_balance_args = record { + address : bitcoin_address; + network : bitcoin_network; + min_confirmations : opt nat32; }; -type send_transaction_request = record { - transaction: blob; - network: bitcoin_network; +type bitcoin_get_balance_query_args = record { + address : bitcoin_address; + network : bitcoin_network; + min_confirmations : opt nat32; +}; + +type bitcoin_send_transaction_args = record { + transaction : blob; + network : bitcoin_network; }; type millisatoshi_per_byte = nat64; @@ -138,125 +167,212 @@ type node_metrics = record { num_block_failures_total : nat64; }; -service ic : { - create_canister : (record { +type create_canister_args = record { settings : opt canister_settings; sender_canister_version : opt nat64; - }) -> (record {canister_id : canister_id}); - update_settings : (record { +}; + +type create_canister_result = record { + canister_id : canister_id; +}; + +type update_settings_args = record { canister_id : principal; settings : canister_settings; sender_canister_version : opt nat64; - }) -> (); - upload_chunk : (record { +}; + +type upload_chunk_args = record { canister_id : principal; chunk : blob; - }) -> (chunk_hash); - clear_chunk_store: (record {canister_id : canister_id}) -> (); - stored_chunks: (record {canister_id : canister_id}) -> (vec chunk_hash); - install_code : (record { - mode : variant { - install; - reinstall; - upgrade : opt record { - skip_pre_upgrade: opt bool; - } +}; + +type clear_chunk_store_args = record { + canister_id : canister_id; +}; + +type stored_chunks_args = record { + canister_id : canister_id; +}; + +type canister_install_mode = variant { + install; + reinstall; + upgrade : opt record { + skip_pre_upgrade : opt bool; }; +}; + +type install_code_args = record { + mode : canister_install_mode; canister_id : canister_id; wasm_module : wasm_module; arg : blob; sender_canister_version : opt nat64; - }) -> (); - install_chunked_code: (record { - mode : variant { - install; - reinstall; - upgrade : opt record { - skip_pre_upgrade: opt bool; - }; - }; - target_canister: canister_id; - storage_canister: opt canister_id; - chunk_hashes_list: vec chunk_hash; - wasm_module_hash: blob; +}; + +type install_chunked_code_args = record { + mode : canister_install_mode; + target_canister : canister_id; + store_canister : opt canister_id; + chunk_hashes_list : vec chunk_hash; + wasm_module_hash : blob; arg : blob; sender_canister_version : opt nat64; - }) -> (); - uninstall_code : (record { +}; + +type uninstall_code_args = record { canister_id : canister_id; sender_canister_version : opt nat64; - }) -> (); - start_canister : (record {canister_id : canister_id}) -> (); - stop_canister : (record {canister_id : canister_id}) -> (); - canister_status : (record {canister_id : canister_id}) -> (record { - status : variant { running; stopping; stopped }; - settings: definite_canister_settings; - module_hash: opt blob; - memory_size: nat; - cycles: nat; - reserved_cycles: nat; - idle_cycles_burned_per_day: nat; - }); - canister_info : (record { - canister_id : canister_id; - num_requested_changes : opt nat64; - }) -> (record { - total_num_changes : nat64; - recent_changes : vec change; - module_hash : opt blob; - controllers : vec principal; - }); - delete_canister : (record {canister_id : canister_id}) -> (); - deposit_cycles : (record {canister_id : canister_id}) -> (); - raw_rand : () -> (blob); - http_request : (record { +}; + +type start_canister_args = record { + canister_id : canister_id; +}; + +type stop_canister_args = record { + canister_id : canister_id; +}; + +type canister_status_args = record { + canister_id : canister_id; +}; + +type canister_status_result = record { + status : variant { running; stopping; stopped }; + settings : definite_canister_settings; + module_hash : opt blob; + memory_size : nat; + cycles : nat; + reserved_cycles : nat; + idle_cycles_burned_per_day : nat; +}; + +type canister_info_args = record { + canister_id : canister_id; + num_requested_changes : opt nat64; +}; + +type canister_info_result = record { + total_num_changes : nat64; + recent_changes : vec change; + module_hash : opt blob; + controllers : vec principal; +}; + +type delete_canister_args = record { + canister_id : canister_id; +}; + +type deposit_cycles_args = record { + canister_id : canister_id; +}; + +type http_request_args = record { url : text; - max_response_bytes: opt nat64; + max_response_bytes : opt nat64; method : variant { get; head; post }; - headers: vec http_header; + headers : vec http_header; body : opt blob; transform : opt record { - function : func (record {response : http_response; context : blob}) -> (http_response) query; - context : blob + function : func(record { response : http_request_result; context : blob }) -> (http_request_result) query; + context : blob; }; - }) -> (http_response); +}; - // Threshold ECDSA signature - ecdsa_public_key : (record { +type ecdsa_public_key_args = record { canister_id : opt canister_id; derivation_path : vec blob; - key_id : record { curve: ecdsa_curve; name: text }; - }) -> (record { public_key : blob; chain_code : blob; }); - sign_with_ecdsa : (record { + key_id : record { curve : ecdsa_curve; name : text }; +}; + +type ecdsa_public_key_result = record { + public_key : blob; + chain_code : blob; +}; + +type sign_with_ecdsa_args = record { message_hash : blob; derivation_path : vec blob; - key_id : record { curve: ecdsa_curve; name: text }; - }) -> (record { signature : blob }); - - // bitcoin interface - bitcoin_get_balance: (get_balance_request) -> (satoshi); - bitcoin_get_balance_query: (get_balance_request) -> (satoshi) query; - bitcoin_get_utxos: (get_utxos_request) -> (get_utxos_response); - bitcoin_get_utxos_query: (get_utxos_request) -> (get_utxos_response) query; - bitcoin_send_transaction: (send_transaction_request) -> (); - bitcoin_get_current_fee_percentiles: (get_current_fee_percentiles_request) -> (vec millisatoshi_per_byte); - - // metrics interface - node_metrics_history : (record { + key_id : record { curve : ecdsa_curve; name : text }; +}; + +type sign_with_ecdsa_result = record { + signature : blob; +}; + +type node_metrics_history_args = record { subnet_id : principal; - start_at_timestamp_nanos: nat64; - }) -> (vec record { + start_at_timestamp_nanos : nat64; +}; + +type node_metrics_history_result = vec record { timestamp_nanos : nat64; node_metrics : vec node_metrics; - }); +}; - // provisional interfaces for the pre-ledger world - provisional_create_canister_with_cycles : (record { - amount: opt nat; +type provisional_create_canister_with_cycles_args = record { + amount : opt nat; settings : opt canister_settings; - specified_id: opt canister_id; + specified_id : opt canister_id; sender_canister_version : opt nat64; - }) -> (record {canister_id : canister_id}); - provisional_top_up_canister : - (record { canister_id: canister_id; amount: nat }) -> (); -} +}; + +type provisional_create_canister_with_cycles_result = record { + canister_id : canister_id; +}; + +type provisional_top_up_canister_args = record { + canister_id : canister_id; + amount : nat; +}; + +type raw_rand_result = blob; + +type stored_chunks_result = vec chunk_hash; + +type upload_chunk_result = chunk_hash; + +type bitcoin_get_balance_result = satoshi; + +type bitcoin_get_balance_query_result = satoshi; + +type bitcoin_get_current_fee_percentiles_result = vec millisatoshi_per_byte; + +service ic : { + create_canister : (create_canister_args) -> (create_canister_result); + update_settings : (update_settings_args) -> (); + upload_chunk : (upload_chunk_args) -> (upload_chunk_result); + clear_chunk_store : (clear_chunk_store_args) -> (); + stored_chunks : (stored_chunks_args) -> (stored_chunks_result); + install_code : (install_code_args) -> (); + install_chunked_code : (install_chunked_code_args) -> (); + uninstall_code : (uninstall_code_args) -> (); + start_canister : (start_canister_args) -> (); + stop_canister : (stop_canister_args) -> (); + canister_status : (canister_status_args) -> (canister_status_result); + canister_info : (canister_info_args) -> (canister_info_result); + delete_canister : (delete_canister_args) -> (); + deposit_cycles : (deposit_cycles_args) -> (); + raw_rand : () -> (raw_rand_result); + http_request : (http_request_args) -> (http_request_result); + + // Threshold ECDSA signature + ecdsa_public_key : (ecdsa_public_key_args) -> (ecdsa_public_key_result); + sign_with_ecdsa : (sign_with_ecdsa_args) -> (sign_with_ecdsa_result); + + // bitcoin interface + bitcoin_get_balance : (bitcoin_get_balance_args) -> (bitcoin_get_balance_result); + bitcoin_get_balance_query : (bitcoin_get_balance_query_args) -> (bitcoin_get_balance_query_result) query; + bitcoin_get_utxos : (bitcoin_get_utxos_args) -> (bitcoin_get_utxos_result); + bitcoin_get_utxos_query : (bitcoin_get_utxos_query_args) -> (bitcoin_get_utxos_query_result) query; + bitcoin_send_transaction : (bitcoin_send_transaction_args) -> (); + bitcoin_get_current_fee_percentiles : (bitcoin_get_current_fee_percentiles_args) -> (bitcoin_get_current_fee_percentiles_result); + + // metrics interface + node_metrics_history : (node_metrics_history_args) -> (node_metrics_history_result); + + // provisional interfaces for the pre-ledger world + provisional_create_canister_with_cycles : (provisional_create_canister_with_cycles_args) -> (provisional_create_canister_with_cycles_result); + provisional_top_up_canister : (provisional_top_up_canister_args) -> (); +}; \ No newline at end of file diff --git a/canisters/management/index.ts b/canisters/management/index.ts index 4251283cda..20a747d244 100644 --- a/canisters/management/index.ts +++ b/canisters/management/index.ts @@ -18,18 +18,24 @@ import { CanisterInfoArgs, CanisterInfoResult } from './canister_info'; import { CanisterStatusArgs, CanisterStatusResult, + ClearChunkStoreArgs, CreateCanisterArgs, CreateCanisterResult, DeleteCanisterArgs, DepositCyclesArgs, + InstallChunkedCodeArgs, InstallCodeArgs, ProvisionalCreateCanisterWithCyclesArgs, ProvisionalCreateCanisterWithCyclesResult, ProvisionalTopUpCanisterArgs, StartCanisterArgs, StopCanisterArgs, + StoredChunksArgs, + StoredChunksResult, UninstallCodeArgs, - UpdateSettingsArgs + UpdateSettingsArgs, + UploadChunkArgs, + UploadChunkResult } from './canister_management'; import { HttpRequestArgs, HttpResponse } from './http_request'; import { @@ -57,7 +63,11 @@ export const managementCanister = Canister({ // canister management create_canister: update([CreateCanisterArgs], CreateCanisterResult), update_settings: update([UpdateSettingsArgs], Void), + upload_chunk: update([UploadChunkArgs], UploadChunkResult), + clear_chunk_store: update([ClearChunkStoreArgs], Void), + stored_chunks: update([StoredChunksArgs], StoredChunksResult), install_code: update([InstallCodeArgs], Void), + install_chunked_code: update([InstallChunkedCodeArgs], Void), uninstall_code: update([UninstallCodeArgs], Void), start_canister: update([StartCanisterArgs], Void), stop_canister: update([StopCanisterArgs], Void), diff --git a/examples/management_canister/src/index.ts b/examples/management_canister/src/index.ts index 2a714e1f32..ed73d76663 100644 --- a/examples/management_canister/src/index.ts +++ b/examples/management_canister/src/index.ts @@ -12,16 +12,19 @@ import { query, serialize, Some, - update + update, + Vec } from 'azle'; import { CanisterInfoArgs, CanisterInfoResult, CanisterStatusArgs, CanisterStatusResult, + ChunkHash, CreateCanisterResult, managementCanister, - ProvisionalCreateCanisterWithCyclesResult + ProvisionalCreateCanisterWithCyclesResult, + StoredChunksResult } from 'azle/canisters/management'; type State = { @@ -79,6 +82,84 @@ export default Canister({ return true; }), + executeUploadChunk: update( + [Principal, blob], + ChunkHash, + async (canisterId, chunk) => { + if (process.env.AZLE_TEST_FETCH === 'true' || false) { + const response = await fetch(`icp://aaaaa-aa/upload_chunk`, { + body: serialize({ + args: [ + { + canister_id: canisterId, + chunk + } + ] + }) + }); + + return await response.json(); + } else { + return await ic.call(managementCanister.upload_chunk, { + args: [ + { + canister_id: canisterId, + chunk + } + ] + }); + } + } + ), + executeClearChunkStore: update([Principal], bool, async (canisterId) => { + if (process.env.AZLE_TEST_FETCH === 'true' || false) { + await fetch(`icp://aaaaa-aa/clear_chunk_store`, { + body: serialize({ + args: [ + { + canister_id: canisterId + } + ] + }) + }); + } else { + await ic.call(managementCanister.clear_chunk_store, { + args: [ + { + canister_id: canisterId + } + ] + }); + } + + return true; + }), + getStoredChunks: update( + [Principal], + StoredChunksResult, + async (canisterId) => { + if (process.env.AZLE_TEST_FETCH === 'true') { + const response = await fetch(`icp://aaaaa-aa/stored_chunks`, { + body: serialize({ + args: [ + { + canister_id: canisterId + } + ] + }) + }); + return await response.json(); + } else { + return await ic.call(managementCanister.stored_chunks, { + args: [ + { + canister_id: canisterId + } + ] + }); + } + } + ), executeInstallCode: update( [Principal, blob], bool, @@ -120,6 +201,51 @@ export default Canister({ return true; } ), + executeInstallChunkedCode: update( + [Principal, Vec(ChunkHash), blob], + bool, + async (canisterId, chunkHashes, wasmModuleHash) => { + if (process.env.AZLE_TEST_FETCH === 'true') { + await fetch(`icp://aaaaa-aa/install_chunked_code`, { + body: serialize({ + args: [ + { + mode: { + install: null + }, + target_canister: canisterId, + store_canister: [], + chunk_hashes_list: chunkHashes, + wasm_module_hash: wasmModuleHash, + arg: Uint8Array.from([]), + sender_canister_version: [] + } + ], + cycles: 100_000_000_000n + }) + }); + } else { + await ic.call(managementCanister.install_chunked_code, { + args: [ + { + mode: { + install: null + }, + target_canister: canisterId, + store_canister: None, + chunk_hashes_list: chunkHashes, + wasm_module_hash: wasmModuleHash, + arg: Uint8Array.from([]), + sender_canister_version: None + } + ], + cycles: 100_000_000_000n + }); + } + + return true; + } + ), executeUninstallCode: update([Principal], bool, async (canisterId) => { if (process.env.AZLE_TEST_FETCH === 'true') { await fetch(`icp://aaaaa-aa/uninstall_code`, { diff --git a/examples/management_canister/test/tests.ts b/examples/management_canister/test/tests.ts index 4cb35e3ea8..e2d728a87f 100644 --- a/examples/management_canister/test/tests.ts +++ b/examples/management_canister/test/tests.ts @@ -1,5 +1,6 @@ import { ActorSubclass } from '@dfinity/agent'; import { Test } from 'azle/test'; +import { createHash } from 'crypto'; import { readFileSync } from 'fs'; import { _SERVICE } from './dfx_generated/management_canister/management_canister.did'; @@ -52,7 +53,7 @@ export function getTests(managementCanister: ActorSubclass<_SERVICE>): Test[] { const result = await managementCanister.executeInstallCode( canisterId, - wasmModule as any + wasmModule ); return { @@ -61,49 +62,132 @@ export function getTests(managementCanister: ActorSubclass<_SERVICE>): Test[] { } }, { - name: 'executeDepositCycles', + name: 'executeUninstallCode', test: async () => { const canisterId = await managementCanister.getCreatedCanisterId(); - const statusBefore = await managementCanister.getCanisterStatus( - { + await managementCanister.executeUninstallCode(canisterId); + + const getCanisterStatusResult = + await managementCanister.getCanisterStatus({ canister_id: canisterId - } - ); + }); - const cyclesBefore = statusBefore.cycles; + const canisterStatus = getCanisterStatusResult; - await managementCanister.executeDepositCycles(canisterId); + return { + Ok: canisterStatus.module_hash.length === 0 + }; + } + }, + { + name: 'executeUploadChunk ', + test: async () => { + const canisterId = + await managementCanister.getCreatedCanisterId(); - const statusAfter = await managementCanister.getCanisterStatus({ - canister_id: canisterId - }); + const wasmModule = Array.from(readFileSync('src/test.wasm')); - const cyclesAfter = statusAfter.cycles; + const chunkUploadResult = + await managementCanister.executeUploadChunk( + canisterId, + wasmModule + ); return { - Ok: cyclesAfter > cyclesBefore + Ok: chunkUploadResult.hash.length === 32 }; } }, { - name: 'executeUninstallCode', + name: 'getStoredChunks', + test: async () => { + const canisterId = + await managementCanister.getCreatedCanisterId(); + + const storedChunks = + await managementCanister.getStoredChunks(canisterId); + + const wasmModule = Uint8Array.from( + readFileSync('src/test.wasm') + ); + const wasmHash = createHash('sha256') + .update(wasmModule) + .digest(); + + return { + Ok: + storedChunks.length === 1 && + Uint8Array.from(wasmHash).toString() === + storedChunks[0].hash.toString() + }; + } + }, + { + name: 'executeInstallChunkedCode', test: async () => { const canisterId = await managementCanister.getCreatedCanisterId(); + const storedChunks = + await managementCanister.getStoredChunks(canisterId); + + const result = + await managementCanister.executeInstallChunkedCode( + canisterId, + storedChunks, + storedChunks[0].hash + ); + await managementCanister.executeUninstallCode(canisterId); - const getCanisterStatusResult = - await managementCanister.getCanisterStatus({ + return { + Ok: result + }; + } + }, + { + name: 'executeClearChunkStore', + test: async () => { + const canisterId = + await managementCanister.getCreatedCanisterId(); + + const result = + await managementCanister.executeClearChunkStore(canisterId); + + const storedChunks = + await managementCanister.getStoredChunks(canisterId); + + return { + Ok: result && storedChunks.length === 0 + }; + } + }, + { + name: 'executeDepositCycles', + test: async () => { + const canisterId = + await managementCanister.getCreatedCanisterId(); + + const statusBefore = await managementCanister.getCanisterStatus( + { canister_id: canisterId - }); + } + ); - const canisterStatus = getCanisterStatusResult; + const cyclesBefore = statusBefore.cycles; + + await managementCanister.executeDepositCycles(canisterId); + + const statusAfter = await managementCanister.getCanisterStatus({ + canister_id: canisterId + }); + + const cyclesAfter = statusAfter.cycles; return { - Ok: canisterStatus.module_hash.length === 0 + Ok: cyclesAfter > cyclesBefore }; } }, @@ -176,7 +260,7 @@ export function getTests(managementCanister: ActorSubclass<_SERVICE>): Test[] { return { Ok: 'running' in canisterStatus.status && - canisterStatus.memory_size === 342n && + canisterStatus.memory_size === 550n && canisterStatus.cycles >= 800_000_000_000n && canisterStatus.settings.freezing_threshold === 2_000_000n && @@ -201,8 +285,8 @@ export function getTests(managementCanister: ActorSubclass<_SERVICE>): Test[] { return { Ok: - canisterInfo.total_num_changes === 3n && - canisterInfo.recent_changes.length === 3 && + canisterInfo.total_num_changes === 5n && + canisterInfo.recent_changes.length === 5 && canisterInfo.module_hash.length === 0 && canisterInfo.controllers.length === 1 }; diff --git a/the_azle_book/src/reference/management_canister/clear_chunk_store.md b/the_azle_book/src/reference/management_canister/clear_chunk_store.md new file mode 100644 index 0000000000..af3fa916c6 --- /dev/null +++ b/the_azle_book/src/reference/management_canister/clear_chunk_store.md @@ -0,0 +1,26 @@ +# clear_chunk_store + +This section is a work in progress. + +Examples: + +- [management_canister](https://github.com/demergent-labs/azle/tree/main/examples/management_canister) + +```typescript +import { bool, Canister, ic, Principal, update } from 'azle'; +import { managementCanister } from 'azle/canisters/management'; + +export default Canister({ + executeClearChunkStore: update([Principal], bool, async (canisterId) => { + await ic.call(managementCanister.clear_chunk_store, { + args: [ + { + canister_id: canisterId + } + ] + }); + + return true; + }) +}); +``` diff --git a/the_azle_book/src/reference/management_canister/install_chunked_code.md b/the_azle_book/src/reference/management_canister/install_chunked_code.md new file mode 100644 index 0000000000..fbf1f11aad --- /dev/null +++ b/the_azle_book/src/reference/management_canister/install_chunked_code.md @@ -0,0 +1,39 @@ +# install_chunked_code + +This section is a work in progress. + +Examples: + +- [management_canister](https://github.com/demergent-labs/azle/tree/main/examples/management_canister) + +```typescript +import { blob, bool, Canister, ic, None, Principal, update } from 'azle'; +import { managementCanister } from 'azle/canisters/management'; + +export default Canister({ + executeInstallChunkedCode: update( + [Principal, blob], + bool, + async (canisterId, wasmModuleHash) => { + await ic.call(managementCanister.install_chunked_code, { + args: [ + { + mode: { + install: null + }, + target_canister: canisterId, + store_canister: None, + chunk_hashes_list: [{ hash: wasmModuleHash }], + wasm_module_hash: wasmModuleHash, + arg: Uint8Array.from([]), + sender_canister_version: None + } + ], + cycles: 100_000_000_000n + }); + + return true; + } + ) +}); +``` diff --git a/the_azle_book/src/reference/management_canister/stored_chunks.md b/the_azle_book/src/reference/management_canister/stored_chunks.md new file mode 100644 index 0000000000..25f064b099 --- /dev/null +++ b/the_azle_book/src/reference/management_canister/stored_chunks.md @@ -0,0 +1,31 @@ +# stored_chunks + +This section is a work in progress. + +Examples: + +- [management_canister](https://github.com/demergent-labs/azle/tree/main/examples/management_canister) + +```typescript +import { Canister, ic, Principal, query } from 'azle'; +import { + managementCanister, + StoredChunksResult +} from 'azle/canisters/management'; + +export default Canister({ + getStoredChunks: query( + [Principal], + StoredChunksResult, + async (canisterId) => { + return await ic.call(managementCanister.stored_chunks, { + args: [ + { + canister_id: canisterId + } + ] + }); + } + ) +}); +``` diff --git a/the_azle_book/src/reference/management_canister/upload_chunk.md b/the_azle_book/src/reference/management_canister/upload_chunk.md new file mode 100644 index 0000000000..17e5bd032f --- /dev/null +++ b/the_azle_book/src/reference/management_canister/upload_chunk.md @@ -0,0 +1,32 @@ +# upload_chunk + +This section is a work in progress. + +Examples: + +- [management_canister](https://github.com/demergent-labs/azle/tree/main/examples/management_canister) + +```typescript +import { blob, Canister, ic, Principal, update } from 'azle'; +import { + managementCanister, + UploadChunkResult +} from 'azle/canisters/management'; + +export default Canister({ + executeUploadChunk: update( + [Principal, blob], + UploadChunkResult, + async (canisterId, wasmChunk) => { + return await ic.call(managementCanister.upload_chunk, { + args: [ + { + canister_id: canisterId, + chunk: wasmChunk + } + ] + }); + } + ) +}); +```