diff --git a/packages/ic-management/README.md b/packages/ic-management/README.md index 2ef4c290..156c4737 100644 --- a/packages/ic-management/README.md +++ b/packages/ic-management/README.md @@ -39,11 +39,11 @@ const agent = await createAgent({ host: HOST, }); -const { getCanisterDetails } = ICMgmtCanister.create({ +const { canisterStatus } = ICMgmtCanister.create({ agent, }); -const details = await getCanisterDetails(YOUR_CANISTER_ID); +const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); ``` ## Features diff --git a/packages/ic-management/src/errors/ic-management.errors.spec.ts b/packages/ic-management/src/errors/ic-management.errors.spec.ts deleted file mode 100644 index b56da816..00000000 --- a/packages/ic-management/src/errors/ic-management.errors.spec.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { mapError, UserNotTheControllerError } from "./ic-management.errors"; - -describe("IC Management Error utils", () => { - describe("mapError", () => { - it("returns error based on code", () => { - expect(mapError(new Error("code: 403"))).toBeInstanceOf( - UserNotTheControllerError - ); - expect( - mapError(new Error("This is an error message with\ncode: 514")) - ).toBeInstanceOf(Error); - expect( - mapError(new Error("And this is yet another one with\ncode: 509")) - ).toBeInstanceOf(Error); - }); - - it("returns Error if no code is found", () => { - expect(mapError(new Error("no code is found here"))).toBeInstanceOf( - Error - ); - expect( - mapError(new Error("erro message with code: 509 in the same line")) - ).toBeInstanceOf(Error); - }); - }); -}); diff --git a/packages/ic-management/src/errors/ic-management.errors.ts b/packages/ic-management/src/errors/ic-management.errors.ts deleted file mode 100644 index d3ef0be6..00000000 --- a/packages/ic-management/src/errors/ic-management.errors.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Parses and throws convenient error class. - * - * @throws UserNotTheControllerError and Error. - */ -export function mapError(error: Error | unknown): Error | unknown { - const statusLine = - error instanceof Error - ? error.message - : "" - .split("\n") - .map((l) => l.trim().toLowerCase()) - .find( - (l) => l.startsWith("code:") || l.startsWith("http status code:") - ); - - if (statusLine?.includes("403")) { - return new UserNotTheControllerError(); - } - return error; -} - -export class UserNotTheControllerError extends Error {} diff --git a/packages/ic-management/src/ic-management.canister.spec.ts b/packages/ic-management/src/ic-management.canister.spec.ts index f25be6a0..801373c4 100644 --- a/packages/ic-management/src/ic-management.canister.spec.ts +++ b/packages/ic-management/src/ic-management.canister.spec.ts @@ -2,15 +2,9 @@ import type { ManagementCanisterRecord } from "@dfinity/agent"; import { ActorSubclass, HttpAgent } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; import { mock } from "jest-mock-extended"; -import { UserNotTheControllerError } from "./errors/ic-management.errors"; import { ICManagementCanister } from "./ic-management.canister"; -import { - mockCanisterDetails, - mockCanisterId, - mockCanisterSettings, -} from "./ic-management.mock"; -import { CanisterStatusDidResponse } from "./types/ic-management.did"; -import { toCanisterDetails } from "./utils/ic-management.converters"; +import { mockCanisterId, mockCanisterSettings } from "./ic-management.mock"; +import { CanisterStatusResponse } from "./types/ic-management.responses"; describe("ICManagementCanister", () => { const mockAgent: HttpAgent = mock(); @@ -23,7 +17,7 @@ describe("ICManagementCanister", () => { }; describe("ICManagementCanister.getCanisterDetails", () => { - it("returns account identifier when success", async () => { + it("returns canister status when success", async () => { const settings = { freezing_threshold: BigInt(2), controllers: [ @@ -34,7 +28,7 @@ describe("ICManagementCanister", () => { memory_allocation: BigInt(4), compute_allocation: BigInt(10), }; - const response: CanisterStatusDidResponse = { + const response: CanisterStatusResponse = { status: { running: null }, memory_size: BigInt(1000), cycles: BigInt(10_000), @@ -46,24 +40,9 @@ describe("ICManagementCanister", () => { const icManagement = await createICManagement(service); - const res = await icManagement.getCanisterDetails(mockCanisterDetails.id); + const res = await icManagement.canisterStatus(mockCanisterId); - expect(res).toEqual( - toCanisterDetails({ response, canisterId: mockCanisterDetails.id }) - ); - }); - - it("throws UserNotTheControllerError", async () => { - const error = new Error("code: 403"); - const service = mock(); - service.canister_status.mockRejectedValue(error); - - const icManagement = await createICManagement(service); - - const call = () => - icManagement.getCanisterDetails(Principal.fromText("aaaaa-aa")); - - expect(call).rejects.toThrowError(UserNotTheControllerError); + expect(res).toEqual(response); }); it("throws Error", async () => { @@ -74,7 +53,7 @@ describe("ICManagementCanister", () => { const icManagement = await createICManagement(service); const call = () => - icManagement.getCanisterDetails(Principal.fromText("aaaaa-aa")); + icManagement.canisterStatus(Principal.fromText("aaaaa-aa")); expect(call).rejects.toThrowError(Error); }); @@ -112,21 +91,6 @@ describe("ICManagementCanister", () => { expect(service.update_settings).toBeCalled(); }); - it("throws UserNotTheControllerError", async () => { - const error = new Error("code: 403"); - const service = mock(); - service.update_settings.mockRejectedValue(error); - - const icManagement = await createICManagement(service); - - const call = () => - icManagement.updateSettings({ - canisterId: mockCanisterId, - settings: mockCanisterSettings, - }); - expect(call).rejects.toThrowError(UserNotTheControllerError); - }); - it("throws Error", async () => { const error = new Error("Test"); const service = mock(); diff --git a/packages/ic-management/src/ic-management.canister.ts b/packages/ic-management/src/ic-management.canister.ts index c0d55390..9b71d872 100644 --- a/packages/ic-management/src/ic-management.canister.ts +++ b/packages/ic-management/src/ic-management.canister.ts @@ -4,14 +4,9 @@ import { } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; import { toNullable } from "@dfinity/utils"; -import { mapError } from "./errors/ic-management.errors"; import type { ICManagementCanisterOptions } from "./types/canister.options"; -import type { CanisterStatusDidResponse } from "./types/ic-management.did"; -import type { - CanisterDetails, - CanisterSettings, -} from "./types/ic-management.response"; -import { toCanisterDetails } from "./utils/ic-management.converters"; +import type { UpdateSettingsParams } from "./types/ic-management.params"; +import type { CanisterStatusResponse } from "./types/ic-management.responses"; export class ICManagementCanister { private constructor(private readonly service: ManagementCanisterRecord) { @@ -30,25 +25,12 @@ export class ICManagementCanister { * Returns canister details (memory size, status, etc.) * * @param {Principal} canisterId - * @returns Promise - * @throws UserNotTheController, Error + * @returns Promise */ - public getCanisterDetails = async ( - canisterId: Principal - ): Promise => { - try { - const rawResponse: CanisterStatusDidResponse = - await this.service.canister_status({ - canister_id: canisterId, - }); - return toCanisterDetails({ - response: rawResponse, - canisterId, - }); - } catch (error: unknown) { - throw mapError(error); - } - }; + canisterStatus = (canisterId: Principal): Promise => + this.service.canister_status({ + canister_id: canisterId, + }); /** * Update canister settings @@ -56,10 +38,8 @@ export class ICManagementCanister { * @param {Object} params * @param {Principal} params.canisterId * @param {CanisterSettings} params.settings - * @returns Promise - * @throws UserNotTheController, Error */ - public updateSettings = async ({ + updateSettings = async ({ canisterId, settings: { controllers, @@ -67,25 +47,14 @@ export class ICManagementCanister { memoryAllocation, computeAllocation, }, - }: { - canisterId: Principal; - settings: Partial; - }): Promise => { - try { - // Empty array does not change the value in the settings. - await this.service.update_settings({ - canister_id: canisterId, - settings: { - controllers: toNullable( - controllers?.map((c) => Principal.fromText(c)) - ), - freezing_threshold: toNullable(freezingThreshold), - memory_allocation: toNullable(memoryAllocation), - compute_allocation: toNullable(computeAllocation), - }, - }); - } catch (error: unknown) { - throw mapError(error); - } - }; + }: UpdateSettingsParams): Promise => + this.service.update_settings({ + canister_id: canisterId, + settings: { + controllers: toNullable(controllers?.map((c) => Principal.fromText(c))), + freezing_threshold: toNullable(freezingThreshold), + memory_allocation: toNullable(memoryAllocation), + compute_allocation: toNullable(computeAllocation), + }, + }); } diff --git a/packages/ic-management/src/ic-management.mock.ts b/packages/ic-management/src/ic-management.mock.ts index fa786ce5..0099a07a 100644 --- a/packages/ic-management/src/ic-management.mock.ts +++ b/packages/ic-management/src/ic-management.mock.ts @@ -1,9 +1,5 @@ import { Identity } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; -import { - CanisterDetails, - CanisterStatus, -} from "./types/ic-management.response"; export const mockPrincipalText = "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; @@ -16,19 +12,6 @@ export const mockIdentity = { export const mockCanisterId = Principal.fromText("ryjl3-tyaaa-aaaaa-aaaba-cai"); -export const mockCanisterDetails: CanisterDetails = { - id: mockCanisterId, - status: CanisterStatus.Running, - memorySize: BigInt(10), - cycles: BigInt(30), - settings: { - controllers: [mockIdentity.getPrincipal().toText()], - freezingThreshold: BigInt(30), - memoryAllocation: BigInt(1000), - computeAllocation: BigInt(2000), - }, -}; - export const mockCanisterSettings = { freezing_threshold: BigInt(2), controllers: [ diff --git a/packages/ic-management/src/index.ts b/packages/ic-management/src/index.ts index 84cc8329..6c9445f4 100644 --- a/packages/ic-management/src/index.ts +++ b/packages/ic-management/src/index.ts @@ -1,2 +1,3 @@ export { ICManagementCanister } from "./ic-management.canister"; -export * from "./types/ic-management.response"; +export * from "./types/ic-management.params"; +export * from "./types/ic-management.responses"; diff --git a/packages/ic-management/src/types/ic-management.params.ts b/packages/ic-management/src/types/ic-management.params.ts new file mode 100644 index 00000000..827f2469 --- /dev/null +++ b/packages/ic-management/src/types/ic-management.params.ts @@ -0,0 +1,14 @@ +import type { Principal } from "@dfinity/principal"; +import type { QueryParams } from "@dfinity/utils/src"; + +export interface CanisterSettings { + controllers?: string[]; + freezingThreshold?: bigint; + memoryAllocation?: bigint; + computeAllocation?: bigint; +} + +export type UpdateSettingsParams = { + canisterId: Principal; + settings: CanisterSettings; +} & Omit; diff --git a/packages/ic-management/src/types/ic-management.response.ts b/packages/ic-management/src/types/ic-management.response.ts deleted file mode 100644 index 9209315d..00000000 --- a/packages/ic-management/src/types/ic-management.response.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Principal } from "@dfinity/principal"; - -export interface CanisterSettings { - controllers: string[]; - freezingThreshold: bigint; - memoryAllocation: bigint; - computeAllocation: bigint; -} - -export enum CanisterStatus { - Stopped, - Stopping, - Running, -} - -export interface CanisterDetails { - id: Principal; - status: CanisterStatus; - memorySize: bigint; - cycles: bigint; - settings: CanisterSettings; - moduleHash?: ArrayBuffer; -} diff --git a/packages/ic-management/src/types/ic-management.did.ts b/packages/ic-management/src/types/ic-management.responses.ts similarity index 52% rename from packages/ic-management/src/types/ic-management.did.ts rename to packages/ic-management/src/types/ic-management.responses.ts index 36f8e0d5..164bb08d 100644 --- a/packages/ic-management/src/types/ic-management.did.ts +++ b/packages/ic-management/src/types/ic-management.responses.ts @@ -1,14 +1,18 @@ import type { definite_canister_settings } from "../../candid/ic-management"; -export type CanisterStatusDid = - | { stopped: null } - | { stopping: null } - | { running: null }; - -export type CanisterStatusDidResponse = { - status: CanisterStatusDid; +export interface CanisterStatusResponse { + status: + | { + stopped: null; + } + | { + stopping: null; + } + | { + running: null; + }; memory_size: bigint; cycles: bigint; settings: definite_canister_settings; module_hash: [] | [Array]; -}; +} diff --git a/packages/ic-management/src/utils/ic-management.converters.ts b/packages/ic-management/src/utils/ic-management.converters.ts deleted file mode 100644 index 9ec0bd6e..00000000 --- a/packages/ic-management/src/utils/ic-management.converters.ts +++ /dev/null @@ -1,42 +0,0 @@ -import type { Principal } from "@dfinity/principal"; -import { nonNullish } from "@dfinity/utils"; -import type { - CanisterStatusDid as RawCanisterStatus, - CanisterStatusDidResponse, -} from "../types/ic-management.did"; -import type { CanisterDetails } from "../types/ic-management.response"; -import { CanisterStatus } from "../types/ic-management.response"; - -const getCanisterStatus = (status: RawCanisterStatus): CanisterStatus => { - if ("stopped" in status) { - return CanisterStatus.Stopped; - } else if ("stopping" in status) { - return CanisterStatus.Stopping; - } else if ("running" in status) { - return CanisterStatus.Running; - } - throw new Error(status); -}; - -export const toCanisterDetails = ({ - response: { memory_size, status, cycles, settings, module_hash }, - canisterId, -}: { - response: CanisterStatusDidResponse; - canisterId: Principal; -}): CanisterDetails => ({ - id: canisterId, - status: getCanisterStatus(status), - memorySize: memory_size, - cycles: cycles, - settings: { - controllers: settings.controllers.map((principal) => principal.toText()), - freezingThreshold: settings.freezing_threshold, - memoryAllocation: settings.memory_allocation, - computeAllocation: settings.compute_allocation, - }, - moduleHash: - module_hash.length > 0 && nonNullish(module_hash[0]) - ? new Uint8Array(module_hash[0]).buffer - : undefined, -});