Skip to content

Commit

Permalink
test(suite): test fulter accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
enjojoy committed Sep 25, 2024
1 parent f107c42 commit a5c0f49
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 44 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isDebugOnlyAccountType, Network, networksCollection } from '@suite-common/wallet-config';
import { Network, networksCollection } from '@suite-common/wallet-config';
import { selectDevice } from '@suite-common/wallet-core';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
Expand All @@ -22,6 +22,7 @@ import {
} from 'src/types/coinmarket/coinmarketVerify';
import { useAccountAddressDictionary } from 'src/hooks/wallet/useAccounts';
import { TrezorDevice } from '@suite-common/suite-types';
import { filterReceiveAccounts } from '@suite-common/wallet-utils';

const getSelectAccountOptions = (
suiteReceiveAccounts: Account[] | undefined,
Expand Down Expand Up @@ -79,33 +80,13 @@ const getSuiteReceiveAccounts = ({
((n.isDebugOnlyNetwork && isDebug) || !n.isDebugOnlyNetwork),
);

const isSameDevice = (account: Account) => account.deviceState === device?.state;
const isSameNetwork = (account: Account) => account.symbol === receiveNetwork;
const isDebugAndIsAccountDebugOnly = (account: Account) =>
isDebugOnlyAccountType(account.accountType, account.symbol) && isDebug;
const isNotDebugOnlyAccount = (account: Account) =>
!isDebugOnlyAccountType(account.accountType, account.symbol);
// Check if the account is not empty
const isNotEmptyAccount = (account: Account) => !account.empty;
// Check if the account is marked as visible
const isVisibleAccount = (account: Account) => account.visible;
const isFirstNormalAccount = (account: Account) =>
account.accountType === 'normal' && account.index === 0;
const isCoinjoinAccount = (account: Account) => account.accountType === 'coinjoin';

if (receiveNetworks.length > 0) {
// Get accounts of the current symbol belonging to the current device.
return accounts.filter(
account =>
isSameDevice(account) &&
isSameNetwork(account) &&
!isCoinjoinAccount(account) &&
(isDebugAndIsAccountDebugOnly(account) || isNotDebugOnlyAccount(account)) &&
(isNotEmptyAccount(account) ||
isVisibleAccount(account) ||
isFirstNormalAccount(account)),
);
}
return filterReceiveAccounts({
accounts,
deviceState: device?.state,
receiveNetwork,
isDebug,
receiveNetworks,
});
}

return undefined;
Expand Down Expand Up @@ -142,6 +123,7 @@ const useCoinmarketVerifyAccount = ({
}),
[accounts, currency, device, isDebug, receiveNetwork],
);

const selectAccountOptions = useMemo(
() => getSelectAccountOptions(suiteReceiveAccounts, device),
[device, suiteReceiveAccounts],
Expand Down
16 changes: 0 additions & 16 deletions suite-common/wallet-config/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
AccountType,
Network,
NetworkFeature,
Networks,
NetworkSymbol,
NormalizedNetworkAccount,
} from './types';
Expand Down Expand Up @@ -45,21 +44,6 @@ export const normalizeNetworkAccounts = (network: Network): NormalizedNetworkAcc
export const isBlockbookBasedNetwork = (symbol: NetworkSymbol) =>
networks[symbol]?.customBackends.some(backend => backend === 'blockbook');

export const isDebugOnlyAccountType = (
accountType: AccountType,
symbol?: NetworkSymbol,
): boolean => {
if (!symbol) return false;

const network = (networks as Networks)?.[symbol];

if (!network) return false;

const accountTypeInfo = network.accountTypes[accountType];

return !!accountTypeInfo?.isDebugOnlyAccountType;
};

export const getNetworkType = (symbol: NetworkSymbol) => networks[symbol]?.networkType;

// Takes into account just network features, not features for specific accountTypes.
Expand Down
113 changes: 113 additions & 0 deletions suite-common/wallet-utils/src/__tests__/accountUtils.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Account } from '@suite-common/wallet-types';
import { testMocks } from '@suite-common/test-utils';
import { Network, networksCollection } from '@suite-common/wallet-config';

import {
accountSearchFn,
Expand All @@ -24,6 +25,8 @@ import {
readUtxoOutpoint,
sortByBIP44AddressIndex,
enhanceAddresses,
isDebugOnlyAccountType,
filterReceiveAccounts,
} from '../accountUtils';
import * as fixtures from '../__fixtures__/accountUtils';

Expand Down Expand Up @@ -337,4 +340,114 @@ describe('account utils', () => {
account.addresses = enhanceAddresses(accountInfo, account);
expect(account.addresses.change).toEqual([]);
});

it('isDebugOnlyAccountType', () => {
expect(isDebugOnlyAccountType('legacy', 'btc')).toBe(false);
expect(isDebugOnlyAccountType('segwit', 'btc')).toBe(false);
expect(isDebugOnlyAccountType('coinjoin', 'btc')).toBe(false);
expect(isDebugOnlyAccountType('taproot', 'btc')).toBe(false);
expect(isDebugOnlyAccountType('ledger', 'btc')).toBe(false);
expect(isDebugOnlyAccountType('legacy', 'eth')).toBe(true);
expect(isDebugOnlyAccountType('ledger', 'eth')).toBe(true);
});

const accounts = [
getWalletAccount({ symbol: 'eth', accountType: 'legacy' }),
getWalletAccount({ symbol: 'eth', accountType: 'normal' }),
getWalletAccount({ symbol: 'eth', accountType: 'ledger' }),
getWalletAccount({ symbol: 'btc', accountType: 'coinjoin' }),
getWalletAccount({ symbol: 'btc', accountType: 'taproot' }),
getWalletAccount({ symbol: 'btc', accountType: 'legacy' }),
getWalletAccount({ symbol: 'btc', accountType: 'segwit' }),
getWalletAccount({ symbol: 'btc', accountType: 'ledger' }),
getWalletAccount({ symbol: 'matic', accountType: 'legacy' }),
getWalletAccount({ symbol: 'matic', accountType: 'normal' }),
getWalletAccount({ symbol: 'matic', accountType: 'ledger' }),
getWalletAccount({ symbol: 'sol', accountType: 'normal', empty: true, visible: false }),
getWalletAccount({ symbol: 'sol', accountType: 'ledger' }),
getWalletAccount({
symbol: 'sol',
accountType: 'ledger',
empty: true,
visible: false,
}),
];

type RunFilterReceiveAccountsTestParams = {
isDebug?: boolean;
receiveNetwork?: string;
deviceState?: `${string}@${string}:${number}`;
};

const runFilterReceiveAccouns = ({
isDebug = true,
receiveNetwork = 'eth',
deviceState = '1stTestnetAddress@device_id:0',
}: RunFilterReceiveAccountsTestParams) => {
const device = getSuiteDevice({
unavailableCapabilities: {
dash: 'no-support',
},
state: deviceState,
});
const unavailableCapabilities = device?.unavailableCapabilities ?? {};

const receiveNetworks = networksCollection.filter(
(n: Network) =>
n.symbol === receiveNetwork &&
!unavailableCapabilities[n.symbol] &&
((n.isDebugOnlyNetwork && isDebug) || !n.isDebugOnlyNetwork),
);

return filterReceiveAccounts({
accounts,
deviceState: device.state,
receiveNetwork,
isDebug,
receiveNetworks,
});
};

it('filterReceiveAccounts: isDebug', () => {
const filteredAccounts = [
getWalletAccount({ symbol: 'eth', accountType: 'legacy' }),
getWalletAccount({ symbol: 'eth', accountType: 'normal' }),
getWalletAccount({ symbol: 'eth', accountType: 'ledger' }),
];

expect(runFilterReceiveAccouns({})).toEqual(filteredAccounts);
});

it('filterReceiveAccounts: isNotDebug', () => {
const filteredAccounts = [getWalletAccount({ symbol: 'eth', accountType: 'normal' })];

expect(runFilterReceiveAccouns({ isDebug: false })).toEqual(filteredAccounts);
});

it('filterReceiveAccounts: isNotSameDevice', () => {
expect(runFilterReceiveAccouns({ deviceState: '2ndTestnetAddress@device_id:0' })).toEqual(
[],
);
});

it('filterReceiveAccounts: isAnotherNetwork', () => {
const filteredAccounts = [
getWalletAccount({ symbol: 'btc', accountType: 'coinjoin' }),
getWalletAccount({ symbol: 'btc', accountType: 'taproot' }),
getWalletAccount({ symbol: 'btc', accountType: 'legacy' }),
getWalletAccount({ symbol: 'btc', accountType: 'segwit' }),
getWalletAccount({ symbol: 'btc', accountType: 'ledger' }),
];

expect(runFilterReceiveAccouns({ receiveNetwork: 'btc' })).toEqual(filteredAccounts);
});

it('filterReceiveAccounts: isEmptyAccount and isNotVisibleAccount + isEmptyAccount and isNotVisibleAccount but isFirstNormalAccount', () => {
const filteredAccounts = [
getWalletAccount({ symbol: 'sol', accountType: 'normal', empty: true, visible: false }),
getWalletAccount({ symbol: 'sol', accountType: 'ledger' }),
];

expect(runFilterReceiveAccouns({ receiveNetwork: 'sol' })).toEqual(filteredAccounts);
});
});
53 changes: 53 additions & 0 deletions suite-common/wallet-utils/src/accountUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
TokenTransfer,
TokenInfo,
} from '@trezor/connect';
import { Network } from '@suite-common/wallet-config';
import { arrayDistinct, bufferUtils } from '@trezor/utils';
import {
networksCompatibility,
Expand Down Expand Up @@ -1153,3 +1154,55 @@ export const isTokenMatchesSearch = (token: TokenInfo, search: string) => {
token.policyId?.toLowerCase().includes(search)
);
};

export const isDebugOnlyAccountType = (
accountType: AccountType,
symbol?: NetworkSymbol,
): boolean => {
if (!symbol) return false;

const network = getNetwork(symbol);

const accountTypeInfo = network.accountTypes[accountType];

return !!accountTypeInfo?.isDebugOnlyAccountType;
};

type FilterRecieveAccountsProps = {
accounts: Account[];
deviceState: string | undefined;
receiveNetwork?: string;
isDebug: boolean;
receiveNetworks: Network[];
};

export const filterReceiveAccounts = ({
accounts,
deviceState,
receiveNetwork,
isDebug,
receiveNetworks,
}: FilterRecieveAccountsProps): Account[] => {
const isSameDevice = (account: Account) => account.deviceState === deviceState;
const isSameNetwork = (account: Account) => account.symbol === receiveNetwork;
const shouldDisplayDebugOnly = (account: Account) =>
isDebug || !isDebugOnlyAccountType(account.accountType, account.symbol);
const isNotEmptyAccount = (account: Account) => !account.empty;
const isVisibleAccount = (account: Account) => account.visible;
const isFirstNormalAccount = (account: Account) =>
account.accountType === 'normal' && account.index === 0;

if (receiveNetworks.length > 0) {
return accounts.filter(
account =>
isSameDevice(account) &&
isSameNetwork(account) &&
shouldDisplayDebugOnly(account) &&
(isNotEmptyAccount(account) ||
isVisibleAccount(account) ||
isFirstNormalAccount(account)),
);
}

return [];
};

0 comments on commit a5c0f49

Please sign in to comment.