From 284e40584f03dd46d5d81adae586304fd9115368 Mon Sep 17 00:00:00 2001 From: David de Kloet Date: Thu, 21 Nov 2024 10:59:32 +0100 Subject: [PATCH] Filter out SNSes without lifecycle --- .../src/lib/stores/sns-aggregator.store.ts | 5 +- frontend/src/lib/types/sns-aggregator.ts | 2 +- .../utils/sns-aggregator-converters.utils.ts | 33 +++++---- .../lib/stores/sns-aggregator.store.spec.ts | 74 +++++++++++++------ .../sns-aggregator-converters.utils.spec.ts | 10 +++ 5 files changed, 86 insertions(+), 38 deletions(-) diff --git a/frontend/src/lib/stores/sns-aggregator.store.ts b/frontend/src/lib/stores/sns-aggregator.store.ts index 47f599b2293..70245b6b3be 100644 --- a/frontend/src/lib/stores/sns-aggregator.store.ts +++ b/frontend/src/lib/stores/sns-aggregator.store.ts @@ -1,5 +1,6 @@ import type { CachedSnsDto } from "$lib/types/sns-aggregator"; import { SnsSwapLifecycle } from "@dfinity/sns"; +import { nonNullish } from "@dfinity/utils"; import { derived, writable, type Readable } from "svelte/store"; /** @@ -35,7 +36,9 @@ export const snsAggregatorStore: SnsAggregatorStore = derived( snsAggregatorIncludingAbortedProjectsStore, (store) => ({ data: store.data?.filter( - (sns) => sns.lifecycle.lifecycle !== SnsSwapLifecycle.Aborted + (sns) => + nonNullish(sns.lifecycle) && + sns.lifecycle.lifecycle !== SnsSwapLifecycle.Aborted ), }) ); diff --git a/frontend/src/lib/types/sns-aggregator.ts b/frontend/src/lib/types/sns-aggregator.ts index 56bd69b132b..12adbe96b99 100644 --- a/frontend/src/lib/types/sns-aggregator.ts +++ b/frontend/src/lib/types/sns-aggregator.ts @@ -229,5 +229,5 @@ export type CachedSnsDto = { derived_state: CachedSnsSwapDerivedDto; swap_params: CachedSwapParamsResponseDto; init: CachedInitResponseDto; - lifecycle: CachedLifecycleResponseDto; + lifecycle: CachedLifecycleResponseDto | null; }; diff --git a/frontend/src/lib/utils/sns-aggregator-converters.utils.ts b/frontend/src/lib/utils/sns-aggregator-converters.utils.ts index bbdff67df26..1f63675d193 100644 --- a/frontend/src/lib/utils/sns-aggregator-converters.utils.ts +++ b/frontend/src/lib/utils/sns-aggregator-converters.utils.ts @@ -467,27 +467,33 @@ const convertDtoToSnsSummarySwap = ( }; const convertDtoToLifecycle = ( - data: CachedLifecycleResponseDto -): SnsGetLifecycleResponse => ({ - decentralization_sale_open_timestamp_seconds: toNullable( - convertOptionalNumToBigInt( - data.decentralization_sale_open_timestamp_seconds - ) - ), - lifecycle: toNullable(data.lifecycle), - // TODO: Add support in SNS Aggregaro for these fields - decentralization_swap_termination_timestamp_seconds: [], -}); + data: CachedLifecycleResponseDto | null +): SnsGetLifecycleResponse | undefined => { + if (isNullish(data)) { + return undefined; + } + return { + decentralization_sale_open_timestamp_seconds: toNullable( + convertOptionalNumToBigInt( + data.decentralization_sale_open_timestamp_seconds + ) + ), + lifecycle: toNullable(data.lifecycle), + // TODO: Add support in SNS Aggregaro for these fields + decentralization_swap_termination_timestamp_seconds: [], + }; +}; type PartialSummary = Omit< SnsSummary, - "metadata" | "token" | "swap" | "init" | "swapParams" + "metadata" | "token" | "swap" | "init" | "swapParams" | "lifecycle" > & { metadata?: SnsSummaryMetadata; token?: IcrcTokenMetadata; swap?: SnsSummarySwap; init?: SnsSwapInit; swapParams?: SnsParams; + lifecycle?: SnsGetLifecycleResponse; }; const isValidSummary = (entry: PartialSummary): entry is SnsSummary => @@ -495,7 +501,8 @@ const isValidSummary = (entry: PartialSummary): entry is SnsSummary => nonNullish(entry.token) && nonNullish(entry.swap) && nonNullish(entry.init) && - nonNullish(entry.swapParams); + nonNullish(entry.swapParams) && + nonNullish(entry.lifecycle); export const convertDtoToSnsSummary = ({ canister_ids: { diff --git a/frontend/src/tests/lib/stores/sns-aggregator.store.spec.ts b/frontend/src/tests/lib/stores/sns-aggregator.store.spec.ts index ebe45b8ac1a..4a7a818adac 100644 --- a/frontend/src/tests/lib/stores/sns-aggregator.store.spec.ts +++ b/frontend/src/tests/lib/stores/sns-aggregator.store.spec.ts @@ -5,6 +5,7 @@ import { import type { CachedSnsDto } from "$lib/types/sns-aggregator"; import { aggregatorMockSnsesDataDto } from "$tests/mocks/sns-aggregator.mock"; import { SnsSwapLifecycle } from "@dfinity/sns"; +import { nonNullish } from "@dfinity/utils"; import { get } from "svelte/store"; describe("sns-aggregator store", () => { @@ -57,10 +58,13 @@ describe("sns-aggregator store", () => { }); describe("snsAggregatorStore", () => { - const snsWithLifecycle = ( - sns: CachedSnsDto, - lifecycle: SnsSwapLifecycle - ) => ({ + const snsWithLifecycle = ({ + sns, + lifecycle, + }: { + sns: CachedSnsDto; + lifecycle: SnsSwapLifecycle; + }) => ({ ...sns, swap_state: { ...sns.swap_state, @@ -69,20 +73,33 @@ describe("sns-aggregator store", () => { lifecycle, }, }, - lifecycle: { - ...sns.lifecycle, - lifecycle, - }, + ...(nonNullish(lifecycle) + ? { + lifecycle: { + ...sns.lifecycle, + lifecycle, + }, + } + : { lifecycle: null }), }); const nonAbortedData = [ - snsWithLifecycle(aggregatorMockSnsesDataDto[0], SnsSwapLifecycle.Pending), - snsWithLifecycle(aggregatorMockSnsesDataDto[1], SnsSwapLifecycle.Open), - snsWithLifecycle( - aggregatorMockSnsesDataDto[2], - SnsSwapLifecycle.Committed - ), - snsWithLifecycle(aggregatorMockSnsesDataDto[3], SnsSwapLifecycle.Adopted), + snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[0], + lifecycle: SnsSwapLifecycle.Pending, + }), + snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[1], + lifecycle: SnsSwapLifecycle.Open, + }), + snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[2], + lifecycle: SnsSwapLifecycle.Committed, + }), + snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[3], + lifecycle: SnsSwapLifecycle.Adopted, + }), ]; it("should start empty", () => { @@ -95,18 +112,29 @@ describe("sns-aggregator store", () => { }); it("should not hold aborted projects", () => { - const abortedProject1 = snsWithLifecycle( - aggregatorMockSnsesDataDto[4], - SnsSwapLifecycle.Aborted - ); - const abortedProject2 = snsWithLifecycle( - aggregatorMockSnsesDataDto[5], - SnsSwapLifecycle.Aborted - ); + const abortedProject1 = snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[4], + lifecycle: SnsSwapLifecycle.Aborted, + }); + const abortedProject2 = snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[5], + lifecycle: SnsSwapLifecycle.Aborted, + }); const data = [abortedProject1, ...nonAbortedData, abortedProject2]; snsAggregatorIncludingAbortedProjectsStore.setData(data); expect(get(snsAggregatorStore).data).toEqual(nonAbortedData); }); + + it("should not hold projects without lifecycle", () => { + const projectWithoutLifecycle = snsWithLifecycle({ + sns: aggregatorMockSnsesDataDto[4], + lifecycle: null, + }); + const data = [projectWithoutLifecycle, ...nonAbortedData]; + + snsAggregatorIncludingAbortedProjectsStore.setData(data); + expect(get(snsAggregatorStore).data).toEqual(nonAbortedData); + }); }); }); diff --git a/frontend/src/tests/lib/utils/sns-aggregator-converters.utils.spec.ts b/frontend/src/tests/lib/utils/sns-aggregator-converters.utils.spec.ts index 12bce5e1318..3081bb9e16e 100644 --- a/frontend/src/tests/lib/utils/sns-aggregator-converters.utils.spec.ts +++ b/frontend/src/tests/lib/utils/sns-aggregator-converters.utils.spec.ts @@ -537,6 +537,16 @@ describe("sns aggregator converters utils", () => { ).toBeUndefined(); }); + it("returns undefined if a lifecycle required field is missing", () => { + const aggregatorMissingLifecycle: CachedSnsDto = { + ...mockData, + lifecycle: null, + }; + expect( + convertDtoToSnsSummary(aggregatorMissingLifecycle) + ).toBeUndefined(); + }); + it("converts fields related to NF participation enhancements", () => { const aggregatorNFAndDirectParticipationFields: CachedSnsDto = { ...mockData,