Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: [LW-11802] enable strict null checks #1536

Open
wants to merge 38 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
419ef6f
chore: enable strict null checks in tsconfig
mchappell Nov 5, 2024
fbe6303
refactor(common): fix ts null check errors
mchappell Nov 5, 2024
926fd00
refactor(cardano): fix ts null checks errors
vetalcore Nov 6, 2024
9f7bba6
fixup! refactor(common): fix ts null check errors
mchappell Nov 6, 2024
cf2b7ce
refactor(core): add strict null checks for add shared wallet flow
mchappell Nov 11, 2024
f47593b
refactor(nami): remove src director from tsconfig exclusions
mchappell Nov 11, 2024
1a56b61
refactor(core): add strict checks on optional address card properties
mchappell Nov 12, 2024
d74de6d
refactor(core): add strict null checks for useRef
mchappell Nov 12, 2024
b88051d
refactor(core): add strict null checks to share wallet cosigner
mchappell Nov 12, 2024
d98c2b7
refactor(core): add strict null check on expected process.env social …
mchappell Nov 12, 2024
a6a0b46
refactor(core): make currentTimelineStep a required property of onboa…
mchappell Nov 12, 2024
3da470f
refactor(core): update all parameter change actions to include all pr…
mchappell Nov 12, 2024
12560bb
refactor(core): add strict null checks for activity details
mchappell Nov 12, 2024
691cbbb
refactor(core): add strict null check to NFT screens
mchappell Nov 12, 2024
50bec69
refactor(core): relax typings for cardano certificate types
mchappell Nov 12, 2024
0a0c43a
refactor(core): add nullish check for optional methods before invoking
mchappell Nov 12, 2024
fd72848
refactor(extension): remove strict null checks
mchappell Nov 13, 2024
bc1981b
refactor(core): use prop spread as a better way to implement optional…
mchappell Nov 13, 2024
f6a6a4b
refactor(core): tighten password verification props which always exist
mchappell Nov 13, 2024
a28dad7
refactor(core): add nullish checks for classnames
mchappell Nov 13, 2024
aee20e5
refactor(core): add strict null checks in dapp transactions
mchappell Nov 13, 2024
b29f1f7
refactor(core): add null checks for transaction hash and coin symbol
mchappell Nov 13, 2024
d7a59d9
refactor(core): add null checks for mapped array properties
mchappell Nov 13, 2024
bec9b6a
refactor(core): add null checks to wallet setup
mchappell Nov 13, 2024
9018e97
refactor(core): add null checks to asset components
mchappell Nov 13, 2024
558503f
refactor(core): update deep partial types for governance actions
mchappell Nov 13, 2024
eccd160
refactor(core): enforce required fallback for images
mchappell Nov 13, 2024
c473ed7
refactor(core): add null checks on handle resolution
mchappell Nov 13, 2024
501d73b
refactor(core): fix linting issues
mchappell Nov 13, 2024
40ee7d5
chore: fix linting in common package
mchappell Nov 13, 2024
bd7f265
refactor: fix ts null checks errors
vetalcore Nov 25, 2024
3e4cd92
refactor: fix sonarcloud issues
vetalcore Nov 25, 2024
c720cdf
refactor(extension): fix unit tests
vetalcore Nov 26, 2024
1f3eab6
refactor(cardano): fix unit tests
vetalcore Nov 26, 2024
ceec0ab
refactor(core): fix unit tests
vetalcore Nov 26, 2024
c3e5ddc
refactor(common): fix unit tests
vetalcore Nov 26, 2024
a2f5018
fix: [lw-11802]: fix e2e
vetalcore Nov 29, 2024
1d39407
fix: [lw-11802]: resolve pr comments
vetalcore Nov 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/browser-extension-wallet/src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"baseUrl": "../src",
"resolveJsonModule": true,
"noEmitOnError": false,
"strictNullChecks": false,
"paths": {
"@assets/*": ["assets/*"],
"@components/*": ["components/*"],
Expand Down
4 changes: 2 additions & 2 deletions apps/browser-extension-wallet/src/utils/format-number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const formatLocaleNumber = (value: string, decimalPlaces: number = DEFAUL
* @param maxDecimals The maximum number of decimal places to include. Default is 0.
* @returns The formatted number string.
*/
export const formatNumberForDisplay = (value: string, maxDecimals = 0): string => {
export const formatNumberForDisplay = (value?: string, maxDecimals = 0): string => {
if (!value) return '0';
// Remove any character that is not a dot or a number
const parsedStringValue = value.replace(/[^\d.]/g, '');
Expand Down Expand Up @@ -137,7 +137,7 @@ export const handleFormattedValueChange = (
* @param decimals The desired decimal places (default = 2)
* @returns The formatted value with the desired decimals and the unit as a string
*/
export const compactNumberWithUnit = (value: number | string, decimals = DEFAULT_DECIMALS): string => {
export const compactNumberWithUnit = (value?: number | string, decimals = DEFAULT_DECIMALS): string => {
const bigNumberValue = value ? new BigNumber(value) : new BigNumber(0);

if (bigNumberValue.isNaN()) return formatLocaleNumber('0', decimals);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { MAX_NFT_TICKER_LENGTH, MAX_TOKEN_TICKER_LENGTH } from '../../../constan

interface InputFieldActionParams {
id: string;
value: string;
value?: string;
maxDecimals?: number;
}

Expand Down Expand Up @@ -176,10 +176,10 @@ export const useSelectedCoins = ({
coinBalance,
spendableCoin?.toString(),
tokensUsed[cardanoCoin.id] || '0',
assetInputItem?.value || '0'
assetInputItem?.value ?? '0'
);
const fiatValue = Wallet.util.convertAdaToFiat({
ada: assetInputItem?.value || '0',
ada: assetInputItem?.value ?? '0',
fiat: prices?.cardano?.price
});
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const StakePoolInfo = ({
onClick?: () => void;
popupView: boolean;
}): React.ReactElement => {
const title = name || ticker || '-';
const subTitle: string | React.ReactElement = ticker || (
const title = name ?? ticker ?? '-';
const subTitle: string | React.ReactElement = ticker ?? (
<Ellipsis className={styles.id} text={id} beforeEllipsis={6} afterEllipsis={8} />
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@ process.env.USE_POSTHOG_ANALYTICS = 'true';
process.env.USE_POSTHOG_ANALYTICS_FOR_OPTED_OUT = 'false';
process.env.POSTHOG_HOST = 'https://e.lw.iog.io';
process.env.POSTHOG_DEV_TOKEN = 'test-token';
process.env.MIN_NUMBER_OF_COSIGNERS = '2';
process.env.TWITTER_URL = 'TWITTER_URL';
process.env.YOUTUBE_URL = 'YOUTUBE_URL';
process.env.DISCORD_URL = 'DISCORD_URL';
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const StakePoolMetricsBrowser = ({ data, popupView }: StakePoolMetricsBro
{t}
</div>
<div className={styles.statBody} data-testid={`${testId}-value`}>
{unit ? formatNumericValue(value, unit) : value}
{unit && value ? formatNumericValue(value, unit) : value}
</div>
</div>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const StakePoolNameBrowser = ({
isOversaturated,
translations
}: StakePoolNameBrowserProps): React.ReactElement => {
const title = name || ticker || '-';
const subTitle: string | React.ReactElement = ticker || (
<Ellipsis className={styles.id} text={id} beforeEllipsis={6} afterEllipsis={8} />
const title = name ?? ticker ?? '-';
const subTitle: string | React.ReactElement = ticker ?? (
<Ellipsis className={styles.id} text={id ?? ''} beforeEllipsis={6} afterEllipsis={8} />
);

return (
Expand All @@ -48,13 +48,15 @@ export const StakePoolNameBrowser = ({
<p className={styles.subTitle} data-testid="stake-pool-item-ticker">
{subTitle}
</p>
<StatusLogo
status={status}
isDelegated={isDelegated}
isOversaturated={isOversaturated}
className={styles.statusLogo}
translations={translations}
/>
{status && (
<StatusLogo
status={status}
isDelegated={!!isDelegated}
isOversaturated={isOversaturated}
className={styles.statusLogo}
translations={translations}
/>
)}
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ import { StakePoolNameBrowser, StakePoolNameBrowserProps } from '../StakePoolNam
import '@testing-library/jest-dom';

describe('Testing StakePoolNameBrowser component', () => {
const name = 'name';
const ticker = 'ticker';
const props: StakePoolNameBrowserProps = {
name: 'name',
ticker: 'ticker',
name,
ticker,
isDelegated: true,
translations: { retiring: 'retiring', retired: 'retired', delegating: 'delegating', saturated: 'saturated' }
};
test('should display all stake pool metrics with icons', async () => {
const { findByText, findByTestId } = render(<StakePoolNameBrowser {...props} />);
const roiLabel = await findByTestId('stake-pool-item-logo');
const nameValue = await findByText(props.name);
const tickerValue = await findByText(props.ticker);
const nameValue = await findByText(name);
const tickerValue = await findByText(ticker);

expect(roiLabel).toBeVisible();
expect(nameValue).toBeVisible();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export const StatusLogo = ({
if (status === 'retired' || status === 'retiring') {
currentStatus = status;
}
const icon = statusIcons[currentStatus];
const description = statusInfo[currentStatus];
const icon = currentStatus ? statusIcons[currentStatus] : undefined;
const description = currentStatus ? statusInfo[currentStatus] : undefined;

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import styles from './Voting.module.scss';
import { Button } from '@lace/common';
import CatalystLogo from '../../assets/images/catalyst-logo.png';
import Icon, { InfoCircleOutlined } from '@ant-design/icons';
import { InfoCircleOutlined } from '@ant-design/icons';
import { TranslationsFor } from '@wallet/util/types';

export interface CatalystConfirmationStepProps {
Expand Down Expand Up @@ -52,7 +52,7 @@ export const CatalystConfirmationStep = ({
<>
<div className={styles.fee}>
<p>
{translations.totalFee} <Icon component={InfoCircleOutlined} />
{translations.totalFee} <InfoCircleOutlined />
</p>
<b>{fee}</b>
</div>
Expand Down
12 changes: 6 additions & 6 deletions packages/cardano/src/ui/components/Voting/CatalystScanStep.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useRef } from 'react';
import { Button } from '@lace/common';
import Icon, { DownloadOutlined } from '@ant-design/icons';
import { DownloadOutlined } from '@ant-design/icons';
import QRCodeStyling from 'qr-code-styling';
import styles from './Voting.module.scss';
import { TranslationsFor } from '@wallet/util/types';
Expand All @@ -16,12 +16,12 @@ export const CatalystScanStep = ({
certificate,
translations
}: CatalystScanStepProps): React.ReactElement => {
const qrCodeRef = useRef(null);
const qrCode = useRef<QRCodeStyling>(null);
const qrCodeRef = useRef<HTMLDivElement | null>(null);
const qrCode = useRef<QRCodeStyling | null>(null);

useEffect(() => {
qrCode.current = new QRCodeStyling({ data: certificate, width: 240, height: 240 });
qrCode.current.append(qrCodeRef.current);
qrCode.current.append(qrCodeRef.current || undefined);
}, [certificate]);

return (
Expand All @@ -34,10 +34,10 @@ export const CatalystScanStep = ({
<div ref={qrCodeRef} />
<div>
<Button
onClick={() => qrCode.current.download({ name: 'certificate', extension: 'png' })}
onClick={() => qrCode.current?.download({ name: 'certificate', extension: 'png' })}
color="secondary"
>
<Icon component={DownloadOutlined} /> {translations.downloadButton}
<DownloadOutlined /> {translations.downloadButton}
</Button>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ describe.skip('Testing build-transaction', () => {

expect(transaction).toBeDefined();
expect(minimumCoinQuantities).toBeDefined();
expect(minimumCoinQuantities.get(output).coinMissing).toBe(BigInt(0));
expect(minimumCoinQuantities.get(output)?.coinMissing).toBe(BigInt(0));
});

test('should validate and build a transaction successfully with coins missing', async () => {
Expand All @@ -39,7 +39,7 @@ describe.skip('Testing build-transaction', () => {

expect(transaction).toBeDefined();
expect(minimumCoinQuantities).toBeDefined();
expect(minimumCoinQuantities.get(output).coinMissing).toBeGreaterThan(BigInt(0));
expect(minimumCoinQuantities.get(output)?.coinMissing).toBeGreaterThan(BigInt(0));
});

test('should throw an error if tx initialization fails', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe('Testing getTxInputsValueAndAddress function', () => {
signed$: of([])
}
}
} as ObservableWallet;
} as unknown as ObservableWallet;

const multiDelegationTransactionMock: Cardano.HydratedTx = {
inputSource: Cardano.InputSource.inputs,
Expand Down Expand Up @@ -194,11 +194,11 @@ describe('Testing getTxInputsValueAndAddress function', () => {
'addr_test1qrmavlv5c7za68rq6n6r0hrcqd604j9zsr6tycwtjf3lef0wc4p9nt0e0wwytcy30mxar65892w3k77e5g2uyhx29lhqjt267p'
);
// From matched output in mocked transaction
expect(inputs[0].value.coins.toString()).toBe('3000000');
expect(inputs[0].value?.coins.toString()).toBe('3000000');
expect(
inputs[0].value.assets
.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
.toString()
inputs[0].value?.assets
?.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
?.toString()
).toBe('30');
});
});
Expand All @@ -225,11 +225,11 @@ describe('Testing getTxInputsValueAndAddress function', () => {
'addr_test1qrmavlv5c7za68rq6n6r0hrcqd604j9zsr6tycwtjf3lef0wc4p9nt0e0wwytcy30mxar65892w3k77e5g2uyhx29lhqjt267p'
);
// From matched output in mocked transaction
expect(inputs[0].value.coins.toString()).toBe('3000000');
expect(inputs[0].value?.coins.toString()).toBe('3000000');
expect(
inputs[0].value.assets
.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
.toString()
inputs[0].value?.assets
?.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
?.toString()
).toBe('30');
});
});
Expand Down Expand Up @@ -261,7 +261,7 @@ describe('Testing getTxInputsValueAndAddress function', () => {
const inputs = await result;
expect(transactionsByHashes).toBeCalledTimes(1);
expect(inputs[0].address).toBe('address');
expect(inputs[0].value.coins.toString()).toBe('3000000');
expect(inputs[0].value?.coins.toString()).toBe('3000000');
});
});

Expand Down Expand Up @@ -329,11 +329,11 @@ describe('Testing getTxInputsValueAndAddress function', () => {
expect(inputs[0].address).toBe(
'addr_test1qrmavlv5c7za68rq6n6r0hrcqd604j9zsr6tycwtjf3lef0wc4p9nt0e0wwytcy30mxar65892w3k77e5g2uyhx29lhqjt267p'
);
expect(inputs[0].value.coins.toString()).toBe('3000000');
expect(inputs[0].value?.coins.toString()).toBe('3000000');
expect(
inputs[0].value.assets
.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
.toString()
inputs[0].value?.assets
?.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
?.toString()
).toBe('30');

// Assert the properties for the second input
Expand All @@ -342,12 +342,12 @@ describe('Testing getTxInputsValueAndAddress function', () => {
);

expect(
inputs[1].value.assets
.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
.toString()
inputs[1].value?.assets
?.get(Cardano.AssetId('6b8d07d69639e9413dd637a1a815a7323c69c86abbafb66dbfdb1aa7'))
?.toString()
).toBe('10');

expect(inputs[1].value.coins.toString()).toBe('100000');
expect(inputs[1].value?.coins.toString()).toBe('100000');

expect(inputs[2].address).toBe(
'addr_test1qrrx8s34r6m0w835qe9tj8mqa4ugkwhllw5l4hwpmhakpy8hukqufzmfnrvvr24tschssxw96z8dq9dz09xkg9eghtkqe07423'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type OutputsMap = Map<string, CardanoOutput>;
type TokenBalanceMap = Map<Cardano.AssetId, bigint>;

export const convertAssetsToBigInt = (
assets: CardanoOutput['value']['assets'],
assets: Map<Cardano.AssetId, string>,
assetsInfo: Assets = new Map()
): TokenBalanceMap => {
const assetMap: TokenBalanceMap = new Map();
Expand Down
2 changes: 1 addition & 1 deletion packages/cardano/src/wallet/lib/build-transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const buildTransaction = async (
wallet: ObservableWallet
): Promise<InitializedCardanoTransaction> => {
const util = createWalletUtil(wallet);
const minimumCoinQuantities = await util.validateOutputs(txProps.outputs);
const minimumCoinQuantities = await util.validateOutputs(txProps.outputs || []);
const transaction = await wallet.initializeTx(txProps);

return { transaction, minimumCoinQuantities };
Expand Down
2 changes: 1 addition & 1 deletion packages/cardano/src/wallet/lib/get-inputs-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const getTxInputsValueAndAddress = async (

for (const input of inputs) {
const output = await util.resolveInput(input);
resolvedInputs.push([{ address: output.address, ...input }, output]);
if (output) resolvedInputs.push([{ address: output.address, ...input }, output]);
}

return resolvedInputs.map((utxo) => {
Expand Down
15 changes: 8 additions & 7 deletions packages/cardano/src/wallet/lib/hardware-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ const DEFAULT_COMMUNICATION_TYPE = KeyManagement.CommunicationType.Web;

// https://github.com/trezor/connect/blob/develop/docs/index.md#trezor-connect-manifest
export const manifest: KeyManagement.TrezorConfig['manifest'] = {
appUrl: process.env.WEBSITE_URL,
email: process.env.EMAIL_ADDRESS
appUrl: process.env.WEBSITE_URL as unknown as string,
email: process.env.EMAIL_ADDRESS as unknown as string
};

const initializeTrezor = () =>
Expand All @@ -28,15 +28,16 @@ const initializeTrezor = () =>
communicationType: DEFAULT_COMMUNICATION_TYPE
});

const connectDevices: Record<HardwareWallets, () => Promise<DeviceConnection>> = {
const connectDevices: Partial<Record<HardwareWallets, () => Promise<DeviceConnection>>> = {
[WalletType.Ledger]: async () =>
await HardwareLedger.LedgerKeyAgent.checkDeviceConnection(DEFAULT_COMMUNICATION_TYPE),
...(AVAILABLE_WALLETS.includes(WalletType.Trezor) && {
[WalletType.Trezor]: async () => await initializeTrezor()
})
};

export const connectDevice = async (model: HardwareWallets): Promise<DeviceConnection> => await connectDevices[model]();
export const connectDevice = async (model: HardwareWallets): Promise<DeviceConnection> =>
await connectDevices[model]?.();

type Descriptor = Partial<USBDevice>;
type DescriptorEntries<T extends Descriptor> = [keyof T, T[keyof T]][];
Expand Down Expand Up @@ -111,18 +112,18 @@ export const getHwExtendedAccountPublicKey = async (
};

type DeviceSpec = {
model: string;
model?: string;
firmwareVersion?: string;
cardanoAppVersion?: string;
};

const makeVersion = (major: number, minor: number, patch: number) => `${major}.${minor}.${patch}`;

export const getDeviceSpec = async (connection: HardwareWalletConnection): Promise<DeviceSpec> => {
if (connection.type === WalletType.Ledger) {
if (connection.type === WalletType.Ledger && typeof connection.value !== 'undefined') {
const { version } = await connection.value.getVersion();
return {
model: connection.value.transport.deviceModel.id,
model: connection.value.transport.deviceModel?.id,
cardanoAppVersion: makeVersion(version.major, version.minor, version.patch)
};
}
Expand Down
4 changes: 0 additions & 4 deletions packages/cardano/src/wallet/test/mocks/ProviderStub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,6 @@ export const mockWalletProvider = (): NetworkInfoProvider &
RewardsProvider &
StakePoolProvider &
UtxoProvider => ({
protocolParameters: jest.fn().mockResolvedValue(protocolParameters),
genesisParameters: jest.fn().mockResolvedValue(genesisParameters),
ledgerTip: jest.fn().mockResolvedValue(ledgerTip),
blocksByHashes: jest
.fn()
.mockResolvedValue([{ epoch: Cardano.EpochNo(currentEpoch.number - 3) } as Cardano.ExtendedBlockInfo]),
Expand All @@ -215,7 +212,6 @@ export const mockWalletProvider = (): NetworkInfoProvider &
retiring: 5
}
}),
healthCheck: jest.fn().mockResolvedValue({ ok: true }),
utxoByAddresses: jest.fn().mockResolvedValue(utxo),
rewardAccountBalance: jest.fn().mockResolvedValue(rewards),
...networkInfoProviderStub()
Expand Down
Loading
Loading