From 474ddea5aa5b7518d2c1d8a50254e5b921d5c6be Mon Sep 17 00:00:00 2001 From: David Dal Busco Date: Tue, 5 Nov 2024 15:35:48 +0100 Subject: [PATCH] feat(frontend): IcCanistersStrict type and validation (#3356) # Motivation This might not suffise but, it's a first step, type wise, to defined the "Index Canister" as optional. # Notes I add to include comments because we cannot just set the index as optional. On the other side, I also need this new validation becase otherwise I cannot split PR #3334 in smaller PRs. # Changes - Provide validation and types `IcCanistersStrictSchema` - Add TODO for making the Index Canister optional typewise --- src/frontend/src/icp/types/ic-token.ts | 3 ++ .../src/icp/validation/ic-token.validation.ts | 5 +++ .../validation/ic-token.validation.spec.ts | 44 ++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/frontend/src/icp/types/ic-token.ts b/src/frontend/src/icp/types/ic-token.ts index ef285fde50..d339a2b4ed 100644 --- a/src/frontend/src/icp/types/ic-token.ts +++ b/src/frontend/src/icp/types/ic-token.ts @@ -1,6 +1,7 @@ import { IcAppMetadataSchema, IcCanistersSchema, + IcCanistersStrictSchema, IcCkInterfaceSchema, IcCkLinkedAssetsSchema, IcCkMetadataSchema, @@ -19,6 +20,8 @@ export type IcAppMetadata = z.infer; export type IcCanisters = z.infer; +export type IcCanistersStrict = z.infer; + export type IcCkLinkedAssets = z.infer; export type IcCkMetadata = z.infer; diff --git a/src/frontend/src/icp/validation/ic-token.validation.ts b/src/frontend/src/icp/validation/ic-token.validation.ts index 0d7cda3375..e3abd714c8 100644 --- a/src/frontend/src/icp/validation/ic-token.validation.ts +++ b/src/frontend/src/icp/validation/ic-token.validation.ts @@ -16,6 +16,11 @@ export const IcAppMetadataSchema = z.object({ export const IcCanistersSchema = z.object({ ledgerCanisterId: CanisterIdTextSchema, + // TODO: Make canister .optional() + indexCanisterId: CanisterIdTextSchema +}); + +export const IcCanistersStrictSchema = IcCanistersSchema.extend({ indexCanisterId: CanisterIdTextSchema }); diff --git a/src/frontend/src/tests/icp/validation/ic-token.validation.spec.ts b/src/frontend/src/tests/icp/validation/ic-token.validation.spec.ts index c4d51274b4..212132684f 100644 --- a/src/frontend/src/tests/icp/validation/ic-token.validation.spec.ts +++ b/src/frontend/src/tests/icp/validation/ic-token.validation.spec.ts @@ -7,6 +7,7 @@ import { import { IcAppMetadataSchema, IcCanistersSchema, + IcCanistersStrictSchema, IcCkInterfaceSchema, IcCkLinkedAssetsSchema, IcCkMetadataSchema, @@ -98,6 +99,14 @@ describe('Schema Validation Tests', () => { expect(IcCanistersSchema.parse(validData)).toEqual(validData); }); + // TODO: uncomment when Index canister becomes optional + // it('should validate with ledger canister only', () => { + // const validData = { + // ledgerCanisterId: mockCanisters.ledgerCanisterId + // }; + // expect(IcCanistersSchema.parse(validData)).toEqual(validData); + // }); + it('should fail with invalid ledger canister id', () => { const invalidData = { ...validData, @@ -120,12 +129,39 @@ describe('Schema Validation Tests', () => { }; expect(() => IcCanistersSchema.parse(invalidData)).toThrow(); }); + }); + + describe('IcCanistersStrictSchema', () => { + const validToken = { + ...mockToken, + ...mockFee, + ...mockCanisters, + ...mockApp + }; + + it('should validate with correct data', () => { + const validData = { + ledgerCanisterId: mockCanisters.ledgerCanisterId, + indexCanisterId: mockCanisters.ledgerCanisterId + }; + + expect(IcCanistersSchema.parse(validData)).toEqual(validData); + }); + + it('should validate a token with index canister correct data', () => { + expect(() => IcCanistersStrictSchema.parse(validToken)).not.toThrow(); + }); it('should fail with missing index canister field', () => { const invalidData = { ledgerCanisterId: IC_CKBTC_LEDGER_CANISTER_ID }; - expect(() => IcCanistersSchema.parse(invalidData)).toThrow(); + expect(() => IcCanistersStrictSchema.parse(invalidData)).toThrow(); + }); + + it('should fail for token with missing index canister field', () => { + const { indexCanisterId: _, ...tokenWithoutIndexCanisterId } = validToken; + expect(() => IcCanistersStrictSchema.parse(tokenWithoutIndexCanisterId)).toThrow(); }); }); @@ -183,6 +219,12 @@ describe('Schema Validation Tests', () => { expect(IcInterfaceSchema.parse(validData)).toEqual(validData); }); + // TODO: uncomment when Index canister becomes optional + // it('should validate without Index canister', () => { + // const { indexCanisterId: _, ...restValidData } = validData; + // expect(IcInterfaceSchema.parse(restValidData)).toEqual(restValidData); + // }); + it('should fail with incorrect IcCanisters data', () => { const invalidData = { ...validData,