diff --git a/CHANGELOG-Nns-Dapp-unreleased.md b/CHANGELOG-Nns-Dapp-unreleased.md index 6bf1e21861a..560fada2654 100644 --- a/CHANGELOG-Nns-Dapp-unreleased.md +++ b/CHANGELOG-Nns-Dapp-unreleased.md @@ -29,6 +29,8 @@ proposal is successful, the changes it released will be moved from this file to #### Fixed +* Stop trying to get swap commitments from aborted SNSes. + #### Security #### Not Published diff --git a/frontend/src/lib/services/public/sns.services.ts b/frontend/src/lib/services/public/sns.services.ts index e961eb95a5e..2241e3b7019 100644 --- a/frontend/src/lib/services/public/sns.services.ts +++ b/frontend/src/lib/services/public/sns.services.ts @@ -10,6 +10,7 @@ import { isLastCall } from "$lib/utils/env.utils"; import { toToastError } from "$lib/utils/error.utils"; import { ProposalStatus, Topic, type ProposalInfo } from "@dfinity/nns"; import { Principal } from "@dfinity/principal"; +import { SnsSwapLifecycle } from "@dfinity/sns"; import { getCurrentIdentity } from "../auth.services"; export const loadSnsProjects = async (): Promise => { @@ -19,7 +20,7 @@ export const loadSnsProjects = async (): Promise => { // We load the wrappers to avoid making calls to SNS-W and Root canister for each project. // The SNS Aggregator gives us the canister ids of the SNS projects. await Promise.all( - aggregatorData.map(async ({ canister_ids }) => { + aggregatorData.map(async ({ canister_ids, lifecycle }) => { const canisterIds = { rootCanisterId: Principal.fromText(canister_ids.root_canister_id), swapCanisterId: Principal.fromText(canister_ids.swap_canister_id), @@ -29,6 +30,9 @@ export const loadSnsProjects = async (): Promise => { ledgerCanisterId: Principal.fromText(canister_ids.ledger_canister_id), indexCanisterId: Principal.fromText(canister_ids.index_canister_id), }; + if (lifecycle.lifecycle === SnsSwapLifecycle.Aborted) { + return; + } // Build certified and uncertified wrappers because SNS aggregator gives certified data. await buildAndStoreWrapper({ identity, diff --git a/frontend/src/tests/lib/services/public/sns.services.spec.ts b/frontend/src/tests/lib/services/public/sns.services.spec.ts index fc06e2e1df8..3cdf3e03313 100644 --- a/frontend/src/tests/lib/services/public/sns.services.spec.ts +++ b/frontend/src/tests/lib/services/public/sns.services.spec.ts @@ -1,7 +1,11 @@ import { clearSnsAggregatorCache } from "$lib/api-services/sns-aggregator.api-service"; import * as agent from "$lib/api/agent.api"; import * as aggregatorApi from "$lib/api/sns-aggregator.api"; -import { clearWrapperCache, wrapper } from "$lib/api/sns-wrapper.api"; +import { + clearWrapperCache, + wrappers as getWrappers, + wrapper, +} from "$lib/api/sns-wrapper.api"; import { snsFunctionsStore } from "$lib/derived/sns-functions.derived"; import { snsTotalTokenSupplyStore } from "$lib/derived/sns-total-token-supply.derived"; import { loadSnsProjects } from "$lib/services/public/sns.services"; @@ -26,6 +30,7 @@ import { } from "$tests/mocks/sns.api.mock"; import { blockAllCallsTo } from "$tests/utils/module.test-utils"; import type { HttpAgent } from "@dfinity/agent"; +import { SnsSwapLifecycle } from "@dfinity/sns"; import { get } from "svelte/store"; import { mock } from "vitest-mock-extended"; @@ -164,5 +169,45 @@ describe("SNS public services", () => { expect(data).not.toBeUndefined(); expect(data?.totalSupply).toEqual(BigInt(totalSupply)); }); + + it("should build and store wrappers, only for non-aborted SNSes", async () => { + const committedSns1 = aggregatorSnsMockWith({ + rootCanisterId: principal(0).toText(), + lifecycle: SnsSwapLifecycle.Committed, + }); + const committedSns2 = aggregatorSnsMockWith({ + rootCanisterId: principal(1).toText(), + lifecycle: SnsSwapLifecycle.Committed, + }); + const abortedSns1 = aggregatorSnsMockWith({ + rootCanisterId: principal(2).toText(), + lifecycle: SnsSwapLifecycle.Aborted, + }); + const abortedSns2 = aggregatorSnsMockWith({ + rootCanisterId: principal(3).toText(), + lifecycle: SnsSwapLifecycle.Aborted, + }); + + vi.spyOn(aggregatorApi, "querySnsProjects").mockResolvedValue([ + committedSns1, + abortedSns1, + committedSns2, + abortedSns2, + ]); + + await loadSnsProjects(); + + const wrappers = await getWrappers({ + identity: mockIdentity, + certified: true, + }); + expect(wrappers).toHaveLength(2); + expect(wrappers.has(committedSns1.canister_ids.root_canister_id)).toBe( + true + ); + expect(wrappers.has(committedSns2.canister_ids.root_canister_id)).toBe( + true + ); + }); }); });