diff --git a/frontend/src/lib/api/canisters.api.ts b/frontend/src/lib/api/canisters.api.ts index 4019c28e20e..0423e613ad0 100644 --- a/frontend/src/lib/api/canisters.api.ts +++ b/frontend/src/lib/api/canisters.api.ts @@ -351,6 +351,33 @@ export const topUpCanister = async ({ logWithTimestamp(`Topping up canister ${canisterId.toText()} complete.`); }; +// Returns the number of cycles that were topped up. But if called again, it +// will return the same number. So this can't be used to tell if the top-up +// wasn't done before. +export const notifyTopUpCanister = async ({ + identity, + blockHeight, + canisterId, +}: { + identity: Identity; + blockHeight: bigint; + canisterId: Principal; +}): Promise => { + logWithTimestamp(`Notifying canister topup ${canisterId.toText()} call...`); + + const { cmc } = await canisters(identity); + try { + return cmc.notifyTopUp({ + canister_id: canisterId, + block_index: blockHeight, + }); + } finally { + logWithTimestamp( + `Notifying canister topup ${canisterId.toText()} complete.` + ); + } +}; + const canisters = async ( identity: Identity ): Promise<{ diff --git a/frontend/src/tests/lib/api/canisters.api.spec.ts b/frontend/src/tests/lib/api/canisters.api.spec.ts index b8fd6183ef9..fb10957ddf8 100644 --- a/frontend/src/tests/lib/api/canisters.api.spec.ts +++ b/frontend/src/tests/lib/api/canisters.api.spec.ts @@ -3,6 +3,7 @@ import { createCanister, detachCanister, getIcpToCyclesExchangeRate, + notifyTopUpCanister, queryCanisterDetails, queryCanisters, renameCanister, @@ -31,6 +32,7 @@ import { LedgerCanister, SubAccount, } from "@dfinity/ledger-icp"; +import { Principal } from "@dfinity/principal"; import * as dfinityUtils from "@dfinity/utils"; import { principalToSubAccount } from "@dfinity/utils"; import { mock } from "vitest-mock-extended"; @@ -422,7 +424,6 @@ describe("canisters-api", () => { }); it("should not notify if transfer fails", async () => { - vi.spyOn(console, "error").mockImplementation(() => undefined); mockLedgerCanister.transfer.mockRejectedValue(new Error()); const call = () => @@ -436,4 +437,30 @@ describe("canisters-api", () => { expect(mockCMCCanister.notifyTopUp).not.toBeCalled(); }); }); + + describe("notifyTopUpCanister", () => { + const canisterId = Principal.fromText("mkam6-f4aaa-aaaaa-qablq-cai"); + + it("should call cmc.notifyTopUp", async () => { + const cycles = 3_000_000_000_000n; + const blockHeight = 14545n; + + mockCMCCanister.notifyTopUp.mockResolvedValue(cycles); + + const call = () => + notifyTopUpCanister({ + identity: mockIdentity, + blockHeight, + canisterId, + }); + + await expect(call()).resolves.toBe(cycles); + + expect(mockCMCCanister.notifyTopUp).toBeCalledTimes(1); + expect(mockCMCCanister.notifyTopUp).toBeCalledWith({ + canister_id: canisterId, + block_index: blockHeight, + }); + }); + }); });