diff --git a/scripts/markets/add-markets.ts b/scripts/markets/add-markets.ts index 846557fad..f48b2d8b6 100644 --- a/scripts/markets/add-markets.ts +++ b/scripts/markets/add-markets.ts @@ -13,17 +13,18 @@ import { IndexerConfig, LocalWallet as LocalWalletType, Network, - ValidatorConfig + ValidatorConfig, } from '@dydxprotocol/v4-client-js'; import { readFileSync } from 'fs'; import Long from 'long'; + import { - createAndSendMarketMapProposal, PerpetualMarketType, Proposal, + createAndSendMarketMapProposal, retry, sleep, - voteOnProposals + voteOnProposals, } from './help'; const LocalWalletModule = await import( @@ -177,15 +178,15 @@ async function addMarkets( ); // Add markets to market map first. - console.log("Submitting market map proposal..."); + console.log('Submitting market map proposal...'); await createAndSendMarketMapProposal( filteredProposals.slice(0, numMarkets), config.validatorEndpoint, config.chainId, - binary, + binary ); await sleep(sleepMsBtwTxs); - console.log("Submitted market map proposal"); + console.log('Submitted market map proposal'); // Get latest gov proposal ID. const allProposalsResp = await client.validatorClient.get.getAllGovProposals(); @@ -215,16 +216,16 @@ async function addMarkets( if (numProposalsSent >= numProposalsToSend) { break; } - const proposal = proposalsToSend[j]; + const proposal = proposalsToSend[j]!; const marketId: number = numExistingMarkets + numProposalsSent + 1; // Send proposal. const exchangeConfigString = `{"exchanges":${JSON.stringify( - proposal.params.exchangeConfigJson + proposal!.params.exchangeConfigJson )}}`; await retry(() => client.submitGovAddNewMarketProposal( - wallets[j], + wallets[j]!, { id: marketId, ticker: proposal.params.ticker, @@ -272,7 +273,7 @@ async function main(): Promise { // Get which env and how many markets to add. const args = process.argv.slice(2); const env = args[0] as Env; - const numMarkets = parseInt(args[1], 10); + const numMarkets = args[1] != null ? parseInt(args[1], 10) : 0; const binary = args[2]; // Validate inputs. diff --git a/scripts/markets/help.ts b/scripts/markets/help.ts index 86b34ef47..ed4177a40 100644 --- a/scripts/markets/help.ts +++ b/scripts/markets/help.ts @@ -13,7 +13,6 @@ import { spawn } from 'child_process'; import * as fs from 'fs'; import Long from 'long'; - const VOTE_FEE: StdFee = { amount: [ { @@ -192,7 +191,7 @@ export async function createAndSendMarketMapProposal( proposals: Proposal[], validatorEndpoint: string, chainId: string, - binary: string, + binary: string ) { const markets: Market[] = proposals.map((proposal) => { const { ticker, priceExponent, minExchanges, exchangeConfigJson } = proposal.params; @@ -205,14 +204,14 @@ export async function createAndSendMarketMapProposal( if (config.adjustByMarket) { const [Base, Quote] = config.adjustByMarket.split('-'); - normalize_by_pair = { Base, Quote }; + normalize_by_pair = { Base: Base!, Quote: Quote! }; } return { name: config.exchangeName, normalize_by_pair, off_chain_ticker: config.ticker, - invert: config.invert || false, + invert: !!config.invert, metadata_JSON: config.metadata_JSON ?? '', }; }); @@ -220,8 +219,8 @@ export async function createAndSendMarketMapProposal( return { ticker: { currency_pair: { - Base: modifiedTicker.split('/')[0], - Quote: modifiedTicker.split('/')[1], + Base: modifiedTicker.split('/')[0]!, + Quote: modifiedTicker.split('/')[1]!, }, decimals: Math.abs(priceExponent).toString(), enabled: false, @@ -233,17 +232,17 @@ export async function createAndSendMarketMapProposal( }); const proposal = { - "title": "Add markets to market map", - "summary":"Add markets to market map", - "messages": [ + title: 'Add markets to market map', + summary: 'Add markets to market map', + messages: [ { - "@type": "/slinky.marketmap.v1.MsgUpsertMarkets", - "authority": "dydx10d07y265gmmuvt4z0w9aw880jnsr700jnmapky", - "markets": markets, + '@type': '/slinky.marketmap.v1.MsgUpsertMarkets', + authority: 'dydx10d07y265gmmuvt4z0w9aw880jnsr700jnmapky', + markets: markets, }, ], - "deposit":"5000000000000000000adv4tnt", - "expedited": true, + deposit: '5000000000000000000adv4tnt', + expedited: true, }; const proposalFile = 'marketMapProposal.json'; @@ -256,30 +255,34 @@ export async function createAndSendMarketMapProposal( binary, ['keys', 'add', 'alice', '--recover'], 'merge panther lobster crazy road hollow amused security before critic about cliff exhibit cause coyote talent happy where lion river tobacco option coconut small' - ) + ); } await execCLI( binary, [ - '--node', validatorEndpoint, - 'tx', 'gov', 'submit-proposal', 'marketMapProposal.json', - '--from', 'alice', - '--fees', '2000000000000000000adv4tnt', - '--chain-id', chainId, - '--gas', 'auto' + '--node', + validatorEndpoint, + 'tx', + 'gov', + 'submit-proposal', + 'marketMapProposal.json', + '--from', + 'alice', + '--fees', + '2000000000000000000adv4tnt', + '--chain-id', + chainId, + '--gas', + 'auto', ], - 'y', - ) + 'y' + ); fs.unlinkSync(proposalFile); } -export function execCLI( - command: string, - args?: string[], - input?: string, -): Promise { +export function execCLI(command: string, args?: string[], input?: string): Promise { return new Promise((resolve, reject) => { const process = spawn(command, args); diff --git a/scripts/markets/validate-other-market-data.ts b/scripts/markets/validate-other-market-data.ts index 06b2d673f..dd9db44d2 100644 --- a/scripts/markets/validate-other-market-data.ts +++ b/scripts/markets/validate-other-market-data.ts @@ -332,7 +332,7 @@ async function validateAgainstLocalnet(proposals: Proposal[]): Promise { network.validatorConfig.chainId, 'v4-chain/protocol/build/dydxprotocold' ); - console.log("Submitted market map proposal"); + console.log('Submitted market map proposal'); await sleep(5000); for (const wallet of wallets) { retry(() => voteOnProposals([1], client, wallet)); @@ -352,7 +352,7 @@ async function validateAgainstLocalnet(proposals: Proposal[]): Promise { const proposalIds: number[] = []; for (let j = 0; j < proposalsToSend.length; j++) { // Use wallets[j] to send out proposalsToSend[j] - const proposal = proposalsToSend[j]; + const proposal = proposalsToSend[j]!; const marketId: number = numExistingMarkets + proposalId; // Send proposal. @@ -361,7 +361,7 @@ async function validateAgainstLocalnet(proposals: Proposal[]): Promise { )}}`; const tx = await retry(() => client.submitGovAddNewMarketProposal( - wallets[j], + wallets[j]!, // @ts-ignore: marketType is not a valid parameter for addNewMarketProposal { id: marketId, @@ -734,7 +734,7 @@ function getProposalsToValidate(newProposals: Record): Set { if (proposalsToValidate.size === 0) { return; } - await validateAgainstLocalnet(Array.from(proposalsToValidate).map((name) => newProposals[name])); + await validateAgainstLocalnet(Array.from(proposalsToValidate).map((name) => newProposals[name]!)); console.log(`\nValidated ${proposalsToValidate.size} proposals. See log for specific names.`); } diff --git a/src/components/DropdownSelectMenu.stories.tsx b/src/components/DropdownSelectMenu.stories.tsx index b9dba78ec..dd8d407cc 100644 --- a/src/components/DropdownSelectMenu.stories.tsx +++ b/src/components/DropdownSelectMenu.stories.tsx @@ -32,7 +32,7 @@ const exampleItems = [ export const DropdownSelectMenuStory: Story< Pick[0], 'items' | 'align' | 'sideOffset' | 'disabled'> > = (args) => { - const [item, setItem] = useState(exampleItems[0].value); + const [item, setItem] = useState(exampleItems[0]!.value); return ( setItem(value)} {...args} /> diff --git a/src/components/RadioButtonCards.stories.tsx b/src/components/RadioButtonCards.stories.tsx index 708196b71..069995c0d 100644 --- a/src/components/RadioButtonCards.stories.tsx +++ b/src/components/RadioButtonCards.stories.tsx @@ -42,7 +42,7 @@ export const RadioButtonCardsStory: Story = ({ withSlotTop, withSlotBottom, }: RadioButtonCardStoryProps) => { - const [item, setItem] = useState(exampleItems[0].value); + const [item, setItem] = useState(exampleItems[0]!.value); return ( [0], 'items'>> = (args) => { - const [item, setItem] = useState(exampleItems[0].value); + const [item, setItem] = useState(exampleItems[0]!.value); return ( setItem(value)} {...args} /> diff --git a/src/components/SelectMenu.stories.tsx b/src/components/SelectMenu.stories.tsx index 7998339d4..c8981af5e 100644 --- a/src/components/SelectMenu.stories.tsx +++ b/src/components/SelectMenu.stories.tsx @@ -29,8 +29,8 @@ const exampleItems: { value: string; label: string }[] = [ ]; export const SelectMenuStory: Story[0]> = () => { - const [value, setValue] = useState(exampleItems[0].value); - const [value2, setValue2] = useState(exampleItems[2].value); + const [value, setValue] = useState(exampleItems[0]!.value); + const [value2, setValue2] = useState(exampleItems[2]!.value); return ( diff --git a/src/components/WalletIcon.tsx b/src/components/WalletIcon.tsx index 2d19583de..05745c5d4 100644 --- a/src/components/WalletIcon.tsx +++ b/src/components/WalletIcon.tsx @@ -11,7 +11,12 @@ export const WalletIcon = ({ wallet, size = '1em' }: { wallet: WalletInfo; size? return <$Image src={wallet.icon} alt={wallet.name} size={size} />; } - return ; + return ( + + ); }; const $Image = styled.img<{ size: string }>` diff --git a/src/components/visx/TimeSeriesChart.tsx b/src/components/visx/TimeSeriesChart.tsx index ef5014a1f..9c92f4717 100644 --- a/src/components/visx/TimeSeriesChart.tsx +++ b/src/components/visx/TimeSeriesChart.tsx @@ -137,10 +137,11 @@ export const TimeSeriesChart = ({ const chartRef = useRef(null); // Chart data - const { xAccessor, yAccessor } = series[0]; + const { xAccessor, yAccessor } = series[0]!; - const earliestDatum = data?.[0]; - const latestDatum = data?.[data.length - 1]; + const atLeastOnePoint = data.length > 0; + const earliestDatum = data[0]; + const latestDatum = data[data.length - 1]; // Chart state const getClampedZoomDomain = useCallback( @@ -148,7 +149,7 @@ export const TimeSeriesChart = ({ return clamp( Math.max(1e-320, Math.min(Number.MAX_SAFE_INTEGER, unclamped)), minZoomDomain, - xAccessor(latestDatum) - xAccessor(earliestDatum) + atLeastOnePoint ? xAccessor(latestDatum!) - xAccessor(earliestDatum!) : 0 ); }, [earliestDatum, latestDatum, minZoomDomain, xAccessor] @@ -211,10 +212,18 @@ export const TimeSeriesChart = ({ const zoom = zoomDomain / minZoomDomain; - const domainBase = [ - clamp(xAccessor(latestDatum) - zoomDomain, xAccessor(earliestDatum), xAccessor(latestDatum)), - xAccessor(latestDatum), - ] as [number, number]; + const domainBase = ( + atLeastOnePoint + ? [ + clamp( + xAccessor(latestDatum!) - zoomDomain, + xAccessor(earliestDatum!), + xAccessor(latestDatum!) + ), + xAccessor(latestDatum!), + ] + : [0, 0] + ) as [number, number]; const domain = [ domainBase[0] - (domainBase[1] - domainBase[0]) * domainBasePadding[0], domainBase[1] + (domainBase[1] - domainBase[0]) * domainBasePadding[1], diff --git a/src/constants/__test__/cctp.spec.ts b/src/constants/__test__/cctp.spec.ts index b953feaf7..71c7d7fdd 100644 --- a/src/constants/__test__/cctp.spec.ts +++ b/src/constants/__test__/cctp.spec.ts @@ -275,12 +275,12 @@ describe('isTokenCctp', () => { recommendedSymbol: 'test-recommendedSymbol', }); it('returns true for cctp token', () => { - const denom = cctpTokens[0].tokenAddress; + const denom = cctpTokens[0]!.tokenAddress; const asset = getTestAssetWithDenom(denom); expect(isTokenCctp(asset)).toBe(true); }); it('returns true for cctp token case insensitive', () => { - const denom = cctpTokens[0].tokenAddress.toLowerCase(); + const denom = cctpTokens[0]!.tokenAddress.toLowerCase(); const asset = getTestAssetWithDenom(denom); expect(isTokenCctp(asset)).toBe(true); }); diff --git a/src/constants/cctp.ts b/src/constants/cctp.ts index 52ae60fcb..f1d31ad55 100644 --- a/src/constants/cctp.ts +++ b/src/constants/cctp.ts @@ -24,7 +24,7 @@ const getHighestFeeChains = (type: NullableTransferType) => type === TransferType.withdrawal ? mainnetChains.filter(({ chainId }) => chainId === '1') : []; // move this out if we need it in another module -const capitalizeNames = (str: string) => str[0].toUpperCase() + str.slice(1); +const capitalizeNames = (str: string) => str[0]!.toUpperCase() + str.slice(1); export const getLowestFeeChainNames = (type: NullableTransferType) => getLowestFeeChains(type).map((token) => capitalizeNames(token.name.toLowerCase())); @@ -35,7 +35,7 @@ export const getMapOfLowestFeeTokensByDenom = (type: NullableTransferType) => if (!acc[token.tokenAddress]) { acc[token.tokenAddress] = []; } - acc[token.tokenAddress].push(token); + acc[token.tokenAddress]!.push(token); return acc; }, {} as Record @@ -47,7 +47,7 @@ const getMapOfChainsByChainId = (chains: CctpTokenInfo[]) => if (!acc[token.chainId]) { acc[token.chainId] = []; } - acc[token.chainId].push(token); + acc[token.chainId]!.push(token); return acc; }, {} as Record @@ -65,7 +65,7 @@ export const cctpTokensByDenomLowerCased = cctpTokens.reduce( if (!acc[lowerCasedAddress]) { acc[lowerCasedAddress] = []; } - acc[lowerCasedAddress].push(token); + acc[lowerCasedAddress]!.push(token); return acc; }, {} as Record @@ -76,7 +76,7 @@ export const cctpTokensByChainId = cctpTokens.reduce( if (!acc[token.chainId]) { acc[token.chainId] = []; } - acc[token.chainId].push(token); + acc[token.chainId]!.push(token); return acc; }, {} as Record diff --git a/src/constants/transfers.ts b/src/constants/transfers.ts index a56ecfc53..18561cc08 100644 --- a/src/constants/transfers.ts +++ b/src/constants/transfers.ts @@ -89,7 +89,7 @@ export const getNetworkTypeFromWalletNetworkType = ( return 'evm'; }; -export const getDefaultTokenDenomFromAssets = (assets: Asset[]): string => { +export const getDefaultTokenDenomFromAssets = (assets: Asset[]): string | undefined => { const cctpToken = assets.find((asset) => { return isTokenCctp(asset); }); diff --git a/src/constants/wallets.ts b/src/constants/wallets.ts index 168e0a843..195af278e 100644 --- a/src/constants/wallets.ts +++ b/src/constants/wallets.ts @@ -108,7 +108,7 @@ type WalletConfig = { icon: string; }; -export const wallets: Record = { +export const wallets = { [WalletType.OtherWallet]: { type: WalletType.OtherWallet, stringKey: STRING_KEYS.OTHER_WALLET, @@ -154,7 +154,7 @@ export const wallets: Record = { stringKey: STRING_KEYS.METAMASK, icon: MetaMaskIcon, }, -}; +} satisfies Record; /** * @description typed data to sign for dYdX Chain onboarding diff --git a/src/hooks/tradingView/useChartMarketAndResolution.ts b/src/hooks/tradingView/useChartMarketAndResolution.ts index 83d9c2ac7..ce68e87be 100644 --- a/src/hooks/tradingView/useChartMarketAndResolution.ts +++ b/src/hooks/tradingView/useChartMarketAndResolution.ts @@ -69,7 +69,7 @@ export const useChartMarketAndResolution = ({ // Different resolutions have different timeframes to display data efficiently. const defaultRange: number | undefined = isViewingUnlaunchedMarket ? LAUNCHABLE_MARKET_RESOLUTION_CONFIGS[resolution]?.defaultRange - : RESOLUTION_CHART_CONFIGS[resolution].defaultRange; + : RESOLUTION_CHART_CONFIGS[resolution]?.defaultRange; if (defaultRange) { const to = Date.now() / 1000; diff --git a/src/hooks/tradingView/useTradingViewDatafeed.ts b/src/hooks/tradingView/useTradingViewDatafeed.ts index 04f43f593..4f57f4d52 100644 --- a/src/hooks/tradingView/useTradingViewDatafeed.ts +++ b/src/hooks/tradingView/useTradingViewDatafeed.ts @@ -225,7 +225,7 @@ export const useTradingViewDatafeed = ( marketId: symbolInfo.ticker!, resolution, fromMs, - toMs: earliestCachedBarTime || toMs, + toMs: earliestCachedBarTime ?? toMs, }); dispatch( diff --git a/src/hooks/transfers/skipClient.tsx b/src/hooks/transfers/skipClient.tsx index b71066fa7..b458ee9c9 100644 --- a/src/hooks/transfers/skipClient.tsx +++ b/src/hooks/transfers/skipClient.tsx @@ -44,10 +44,10 @@ const useSkipClientContext = () => { if (chainId === getNeutronChainId()) return neutronValidator; if (chainId === getOsmosisChainId()) return osmosisValidator; if (chainId === selectedDydxChainId) - return compositeClient?.network.validatorConfig.restEndpoint ?? validators[0]; + return compositeClient?.network.validatorConfig.restEndpoint ?? validators[0]!; if (chainId === getSolanaChainId()) return solanaRpcUrl; const evmRpcUrls = RPCUrlsByChainId[chainId]; - if (evmRpcUrls) return evmRpcUrls[0]; + if (evmRpcUrls?.length) return evmRpcUrls[0]!; throw new Error(`Error: no rpc endpoint found for chainId: ${chainId}`); }, }, diff --git a/src/hooks/useAccountBalance.ts b/src/hooks/useAccountBalance.ts index 6c466971b..1ceb6f2b1 100644 --- a/src/hooks/useAccountBalance.ts +++ b/src/hooks/useAccountBalance.ts @@ -200,7 +200,7 @@ export const useAccountBalance = ({ const currentBalance = current.account.data.parsed.info.tokenAmount.uiAmount; const largestBalance = largest.account.data.parsed.info.tokenAmount.uiAmount; return currentBalance >= largestBalance ? current : largest; - }, accounts[0]); + }, accounts[0]!); return { data: { diff --git a/src/hooks/useAffiliatesInfo.ts b/src/hooks/useAffiliatesInfo.ts index 622579699..e380e93e8 100644 --- a/src/hooks/useAffiliatesInfo.ts +++ b/src/hooks/useAffiliatesInfo.ts @@ -72,7 +72,7 @@ export const useAffiliatesInfo = (dydxAddress?: string) => { const maxRevshare = lastTier ? lastTier.takerFeeSharePpm / 1_000_000 : DEFAULT_MAX_AFFILIATE_SHARE; - const taker3FeeTier = feeTiers?.[2].taker ?? DEFAULT_TAKER_3_FEE; + const taker3FeeTier = feeTiers?.[2]?.taker ?? DEFAULT_TAKER_3_FEE; const maxEarning = taker3FeeTier * maxRevshare * REF_SHARE_VOLUME_CAP_USD; const maxVipEarning = taker3FeeTier * MAX_AFFILIATE_VIP_SHARE * REF_SHARE_VOLUME_CAP_USD; diff --git a/src/hooks/useAnalytics.ts b/src/hooks/useAnalytics.ts index d2b336a97..82a67bb67 100644 --- a/src/hooks/useAnalytics.ts +++ b/src/hooks/useAnalytics.ts @@ -143,6 +143,7 @@ export const useAnalytics = () => { const lastSuccessfulIndexerRpcQuery = (websocketEndpoint && + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing lastSuccessfulWebsocketRequestByOrigin[new URL(websocketEndpoint).origin]) || undefined; diff --git a/src/hooks/useBreakpoints.ts b/src/hooks/useBreakpoints.ts index 0906f803f..6f06766d5 100644 --- a/src/hooks/useBreakpoints.ts +++ b/src/hooks/useBreakpoints.ts @@ -40,21 +40,21 @@ export const useBreakpoints = () => { const callbacks: { [key: string]: (e: MediaQueryListEvent) => void } = {}; objectEntries(mediaQueryLists).forEach(([key, mediaQueryList]) => { - const [, setMatches] = state[key]; + const [, setMatches] = state[key]!; callbacks[key] = (e) => { setMatches(e.matches); }; if (mediaQueryList.addEventListener) { - mediaQueryList.addEventListener('change', callbacks[key]); + mediaQueryList.addEventListener('change', callbacks[key]!); } }); return () => { objectEntries(mediaQueryLists).forEach(([key, mediaQueryList]) => { if (mediaQueryList.removeEventListener) { - mediaQueryList.removeEventListener('change', callbacks[key]); + mediaQueryList.removeEventListener('change', callbacks[key]!); } }); }; diff --git a/src/hooks/useDydxClient.tsx b/src/hooks/useDydxClient.tsx index 1343f53f7..b00377777 100644 --- a/src/hooks/useDydxClient.tsx +++ b/src/hooks/useDydxClient.tsx @@ -393,7 +393,7 @@ const useDydxClientContext = () => { const { candles } = (await indexerClient.markets.getPerpetualMarketCandles( marketId, - RESOLUTION_MAP[resolution], + RESOLUTION_MAP[resolution]!, fromIso, toIso, limit @@ -438,10 +438,10 @@ const useDydxClientContext = () => { const length = candlesInRange.length; if (length) { - const oldestTime = new Date(candlesInRange[length - 1].startedAt).getTime(); + const oldestTime = new Date(candlesInRange[length - 1]!.startedAt).getTime(); if (oldestTime > fromMs) { - toIso = candlesInRange[length - 1].startedAt; + toIso = candlesInRange[length - 1]!.startedAt; } else { break; } @@ -461,7 +461,7 @@ const useDydxClientContext = () => { const results = await Promise.all(promises); const screenedAddresses = Object.fromEntries( - addresses.map((address, index) => [address, results[index]?.restricted]) + addresses.map((address, index) => [address, !!results[index]?.restricted]) ); updateSanctionedAddresses(screenedAddresses); diff --git a/src/hooks/useEndpointsConfig.ts b/src/hooks/useEndpointsConfig.ts index e6f1c948b..bd95ceb58 100644 --- a/src/hooks/useEndpointsConfig.ts +++ b/src/hooks/useEndpointsConfig.ts @@ -23,7 +23,7 @@ export const useEndpointsConfig = () => { const endpointsConfig: EndpointsConfig = ENVIRONMENT_CONFIG_MAP[selectedNetwork].endpoints; return { - indexer: endpointsConfig.indexers[0], // assume there's only one option for indexer endpoints + indexer: endpointsConfig.indexers[0]!, // assume there's only one option for indexer endpoints validators: endpointsConfig.validators, skip: endpointsConfig.skip, nobleValidator: endpointsConfig.nobleValidator, diff --git a/src/hooks/useLaunchableMarkets.ts b/src/hooks/useLaunchableMarkets.ts index 9c15b788b..5ac0f2aea 100644 --- a/src/hooks/useLaunchableMarkets.ts +++ b/src/hooks/useLaunchableMarkets.ts @@ -45,25 +45,27 @@ export const useMetadataService = () => { const data: Record = {}; Object.keys(info ?? {}).forEach((key) => { - if (info?.[key] && prices?.[key]) { - const tickSizeDecimals = getTickSizeDecimalsFromPrice(prices[key].price); + const infoKey = info?.[key]; + const pricesKey = prices?.[key]; + if (infoKey && pricesKey) { + const tickSizeDecimals = getTickSizeDecimalsFromPrice(pricesKey.price); data[key] = { id: key, - name: info[key].name, - logo: info[key].logo, + name: infoKey.name, + logo: infoKey.logo, urls: { - website: info[key].urls.website, - technicalDoc: info[key].urls.technical_doc, - cmc: info[key].urls.cmc, + website: infoKey.urls.website, + technicalDoc: infoKey.urls.technical_doc, + cmc: infoKey.urls.cmc, }, - sectorTags: info[key].sector_tags, - exchanges: info[key].exchanges, - price: prices[key].price, - percentChange24h: prices[key].percent_change_24h, - marketCap: prices[key].market_cap, - volume24h: prices[key].volume_24h, - reportedMarketCap: prices[key].self_reported_market_cap, + sectorTags: infoKey.sector_tags, + exchanges: infoKey.exchanges, + price: pricesKey.price, + percentChange24h: pricesKey.percent_change_24h, + marketCap: pricesKey.market_cap, + volume24h: pricesKey.volume_24h, + reportedMarketCap: pricesKey.self_reported_market_cap, tickSizeDecimals, }; } @@ -136,6 +138,6 @@ export const useMetadataServiceCandles = ( return { ...candlesQuery, - data: candlesQuery.data?.[asset ?? ''].map(mapMetadataServiceCandles), + data: candlesQuery.data?.[asset ?? '']?.map(mapMetadataServiceCandles), }; }; diff --git a/src/hooks/useLocalNotifications.tsx b/src/hooks/useLocalNotifications.tsx index 04dbf3c80..55179aff2 100644 --- a/src/hooks/useLocalNotifications.tsx +++ b/src/hooks/useLocalNotifications.tsx @@ -61,7 +61,7 @@ const useLocalNotificationsContext = () => { const { dydxAddress } = useAccounts(); - const transferNotifications = dydxAddress ? allTransferNotifications[dydxAddress] || [] : []; + const transferNotifications = dydxAddress ? allTransferNotifications[dydxAddress] ?? [] : []; const setTransferNotifications = useCallback( (notifications: TransferNotifcation[]) => { @@ -71,7 +71,7 @@ const useLocalNotificationsContext = () => { updatedNotifications[dydxAddress] = [ ...notifications, - ...(updatedNotifications[dydxAddress] || []).slice(notifications.length), + ...(updatedNotifications[dydxAddress] ?? []).slice(notifications.length), ]; return updatedNotifications; diff --git a/src/hooks/useMatchingEvmNetwork.ts b/src/hooks/useMatchingEvmNetwork.ts index e045811cb..f60e5cd99 100644 --- a/src/hooks/useMatchingEvmNetwork.ts +++ b/src/hooks/useMatchingEvmNetwork.ts @@ -35,9 +35,9 @@ export const useMatchingEvmNetwork = ({ const matchNetwork = useCallback(async () => { if (!isMatchingNetwork) { if (sourceAccount.walletInfo?.connectorType === ConnectorType.Privy) { - await wallets?.[0].switchChain(Number(chainId)); + await wallets[0]?.switchChain(Number(chainId)); } else { - await switchChainAsync?.({ chainId: Number(chainId) }, { onError, onSuccess }); + await switchChainAsync({ chainId: Number(chainId) }, { onError, onSuccess }); } } }, [chainId, chain]); diff --git a/src/hooks/useNotifications.tsx b/src/hooks/useNotifications.tsx index f292a3598..bf0fdccea 100644 --- a/src/hooks/useNotifications.tsx +++ b/src/hooks/useNotifications.tsx @@ -200,12 +200,12 @@ const useNotificationsContext = () => { updateStatus(thisNotification, newStatus); } else if (JSON.stringify(updateKey) !== JSON.stringify(notification.updateKey)) { // updateKey changed - update existing notification - const thisNotification = notifications[key]; + const thisNotification = notifications[key]!; thisNotification.updateKey = updateKey; updateStatus(thisNotification, NotificationStatus.Updated); } else if (shouldUnhide && notification.status === NotificationStatus.Hidden) { - const thisNotification = notifications[key]; + const thisNotification = notifications[key]!; updateStatus(thisNotification, NotificationStatus.Updated); } } else { @@ -273,9 +273,10 @@ const useNotificationsContext = () => { if ( notification.status < NotificationStatus.Seen && notification.timestamps[notification.status]! > pushNotificationsLastUpdated && - !globalThis.document.hasFocus() + !globalThis.document.hasFocus() && + getDisplayData(notification) != null ) { - const displayData = getDisplayData(notification); + const displayData = getDisplayData(notification)!; const iconUrl = displayData.icon && diff --git a/src/hooks/vaultsHooks.ts b/src/hooks/vaultsHooks.ts index 36e82ad56..7f8d8768a 100644 --- a/src/hooks/vaultsHooks.ts +++ b/src/hooks/vaultsHooks.ts @@ -389,7 +389,7 @@ function getErrorToRenderFromErrorMessage( if (errorMessage.indexOf('insufficient funds: insufficient funds') > 0) { return stringGetter({ key: STRING_KEYS.BROADCAST_ERROR_SDK_5 }); } - return errorMessage.split('\n')[0]; + return errorMessage.split('\n')[0]!; } export const useVaultFormErrorState = () => { diff --git a/src/layout/NotificationsToastArea/NotifcationStack.tsx b/src/layout/NotificationsToastArea/NotifcationStack.tsx index fe8af0f24..9d5008b83 100644 --- a/src/layout/NotificationsToastArea/NotifcationStack.tsx +++ b/src/layout/NotificationsToastArea/NotifcationStack.tsx @@ -24,7 +24,7 @@ type ElementProps = { notifications: { notification: Notification; key: string; - displayData: NotificationDisplayData; + displayData: NotificationDisplayData | undefined; }[]; }; @@ -63,26 +63,26 @@ export const NotificationStack = ({ notifications, className }: ElementProps & S isOpen={notification.status < NotificationStatus.Unseen} layer={idx} notification={notification} - slotIcon={displayData.icon} - slotTitle={displayData.title} - slotTitleLeft={displayData.slotTitleLeft} - slotTitleRight={displayData.slotTitleRight} - slotDescription={displayData.body} - slotCustomContent={displayData.renderCustomBody?.({ isToast: true, notification })} + slotIcon={displayData?.icon} + slotTitle={displayData?.title} + slotTitleLeft={displayData?.slotTitleLeft} + slotTitleRight={displayData?.slotTitleRight} + slotDescription={displayData?.body} + slotCustomContent={displayData?.renderCustomBody?.({ isToast: true, notification })} onClick={() => onNotificationAction(notification)} slotAction={ - displayData.renderActionSlot ? ( + displayData?.renderActionSlot ? ( displayData.renderActionSlot({ isToast: true, notification }) - ) : displayData.actionDescription ? ( + ) : displayData?.actionDescription ? ( ) : undefined } - actionDescription={displayData.actionDescription} - actionAltText={displayData.actionAltText} - duration={displayData.toastDuration ?? Infinity} - sensitivity={displayData.toastSensitivity} + actionDescription={displayData?.actionDescription} + actionAltText={displayData?.actionAltText} + duration={displayData?.toastDuration ?? Infinity} + sensitivity={displayData?.toastSensitivity} setIsOpen={(isOpen: boolean, isClosedFromTimeout?: boolean) => { if (!isOpen) if (isClosedFromTimeout) diff --git a/src/layout/NotificationsToastArea/index.tsx b/src/layout/NotificationsToastArea/index.tsx index d942d8b31..b58dbfb65 100644 --- a/src/layout/NotificationsToastArea/index.tsx +++ b/src/layout/NotificationsToastArea/index.tsx @@ -46,10 +46,11 @@ export const NotificationsToastArea = ({ className }: StyleProps) => { .map((notification) => ({ notification, key: getKey(notification), - displayData: getDisplayData(notification), + displayData: getDisplayData(notification)!, // verified below })) .filter( ({ displayData, notification }) => + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition displayData && notification.status < NotificationStatus.Unseen ) .slice(-MAX_NUM_TOASTS); @@ -61,7 +62,7 @@ export const NotificationsToastArea = ({ className }: StyleProps) => { return ( {Object.keys(notificationMapByType).map((groupKey) => ( - + ))} ); diff --git a/src/lib/abacus/dydxChainTransactions.ts b/src/lib/abacus/dydxChainTransactions.ts index 163ed18d0..e36c86e0d 100644 --- a/src/lib/abacus/dydxChainTransactions.ts +++ b/src/lib/abacus/dydxChainTransactions.ts @@ -376,7 +376,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { // take out fee from amount before sweeping const amount = parseInt(ibcMsg.value.token.amount, 10) - - Math.floor(parseInt(fee.amount[0].amount, 10) * GAS_MULTIPLIER); + Math.floor(parseInt(fee.amount[0]!.amount, 10) * GAS_MULTIPLIER); if (amount <= 0) { throw new Error('noble balance does not cover fees'); @@ -466,7 +466,7 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { // take out fee from amount before sweeping const amount = parseInt(ibcMsg.value.amount, 10) - - Math.floor(parseInt(fee.amount[0].amount, 10) * GAS_MULTIPLIER); + Math.floor(parseInt(fee.amount[0]!.amount, 10) * GAS_MULTIPLIER); if (amount <= 0) { throw new Error('noble balance does not cover fees'); @@ -504,14 +504,14 @@ class DydxChainTransactions implements AbacusDYDXChainTransactionsProtocol { // take out fee from amount before sweeping const amount = - parseInt(ibcMsgs[0].value.amount, 10) - - Math.floor(parseInt(fee.amount[0].amount, 10) * GAS_MULTIPLIER); + parseInt(ibcMsgs[0]!.value.amount, 10) - + Math.floor(parseInt(fee.amount[0]!.amount, 10) * GAS_MULTIPLIER); if (amount <= 0) { throw new Error('noble balance does not cover fees'); } - ibcMsgs[0].value.amount = amount.toString(); + ibcMsgs[0]!.value.amount = amount.toString(); dd.info('cctpMultiMsgWithdraw attempting to submit tx', { ibcMsgs, fee, amount }); const tx = await this.nobleClient.send(ibcMsgs); diff --git a/src/lib/assetUtils.ts b/src/lib/assetUtils.ts index cc8b15d2c..7cbd27804 100644 --- a/src/lib/assetUtils.ts +++ b/src/lib/assetUtils.ts @@ -28,8 +28,8 @@ export const getDisplayableAssetFromTicker = ( part?: 'base' | 'dex' | 'address' | 'full' ): string => { const [fullBaseAsset] = ticker.split('-'); - if (part === 'full') return fullBaseAsset; - return getDisplayableAssetFromBaseAsset(fullBaseAsset, part); + if (part === 'full') return fullBaseAsset!; + return getDisplayableAssetFromBaseAsset(fullBaseAsset!, part); }; /** @@ -39,7 +39,7 @@ export const getDisplayableAssetFromTicker = ( */ export const getDisplayableTickerFromMarket = (market: string): string => { const [fullBaseAsset, quoteAsset] = market.split('-'); - const base = getDisplayableAssetFromBaseAsset(fullBaseAsset); + const base = getDisplayableAssetFromBaseAsset(fullBaseAsset!); if (!base || !quoteAsset || !fullBaseAsset) return ''; @@ -51,7 +51,7 @@ export const getTickerFromMarketmapId = (marketmapId: string): string => { }; export const getAssetFromMarketId = (marketId: string): string => { - return marketId.split('-')[0]; + return marketId.split('-')[0]!; }; const SKIP_NATIVE_DENOM_SUFFIX = 'native'; diff --git a/src/lib/consistentAssetSize.ts b/src/lib/consistentAssetSize.ts index d4d88cc40..19e1eb381 100644 --- a/src/lib/consistentAssetSize.ts +++ b/src/lib/consistentAssetSize.ts @@ -61,7 +61,7 @@ export const getConsistentAssetSizeString = ( return { displayDivisor: 1, displaySuffix: '' }; } return { - displayDivisor: 10 ** supportedLocaleToSuffixPowers[selectedLocale][unitToUse], + displayDivisor: 10 ** supportedLocaleToSuffixPowers[selectedLocale]![unitToUse]!, displaySuffix: unitToUse, }; })(); diff --git a/src/lib/language.ts b/src/lib/language.ts index c541b6d18..282314a17 100644 --- a/src/lib/language.ts +++ b/src/lib/language.ts @@ -3,6 +3,7 @@ export const getBrowserLanguage = (): string => { const navigator = globalThis.navigator; return ( (navigator && + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing ((navigator.languages && navigator.languages[0]) || navigator.language || (navigator as any).userLanguage)) || diff --git a/src/lib/notifications.ts b/src/lib/notifications.ts index 2c23be638..698b354ff 100644 --- a/src/lib/notifications.ts +++ b/src/lib/notifications.ts @@ -2,5 +2,7 @@ import { SingleSessionAbacusNotificationTypes } from '@/constants/notifications' export const isAbacusNotificationSingleSession = (notificationId: string) => { const notificationType = notificationId.split(':')[0]; - return SingleSessionAbacusNotificationTypes.includes(notificationType); + return ( + notificationType != null && SingleSessionAbacusNotificationTypes.includes(notificationType!) + ); }; diff --git a/src/lib/numbers.ts b/src/lib/numbers.ts index b4502a0ae..78a1bfe8c 100644 --- a/src/lib/numbers.ts +++ b/src/lib/numbers.ts @@ -76,7 +76,7 @@ export function bytesToBigInt(u: Uint8Array): bigint { return BigInt(0); } // eslint-disable-next-line no-bitwise - const negated: boolean = (u[0] & 1) === 1; + const negated: boolean = (u[0]! & 1) === 1; const hex: string = Buffer.from(u.slice(1)).toString('hex'); const abs: bigint = BigInt(`0x${hex}`); return negated ? -abs : abs; diff --git a/src/lib/orders.ts b/src/lib/orders.ts index bfcb7ed40..3d74fc882 100644 --- a/src/lib/orders.ts +++ b/src/lib/orders.ts @@ -139,7 +139,7 @@ export const getHydratedTradingData = < perpetualMarkets: Record; }): T & AddedProps => ({ ...data, - asset: assets[perpetualMarkets[data.marketId]?.assetId], + asset: assets[perpetualMarkets[data.marketId]?.assetId ?? ''], stepSizeDecimals: perpetualMarkets[data.marketId]?.configs?.stepSizeDecimals, tickSizeDecimals: perpetualMarkets[data.marketId]?.configs?.tickSizeDecimals, ...('side' in data && { orderSide: convertAbacusOrderSide(data.side) }), diff --git a/src/lib/skip.ts b/src/lib/skip.ts index bdccaf7a4..5965bdc9d 100644 --- a/src/lib/skip.ts +++ b/src/lib/skip.ts @@ -71,7 +71,10 @@ export const fetchSkipStatus = async ({ transactionHash, chainId, baseUrl }: Ski }; const getTransferFromStatusResponse = (skipStatusResponse: TxStatusResponseJSON) => { - return skipStatusResponse.transfers[0]; + if (!skipStatusResponse.transfers.length) { + throw new Error('Skip status response was empty.'); + } + return skipStatusResponse.transfers[0]!; }; const getChainNameFromId = (chainId: string | undefined) => { diff --git a/src/lib/testFlags.ts b/src/lib/testFlags.ts index 04d24ca95..d0a5bfaab 100644 --- a/src/lib/testFlags.ts +++ b/src/lib/testFlags.ts @@ -30,7 +30,7 @@ class TestFlags { return !!this.queryParams.displayinitializingmarkets; } - get addressOverride(): string { + get addressOverride(): string | undefined { return this.queryParams.address; } diff --git a/src/lib/tradingView/dydxfeed/utils.ts b/src/lib/tradingView/dydxfeed/utils.ts index 7af7eaeaf..a01591ebf 100644 --- a/src/lib/tradingView/dydxfeed/utils.ts +++ b/src/lib/tradingView/dydxfeed/utils.ts @@ -25,7 +25,7 @@ export function getBarTime( fillTimeMs: number, resolution: ResolutionString ): number | undefined { - const intervalMs = RESOLUTION_TO_INTERVAL_MS[resolution]; + const intervalMs = RESOLUTION_TO_INTERVAL_MS[resolution]!; const [startBn, intervalSizeBn, fillTimeBn] = [ BigNumber(chartStartTimeMs), @@ -69,7 +69,7 @@ export const getMarkForOrderFills = ( selectedLocale, } ); - const fill = orderFills[0]; + const fill = orderFills[0]!; const fillDetails = getFillDetails()(store.getState(), fill.id); const textParams = { diff --git a/src/lib/tradingView/launchableMarketFeed/index.ts b/src/lib/tradingView/launchableMarketFeed/index.ts index d5032991e..f03f779e9 100644 --- a/src/lib/tradingView/launchableMarketFeed/index.ts +++ b/src/lib/tradingView/launchableMarketFeed/index.ts @@ -134,7 +134,7 @@ export const getLaunchableMarketDatafeed = ( if (!cachedBars.length) { const candlesResponse = await metadataClient.getCandles({ asset, - timeframe: RESOLUTION_TO_TIMEFRAME_MAP[resolution], + timeframe: RESOLUTION_TO_TIMEFRAME_MAP[resolution]!, }); const fetchedCandles: MetadataServiceCandlesResponse[string] | undefined = diff --git a/src/lib/tradingView/utils.ts b/src/lib/tradingView/utils.ts index 0c56c82e3..eb052f9fc 100644 --- a/src/lib/tradingView/utils.ts +++ b/src/lib/tradingView/utils.ts @@ -156,7 +156,7 @@ export const getHistorySlice = ({ firstDataRequest: boolean; orderbookCandlesToggleOn: boolean; }): TradingViewChartBar[] => { - if (!bars || (!firstDataRequest && bars.length > 0 && toMs < bars[0].time)) { + if (!bars || (!firstDataRequest && bars.length > 0 && toMs < bars[0]!.time)) { return []; } diff --git a/src/pages/Profile.tsx b/src/pages/Profile.tsx index d42bf0f33..3da5dd636 100644 --- a/src/pages/Profile.tsx +++ b/src/pages/Profile.tsx @@ -159,7 +159,9 @@ const Profile = () => { {sourceAccount.walletInfo.connectorType === ConnectorType.Injected ? sourceAccount.walletInfo.name - : stringGetter({ key: wallets[sourceAccount.walletInfo.name].stringKey })} + : stringGetter({ + key: wallets[sourceAccount.walletInfo.name as keyof typeof wallets].stringKey, + })} ) : ( diff --git a/src/pages/vaults/VaultPnlChart.tsx b/src/pages/vaults/VaultPnlChart.tsx index 2fc12b804..8a1f6b355 100644 --- a/src/pages/vaults/VaultPnlChart.tsx +++ b/src/pages/vaults/VaultPnlChart.tsx @@ -68,7 +68,8 @@ export const VaultPnlChart = ({ className }: VaultPnlChartProps) => { ); const timeUnitsToRender = useMemo(() => { - const dataRange = data.length > 1 ? (data[data.length - 1].date ?? 0) - (data[0].date ?? 0) : 0; + const dataRange = + data.length > 1 ? (data[data.length - 1]!.date ?? 0) - (data[0]!.date ?? 0) : 0; const validRanges = TIME_RANGES.filter((t) => t.time <= dataRange + timeUnits.day * 3); return validRanges.map((t) => ({ value: t.value, @@ -117,9 +118,9 @@ export const VaultPnlChart = ({ className }: VaultPnlChartProps) => { ? relevantDataPoints[relevantDataPoints.length - 1] : undefined; const pnlDiff = atLeastTwoPoints - ? relevantDataPoints[relevantDataPoints.length - 1] - relevantDataPoints[0] + ? relevantDataPoints[relevantDataPoints.length - 1]! - relevantDataPoints[0]! : undefined; - const pnlDiffPercent = atLeastTwoPoints ? (pnlDiff ?? 0) / relevantDataPoints[0] : undefined; + const pnlDiffPercent = atLeastTwoPoints ? (pnlDiff ?? 0) / relevantDataPoints[0]! : undefined; const xAccessorFunc = useCallback((datum: VaultPnlDatum) => datum?.date ?? 0, []); const yAccessorFunc = useCallback( @@ -135,7 +136,7 @@ export const VaultPnlChart = ({ className }: VaultPnlChartProps) => { yAccessor: yAccessorFunc, colorAccessor: () => atLeastTwoPoints - ? relevantDataPoints[relevantDataPoints.length - 1] - relevantDataPoints[0] >= 0 + ? relevantDataPoints[relevantDataPoints.length - 1]! - relevantDataPoints[0]! >= 0 ? 'var(--color-positive)' : 'var(--color-negative)' : 'var(--color-positive)', @@ -167,7 +168,7 @@ export const VaultPnlChart = ({ className }: VaultPnlChartProps) => { const onVisibleDataChange = useCallback((inRangeData: VaultPnlDatum[]) => { setVisibleTimeRange( inRangeData.length > 1 - ? [inRangeData[0].date ?? 0, inRangeData[inRangeData.length - 1].date ?? 0] + ? [inRangeData[0]!.date ?? 0, inRangeData[inRangeData.length - 1]!.date ?? 0] : undefined ); }, []); diff --git a/src/services/numia.ts b/src/services/numia.ts index 267d97b52..c1625b4d2 100644 --- a/src/services/numia.ts +++ b/src/services/numia.ts @@ -13,8 +13,8 @@ type ChainRevenue = { export const getChainRevenue = async ({ startDate, endDate }: GetChainRevenueRequest) => { const url = new URL(`${import.meta.env.VITE_NUMIA_BASE_URL}/dydx/tokenomics/chain_revenue`); - url.searchParams.set('start_date', startDate.toISOString().split('T')[0]); - url.searchParams.set('end_date', endDate.toISOString().split('T')[0]); + url.searchParams.set('start_date', startDate.toISOString().split('T')[0]!); + url.searchParams.set('end_date', endDate.toISOString().split('T')[0]!); const response = await fetch(url); const data = await response.json(); diff --git a/src/state/accountSelectors.ts b/src/state/accountSelectors.ts index 2a593f690..2c6ea7191 100644 --- a/src/state/accountSelectors.ts +++ b/src/state/accountSelectors.ts @@ -180,7 +180,7 @@ export const getMarketOrders = createAppSelector( return (orders ?? []).reduce( (marketOrders, order) => { marketOrders[order.marketId] ??= []; - marketOrders[order.marketId].push(order); + marketOrders[order.marketId]!.push(order); return marketOrders; }, {} as { [marketId: string]: SubaccountOrder[] } @@ -273,7 +273,7 @@ export const getMarketSubaccountOpenOrders = createAppSelector( return (orders ?? []).reduce( (marketOrders, order) => { marketOrders[order.marketId] ??= []; - marketOrders[order.marketId].push(order); + marketOrders[order.marketId]!.push(order); return marketOrders; }, {} as { [marketId: string]: SubaccountOrder[] } @@ -398,7 +398,7 @@ export const getMarketFills = createAppSelector( return (fills ?? []).reduce( (marketFills, fill) => { marketFills[fill.marketId] ??= []; - marketFills[fill.marketId].push(fill); + marketFills[fill.marketId]!.push(fill); return marketFills; }, {} as { [marketId: string]: SubaccountFill[] } @@ -432,7 +432,7 @@ export const getFillDetails = () => export const getCurrentMarketFills = createAppSelector( [getCurrentMarketId, getMarketFills], (currentMarketId, marketFills): SubaccountFill[] => - !currentMarketId ? [] : marketFills[currentMarketId] + !currentMarketId ? [] : marketFills[currentMarketId] ?? [] ); const getFillsForOrderId = createAppSelector( @@ -468,7 +468,7 @@ export const getMarketFundingPayments = createAppSelector( return (fundingPayments ?? []).reduce( (marketFundingPayments, fundingPayment) => { marketFundingPayments[fundingPayment.marketId] ??= []; - marketFundingPayments[fundingPayment.marketId].push(fundingPayment); + marketFundingPayments[fundingPayment.marketId]!.push(fundingPayment); return marketFundingPayments; }, {} as { [marketId: string]: SubaccountFundingPayment[] } @@ -483,7 +483,7 @@ export const getMarketFundingPayments = createAppSelector( export const getCurrentMarketFundingPayments = createAppSelector( [getCurrentMarketId, getMarketFundingPayments], (currentMarketId, marketFundingPayments): SubaccountFundingPayment[] => - !currentMarketId ? [] : marketFundingPayments[currentMarketId] + !currentMarketId ? [] : marketFundingPayments[currentMarketId] ?? [] ); /** diff --git a/src/state/localOrders.ts b/src/state/localOrders.ts index b686c5d39..d8ddc5a13 100644 --- a/src/state/localOrders.ts +++ b/src/state/localOrders.ts @@ -286,17 +286,21 @@ const updateCancelAllOrderIds = ( }; const updateKey = (currentKey: string) => ({ - ...state.localCancelAlls[currentKey], - [key]: getNewOrderIds(state.localCancelAlls[currentKey]), + ...state.localCancelAlls[currentKey]!, + [key]: getNewOrderIds(state.localCancelAlls[currentKey]!), }); state.localCancelAlls = { ...state.localCancelAlls, - ...(state.localCancelAlls[CANCEL_ALL_ORDERS_KEY] && { - [CANCEL_ALL_ORDERS_KEY]: updateKey(CANCEL_ALL_ORDERS_KEY), - }), - ...(state.localCancelAlls[cancelAllKey] && { - [cancelAllKey]: updateKey(cancelAllKey), - }), + ...(state.localCancelAlls[CANCEL_ALL_ORDERS_KEY] + ? { + [CANCEL_ALL_ORDERS_KEY]: updateKey(CANCEL_ALL_ORDERS_KEY), + } + : {}), + ...(state.localCancelAlls[cancelAllKey] + ? { + [cancelAllKey]: updateKey(cancelAllKey), + } + : {}), }; }; diff --git a/src/state/localizationMiddleware.ts b/src/state/localizationMiddleware.ts index 415d3891e..e05f9eb6c 100644 --- a/src/state/localizationMiddleware.ts +++ b/src/state/localizationMiddleware.ts @@ -58,7 +58,7 @@ export default (store: any) => (next: any) => async (action: PayloadAction) store.dispatch(setSelectedLocale({ locale: localStorageLocale })); } else { const browserLanguage = getBrowserLanguage(); - const browserLanguageBaseTag = browserLanguage.split('-')[0].toLowerCase(); + const browserLanguageBaseTag = browserLanguage.split('-')[0]!.toLowerCase(); let locale = (SUPPORTED_BASE_TAGS_LOCALE_MAPPING[browserLanguageBaseTag] ?? SupportedLocales.EN) as SupportedLocales; diff --git a/src/state/perpetuals.ts b/src/state/perpetuals.ts index 1f573d6b1..1d87724dc 100644 --- a/src/state/perpetuals.ts +++ b/src/state/perpetuals.ts @@ -67,14 +67,18 @@ export const perpetualsSlice = createSlice({ ) => { const { candles, marketId, resolution } = action.payload; - const candleState = state.candles[marketId] - ? { ...state.candles[marketId], selectedResolution: resolution } - : { - data: Object.fromEntries( - Object.keys(RESOLUTION_MAP).map((resolutionString: string) => [resolutionString, []]) - ), - selectedResolution: resolution, - }; + const candleState: CandleDataByMarket = + state.candles[marketId] != null + ? { ...state.candles[marketId]!, selectedResolution: resolution } + : { + data: Object.fromEntries( + Object.keys(RESOLUTION_MAP).map((resolutionString: string) => [ + resolutionString, + [], + ]) + ), + selectedResolution: resolution, + }; const existingCandles = (candleState.data[resolution] ??= []); @@ -82,7 +86,8 @@ export const perpetualsSlice = createSlice({ ...existingCandles, ...(existingCandles.length ? candles.filter( - ({ startedAt }) => startedAt < existingCandles[existingCandles.length - 1].startedAt + ({ startedAt }) => + startedAt < (existingCandles[existingCandles.length - 1]?.startedAt ?? 0) ) : candles), ]; @@ -134,14 +139,15 @@ export const perpetualsSlice = createSlice({ ) => { const { marketId, resolution } = action.payload; - const candleState = state.candles[marketId] - ? { ...state.candles[marketId], selectedResolution: resolution } - : { - data: Object.fromEntries( - objectKeys(RESOLUTION_MAP).map((resolutionString) => [resolutionString, []]) - ), - selectedResolution: resolution, - }; + const candleState = + state.candles[marketId] != null + ? { ...state.candles[marketId]!, selectedResolution: resolution } + : { + data: Object.fromEntries( + objectKeys(RESOLUTION_MAP).map((resolutionString) => [resolutionString, []]) + ), + selectedResolution: resolution, + }; state.candles[marketId] = candleState; }, diff --git a/src/views/PositionInfo.tsx b/src/views/PositionInfo.tsx index 1cdd97d82..9af43b064 100644 --- a/src/views/PositionInfo.tsx +++ b/src/views/PositionInfo.tsx @@ -87,7 +87,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo size, unrealizedPnl, unrealizedPnlPercent, - } = currentMarketPosition || {}; + } = currentMarketPosition ?? {}; const netFundingBN = MustBigNumber(netFunding); @@ -166,7 +166,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo } } - const mainFieldsContent: PositionInfoItems[] = [ + const mainFieldsContent = [ { key: 'leverage', type: OutputType.Multiple, @@ -228,7 +228,7 @@ export const PositionInfo = ({ showNarrowVariation }: { showNarrowVariation?: bo value: realizedPnl?.current ?? undefined, withBaseFont: true, }, - ]; + ] as const satisfies readonly PositionInfoItems[]; const createDetailItem = ({ key, diff --git a/src/views/charts/DepthChart/index.tsx b/src/views/charts/DepthChart/index.tsx index 4dd689723..7cfe5eaca 100644 --- a/src/views/charts/DepthChart/index.tsx +++ b/src/views/charts/DepthChart/index.tsx @@ -8,9 +8,9 @@ import { AreaSeries, Axis, DataProvider, - EventEmitterProvider, // AnimatedAxis, - Grid, // AnimatedGrid, - LineSeries, // AnimatedAreaSeries, + EventEmitterProvider, + Grid, + LineSeries, buildChartTheme, darkTheme, type EventHandlerParams, @@ -94,9 +94,9 @@ export const DepthChart = ({ // Mid-market price ± 1.5% midMarketPrice * 0.015, // Mid-market price ± halfway to lowest bid - (midMarketPrice - lowestBid.price) / 2, + (midMarketPrice - (lowestBid?.price ?? 0)) / 2, // Mid-market price ± halfway to highest ask - (highestAsk.price - midMarketPrice) / 2 + ((highestAsk?.price ?? midMarketPrice) - midMarketPrice) / 2 ) ); } @@ -109,8 +109,8 @@ export const DepthChart = ({ return { domain: [0, 0] as const, range: [0, 0] as const }; const newDomain = [ - clamp(midMarketPrice - zoomDomain, 0, highestBid.price), - clamp(midMarketPrice + zoomDomain, lowestAsk.price, highestAsk.price), + clamp(midMarketPrice - zoomDomain, 0, highestBid?.price ?? 0), + clamp(midMarketPrice + zoomDomain, lowestAsk?.price ?? 0, highestAsk?.price ?? 0), ] as const; const newRange = [ @@ -175,8 +175,14 @@ export const DepthChart = ({ 1e-320, Math.min(Number.MAX_SAFE_INTEGER, zoomDomain * Math.exp(wheelDelta / 1000)) ), - Math.min(midMarketPrice - highestBid.price, lowestAsk.price - midMarketPrice), - Math.max(midMarketPrice - lowestBid.price, highestAsk.price - midMarketPrice) + Math.min( + midMarketPrice - (highestBid?.price ?? 0), + (lowestAsk?.price ?? 0) - midMarketPrice + ), + Math.max( + midMarketPrice - (lowestBid?.price ?? 0), + (highestAsk?.price ?? 0) - midMarketPrice + ) ) ); }; @@ -227,15 +233,15 @@ export const DepthChart = ({ 0 ? [ { - ...highestBid, + ...highestBid!, depth: 0, }, ...bids, { - ...lowestBid, + ...lowestBid!, price: 0, }, ].reverse() @@ -258,10 +264,10 @@ export const DepthChart = ({ 0 ? [ { - ...lowestAsk, + ...lowestAsk!, depth: 0, }, ...asks, diff --git a/src/views/charts/FundingChart/Tooltip.tsx b/src/views/charts/FundingChart/Tooltip.tsx index e214202d7..adb8b7c3f 100644 --- a/src/views/charts/FundingChart/Tooltip.tsx +++ b/src/views/charts/FundingChart/Tooltip.tsx @@ -12,7 +12,7 @@ import { TooltipContent } from '@/components/visx/TooltipContent'; type FundingChartTooltipProps = { fundingRateView: FundingRateResolution; - latestDatum: FundingChartDatum; + latestDatum: FundingChartDatum | undefined; } & Pick, 'tooltipData'>; export const FundingChartTooltipContent = ({ @@ -33,7 +33,7 @@ export const FundingChartTooltipContent = ({ [FundingDirection.ToLong]: 'var(--color-negative)', [FundingDirection.ToShort]: 'var(--color-positive)', [FundingDirection.None]: 'var(--color-layer-6)', - }[tooltipDatum.direction] + }[tooltipDatum?.direction ?? FundingDirection.None] } >

@@ -65,7 +65,7 @@ export const FundingChartTooltipContent = ({ key: STRING_KEYS.SHORT_POSITION_SHORT, })}`, [FundingDirection.None]: undefined, - }[tooltipDatum.direction] + }[tooltipDatum?.direction ?? FundingDirection.None] } /> ), @@ -84,9 +84,10 @@ export const FundingChartTooltipContent = ({ type={OutputType.SmallPercent} value={ { - [FundingRateResolution.OneHour]: tooltipDatum.fundingRate, - [FundingRateResolution.EightHour]: tooltipDatum.fundingRate * 8, - [FundingRateResolution.Annualized]: tooltipDatum.fundingRate * (24 * 365), + [FundingRateResolution.OneHour]: tooltipDatum?.fundingRate ?? 0, + [FundingRateResolution.EightHour]: tooltipDatum?.fundingRate ?? 0 * 8, + [FundingRateResolution.Annualized]: + tooltipDatum?.fundingRate ?? 0 * (24 * 365), }[fundingRateView] } showSign={ShowSign.Both} @@ -98,7 +99,7 @@ export const FundingChartTooltipContent = ({ label: isShowingCurrentFundingRate ? 'Time Remaining' : stringGetter({ key: STRING_KEYS.TIME }), - value: , + value: , }, ] satisfies Array } diff --git a/src/views/charts/FundingChart/index.tsx b/src/views/charts/FundingChart/index.tsx index c037fb165..0d45c9eab 100644 --- a/src/views/charts/FundingChart/index.tsx +++ b/src/views/charts/FundingChart/index.tsx @@ -51,7 +51,7 @@ export const FundingChart = ({ selectedLocale }: ElementProps) => { // Chart data const data = useAppSelector(calculateFundingRateHistory, shallowEqual); - const latestDatum = data?.[data.length - 1]; + const latestDatum = data[data.length - 1]; // Chart state const [fundingRateView, setFundingRateView] = useState(FundingRateResolution.OneHour); @@ -97,7 +97,7 @@ export const FundingChart = ({ selectedLocale }: ElementProps) => { return ( ); @@ -108,13 +108,13 @@ export const FundingChart = ({ selectedLocale }: ElementProps) => { return ( <$YAxisLabelOutput type={OutputType.SmallPercent} - value={getAllFundingRates(tooltipDatum.fundingRate)[fundingRateView]} + value={getAllFundingRates(tooltipDatum?.fundingRate)[fundingRateView]} accentColor={ { [FundingDirection.ToLong]: 'var(--color-negative)', [FundingDirection.ToShort]: 'var(--color-positive)', [FundingDirection.None]: 'var(--color-layer-6)', - }[tooltipDatum.direction] + }[tooltipDatum?.direction ?? FundingDirection.None] } /> ); @@ -174,7 +174,7 @@ export const FundingChart = ({ selectedLocale }: ElementProps) => { type={OutputType.SmallPercent} value={latestFundingRate} fractionDigits={TINY_PERCENT_DECIMALS} - isNegative={latestFundingRate < 0} + isNegative={(latestFundingRate ?? 0) < 0} /> diff --git a/src/views/charts/LaunchableMarketChart.tsx b/src/views/charts/LaunchableMarketChart.tsx index 9a4fd9fb2..ec51b8461 100644 --- a/src/views/charts/LaunchableMarketChart.tsx +++ b/src/views/charts/LaunchableMarketChart.tsx @@ -96,9 +96,9 @@ export const LaunchableMarketChart = ({ const yAccessorFunc = useCallback((datum: TradingViewBar) => datum.close, []); const colorString = useMemo(() => { - if (!candlesQuery.data) return 'var(--color-text-1)'; - const first = candlesQuery.data[0]; - const last = candlesQuery.data[candlesQuery.data.length - 1]; + if (!candlesQuery.data || candlesQuery.data.length < 1) return 'var(--color-text-1)'; + const first = candlesQuery.data[0]!; + const last = candlesQuery.data[candlesQuery.data.length - 1]!; if (first.close > last.close) return 'var(--color-negative)'; return 'var(--color-positive)'; }, [candlesQuery.data]); diff --git a/src/views/charts/PnlChart.tsx b/src/views/charts/PnlChart.tsx index 3690106a5..a40cf186c 100644 --- a/src/views/charts/PnlChart.tsx +++ b/src/views/charts/PnlChart.tsx @@ -174,7 +174,7 @@ export const PnlChart = ({ setIsZooming(true); } else { setIsZooming(false); - setSelectedPeriod(periodOptions[defaultPeriodIx]); + setSelectedPeriod(periodOptions[defaultPeriodIx]!); } } }, NORMAL_DEBOUNCE_MS), diff --git a/src/views/charts/TradingRewardsChart.tsx b/src/views/charts/TradingRewardsChart.tsx index 7696b7501..5b8dd1e73 100644 --- a/src/views/charts/TradingRewardsChart.tsx +++ b/src/views/charts/TradingRewardsChart.tsx @@ -169,7 +169,7 @@ export const TradingRewardsChart = ({ } else { // Update period to new selected period setIsZooming(false); - setSelectedPeriod(periodOptions[predefinedPeriodIx]); + setSelectedPeriod(periodOptions[predefinedPeriodIx]!); } } }, NORMAL_DEBOUNCE_MS), diff --git a/src/views/dialogs/GeoComplianceDialog.tsx b/src/views/dialogs/GeoComplianceDialog.tsx index f76aab4b0..f55b38d49 100644 --- a/src/views/dialogs/GeoComplianceDialog.tsx +++ b/src/views/dialogs/GeoComplianceDialog.tsx @@ -70,7 +70,7 @@ export const GeoComplianceDialog = ({ setIsOpen }: DialogProps { const action = - residence && isBlockedGeo(COUNTRIES_MAP[residence]) + residence && isBlockedGeo(COUNTRIES_MAP[residence]!) ? ComplianceAction.INVALID_SURVEY : ComplianceAction.VALID_SURVEY; diff --git a/src/views/dialogs/ManageFundsDialog.tsx b/src/views/dialogs/ManageFundsDialog.tsx index 9f50d4cc3..3a832166b 100644 --- a/src/views/dialogs/ManageFundsDialog.tsx +++ b/src/views/dialogs/ManageFundsDialog.tsx @@ -69,7 +69,7 @@ export const ManageFundsDialog = ({ hasHeaderBorder tw="[--dialog-content-paddingTop:1.5rem]" > - {transferTypeConfig[currentType].component} + {transferTypeConfig[currentType]?.component} ); }; diff --git a/src/views/dialogs/OnboardingDialog/ChooseWallet.tsx b/src/views/dialogs/OnboardingDialog/ChooseWallet.tsx index 081cda8f8..2bd177569 100644 --- a/src/views/dialogs/OnboardingDialog/ChooseWallet.tsx +++ b/src/views/dialogs/OnboardingDialog/ChooseWallet.tsx @@ -42,7 +42,7 @@ export const ChooseWallet = ({ selectedWallet.connectorType === ConnectorType.Injected ? selectedWallet.name : stringGetter({ - key: wallets[selectedWallet.name].stringKey, + key: wallets[selectedWallet.name as keyof typeof wallets].stringKey, }), }, })} @@ -63,7 +63,7 @@ export const ChooseWallet = ({ <$WalletName> {wallet.connectorType === ConnectorType.Injected ? wallet.name - : stringGetter({ key: wallets[wallet.name].stringKey })} + : stringGetter({ key: wallets[wallet.name as keyof typeof wallets].stringKey })} ))} diff --git a/src/views/dialogs/StakingRewardDialog.tsx b/src/views/dialogs/StakingRewardDialog.tsx index 4a551d7b5..caafb3a3f 100644 --- a/src/views/dialogs/StakingRewardDialog.tsx +++ b/src/views/dialogs/StakingRewardDialog.tsx @@ -56,7 +56,7 @@ export const StakingRewardDialog = ({ getWithdrawRewardFee(validators) .then((stdFee) => { if (stdFee.amount.length > 0) { - const feeAmount = stdFee.amount[0].amount; + const feeAmount = stdFee.amount[0]!.amount; setFee(MustBigNumber(formatUnits(BigInt(feeAmount), usdcDecimals))); } else { setFee(undefined); diff --git a/src/views/dialogs/UnstakeDialog.tsx b/src/views/dialogs/UnstakeDialog.tsx index b526c8687..f7ff87f81 100644 --- a/src/views/dialogs/UnstakeDialog.tsx +++ b/src/views/dialogs/UnstakeDialog.tsx @@ -21,10 +21,10 @@ export const UnstakeDialog = ({ setIsOpen }: DialogProps) => const [currentStep, setCurrentStep] = useState(StakeFormSteps.EditInputs); const { nativeStakingBalance } = useAccountBalance(); - const { stakingValidators, currentDelegations } = useStakingValidator() ?? {}; - const { chainTokenImage, chainTokenLabel } = useTokenConfigs(); + const { stakingValidators, currentDelegations } = useStakingValidator(); + const { chainTokenLabel, chainTokenImage } = useTokenConfigs(); - const closeDialog = () => setIsOpen?.(false); + const closeDialog = () => setIsOpen(false); const dialogProps: { [key in StakeFormSteps]: { @@ -43,7 +43,7 @@ export const UnstakeDialog = ({ setIsOpen }: DialogProps) => params: { VALIDATOR: ( ), diff --git a/src/views/forms/AdjustTargetLeverageForm.tsx b/src/views/forms/AdjustTargetLeverageForm.tsx index 9df2991c7..b97ea81cf 100644 --- a/src/views/forms/AdjustTargetLeverageForm.tsx +++ b/src/views/forms/AdjustTargetLeverageForm.tsx @@ -81,8 +81,8 @@ export const AdjustTargetLeverageForm = ({ min={1} max={maxLeverage} value={MustBigNumber(leverage).abs().toNumber()} - onSliderDrag={([value]: number[]) => setLeverage(value.toString())} - onValueCommit={([value]: number[]) => setLeverage(value.toString())} + onSliderDrag={([value]: number[]) => setLeverage(value!.toString())} + onValueCommit={([value]: number[]) => setLeverage(value!.toString())} /> <$InnerInputContainer> diff --git a/src/views/forms/SelectMarginModeForm.tsx b/src/views/forms/SelectMarginModeForm.tsx index 7c2b73a49..e065e8a1e 100644 --- a/src/views/forms/SelectMarginModeForm.tsx +++ b/src/views/forms/SelectMarginModeForm.tsx @@ -42,7 +42,7 @@ export const SelectMarginModeForm = ({ radioItems={[ { value: AbacusMarginMode.Cross.rawValue, - label: stringGetter({ key: MARGIN_MODE_STRINGS[AbacusMarginMode.Cross.rawValue] }), + label: stringGetter({ key: MARGIN_MODE_STRINGS[AbacusMarginMode.Cross.rawValue]! }), body: ( <$TertiarySpan> {stringGetter({ key: STRING_KEYS.CROSS_MARGIN_DESCRIPTION })} @@ -51,7 +51,7 @@ export const SelectMarginModeForm = ({ }, { value: AbacusMarginMode.Isolated.rawValue, - label: stringGetter({ key: MARGIN_MODE_STRINGS[AbacusMarginMode.Isolated.rawValue] }), + label: stringGetter({ key: MARGIN_MODE_STRINGS[AbacusMarginMode.Isolated.rawValue]! }), body: ( <$TertiarySpan> {stringGetter({ key: STRING_KEYS.ISOLATED_MARGIN_DESCRIPTION })} diff --git a/src/views/forms/StakingForms/StakeForm/index.tsx b/src/views/forms/StakingForms/StakeForm/index.tsx index 61ea30822..50855c47c 100644 --- a/src/views/forms/StakingForms/StakeForm/index.tsx +++ b/src/views/forms/StakingForms/StakeForm/index.tsx @@ -55,7 +55,7 @@ export const StakeForm = ({ const stringGetter = useStringGetter(); const { delegate, getDelegateFee } = useSubaccount(); const { nativeTokenBalance: balance, nativeStakingBalance } = useAccountBalance(); - const { selectedValidator, setSelectedValidator, defaultValidator } = useStakingValidator() ?? {}; + const { selectedValidator, setSelectedValidator, defaultValidator } = useStakingValidator(); const { chainTokenLabel, chainTokenDecimals } = useTokenConfigs(); const { mintscanValidatorsLearnMore } = useURLConfigs(); @@ -103,7 +103,7 @@ export const StakeForm = ({ getDelegateFee(selectedValidator.operatorAddress, amountBN.toNumber()) .then((stdFee) => { if (stdFee.amount.length > 0) { - const feeAmount = stdFee.amount[0].amount; + const feeAmount = stdFee.amount[0]!.amount; setFee(MustBigNumber(formatUnits(BigInt(feeAmount), chainTokenDecimals))); } }) @@ -199,7 +199,7 @@ export const StakeForm = ({ hasInvalidNewValue={newStakedBalanceBN?.isNegative()} withDiff={ newStakedBalanceBN !== undefined && - !MustBigNumber(nativeStakingBalance).eq(newStakedBalanceBN ?? 0) + !MustBigNumber(nativeStakingBalance).eq(newStakedBalanceBN) } /> ), diff --git a/src/views/forms/StakingForms/UnstakeForm/UnstakeFormInputContents.tsx b/src/views/forms/StakingForms/UnstakeForm/UnstakeFormInputContents.tsx index 9c6986f3f..738068d64 100644 --- a/src/views/forms/StakingForms/UnstakeForm/UnstakeFormInputContents.tsx +++ b/src/views/forms/StakingForms/UnstakeForm/UnstakeFormInputContents.tsx @@ -53,12 +53,12 @@ export const UnstakeFormInputContents = ({ }: ElementProps) => { const stringGetter = useStringGetter(); const { chainTokenLabel } = useTokenConfigs(); - const { stakingValidators, currentDelegations } = useStakingValidator() ?? {}; + const { stakingValidators, currentDelegations } = useStakingValidator(); const allAmountsEmpty = - !amounts || Object.values(amounts).filter((amount) => amount !== undefined).length === 0; + Object.values(amounts).filter((amount) => amount !== undefined).length === 0; const showClearButton = - amounts && Object.values(amounts).filter((amount) => amount !== undefined).length > 0; + Object.values(amounts).filter((amount) => amount !== undefined).length > 0; const debouncedChangeTrack = useMemo( () => @@ -110,19 +110,19 @@ export const UnstakeFormInputContents = ({ value: ( - parseFloat(currentDelegations[0].amount) + (amounts[currentDelegations[0]!.validator] ?? 0) > + parseFloat(currentDelegations[0]!.amount) } withDiff={Boolean( - (amounts[currentDelegations[0].validator] ?? 0) && - parseFloat(currentDelegations[0].amount) + (amounts[currentDelegations[0]!.validator] ?? 0) && + parseFloat(currentDelegations[0]!.amount) )} /> ), @@ -135,20 +135,20 @@ export const UnstakeFormInputContents = ({ label={stringGetter({ key: STRING_KEYS.AMOUNT_TO_UNSTAKE })} type={InputType.Number} onChange={({ floatValue }: NumberFormatValues) => - onChangeAmount(currentDelegations[0].validator, floatValue) + onChangeAmount(currentDelegations[0]!.validator, floatValue) } - value={amounts[currentDelegations[0].validator] ?? undefined} + value={amounts[currentDelegations[0]!.validator] ?? undefined} slotRight={ isPressed ? onChangeAmount( - currentDelegations[0].validator, - parseFloat(currentDelegations[0].amount) + currentDelegations[0]!.validator, + parseFloat(currentDelegations[0]!.amount) ) - : onChangeAmount(currentDelegations[0].validator, undefined) + : onChangeAmount(currentDelegations[0]!.validator, undefined) } /> } diff --git a/src/views/forms/StakingForms/UnstakeForm/UnstakeFormPreviewContents.tsx b/src/views/forms/StakingForms/UnstakeForm/UnstakeFormPreviewContents.tsx index 699f2b7eb..036611bbe 100644 --- a/src/views/forms/StakingForms/UnstakeForm/UnstakeFormPreviewContents.tsx +++ b/src/views/forms/StakingForms/UnstakeForm/UnstakeFormPreviewContents.tsx @@ -17,6 +17,7 @@ import { Output, OutputType } from '@/components/Output'; import { ValidatorIcons } from '@/components/ValidatorIcons'; import { MustBigNumber } from '@/lib/numbers'; +import { isPresent } from '@/lib/typeUtils'; import { StakePreviewContents } from '../shared/StakePreviewContents'; @@ -34,14 +35,17 @@ export const UnstakeFormPreviewContents = ({ setCurrentStep, }: ElementProps) => { const stringGetter = useStringGetter(); - const { chainTokenImage, chainTokenLabel } = useTokenConfigs(); - const { stakingValidators, currentDelegations } = useStakingValidator() ?? {}; + const { chainTokenLabel, chainTokenImage } = useTokenConfigs(); + const { stakingValidators, currentDelegations } = useStakingValidator(); + const delegationsToUnstake = currentDelegations?.filter((delegation) => MustBigNumber(amounts[delegation.validator]).gt(0) ) ?? []; const unstakingValidators = stakingValidators - ? delegationsToUnstake.map((delegation) => stakingValidators[delegation.validator]?.[0]) + ? delegationsToUnstake + .map((delegation) => stakingValidators[delegation.validator]?.[0]) + .filter(isPresent) : []; return ( @@ -49,7 +53,7 @@ export const UnstakeFormPreviewContents = ({ submitText={stringGetter({ key: STRING_KEYS.CONFIRM_UNSTAKE })} isLoading={isLoading} slotLeftHeading={stringGetter({ - key: unstakingValidators?.length === 1 ? STRING_KEYS.VALIDATOR : STRING_KEYS.VALIDATORS, + key: unstakingValidators.length === 1 ? STRING_KEYS.VALIDATOR : STRING_KEYS.VALIDATORS, })} slotRightHeading={stringGetter({ key: STRING_KEYS.AMOUNT_TO_UNSTAKE, diff --git a/src/views/forms/StakingForms/UnstakeForm/index.tsx b/src/views/forms/StakingForms/UnstakeForm/index.tsx index d3bee1b3e..0e1d13692 100644 --- a/src/views/forms/StakingForms/UnstakeForm/index.tsx +++ b/src/views/forms/StakingForms/UnstakeForm/index.tsx @@ -115,7 +115,7 @@ export const UnstakeForm = ({ getUndelegateFee(amounts) .then((stdFee) => { if (stdFee.amount.length > 0) { - const feeAmount = stdFee.amount[0].amount; + const feeAmount = stdFee.amount[0]!.amount; setFee(MustBigNumber(formatUnits(BigInt(feeAmount), chainTokenDecimals))); } }) diff --git a/src/views/forms/TradeForm/LeverageSlider.tsx b/src/views/forms/TradeForm/LeverageSlider.tsx index 3cfe76004..18d9ee038 100644 --- a/src/views/forms/TradeForm/LeverageSlider.tsx +++ b/src/views/forms/TradeForm/LeverageSlider.tsx @@ -89,7 +89,7 @@ export const LeverageSlider = ({ const onSliderDrag = ([newLeverage]: number[]) => { setLeverageInputValue(`${newLeverage}`); - debouncedSetAbacusLeverage(newLeverage); + debouncedSetAbacusLeverage(newLeverage!); }; const onValueCommit = ([newLeverage]: number[]) => { diff --git a/src/views/forms/TradeForm/MarginModeSelector.tsx b/src/views/forms/TradeForm/MarginModeSelector.tsx index 292f35f0d..bd0946b16 100644 --- a/src/views/forms/TradeForm/MarginModeSelector.tsx +++ b/src/views/forms/TradeForm/MarginModeSelector.tsx @@ -50,7 +50,7 @@ export const MarginModeSelector = ({ <$Text> {marginMode && stringGetter({ - key: MARGIN_MODE_STRINGS[marginMode.rawValue], + key: MARGIN_MODE_STRINGS[marginMode.rawValue]!, })} @@ -74,7 +74,7 @@ export const MarginModeSelector = ({ <$Text> {marginMode && stringGetter({ - key: MARGIN_MODE_STRINGS[marginMode.rawValue], + key: MARGIN_MODE_STRINGS[marginMode.rawValue]!, })} diff --git a/src/views/menus/NotificationsMenu.tsx b/src/views/menus/NotificationsMenu.tsx index 72d5cf9d8..ac64b7781 100644 --- a/src/views/menus/NotificationsMenu.tsx +++ b/src/views/menus/NotificationsMenu.tsx @@ -89,8 +89,8 @@ export const NotificationsMenu = ({ ) .map((notification) => ({ notification, - key: getKey?.(notification), - displayData: getDisplayData?.(notification), + key: getKey(notification), + displayData: getDisplayData(notification)!, })) .map(({ notification, key, displayData }) => ({ value: key, diff --git a/src/views/menus/useGlobalCommands.tsx b/src/views/menus/useGlobalCommands.tsx index 0da111ff7..4fb03e233 100644 --- a/src/views/menus/useGlobalCommands.tsx +++ b/src/views/menus/useGlobalCommands.tsx @@ -35,7 +35,8 @@ export const useGlobalCommands = (): MenuConfig safeAssign({}, market, allAssets[market?.assetId] ?? {}) + (market): PerpetualMarket & Asset => + safeAssign({}, market, allAssets[market?.assetId] ?? ({} as Asset)) ); return [ diff --git a/src/views/tables/FillsTable.tsx b/src/views/tables/FillsTable.tsx index deed14102..c33554ab2 100644 --- a/src/views/tables/FillsTable.tsx +++ b/src/views/tables/FillsTable.tsx @@ -35,6 +35,7 @@ import { getAssets } from '@/state/assetsSelectors'; import { openDialog } from '@/state/dialogs'; import { getPerpetualMarkets } from '@/state/perpetualsSelectors'; +import { mapIfPresent } from '@/lib/do'; import { MustBigNumber } from '@/lib/numbers'; import { getHydratedTradingData } from '@/lib/orders'; import { orEmptyRecord } from '@/lib/typeUtils'; @@ -358,9 +359,11 @@ export const FillsTable = ({ return () => { dispatch(viewedFills(currentMarket)); }; - }, [currentMarket]); + }, [currentMarket, dispatch]); - const symbol = currentMarket ? allAssets[allPerpetualMarkets[currentMarket]?.assetId]?.id : null; + const symbol = mapIfPresent(currentMarket, (market) => + mapIfPresent(allPerpetualMarkets[market]?.assetId, (assetId) => allAssets[assetId]?.id) + ); const fillsData = useMemo( () => diff --git a/src/views/tables/OrdersTable.tsx b/src/views/tables/OrdersTable.tsx index 074ac4bcd..4bfc5e6b3 100644 --- a/src/views/tables/OrdersTable.tsx +++ b/src/views/tables/OrdersTable.tsx @@ -45,6 +45,7 @@ import { getAssets } from '@/state/assetsSelectors'; import { openDialog } from '@/state/dialogs'; import { getPerpetualMarkets } from '@/state/perpetualsSelectors'; +import { mapIfPresent } from '@/lib/do'; import { MustBigNumber } from '@/lib/numbers'; import { getHydratedTradingData, @@ -404,7 +405,9 @@ export const OrdersTable = ({ if (hasUnseenOrderUpdates) dispatch(viewedOrders()); }, [hasUnseenOrderUpdates]); - const symbol = currentMarket ? allAssets[allPerpetualMarkets[currentMarket]?.assetId]?.id : null; + const symbol = mapIfPresent(currentMarket, (market) => + mapIfPresent(allPerpetualMarkets[market]?.assetId, (assetId) => allAssets[assetId]?.id) + ); const ordersData = useMemo( () => diff --git a/src/views/tables/PositionsTable.tsx b/src/views/tables/PositionsTable.tsx index 9b5759ded..62435d883 100644 --- a/src/views/tables/PositionsTable.tsx +++ b/src/views/tables/PositionsTable.tsx @@ -80,7 +80,7 @@ export enum PositionsTableColumnKey { } type PositionTableRow = { - asset: Asset; + asset: Asset | undefined; oraclePrice: Nullable; tickSizeDecimals: number; fundingRate: Nullable; diff --git a/src/views/tables/PositionsTable/PositionsTriggersCell.tsx b/src/views/tables/PositionsTable/PositionsTriggersCell.tsx index 7612ad443..a8adaaeab 100644 --- a/src/views/tables/PositionsTable/PositionsTriggersCell.tsx +++ b/src/views/tables/PositionsTable/PositionsTriggersCell.tsx @@ -135,7 +135,7 @@ export const PositionsTriggersCell = ({ } if (orders.length === 1) { - const order = orders[0]; + const order = orders[0]!; const { size, triggerPrice } = order; const isPartialPosition = !!(positionSize && Math.abs(size) < Math.abs(positionSize)); diff --git a/src/views/tables/PositionsTable/PositionsTriggersCellDeprecated.tsx b/src/views/tables/PositionsTable/PositionsTriggersCellDeprecated.tsx index 51d2da2b6..e09474b16 100644 --- a/src/views/tables/PositionsTable/PositionsTriggersCellDeprecated.tsx +++ b/src/views/tables/PositionsTable/PositionsTriggersCellDeprecated.tsx @@ -173,7 +173,7 @@ export const PositionsTriggersCellDeprecated = ({ } if (orders.length === 1) { - const order = orders[0]; + const order = orders[0]!; const { size, triggerPrice } = order; const isPartialPosition = !!(positionSize && Math.abs(size) < Math.abs(positionSize)); diff --git a/tsconfig.json b/tsconfig.json index f470b7636..6efb2030c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ "jsx": "react-jsx", "baseUrl": "./", "useUnknownInCatchVariables": false, + "noUncheckedIndexedAccess": true, "paths": { "@/*": ["src/*"] },