Skip to content

Commit

Permalink
feat(frontend): isIcToken and isIcTokenCanistersStrict validation (#3357
Browse files Browse the repository at this point in the history
)

# Motivation

We will need to know if IC tokens are provided with or without Index
Canister ID. Unrelated but, somehow related, we also want to know if a
token is just a token or an IC token.

# Notes

Some test uncommented and will be activated in PR #3334 because they
cannot be active unless the Index Canister ID is set to optional.

# Changes

- New validators `isIcToken`, `isNotIcToken`, `isIcTokenCanistersStrict`
and `isNotIcTokenCanistersStrict`
  • Loading branch information
peterpeterparker authored Nov 5, 2024
1 parent b7135b5 commit 09a3f68
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 0 deletions.
19 changes: 19 additions & 0 deletions src/frontend/src/icp/validation/ic-token.validation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { IcCanistersStrictSchema, IcTokenSchema } from '$icp/schema/ic-token.schema';
import type { IcCanistersStrict, IcToken } from '$icp/types/ic-token';
import type { Token } from '$lib/types/token';

export const isIcToken = (token: Token): token is IcToken => {
const { success } = IcTokenSchema.safeParse(token);
return success;
};

export const isNotIcToken = (token: Token): token is Exclude<Token, IcToken> => !isIcToken(token);

export const isIcTokenCanistersStrict = (token: IcToken): token is IcToken & IcCanistersStrict => {
const { success } = IcCanistersStrictSchema.safeParse(token);
return success;
};

export const isNotIcTokenCanistersStrict = (
token: IcToken
): token is Exclude<IcToken, IcToken & IcCanistersStrict> => !isIcTokenCanistersStrict(token);
87 changes: 87 additions & 0 deletions src/frontend/src/tests/icp/validation/ic-token.validation.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { ICP_NETWORK } from '$env/networks.env';
import { IC_CKBTC_INDEX_CANISTER_ID, IC_CKBTC_LEDGER_CANISTER_ID } from '$env/networks.icrc.env';
import type { IcCanisters, IcToken } from '$icp/types/ic-token';
import {
isIcToken,
isIcTokenCanistersStrict,
isNotIcToken,
isNotIcTokenCanistersStrict
} from '$icp/validation/ic-token.validation';
import type { Token } from '$lib/types/token';
import { parseTokenId } from '$lib/validation/token.validation';
import { describe, expect, it } from 'vitest';

describe('ic-token.validation', () => {
const validToken: Token = {
id: parseTokenId('TokenId'),
network: ICP_NETWORK,
standard: 'icp',
category: 'default',
name: 'SampleToken',
symbol: 'STK',
decimals: 8
};

const validIcCanisters: IcCanisters = {
ledgerCanisterId: IC_CKBTC_LEDGER_CANISTER_ID,
// TODO: to be removed when indexCanisterId becomes optional
indexCanisterId: IC_CKBTC_INDEX_CANISTER_ID
};

const validIcToken: IcToken = {
...validToken,
...validIcCanisters,
fee: 123n,
position: 1
};

describe('isIcToken', () => {
it('should return true for a valid IcToken', () => {
expect(isIcToken(validIcToken)).toBe(true);
});

it('should return false for an invalid IcToken', () => {
expect(isIcToken(validToken)).toBe(false);
});
});

describe('isNotIcToken', () => {
it('should return false for a valid IcToken', () => {
expect(isNotIcToken(validIcToken)).toBe(false);
});

it('should return true for an invalid IcToken', () => {
expect(isNotIcToken(validToken)).toBe(true);
});
});

describe('isIcTokenCanistersStrict', () => {
it('should return true for a valid IcToken with IcCanistersStrict', () => {
expect(isIcTokenCanistersStrict(validIcToken)).toBe(true);
});

// TODO: test missing indexCanisterId when it becomes optional
// it('should return false for a valid IcToken without strict canisters fields', () => {
// expect(isIcTokenCanistersStrict(validIcToken)).toBe(false);
// });

it('should return false for a token type casted to IcToken', () => {
expect(isIcTokenCanistersStrict(validToken as IcToken)).toBe(false);
});
});

describe('isNotIcTokenCanistersStrict', () => {
it('should return false for a valid IcToken with IcCanistersStrict', () => {
expect(isNotIcTokenCanistersStrict(validIcToken)).toBe(false);
});

// TODO: test missing indexCanisterId when it becomes optional
// it('should return true for a valid IcToken without strict canisters fields', () => {
// expect(isNotIcTokenCanistersStrict(validIcToken)).toBe(true);
// });

it('should return true for a token type casted to IcToken', () => {
expect(isNotIcTokenCanistersStrict(validToken as IcToken)).toBe(true);
});
});
});

0 comments on commit 09a3f68

Please sign in to comment.