diff --git a/CHANGELOG.md b/CHANGELOG.md index b215f331..4b23b1c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Added `memoToNeuronSubaccount` and `memoToNeuronAccountIdentifier`. - Support new neuron field `voting_power_refreshed_timestamp_seconds`. +- Add support for fetching the canister logs in `@dfinity@ic-management`. - Add `nowInBigIntNanoSeconds` to `@dfinity/utils`, a trivial function that is actually used across all our dapps. ## Build diff --git a/packages/ic-management/README.md b/packages/ic-management/README.md index 7d06a9b8..3c96930a 100644 --- a/packages/ic-management/README.md +++ b/packages/ic-management/README.md @@ -54,7 +54,7 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); ### :factory: ICManagementCanister -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L30) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L33) #### Methods @@ -72,6 +72,7 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); - [canisterStatus](#gear-canisterstatus) - [deleteCanister](#gear-deletecanister) - [provisionalCreateCanisterWithCycles](#gear-provisionalcreatecanisterwithcycles) +- [fetchCanisterLogs](#gear-fetchcanisterlogs) ##### :gear: create @@ -79,7 +80,7 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); | -------- | ---------------------------------------------------------------- | | `create` | `(options: ICManagementCanisterOptions) => ICManagementCanister` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L35) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L38) ##### :gear: createCanister @@ -89,7 +90,7 @@ Create a new canister | ---------------- | ------------------------------------------------------------------------------------- | | `createCanister` | `({ settings, senderCanisterVersion, }?: CreateCanisterParams) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L75) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L78) ##### :gear: updateSettings @@ -99,7 +100,7 @@ Update canister settings | ---------------- | ------------------------------------------------------------------------------------------- | | `updateSettings` | `({ canisterId, senderCanisterVersion, settings, }: UpdateSettingsParams) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L96) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L99) ##### :gear: installCode @@ -109,7 +110,7 @@ Install code to a canister | ------------- | ----------------------------------------------------------------------------------------------------- | | `installCode` | `({ mode, canisterId, wasmModule, arg, senderCanisterVersion, }: InstallCodeParams) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L118) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L121) ##### :gear: uploadChunk @@ -124,7 +125,7 @@ Parameters: - `params.canisterId`: The canister in which the chunks will be stored. - `params.chunk`: A chunk of Wasm module. -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L143) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L146) ##### :gear: clearChunkStore @@ -138,7 +139,7 @@ Parameters: - `params.canisterId`: The canister in which the chunks are stored. -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L163) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L166) ##### :gear: storedChunks @@ -152,7 +153,7 @@ Parameters: - `params.canisterId`: The canister in which the chunks are stored. -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L182) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L185) ##### :gear: installChunkedCode @@ -172,7 +173,7 @@ Parameters: - `params.storeCanisterId`: Specifies the canister in whose chunk storage the chunks are stored (this parameter defaults to target_canister if not specified). - `params.wasmModuleHash`: The Wasm module hash as hex string. Used to check that the SHA-256 hash of wasm_module is equal to the wasm_module_hash parameter and can calls install_code with parameters. -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L207) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L210) ##### :gear: uninstallCode @@ -182,7 +183,7 @@ Uninstall code from a canister | --------------- | -------------------------------------------------------------------------------- | | `uninstallCode` | `({ canisterId, senderCanisterVersion, }: UninstallCodeParams) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L240) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L243) ##### :gear: startCanister @@ -192,7 +193,7 @@ Start a canister | --------------- | ------------------------------------------ | | `startCanister` | `(canisterId: Principal) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L255) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L258) ##### :gear: stopCanister @@ -202,7 +203,7 @@ Stop a canister | -------------- | ------------------------------------------ | | `stopCanister` | `(canisterId: Principal) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L264) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L267) ##### :gear: canisterStatus @@ -212,7 +213,7 @@ Get canister details (memory size, status, etc.) | ---------------- | ------------------------------------------------------------ | | `canisterStatus` | `(canisterId: Principal) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L273) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L276) ##### :gear: deleteCanister @@ -222,7 +223,7 @@ Deletes a canister | ---------------- | ------------------------------------------ | | `deleteCanister` | `(canisterId: Principal) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L284) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L287) ##### :gear: provisionalCreateCanisterWithCycles @@ -232,7 +233,17 @@ Creates a canister. Only available on development instances. | ------------------------------------- | ------------------------------------------------------------------------------------------------------- | | `provisionalCreateCanisterWithCycles` | `({ settings, amount, canisterId, }?: ProvisionalCreateCanisterWithCyclesParams) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L296) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L299) + +##### :gear: fetchCanisterLogs + +Given a canister ID as input, this method returns a vector of logs of that canister including its trap messages. The canister logs are not collected in canister methods running in non-replicated mode (NRQ, CQ, CRy, CRt, CC, and F modes, as defined in Overview of imports). The total size of all returned logs does not exceed 4KiB. If new logs are added resulting in exceeding the maximum total log size of 4KiB, the oldest logs will be removed. Logs persist across canister upgrades and they are deleted if the canister is reinstalled or uninstalled. + +| Method | Type | +| ------------------- | ---------------------------------------------------------------- | +| `fetchCanisterLogs` | `(canisterId: Principal) => Promise` | + +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/ic-management/src/ic-management.canister.ts#L321) diff --git a/packages/ic-management/src/ic-management.canister.spec.ts b/packages/ic-management/src/ic-management.canister.spec.ts index baf0c06e..55b48bda 100644 --- a/packages/ic-management/src/ic-management.canister.spec.ts +++ b/packages/ic-management/src/ic-management.canister.spec.ts @@ -25,7 +25,10 @@ import { type StoredChunksParams, type UploadChunkParams, } from "./types/ic-management.params"; -import { CanisterStatusResponse } from "./types/ic-management.responses"; +import { + CanisterStatusResponse, + type FetchCanisterLogsResponse, +} from "./types/ic-management.responses"; describe("ICManagementCanister", () => { const mockAgent: HttpAgent = mock(); @@ -667,4 +670,52 @@ describe("ICManagementCanister", () => { expect(call).rejects.toThrowError(Error); }); }); + + describe("fetchCanisterLogs", () => { + it("returns canister logs when success", async () => { + const settings = { + freezing_threshold: BigInt(2), + controllers: [mockPrincipal], + memory_allocation: BigInt(4), + compute_allocation: BigInt(10), + reserved_cycles_limit: BigInt(11), + log_visibility: { controllers: null }, + wasm_memory_limit: BigInt(500_00), + }; + const response: FetchCanisterLogsResponse = { + canister_log_records: [ + { + idx: 123n, + content: [1, 2, 3], + timestamp_nanos: 12345n, + }, + { + idx: 456n, + content: [9, 8, 7], + timestamp_nanos: 12346n, + }, + ], + }; + const service = mock(); + service.fetch_canister_logs.mockResolvedValue(response); + + const icManagement = await createICManagement(service); + + const res = await icManagement.fetchCanisterLogs(mockCanisterId); + + expect(res).toEqual(response); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.fetch_canister_logs.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.fetchCanisterLogs(mockCanisterId); + + expect(call).rejects.toThrowError(Error); + }); + }); }); diff --git a/packages/ic-management/src/ic-management.canister.ts b/packages/ic-management/src/ic-management.canister.ts index b10c19e1..4cb9f0e3 100644 --- a/packages/ic-management/src/ic-management.canister.ts +++ b/packages/ic-management/src/ic-management.canister.ts @@ -25,7 +25,10 @@ import { type UpdateSettingsParams, type UploadChunkParams, } from "./types/ic-management.params"; -import type { CanisterStatusResponse } from "./types/ic-management.responses"; +import type { + CanisterStatusResponse, + FetchCanisterLogsResponse, +} from "./types/ic-management.responses"; export class ICManagementCanister { private constructor(private readonly service: IcManagementService) { @@ -308,4 +311,17 @@ export class ICManagementCanister { return canister_id; }; + + /** + * Given a canister ID as input, this method returns a vector of logs of that canister including its trap messages. The canister logs are not collected in canister methods running in non-replicated mode (NRQ, CQ, CRy, CRt, CC, and F modes, as defined in Overview of imports). The total size of all returned logs does not exceed 4KiB. If new logs are added resulting in exceeding the maximum total log size of 4KiB, the oldest logs will be removed. Logs persist across canister upgrades and they are deleted if the canister is reinstalled or uninstalled. + * + * @param {Principal} canisterId + * @returns {Promise} + */ + fetchCanisterLogs = ( + canisterId: Principal, + ): Promise => + this.service.fetch_canister_logs({ + canister_id: canisterId, + }); } diff --git a/packages/ic-management/src/types/ic-management.responses.ts b/packages/ic-management/src/types/ic-management.responses.ts index 37204781..2d06b8ef 100644 --- a/packages/ic-management/src/types/ic-management.responses.ts +++ b/packages/ic-management/src/types/ic-management.responses.ts @@ -5,3 +5,8 @@ export type CanisterStatusResponse = ServiceResponse< IcManagementService, "canister_status" >; + +export type FetchCanisterLogsResponse = ServiceResponse< + IcManagementService, + "fetch_canister_logs" +>;