diff --git a/.github/issue_template/bug_report_task.md b/.github/issue_template/bug_report_task.md new file mode 100644 index 0000000..5fd500d --- /dev/null +++ b/.github/issue_template/bug_report_task.md @@ -0,0 +1,35 @@ +--- +name: Bug report task +about: Create a bug report task to help us fix an existing bug +--- + +#### **Description** + + + +#### **Steps To Reproduce** + + + +#### **Actual result** + + + +#### **Expected result** + + + +#### **Attachments** + + + +#### **Additional context** + + diff --git a/.github/issue_template/common_task.md b/.github/issue_template/common_task.md new file mode 100644 index 0000000..6f52337 --- /dev/null +++ b/.github/issue_template/common_task.md @@ -0,0 +1,19 @@ +--- +name: Common task +about: Create a common task to implement a feature, do refactor, or update docs +--- + +## Description + + + +## Acceptance Criteria +- [ ] _Your acceptance criteria_ + +#### **Attachments** + + + +## Additional context + + diff --git a/.gitignore b/.gitignore index 3ce6f93..0528449 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ yarn-error.log* # vercel .vercel + +.idea diff --git a/package.json b/package.json index 3f3cbf3..5105a33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@mento-protocol/mento-web", - "version": "2.3.0", + "version": "2.3.3", "description": "A simple DApp for Celo Mento exchanges", "keywords": [ "Celo", @@ -45,7 +45,7 @@ "frappe-charts": "^1.6.2", "jsbi": "^4.3.0", "lottie-react": "^2.4.0", - "next": "13.5.7-canary.37", + "next": "14.2.15", "react": "^18.2.0", "react-dom": "^18.2.0", "react-redux": "^8.1.0", diff --git a/src/components/nav/BalancesSummary.tsx b/src/components/nav/BalancesSummary.tsx index 033c041..38ce044 100644 --- a/src/components/nav/BalancesSummary.tsx +++ b/src/components/nav/BalancesSummary.tsx @@ -13,10 +13,16 @@ export function BalancesSummary() { {tokenIds.map((id) => { const balance = fromWeiRounded(balances[id], Tokens[id].decimals) if (balance !== '0') { + const token = Tokens[id] // TODO: @bayo Either revert this !== 0 check or add some animation for when balances are loading return ( -
- +
+
{balance}
) diff --git a/src/components/nav/ConnectButton.tsx b/src/components/nav/ConnectButton.tsx index 1f813eb..934dd4b 100644 --- a/src/components/nav/ConnectButton.tsx +++ b/src/components/nav/ConnectButton.tsx @@ -6,6 +6,7 @@ import { Identicon } from 'src/components/Identicon' import { SolidButton } from 'src/components/buttons/SolidButton' import { BalancesSummary } from 'src/components/nav/BalancesSummary' import { NetworkModal } from 'src/components/nav/NetworkModal' +import { cleanupStaleWalletSessions } from 'src/config/wallets' import ClipboardDark from 'src/images/icons/clipboard-plus-dark.svg' import Clipboard from 'src/images/icons/clipboard-plus.svg' import CubeDark from 'src/images/icons/cube-dark.svg' @@ -24,6 +25,11 @@ export function ConnectButton() { const { openConnectModal } = useConnectModal() const { disconnect } = useDisconnect() + const onClickConnect = () => { + cleanupStaleWalletSessions() + openConnectModal?.() + } + const onClickCopy = async () => { if (!address) return await tryClipboardSet(address) @@ -91,7 +97,7 @@ export function ConnectButton() { styles="sm:mr-3" /> } - onClick={openConnectModal} + onClick={onClickConnect} >
Connect
diff --git a/src/components/nav/NetworkModal.tsx b/src/components/nav/NetworkModal.tsx index b4f9ae3..a75f02b 100644 --- a/src/components/nav/NetworkModal.tsx +++ b/src/components/nav/NetworkModal.tsx @@ -1,5 +1,6 @@ import { toast } from 'react-toastify' import { ChainMetadata, allChains, chainIdToChain } from 'src/config/chains' +import { cleanupStaleWalletSessions } from 'src/config/wallets' import { reset as accountReset } from 'src/features/accounts/accountSlice' import { reset as blockReset } from 'src/features/blocks/blockSlice' import { resetTokenPrices } from 'src/features/chart/tokenPriceSlice' @@ -15,6 +16,7 @@ interface Props { } export function NetworkModal({ isOpen, close }: Props) { + const baseLocator = 'networkModal' const latestBlock = useAppSelector((s) => s.block.latestBlock) const chainId = useChainId() const currentChain = chainIdToChain[chainId] @@ -25,6 +27,7 @@ export function NetworkModal({ isOpen, close }: Props) { try { if (!switchNetworkAsync) throw new Error('switchNetworkAsync undefined') logger.debug('Resetting and switching to network', c.name) + cleanupStaleWalletSessions() await switchNetworkAsync(c.chainId) dispatch(blockReset()) dispatch(accountReset()) @@ -38,38 +41,47 @@ export function NetworkModal({ isOpen, close }: Props) { return ( -
-
-
+
+
+
Connected to:
-
+
{currentChain?.name || 'Unknown'}
-
+
Block Number:
-
+
{latestBlock?.number || 'Unknown'}
-
+
Node Rpc Url:
-
+
{shortenUrl(currentChain?.rpcUrl) || 'Unknown'}
-
+
{allChains.map((c) => (
-
- Sending two transactions: Approve and Swap +
+ {needsApproval + ? 'Sending two transactions: Approve and Swap' + : 'Sending swap transaction'} +
+
+ {`Sign with ${connector?.name || 'wallet'} to proceed`}
-
{`Sign with ${ - connector?.name || 'wallet' - } to proceed`}
) diff --git a/src/features/swap/SwapForm.tsx b/src/features/swap/SwapForm.tsx index 917d8de..b8e567f 100644 --- a/src/features/swap/SwapForm.tsx +++ b/src/features/swap/SwapForm.tsx @@ -20,7 +20,7 @@ import { reset as blockReset } from 'src/features/blocks/blockSlice' import { resetTokenPrices } from 'src/features/chart/tokenPriceSlice' import { useAppDispatch, useAppSelector } from 'src/features/store/hooks' import { SettingsMenu } from 'src/features/swap/SettingsMenu' -import { setFormValues, reset as swapReset } from 'src/features/swap/swapSlice' +import { setConfirmView, setFormValues, reset as swapReset } from 'src/features/swap/swapSlice' import { SwapDirection, SwapFormValues } from 'src/features/swap/types' import { useFormValidator } from 'src/features/swap/useFormValidator' import { useSwapQuote } from 'src/features/swap/useSwapQuote' @@ -60,18 +60,21 @@ export function SwapFormCard() { } function SwapForm() { - const balances = useAppSelector((s) => s.account.balances) + const { balances, lastUpdated } = useAppSelector((s) => s.account) const { showSlippage } = useAppSelector((s) => s.swap) const dispatch = useAppDispatch() const onSubmit = (values: SwapFormValues) => { dispatch(setFormValues(values)) + dispatch(setConfirmView(true)) // Switch to confirm view } - const validateForm = useFormValidator(balances) + const validateForm = useFormValidator(balances, lastUpdated) + const storedFormValues = useAppSelector((s) => s.swap.formValues) // Get stored form values + const initialFormValues = storedFormValues || initialValues // Use stored values if they exist return ( - initialValues={initialValues} + initialValues={initialFormValues} onSubmit={onSubmit} validate={validateForm} validateOnChange={true} @@ -329,7 +332,7 @@ function SubmitButton() { const showLongError = typeof error === 'string' && error?.length > 50 return ( -
+
{showLongError ? (
{error}
) : null} diff --git a/src/features/swap/swapSlice.ts b/src/features/swap/swapSlice.ts index 26477bc..32d45db 100644 --- a/src/features/swap/swapSlice.ts +++ b/src/features/swap/swapSlice.ts @@ -6,6 +6,7 @@ export interface SwapState { toCeloRates: ToCeloRates showSlippage: boolean showChart: boolean + confirmView: boolean } const initialState: SwapState = { @@ -13,6 +14,7 @@ const initialState: SwapState = { toCeloRates: {}, showSlippage: false, showChart: false, + confirmView: false, } export const swapSlice = createSlice({ @@ -29,8 +31,12 @@ export const swapSlice = createSlice({ state.showChart = action.payload }, reset: () => initialState, + setConfirmView(state, action) { + state.confirmView = action.payload + }, }, }) -export const { setFormValues, setShowSlippage, setShowChart, reset } = swapSlice.actions +export const { setFormValues, setShowSlippage, setShowChart, reset, setConfirmView } = + swapSlice.actions export const swapReducer = swapSlice.reducer diff --git a/src/features/swap/useAllowance.tsx b/src/features/swap/useAllowance.tsx new file mode 100644 index 0000000..467bab6 --- /dev/null +++ b/src/features/swap/useAllowance.tsx @@ -0,0 +1,43 @@ +import { useQuery } from '@tanstack/react-query' +import { Contract } from 'ethers' +import { ERC20_ABI } from 'src/config/consts' +import { BrokerAddresses } from 'src/config/exchanges' +import { TokenId, getTokenAddress } from 'src/config/tokens' +import { getProvider } from 'src/features/providers' +import { logger } from 'src/utils/logger' + +async function fetchAllowance( + tokenAddr: string, + accountAddress: string, + chainId: number +): Promise { + logger.info(`Fetching allowance for token ${tokenAddr} on chain ${chainId}`) + const provider = getProvider(chainId) + const contract = new Contract(tokenAddr, ERC20_ABI, provider) + const brokerAddress = BrokerAddresses[chainId as keyof typeof BrokerAddresses] + + const allowance = await contract.allowance(accountAddress, brokerAddress) + logger.info(`Allowance: ${allowance.toString()}`) + return allowance.toString() +} + +export function useAllowance(chainId: number, tokenId: TokenId, accountAddress?: string) { + const { data: allowance, isLoading } = useQuery( + ['tokenAllowance', chainId, tokenId, accountAddress], + async () => { + if (!accountAddress) return '0' + const tokenAddr = getTokenAddress(tokenId, chainId) + return fetchAllowance(tokenAddr, accountAddress, chainId) + }, + { + retry: false, + enabled: Boolean(accountAddress && chainId && tokenId), + staleTime: 5000, // Consider allowance stale after 5 seconds + } + ) + + return { + allowance: allowance || '0', + isLoading, + } +} diff --git a/src/features/swap/useFormValidator.ts b/src/features/swap/useFormValidator.ts index 410731f..4f26f1a 100644 --- a/src/features/swap/useFormValidator.ts +++ b/src/features/swap/useFormValidator.ts @@ -9,11 +9,12 @@ import { areAmountsNearlyEqual, parseAmount, toWei } from 'src/utils/amount' import { logger } from 'src/utils/logger' import { useChainId } from 'wagmi' -export function useFormValidator(balances: AccountBalances) { +export function useFormValidator(balances: AccountBalances, lastUpdated: number | null) { const chainId = useChainId() return useCallback( (values?: SwapFormValues): Promise> => { return (async () => { + if (!lastUpdated) return { fromTokenId: 'Balance still loading' } if (!values || !values.amount) return { amount: 'Amount Required' } const parsedAmount = parseAmount(values.amount) if (!parsedAmount) return { amount: 'Amount is Invalid' } @@ -33,7 +34,7 @@ export function useFormValidator(balances: AccountBalances) { return {} }) }, - [balances, chainId] + [balances, chainId, lastUpdated] ) } diff --git a/src/features/swap/useSwapQuote.ts b/src/features/swap/useSwapQuote.ts index 5510006..f6842ba 100644 --- a/src/features/swap/useSwapQuote.ts +++ b/src/features/swap/useSwapQuote.ts @@ -48,7 +48,7 @@ export function useSwapQuote( quoteWei = (await mento.getAmountIn(fromTokenAddr, toTokenAddr, amountWeiBN)).toString() } - const quote = fromWei(quoteWei, quoteDecimals).toString() + const quote = fromWei(quoteWei, quoteDecimals) const rateIn = calcExchangeRate(amountWei, amountDecimals, quoteWei, quoteDecimals) const rate = isSwapIn ? rateIn : invertExchangeRate(rateIn) diff --git a/src/features/swap/useSwapTransaction.ts b/src/features/swap/useSwapTransaction.ts index 6680883..3532161 100644 --- a/src/features/swap/useSwapTransaction.ts +++ b/src/features/swap/useSwapTransaction.ts @@ -36,8 +36,10 @@ export function useSwapTransaction( !isApproveConfirmed || new BigNumber(amountInWei).lte(0) || new BigNumber(thresholdAmountInWei).lte(0) - ) + ) { + logger.debug('Skipping swap transaction') return null + } const sdk = await getMentoSdk(chainId) const fromTokenAddr = getTokenAddress(fromToken, chainId) const toTokenAddr = getTokenAddress(toToken, chainId) diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 9b3d369..1fdf637 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -6,11 +6,15 @@ import { SwapConfirmCard } from 'src/features/swap/SwapConfirm' import { SwapFormCard } from 'src/features/swap/SwapForm' export default function SwapPage() { - const { formValues, showChart } = useAppSelector((state) => state.swap) + const { formValues, showChart, confirmView } = useAppSelector((state) => state.swap) return (
- {!formValues ? : } + {!formValues || !confirmView ? ( + + ) : ( + + )}{' '}
{config.showPriceChart && showChart && (
diff --git a/src/utils/amount.ts b/src/utils/amount.ts index b5eb359..f3a98d6 100644 --- a/src/utils/amount.ts +++ b/src/utils/amount.ts @@ -11,11 +11,11 @@ export type NumberT = BigNumber.Value export function fromWei( value: NumberT | null | undefined, decimals = STANDARD_TOKEN_DECIMALS -): number { - if (!value) return 0 +): string { + if (!value) return '0' const valueString = value.toString().trim() const flooredValue = new BigNumber(valueString).toFixed(0, BigNumber.ROUND_FLOOR) - return parseFloat(formatUnits(flooredValue, decimals)) + return formatUnits(flooredValue, decimals) } // Similar to fromWei above but rounds to set number of decimals diff --git a/yarn.lock b/yarn.lock index 3da01b0..36bc5bd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1940,7 +1940,7 @@ __metadata: jest: ^29.5.0 jsbi: ^4.3.0 lottie-react: ^2.4.0 - next: 13.5.7-canary.37 + next: 14.2.15 postcss: ^8.4.32 prettier: ^2.8.8 react: ^18.2.0 @@ -2124,10 +2124,10 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/env@npm:13.5.7-canary.37" - checksum: cbeba53f806a30fdbbbaa48785b0784702953d2e4e3a7bc6a14cb7e6e6e005232050cc627368b233257b1d60bcc41af5cfd6d0ee789497e4c4736f40e3956177 +"@next/env@npm:14.2.15": + version: 14.2.15 + resolution: "@next/env@npm:14.2.15" + checksum: bf794604ee62e86ca092120c790815c0caf367009966baa14e75dbd8454a59df524327539d5febc7da42841c3bf6a10443ae0f95280599352a8def56291857fd languageName: node linkType: hard @@ -2140,65 +2140,65 @@ __metadata: languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-darwin-arm64@npm:13.5.7-canary.37" +"@next/swc-darwin-arm64@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-darwin-arm64@npm:14.2.15" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-darwin-x64@npm:13.5.7-canary.37" +"@next/swc-darwin-x64@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-darwin-x64@npm:14.2.15" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-linux-arm64-gnu@npm:13.5.7-canary.37" +"@next/swc-linux-arm64-gnu@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-linux-arm64-gnu@npm:14.2.15" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-linux-arm64-musl@npm:13.5.7-canary.37" +"@next/swc-linux-arm64-musl@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-linux-arm64-musl@npm:14.2.15" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-linux-x64-gnu@npm:13.5.7-canary.37" +"@next/swc-linux-x64-gnu@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-linux-x64-gnu@npm:14.2.15" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-linux-x64-musl@npm:13.5.7-canary.37" +"@next/swc-linux-x64-musl@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-linux-x64-musl@npm:14.2.15" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-win32-arm64-msvc@npm:13.5.7-canary.37" +"@next/swc-win32-arm64-msvc@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-win32-arm64-msvc@npm:14.2.15" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-win32-ia32-msvc@npm:13.5.7-canary.37" +"@next/swc-win32-ia32-msvc@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-win32-ia32-msvc@npm:14.2.15" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@next/swc-win32-x64-msvc@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "@next/swc-win32-x64-msvc@npm:13.5.7-canary.37" +"@next/swc-win32-x64-msvc@npm:14.2.15": + version: 14.2.15 + resolution: "@next/swc-win32-x64-msvc@npm:14.2.15" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -2633,12 +2633,20 @@ __metadata: languageName: node linkType: hard -"@swc/helpers@npm:0.5.2": - version: 0.5.2 - resolution: "@swc/helpers@npm:0.5.2" +"@swc/counter@npm:^0.1.3": + version: 0.1.3 + resolution: "@swc/counter@npm:0.1.3" + checksum: df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 + languageName: node + linkType: hard + +"@swc/helpers@npm:0.5.5": + version: 0.5.5 + resolution: "@swc/helpers@npm:0.5.5" dependencies: + "@swc/counter": ^0.1.3 tslib: ^2.4.0 - checksum: 51d7e3d8bd56818c49d6bfbd715f0dbeedc13cf723af41166e45c03e37f109336bbcb57a1f2020f4015957721aeb21e1a7fff281233d797ff7d3dd1f447fa258 + checksum: d4f207b191e54b29460804ddf2984ba6ece1d679a0b2f6a9c765dcf27bba92c5769e7965668a4546fb9f1021eaf0ff9be4bf5c235ce12adcd65acdfe77187d11 languageName: node linkType: hard @@ -4661,13 +4669,20 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001449, caniuse-lite@npm:^1.0.30001464": +"caniuse-lite@npm:^1.0.30001400, caniuse-lite@npm:^1.0.30001449, caniuse-lite@npm:^1.0.30001464": version: 1.0.30001568 resolution: "caniuse-lite@npm:1.0.30001568" checksum: 7092aaa246dc8531fbca5b47be91e92065db7e5c04cc9e3d864e848f8f1be769ac6754429e843a5e939f7331a771e8b0a1bc3b13495c66b748c65e2f5bdb1220 languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001579": + version: 1.0.30001690 + resolution: "caniuse-lite@npm:1.0.30001690" + checksum: f2c1b595f15d8de4d9ccd155d61ac9f00ac62f1515870505a0186266fd52aef169fcddc90d8a4814e52b77107244806466fadc2c216662f23f1022a430e735ee + languageName: node + linkType: hard + "case@npm:^1.6.3": version: 1.6.3 resolution: "case@npm:1.6.3" @@ -6394,13 +6409,6 @@ __metadata: languageName: node linkType: hard -"glob-to-regexp@npm:^0.4.1": - version: 0.4.1 - resolution: "glob-to-regexp@npm:0.4.1" - checksum: e795f4e8f06d2a15e86f76e4d92751cf8bbfcf0157cea5c2f0f35678a8195a750b34096b1256e436f0cebc1883b5ff0888c47348443e69546a5a87f9e1eb1167 - languageName: node - linkType: hard - "glob@npm:7.1.6": version: 7.1.6 resolution: "glob@npm:7.1.6" @@ -6508,7 +6516,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.2": +"graceful-fs@npm:^4.2.11": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: ac85f94da92d8eb6b7f5a8b20ce65e43d66761c55ce85ac96df6865308390da45a8d3f0296dd3a663de65d30ba497bd46c696cc1e248c72b13d6d567138a4fc7 @@ -8456,28 +8464,29 @@ __metadata: languageName: node linkType: hard -"next@npm:13.5.7-canary.37": - version: 13.5.7-canary.37 - resolution: "next@npm:13.5.7-canary.37" +"next@npm:14.2.15": + version: 14.2.15 + resolution: "next@npm:14.2.15" dependencies: - "@next/env": 13.5.7-canary.37 - "@next/swc-darwin-arm64": 13.5.7-canary.37 - "@next/swc-darwin-x64": 13.5.7-canary.37 - "@next/swc-linux-arm64-gnu": 13.5.7-canary.37 - "@next/swc-linux-arm64-musl": 13.5.7-canary.37 - "@next/swc-linux-x64-gnu": 13.5.7-canary.37 - "@next/swc-linux-x64-musl": 13.5.7-canary.37 - "@next/swc-win32-arm64-msvc": 13.5.7-canary.37 - "@next/swc-win32-ia32-msvc": 13.5.7-canary.37 - "@next/swc-win32-x64-msvc": 13.5.7-canary.37 - "@swc/helpers": 0.5.2 + "@next/env": 14.2.15 + "@next/swc-darwin-arm64": 14.2.15 + "@next/swc-darwin-x64": 14.2.15 + "@next/swc-linux-arm64-gnu": 14.2.15 + "@next/swc-linux-arm64-musl": 14.2.15 + "@next/swc-linux-x64-gnu": 14.2.15 + "@next/swc-linux-x64-musl": 14.2.15 + "@next/swc-win32-arm64-msvc": 14.2.15 + "@next/swc-win32-ia32-msvc": 14.2.15 + "@next/swc-win32-x64-msvc": 14.2.15 + "@swc/helpers": 0.5.5 busboy: 1.6.0 - caniuse-lite: ^1.0.30001406 + caniuse-lite: ^1.0.30001579 + graceful-fs: ^4.2.11 postcss: 8.4.31 styled-jsx: 5.1.1 - watchpack: 2.4.0 peerDependencies: "@opentelemetry/api": ^1.1.0 + "@playwright/test": ^1.41.2 react: ^18.2.0 react-dom: ^18.2.0 sass: ^1.3.0 @@ -8503,11 +8512,13 @@ __metadata: peerDependenciesMeta: "@opentelemetry/api": optional: true + "@playwright/test": + optional: true sass: optional: true bin: next: dist/bin/next - checksum: 1b10587ee764d86e4a9135359fdf6d636f549326518a8c45efdbc6fc55ad8dd4e3214d6db7bc0ec35992b87c07ae34da4452a794c16a60e1aa59d5f324ce0183 + checksum: bed22817ea82c679e78c1f1e6530991ae89f3c51d547a876dddcda4a3b34cbb970af7c714793e1a1f0a1974859ccc97e10b5aceb61e9807ea94318116e8e7dd6 languageName: node linkType: hard @@ -11076,16 +11087,6 @@ __metadata: languageName: node linkType: hard -"watchpack@npm:2.4.0": - version: 2.4.0 - resolution: "watchpack@npm:2.4.0" - dependencies: - glob-to-regexp: ^0.4.1 - graceful-fs: ^4.1.2 - checksum: 23d4bc58634dbe13b86093e01c6a68d8096028b664ab7139d58f0c37d962d549a940e98f2f201cecdabd6f9c340338dc73ef8bf094a2249ef582f35183d1a131 - languageName: node - linkType: hard - "webextension-polyfill-ts@npm:^0.22.0": version: 0.22.0 resolution: "webextension-polyfill-ts@npm:0.22.0"