diff --git a/packages/ic-management/README.md b/packages/ic-management/README.md index cb82d5ad..c1e6e047 100644 --- a/packages/ic-management/README.md +++ b/packages/ic-management/README.md @@ -57,8 +57,15 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); #### Methods - [create](#gear-create) -- [canisterStatus](#gear-canisterstatus) +- [createCanister](#gear-createcanister) - [updateSettings](#gear-updatesettings) +- [installCode](#gear-installcode) +- [uninstallCode](#gear-uninstallcode) +- [startCanister](#gear-startcanister) +- [stopCanister](#gear-stopcanister) +- [canisterStatus](#gear-canisterstatus) +- [canisterInfo](#gear-canisterinfo) +- [deleteCanister](#gear-deletecanister) ##### :gear: create @@ -66,21 +73,77 @@ const { status, memory_size, ...rest } = await canisterStatus(YOUR_CANISTER_ID); | -------- | ---------------------------------------------------------------- | | `create` | `(options: ICManagementCanisterOptions) => ICManagementCanister` | -##### :gear: canisterStatus +##### :gear: createCanister -Returns canister details (memory size, status, etc.) +Create a new canister -| Method | Type | -| ---------------- | ------------------------------------------------------------ | -| `canisterStatus` | `(canisterId: Principal) => Promise` | +| Method | Type | +| ---------------- | ------------------------------------------------------------------------------------ | +| `createCanister` | `({ settings, senderCanisterVerion, }?: CreateCanisterParams) => Promise` | ##### :gear: updateSettings Update canister settings -| Method | Type | -| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `updateSettings` | `({ canisterId, settings: { controllers, freezingThreshold, memoryAllocation, computeAllocation, }, }: UpdateSettingsParams) => Promise` | +| Method | Type | +| ---------------- | ------------------------------------------------------------------------------------------ | +| `updateSettings` | `({ canisterId, senderCanisterVerion, settings, }: UpdateSettingsParams) => Promise` | + +##### :gear: installCode + +Install code to a canister + +| Method | Type | +| ------------- | ---------------------------------------------------------------------------------------------------- | +| `installCode` | `({ mode, canisterId, wasmModule, arg, senderCanisterVerion, }: InstallCodeParams) => Promise` | + +##### :gear: uninstallCode + +Uninstall code from a canister + +| Method | Type | +| --------------- | ------------------------------------------------------------------------------- | +| `uninstallCode` | `({ canisterId, senderCanisterVerion, }: UninstallCodeParams) => Promise` | + +##### :gear: startCanister + +Start a canister + +| Method | Type | +| --------------- | ------------------------------------------ | +| `startCanister` | `(canisterId: Principal) => Promise` | + +##### :gear: stopCanister + +Stop a canister + +| Method | Type | +| -------------- | ------------------------------------------ | +| `stopCanister` | `(canisterId: Principal) => Promise` | + +##### :gear: canisterStatus + +Get canister details (memory size, status, etc.) + +| Method | Type | +| ---------------- | --------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | +| `canisterStatus` | `(canisterId: Principal) => Promise<{ status: { stopped: null; } or { stopping: null; } | { running: null; }; memory_size: bigint; cycles: bigint; settings: definite_canister_settings; idle_cycles_burned_per_day: bigint; module_hash: [] | [...]; }>` | + +##### :gear: canisterInfo + +Get canister info (controllers, module hash, changes, etc.) + +| Method | Type | +| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `canisterInfo` | `({ canisterId, numRequestChanges, }: CanisterInfoParams) => Promise<{ controllers: Principal[]; module_hash: [] or [Uint8Array]; recent_changes: change[]; total_num_changes: bigint; }>` | + +##### :gear: deleteCanister + +Deletes a canister + +| Method | Type | +| ---------------- | ------------------------------------------ | +| `deleteCanister` | `(canisterId: Principal) => Promise` | diff --git a/packages/ic-management/src/ic-management.canister.spec.ts b/packages/ic-management/src/ic-management.canister.spec.ts index 801373c4..1eaf687f 100644 --- a/packages/ic-management/src/ic-management.canister.spec.ts +++ b/packages/ic-management/src/ic-management.canister.spec.ts @@ -1,59 +1,66 @@ -import type { ManagementCanisterRecord } from "@dfinity/agent"; import { ActorSubclass, HttpAgent } from "@dfinity/agent"; -import { Principal } from "@dfinity/principal"; +import { ServiceResponse } from "@dfinity/utils"; import { mock } from "jest-mock-extended"; +import type { _SERVICE as IcManagementService } from "../candid/ic-management"; import { ICManagementCanister } from "./ic-management.canister"; -import { mockCanisterId, mockCanisterSettings } from "./ic-management.mock"; -import { CanisterStatusResponse } from "./types/ic-management.responses"; +import { + mappedMockCanisterSettings, + mockCanisterId, + mockCanisterSettings, + mockPrincipal, + mockPrincipalText, +} from "./ic-management.mock"; +import { + CanisterSettings, + InstallCodeParams, + InstallMode, + toInstallMode, +} from "./types/ic-management.params"; +import { + CanisterInfoResponse, + CanisterStatusResponse, +} from "./types/ic-management.responses"; describe("ICManagementCanister", () => { const mockAgent: HttpAgent = mock(); - const createICManagement = async (service: ManagementCanisterRecord) => { + const createICManagement = async (service: IcManagementService) => { return ICManagementCanister.create({ agent: mockAgent, - serviceOverride: service as ActorSubclass, + serviceOverride: service as ActorSubclass, }); }; - describe("ICManagementCanister.getCanisterDetails", () => { - it("returns canister status when success", async () => { - const settings = { - freezing_threshold: BigInt(2), - controllers: [ - Principal.fromText( - "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe" - ), - ], - memory_allocation: BigInt(4), - compute_allocation: BigInt(10), - }; - const response: CanisterStatusResponse = { - status: { running: null }, - memory_size: BigInt(1000), - cycles: BigInt(10_000), - settings, - module_hash: [], - }; - const service = mock(); - service.canister_status.mockResolvedValue(response); + describe("createCanister", () => { + it("returns canister id when success", async () => { + const response: ServiceResponse = + { + canister_id: mockCanisterId, + }; + const service = mock(); + service.create_canister.mockResolvedValue(response); const icManagement = await createICManagement(service); - const res = await icManagement.canisterStatus(mockCanisterId); + const res = await icManagement.createCanister({ + settings: mockCanisterSettings, + }); - expect(res).toEqual(response); + expect(res).toEqual(response.canister_id); + expect(service.create_canister).toHaveBeenCalledWith({ + settings: [mappedMockCanisterSettings], + sender_canister_version: [], + }); }); it("throws Error", async () => { const error = new Error("Test"); - const service = mock(); - service.canister_status.mockRejectedValue(error); + const service = mock(); + service.create_canister.mockRejectedValue(error); const icManagement = await createICManagement(service); - const call = () => - icManagement.canisterStatus(Principal.fromText("aaaaa-aa")); + const call = () => icManagement.createCanister(); expect(call).rejects.toThrowError(Error); }); @@ -61,7 +68,7 @@ describe("ICManagementCanister", () => { describe("updateSettings", () => { it("calls update_settings with new settings", async () => { - const service = mock(); + const service = mock(); service.update_settings.mockResolvedValue(undefined); const icManagement = await createICManagement(service); @@ -70,16 +77,19 @@ describe("ICManagementCanister", () => { canisterId: mockCanisterId, settings: mockCanisterSettings, }); - expect(service.update_settings).toBeCalled(); + + expect(service.update_settings).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + settings: mappedMockCanisterSettings, + sender_canister_version: [], + }); }); it("works when passed partial settings", async () => { - const partialSettings = { - controllers: [ - "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe", - ], + const partialSettings: CanisterSettings = { + controllers: [mockPrincipalText], }; - const service = mock(); + const service = mock(); service.update_settings.mockResolvedValue(undefined); const icManagement = await createICManagement(service); @@ -88,12 +98,21 @@ describe("ICManagementCanister", () => { canisterId: mockCanisterId, settings: partialSettings, }); - expect(service.update_settings).toBeCalled(); + expect(service.update_settings).toBeCalledWith({ + canister_id: mockCanisterId, + sender_canister_version: [], + settings: { + compute_allocation: [], + controllers: [[mockPrincipal]], + freezing_threshold: [], + memory_allocation: [], + }, + }); }); it("throws Error", async () => { const error = new Error("Test"); - const service = mock(); + const service = mock(); service.update_settings.mockRejectedValue(error); const icManagement = await createICManagement(service); @@ -103,6 +122,242 @@ describe("ICManagementCanister", () => { canisterId: mockCanisterId, settings: mockCanisterSettings, }); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("installCode", () => { + it.each([InstallMode.Install, InstallMode.Reinstall, InstallMode.Upgrade])( + "calls install_code with mode %s", + async (mode) => { + const params: InstallCodeParams = { + wasmModule: new Uint8Array([1, 2, 3]), + mode, + arg: new Uint8Array(), + canisterId: mockCanisterId, + }; + const service = mock(); + service.install_code.mockResolvedValue(undefined); + + const icManagement = await createICManagement(service); + + await icManagement.installCode(params); + + expect(service.install_code).toHaveBeenCalledWith({ + wasm_module: params.wasmModule, + mode: toInstallMode(params.mode), + canister_id: params.canisterId, + arg: params.arg, + sender_canister_version: [], + }); + } + ); + + it("throws Error", async () => { + const params: InstallCodeParams = { + wasmModule: new Uint8Array([1, 2, 3]), + mode: InstallMode.Install, + arg: new Uint8Array(), + canisterId: mockCanisterId, + }; + const error = new Error("Test"); + const service = mock(); + service.install_code.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.installCode(params); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("uninstallCode", () => { + it("calls uninstall_code", async () => { + const service = mock(); + service.uninstall_code.mockResolvedValue(undefined); + + const icManagement = await createICManagement(service); + + await icManagement.uninstallCode({ canisterId: mockCanisterId }); + + expect(service.uninstall_code).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + sender_canister_version: [], + }); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.uninstall_code.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => + icManagement.uninstallCode({ canisterId: mockCanisterId }); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("startCanister", () => { + it("calls start_canister", async () => { + const service = mock(); + service.start_canister.mockResolvedValue(undefined); + + const icManagement = await createICManagement(service); + + await icManagement.startCanister(mockCanisterId); + + expect(service.start_canister).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + }); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.start_canister.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.startCanister(mockCanisterId); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("stopCanister", () => { + it("calls stop_canister", async () => { + const service = mock(); + service.stop_canister.mockResolvedValue(undefined); + + const icManagement = await createICManagement(service); + + await icManagement.stopCanister(mockCanisterId); + + expect(service.stop_canister).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + }); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.stop_canister.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.stopCanister(mockCanisterId); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("canisterStatus", () => { + it("returns canister status when success", async () => { + const settings = { + freezing_threshold: BigInt(2), + controllers: [mockPrincipal], + memory_allocation: BigInt(4), + compute_allocation: BigInt(10), + }; + const response: CanisterStatusResponse = { + status: { running: null }, + memory_size: BigInt(1000), + cycles: BigInt(10_000), + settings, + idle_cycles_burned_per_day: BigInt(0), + module_hash: [], + }; + const service = mock(); + service.canister_status.mockResolvedValue(response); + + const icManagement = await createICManagement(service); + + const res = await icManagement.canisterStatus(mockCanisterId); + + expect(res).toEqual(response); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.canister_status.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.canisterStatus(mockCanisterId); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("canisterInfo", () => { + it("returns canister info when success", async () => { + const response: CanisterInfoResponse = { + controllers: [mockPrincipal], + module_hash: [new Uint8Array([1, 2, 3])], + recent_changes: [], + total_num_changes: BigInt(0), + }; + const service = mock(); + service.canister_info.mockResolvedValue(response); + + const icManagement = await createICManagement(service); + + const res = await icManagement.canisterInfo({ + canisterId: mockCanisterId, + }); + + expect(res).toEqual(response); + expect(service.canister_info).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + num_requested_changes: [], + }); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.canister_info.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => + icManagement.canisterInfo({ + canisterId: mockCanisterId, + }); + + expect(call).rejects.toThrowError(Error); + }); + }); + + describe("deleteCanister", () => { + it("calls delete_canister", async () => { + const service = mock(); + service.delete_canister.mockResolvedValue(undefined); + + const icManagement = await createICManagement(service); + + await icManagement.deleteCanister(mockCanisterId); + + expect(service.delete_canister).toHaveBeenCalledWith({ + canister_id: mockCanisterId, + }); + }); + + it("throws Error", async () => { + const error = new Error("Test"); + const service = mock(); + service.delete_canister.mockRejectedValue(error); + + const icManagement = await createICManagement(service); + + const call = () => icManagement.deleteCanister(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 9b71d872..366abc7c 100644 --- a/packages/ic-management/src/ic-management.canister.ts +++ b/packages/ic-management/src/ic-management.canister.ts @@ -1,60 +1,178 @@ -import { - getManagementCanister, - type ManagementCanisterRecord, -} from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; -import { toNullable } from "@dfinity/utils"; +import { createServices, toNullable } from "@dfinity/utils"; +import type { _SERVICE as IcManagementService } from "../candid/ic-management"; +import { idlFactory as certifiedIdlFactory } from "../candid/ic-management.certified.idl"; +import { idlFactory } from "../candid/ic-management.idl"; import type { ICManagementCanisterOptions } from "./types/canister.options"; -import type { UpdateSettingsParams } from "./types/ic-management.params"; -import type { CanisterStatusResponse } from "./types/ic-management.responses"; +import type { + CanisterInfoParams, + CreateCanisterParams, + UninstallCodeParams, +} from "./types/ic-management.params"; +import { + toCanisterSettings, + toInstallMode, + type InstallCodeParams, + type UpdateSettingsParams, +} from "./types/ic-management.params"; +import type { + CanisterInfoResponse, + CanisterStatusResponse, +} from "./types/ic-management.responses"; export class ICManagementCanister { - private constructor(private readonly service: ManagementCanisterRecord) { + private constructor(private readonly service: IcManagementService) { this.service = service; } public static create(options: ICManagementCanisterOptions) { - const agent = options.agent; - - const service = options.serviceOverride ?? getManagementCanister({ agent }); + const { service } = createServices({ + options: { + ...options, + canisterId: Principal.fromText("aaaaa-aa"), + }, + idlFactory, + certifiedIdlFactory, + }); return new ICManagementCanister(service); } /** - * Returns canister details (memory size, status, etc.) + * Create a new canister * - * @param {Principal} canisterId - * @returns Promise + * @param {Object} params + * @param {CanisterSettings} params.settings + * @param {BigInt} params.senderCanisterVersion + * @returns {Promise} */ - canisterStatus = (canisterId: Principal): Promise => - this.service.canister_status({ - canister_id: canisterId, + createCanister = async ({ + settings, + senderCanisterVerion, + }: CreateCanisterParams = {}): Promise => { + const { canister_id } = await this.service.create_canister({ + settings: toNullable(toCanisterSettings(settings)), + sender_canister_version: toNullable(senderCanisterVerion), }); + return canister_id; + }; + /** * Update canister settings * * @param {Object} params * @param {Principal} params.canisterId + * @param {BigInt} params.sender_canister_version * @param {CanisterSettings} params.settings + * @returns {Promise} */ - updateSettings = async ({ + updateSettings = ({ canisterId, - settings: { - controllers, - freezingThreshold, - memoryAllocation, - computeAllocation, - }, + senderCanisterVerion, + settings, }: 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), - }, + sender_canister_version: toNullable(senderCanisterVerion), + settings: toCanisterSettings(settings), + }); + + /** + * Install code to a canister + * + * @param {Object} params + * @param {InstallMode} params.mode + * @param {Principal} params.canisterId + * @param {Uint8Array} params.wasmModule + * @param {Uint8Array} params.arg + * @param {BigInt} params.senderCanisterVersion + * @returns {Promise} + */ + installCode = ({ + mode, + canisterId, + wasmModule, + arg, + senderCanisterVerion, + }: InstallCodeParams): Promise => + this.service.install_code({ + mode: toInstallMode(mode), + canister_id: canisterId, + wasm_module: wasmModule, + arg, + sender_canister_version: toNullable(senderCanisterVerion), + }); + + /** + * Uninstall code from a canister + * + * @param {Object} params + * @param {Principal} params.canisterId + * @param {BigInt} params.senderCanisterVersion + * @returns {Promise} + */ + uninstallCode = ({ + canisterId, + senderCanisterVerion, + }: UninstallCodeParams): Promise => + this.service.uninstall_code({ + canister_id: canisterId, + sender_canister_version: toNullable(senderCanisterVerion), + }); + + /** + * Start a canister + * + * @param {Principal} canisterId + * @returns {Promise} + */ + startCanister = (canisterId: Principal): Promise => + this.service.start_canister({ canister_id: canisterId }); + + /** + * Stop a canister + * + * @param {Principal} canisterId + * @returns {Promise} + */ + stopCanister = (canisterId: Principal): Promise => + this.service.stop_canister({ canister_id: canisterId }); + + /** + * Get canister details (memory size, status, etc.) + * + * @param {Principal} canisterId + * @returns {Promise} + */ + canisterStatus = (canisterId: Principal): Promise => + this.service.canister_status({ + canister_id: canisterId, + }); + + /** + * Get canister info (controllers, module hash, changes, etc.) + * + * @param {Object} params + * @param {Principal} params.canisterId + * @param {BigInt} params.numRequestChanges + * @returns {Promise} + */ + canisterInfo = ({ + canisterId, + numRequestChanges, + }: CanisterInfoParams): Promise => + this.service.canister_info({ + canister_id: canisterId, + num_requested_changes: toNullable(numRequestChanges), }); + + /** + * Deletes a canister + * + * @param {Principal} canisterId + * @returns {Promise} + */ + deleteCanister = (canisterId: Principal): Promise => + this.service.delete_canister({ canister_id: canisterId }); } diff --git a/packages/ic-management/src/ic-management.mock.ts b/packages/ic-management/src/ic-management.mock.ts index 0099a07a..26238989 100644 --- a/packages/ic-management/src/ic-management.mock.ts +++ b/packages/ic-management/src/ic-management.mock.ts @@ -1,5 +1,9 @@ import { Identity } from "@dfinity/agent"; import { Principal } from "@dfinity/principal"; +import { + CanisterSettings, + toCanisterSettings, +} from "./types/ic-management.params"; export const mockPrincipalText = "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe"; @@ -12,11 +16,12 @@ export const mockIdentity = { export const mockCanisterId = Principal.fromText("ryjl3-tyaaa-aaaaa-aaaba-cai"); -export const mockCanisterSettings = { - freezing_threshold: BigInt(2), - controllers: [ - "xlmdg-vkosz-ceopx-7wtgu-g3xmd-koiyc-awqaq-7modz-zf6r6-364rh-oqe", - ], - memory_allocation: BigInt(4), - compute_allocation: BigInt(10), +export const mockCanisterSettings: CanisterSettings = { + freezingThreshold: BigInt(2), + controllers: [mockPrincipalText], + memoryAllocation: BigInt(4), + computeAllocation: BigInt(10), }; + +export const mappedMockCanisterSettings = + toCanisterSettings(mockCanisterSettings); diff --git a/packages/ic-management/src/types/canister.options.ts b/packages/ic-management/src/types/canister.options.ts index 78129a10..3a5d7a07 100644 --- a/packages/ic-management/src/types/canister.options.ts +++ b/packages/ic-management/src/types/canister.options.ts @@ -1,7 +1,7 @@ -import type { ManagementCanisterRecord as ManagementCanisterService } from "@dfinity/agent"; import type { CanisterOptions } from "@dfinity/utils"; +import type { _SERVICE as IcManagementService } from "../../candid/ic-management"; export type ICManagementCanisterOptions = Pick< - CanisterOptions, + CanisterOptions, "agent" | "serviceOverride" >; diff --git a/packages/ic-management/src/types/ic-management.params.ts b/packages/ic-management/src/types/ic-management.params.ts index 827f2469..d8b00596 100644 --- a/packages/ic-management/src/types/ic-management.params.ts +++ b/packages/ic-management/src/types/ic-management.params.ts @@ -1,5 +1,9 @@ -import type { Principal } from "@dfinity/principal"; -import type { QueryParams } from "@dfinity/utils/src"; +import { Principal } from "@dfinity/principal"; +import { toNullable, type ServiceParam } from "@dfinity/utils"; +import type { + canister_settings, + _SERVICE as IcManagementService, +} from "../../candid/ic-management"; export interface CanisterSettings { controllers?: string[]; @@ -8,7 +12,67 @@ export interface CanisterSettings { computeAllocation?: bigint; } -export type UpdateSettingsParams = { +export const toCanisterSettings = ({ + controllers, + freezingThreshold, + memoryAllocation, + computeAllocation, +}: CanisterSettings = {}): canister_settings => { + return { + controllers: toNullable(controllers?.map((c) => Principal.fromText(c))), + freezing_threshold: toNullable(freezingThreshold), + memory_allocation: toNullable(memoryAllocation), + compute_allocation: toNullable(computeAllocation), + }; +}; + +export interface CreateCanisterParams { + settings?: CanisterSettings; + senderCanisterVerion?: bigint; +} + +export interface UpdateSettingsParams { canisterId: Principal; + senderCanisterVerion?: bigint; settings: CanisterSettings; -} & Omit; +} + +export enum InstallMode { + Install, + Reinstall, + Upgrade, +} + +export type InstallModeParam = ServiceParam< + IcManagementService, + "install_code" +>[0]["mode"]; + +export const toInstallMode = (installMode: InstallMode): InstallModeParam => { + switch (installMode) { + case InstallMode.Install: + return { install: null }; + case InstallMode.Reinstall: + return { reinstall: null }; + case InstallMode.Upgrade: + return { upgrade: null }; + } +}; + +export interface InstallCodeParams { + mode: InstallMode; + canisterId: Principal; + wasmModule: Uint8Array; + arg: Uint8Array; + senderCanisterVerion?: bigint; +} + +export interface UninstallCodeParams { + canisterId: Principal; + senderCanisterVerion?: bigint; +} + +export interface CanisterInfoParams { + canisterId: Principal; + numRequestChanges?: bigint; +} diff --git a/packages/ic-management/src/types/ic-management.responses.ts b/packages/ic-management/src/types/ic-management.responses.ts index 164bb08d..4ff46695 100644 --- a/packages/ic-management/src/types/ic-management.responses.ts +++ b/packages/ic-management/src/types/ic-management.responses.ts @@ -1,18 +1,12 @@ -import type { definite_canister_settings } from "../../candid/ic-management"; +import type { ServiceResponse } from "@dfinity/utils"; +import type { _SERVICE as IcManagementService } from "../../candid/ic-management"; -export interface CanisterStatusResponse { - status: - | { - stopped: null; - } - | { - stopping: null; - } - | { - running: null; - }; - memory_size: bigint; - cycles: bigint; - settings: definite_canister_settings; - module_hash: [] | [Array]; -} +export type CanisterStatusResponse = ServiceResponse< + IcManagementService, + "canister_status" +>; + +export type CanisterInfoResponse = ServiceResponse< + IcManagementService, + "canister_info" +>; diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index f0ed7552..e8095559 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -1,6 +1,7 @@ export * from "./enums/token.enums"; export * from "./parser/token"; export * from "./services/canister"; +export * from "./types/actor-type.utils"; export type { CanisterOptions } from "./types/canister.options"; export type { QueryParams } from "./types/query.params"; export * from "./utils/actor.utils"; diff --git a/packages/utils/src/types/actor-type.utils.ts b/packages/utils/src/types/actor-type.utils.ts new file mode 100644 index 00000000..0d0405e4 --- /dev/null +++ b/packages/utils/src/types/actor-type.utils.ts @@ -0,0 +1,15 @@ +import type { ActorMethod } from "@dfinity/agent"; + +export type ServiceParam = S[K] extends ActorMethod< + infer A, + unknown +> + ? A + : never; + +export type ServiceResponse = S[K] extends ActorMethod< + never, + infer R +> + ? Awaited + : never;