diff --git a/.changeset/lemon-maps-rest.md b/.changeset/lemon-maps-rest.md new file mode 100644 index 0000000000..ae7e7aa865 --- /dev/null +++ b/.changeset/lemon-maps-rest.md @@ -0,0 +1,6 @@ +--- +"@fuels/playwright-utils": minor +"fuels-wallet": minor +--- + +feat: performance improvement from rework on send transaction machine flows diff --git a/.github/workflows/pr-tests-e2e-assets.yml b/.github/workflows/pr-tests-e2e-assets.yml index 2d7b75ca27..1494154812 100644 --- a/.github/workflows/pr-tests-e2e-assets.yml +++ b/.github/workflows/pr-tests-e2e-assets.yml @@ -32,7 +32,7 @@ jobs: - name: Upload Test Report if: failure() - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: e2e-test-report path: packages/e2e-assets/playwright-html \ No newline at end of file diff --git a/examples/cra-dapp/package.json b/examples/cra-dapp/package.json index adfaecf44b..6550e16cd4 100644 --- a/examples/cra-dapp/package.json +++ b/examples/cra-dapp/package.json @@ -20,6 +20,6 @@ "@types/react-dom": "18.3.0", "@vitejs/plugin-react": "4.2.1", "typescript": "5.2.2", - "vite": "6.0.3" + "vite": "6.0.8" } } diff --git a/package.json b/package.json index 8837d61a5c..146081a67f 100644 --- a/package.json +++ b/package.json @@ -98,6 +98,9 @@ "allowAny": ["react", "react-dom"], "ignoreMissing": ["react", "react-dom"] }, + "auditConfig": { + "ignoreGhsas": ["GHSA-vg6x-rcgg-rjx6"] + }, "overrides": { "follow-redirects": ">=1.15.6", "glob-parent@<5.1.2": ">=5.1.2", @@ -128,7 +131,8 @@ "secp256k1@=5.0.0": ">=5.0.1", "elliptic@<6.6.0": ">=6.6.0", "cross-spawn@<7.0.5": ">=7.0.5", - "nanoid@<3.3.8": "3.3.8" + "nanoid@<3.3.8": "3.3.8", + "store2@<2.14.4": ">=2.14.4" } } } diff --git a/packages/app/package.json b/packages/app/package.json index b8e9e7af3f..fe43b516e8 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -102,7 +102,7 @@ "ts-jest-mock-import-meta": "1.1.0", "tsconfig-paths-webpack-plugin": "4.1.0", "typescript": "5.2.2", - "vite": "6.0.3", + "vite": "6.0.8", "vite-plugin-clean": "1.0.0", "vite-plugin-static-copy": "2.2.0", "vite-tsconfig-paths": "5.1.4", diff --git a/packages/app/playwright/crx/assets.test.ts b/packages/app/playwright/crx/assets.test.ts index 813bd8d9f3..46f6d783f3 100644 --- a/packages/app/playwright/crx/assets.test.ts +++ b/packages/app/playwright/crx/assets.test.ts @@ -41,9 +41,14 @@ test.describe('Check assets', () => { }); test('should show valid asset value 0.002000', async () => { - expect( - await page.getByText('0.002000', { exact: true }).isVisible() - ).toBeTruthy(); + await expect + .poll( + async () => { + return await page.getByText('0.002000', { exact: true }).isVisible(); + }, + { timeout: 10000 } + ) + .toBeTruthy(); }); test('should show USDCIcon AlertTriangle', async () => { diff --git a/packages/app/playwright/crx/crx.test.ts b/packages/app/playwright/crx/crx.test.ts index e6a1735ccb..79a46042cb 100644 --- a/packages/app/playwright/crx/crx.test.ts +++ b/packages/app/playwright/crx/crx.test.ts @@ -90,10 +90,11 @@ test.describe('FuelWallet Extension', () => { extensionId, }) => { const popupPage = await context.newPage(); - await popupPage.goto(`chrome-extension://${extensionId}/popup.html`); - const page = await context.waitForEvent('page', { + const pagePromise = context.waitForEvent('page', { predicate: (page) => page.url().includes('sign-up'), }); + await popupPage.goto(`chrome-extension://${extensionId}/popup.html`); + const page = await pagePromise; expect(page.url()).toContain('sign-up'); }); diff --git a/packages/app/playwright/e2e/SendTransaction.test.ts b/packages/app/playwright/e2e/SendTransaction.test.ts index 464d1e34ea..556b3bb0a8 100644 --- a/packages/app/playwright/e2e/SendTransaction.test.ts +++ b/packages/app/playwright/e2e/SendTransaction.test.ts @@ -59,8 +59,6 @@ test.describe('SendTransaction', () => { const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); @@ -95,8 +93,6 @@ test.describe('SendTransaction', () => { // make sure the button is enabled const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); @@ -140,8 +136,6 @@ test.describe('SendTransaction', () => { const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); @@ -173,12 +167,9 @@ test.describe('SendTransaction', () => { // Waiting button change to Review in order to ensure that fee amount is updated await page.waitForSelector('button:has-text("Review")'); - await page.waitForTimeout(1000); const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); @@ -215,12 +206,9 @@ test.describe('SendTransaction', () => { // Waiting button change to Review in order to change fee amount await page.waitForSelector('button:has-text("Review")'); - await page.waitForTimeout(1000); const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); @@ -253,27 +241,38 @@ test.describe('SendTransaction', () => { // Waiting button change to Review in order to ensure that fee amount is updated await page.waitForSelector('button:has-text("Review")'); - await page.waitForTimeout(1000); // Selecting and extracting regular fee amount + await expect + .poll( + async () => { + return await getByAriaLabel(page, 'fee value:Regular').isVisible(); + }, + { timeout: 10000 } + ) + .toBeTruthy(); const regularFeeComponent = getByAriaLabel(page, 'fee value:Regular'); await regularFeeComponent.click(); // Waiting button change to Review in order to ensure that fee amount is updated await page.waitForSelector('button:has-text("Review")'); - await page.waitForTimeout(1000); const btnLocatorBeforeApprv = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocatorBeforeApprv); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocatorBeforeApprv); await btnLocatorBeforeApprv.click(); // Waiting button change to Approve in order to get updated fee amount await page.waitForSelector('button:has-text("Submit")'); - await page.waitForTimeout(1000); + await expect + .poll( + async () => { + return await getButtonByText(page, 'Back').isVisible(); + }, + { timeout: 10000 } + ) + .toBeTruthy(); // Going back to select other fee value await getButtonByText(page, 'Back').click(); @@ -283,27 +282,37 @@ test.describe('SendTransaction', () => { // Waiting button change to Review in order to change fee amount await page.waitForSelector('button:has-text("Review")'); - await page.waitForTimeout(1000); const btnLocator = getButtonByText(page, 'Review'); - await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); await expectButtonToBeEnabled(btnLocator); await btnLocator.click(); // Waiting button change to Approve in order to get updated fee amount await page.waitForSelector('button:has-text("Submit")'); - await page.waitForTimeout(1000); await hasText(page, '0.001 ETH'); - await page.waitForTimeout(1000); + await expect + .poll( + async () => { + return await getButtonByText(page, 'Submit').isEnabled(); + }, + { timeout: 10000 } + ) + .toBeTruthy(); await getButtonByText(page, 'Submit').click(); await hasText(page, '0.001 ETH'); // Wait for transaction to be confirmed - await hasText(page, 'success'); + await expect + .poll( + async () => { + return await hasText(page, 'success'); + }, + { timeout: 10000 } + ) + .toBeTruthy(); }); test('Send max amount transaction', async () => { @@ -337,15 +346,12 @@ test.describe('SendTransaction', () => { // Fee values change await new Promise((resolve) => setTimeout(resolve, 3000)); - const maxAmountAfterFee = await getInputByName(page, 'amount').inputValue(); - // Submit transaction const btnLocator = getButtonByText(page, 'Review'); await expectButtonToBeEnabled(btnLocator); - await page.waitForTimeout(5000); - await expectButtonToBeEnabled(btnLocator); + const maxAmountAfterFee = await getInputByName(page, 'amount').inputValue(); await btnLocator.click(); // Approve transaction diff --git a/packages/app/src/systems/DApp/hooks/useTransactionRequest.tsx b/packages/app/src/systems/DApp/hooks/useTransactionRequest.tsx index 6ff1ba477f..554cf9872c 100644 --- a/packages/app/src/systems/DApp/hooks/useTransactionRequest.tsx +++ b/packages/app/src/systems/DApp/hooks/useTransactionRequest.tsx @@ -26,9 +26,6 @@ const selectors = { proposedTxRequest(state: TransactionRequestState) { return state.context.response?.proposedTxRequest; }, - isLoadingAccounts(state: TransactionRequestState) { - return state.matches('fetchingAccount'); - }, errors(state: TransactionRequestState) { if (!state.context.errors) return {}; const simulateTxErrors = state.context.errors?.simulateTxErrors; @@ -36,22 +33,19 @@ const selectors = { const txApproveError = state.context.errors?.txApproveError; return { txApproveError, simulateTxErrors, hasSimulateTxErrors }; }, - status(externalLoading?: boolean) { - return useCallback( - (state: TransactionRequestState) => { - const isLoading = state.hasTag('loading'); - const isClosed = state.matches('done') || state.matches('failed'); - - if (state.matches('idle')) return TxRequestStatus.idle; - if (externalLoading || isLoading) return TxRequestStatus.loading; - if (state.matches('txFailed')) return TxRequestStatus.failed; - if (state.matches('txSuccess')) return TxRequestStatus.success; - if (state.matches('sendingTx')) return TxRequestStatus.sending; - if (isClosed) return TxRequestStatus.inactive; - return TxRequestStatus.waitingApproval; - }, - [externalLoading] - ); + status() { + return useCallback((state: TransactionRequestState) => { + const isLoading = state.hasTag('loading'); + const isClosed = state.matches('done') || state.matches('failed'); + + if (state.matches('idle')) return TxRequestStatus.idle; + if (isLoading) return TxRequestStatus.loading; + if (state.matches('txFailed')) return TxRequestStatus.failed; + if (state.matches('txSuccess')) return TxRequestStatus.success; + if (state.matches('sendingTx')) return TxRequestStatus.sending; + if (isClosed) return TxRequestStatus.inactive; + return TxRequestStatus.waitingApproval; + }, []); }, title(state: TransactionRequestState) { if (state.matches('txSuccess')) return 'Transaction sent'; @@ -95,12 +89,11 @@ export function useTransactionRequest(opts: UseTransactionRequestOpts = {}) { }, }); - const isLoadingAccounts = useSelector(service, selectors.isLoadingAccounts); const account = useSelector(service, selectors.account); const ctx = useSelector(service, selectors.context); const errors = useSelector(service, selectors.errors); const providerUrl = ctx.input.providerUrl; - const txStatusSelector = selectors.status(isLoadingAccounts); + const txStatusSelector = selectors.status(); const txStatus = useSelector(service, txStatusSelector); const title = useSelector(service, selectors.title); const txSummarySimulated = useSelector(service, selectors.txSummarySimulated); diff --git a/packages/app/src/systems/DApp/machines/transactionRequestMachine.tsx b/packages/app/src/systems/DApp/machines/transactionRequestMachine.tsx index f1d222d472..01fcabf10e 100644 --- a/packages/app/src/systems/DApp/machines/transactionRequestMachine.tsx +++ b/packages/app/src/systems/DApp/machines/transactionRequestMachine.tsx @@ -1,9 +1,10 @@ -import type { Account } from '@fuel-wallet/types'; +import type { Account, AccountWithBalance } from '@fuel-wallet/types'; import type { BN, TransactionRequest, TransactionSummary } from 'fuels'; import type { InterpreterFrom, StateFrom } from 'xstate'; import { assign, createMachine } from 'xstate'; import { AccountService } from '~/systems/Account'; import { FetchMachine, assignErrorMessage, delay } from '~/systems/Core'; +import { NetworkService } from '~/systems/Network'; import type { GroupedErrors, VMApiError } from '~/systems/Transaction'; import type { TxInputs } from '~/systems/Transaction/services'; import { TxService } from '~/systems/Transaction/services'; @@ -23,11 +24,11 @@ type MachineContext = { origin?: string; title?: string; favIconUrl?: string; - address?: string; isOriginRequired?: boolean; providerUrl?: string; transactionRequest?: TransactionRequest; - account?: Account; + address?: string; + account?: AccountWithBalance; tip?: BN; gasLimit?: BN; skipCustomFee?: boolean; @@ -49,13 +50,13 @@ type MachineContext = { }; }; -type EstimateDefaultTipsReturn = { - regularTip: BN; - fastTip: BN; -}; - -type EstimateGasLimitReturn = { - maxGasLimit: BN; +type PrepareInputForSimulateTransactionReturn = { + estimated: { + regularTip: BN; + fastTip: BN; + maxGasLimit: BN; + }; + account: AccountWithBalance; }; type SimulateTransactionReturn = { @@ -69,18 +70,12 @@ type MachineServices = { send: { data: TransactionSummary; }; - estimateDefaultTips: { - data: EstimateDefaultTipsReturn; - }; - estimateGasLimit: { - data: EstimateGasLimitReturn; + prepareInputForSimulateTransaction: { + data: PrepareInputForSimulateTransactionReturn; }; simulateTransaction: { data: SimulateTransactionReturn; }; - fetchAccount: { - data: Account; - }; }; type MachineEvents = @@ -111,50 +106,31 @@ export const transactionRequestMachine = createMachine( states: { idle: { on: { - START: { - actions: ['assignTxRequestData'], - target: 'estimatingInitialTips', - }, - }, - }, - estimatingInitialTips: { - tags: ['loading'], - invoke: { - src: 'estimateDefaultTips', - onDone: [ - { - cond: FetchMachine.hasError, - target: 'failed', - }, - { - actions: ['assignDefaultTips'], - target: 'estimatingGasLimit', - }, - ], - }, - }, - estimatingGasLimit: { - invoke: { - src: 'estimateGasLimit', - onDone: [ + START: [ { - cond: FetchMachine.hasError, - target: 'failed', + cond: (_ctx, event) => + event.input?.fees?.maxGasLimit != null && + event.input?.fees?.fastTip != null && + event.input?.fees?.regularTip != null, + actions: ['assignTxRequestData'], + target: 'simulatingTransaction', }, { - actions: ['assignGasLimit'], - target: 'fetchingAccount', + actions: ['assignTxRequestData'], + target: 'prepareInputForSimulateTransaction', }, ], }, }, - fetchingAccount: { - entry: ['openDialog'], + prepareInputForSimulateTransaction: { tags: ['loading'], invoke: { - src: 'fetchAccount', + src: 'prepareInputForSimulateTransaction', data: { - input: (ctx: MachineContext) => ctx.input, + input: (ctx: MachineContext) => ({ + address: ctx.input.address, + account: ctx.input.account, + }), }, onDone: [ { @@ -162,13 +138,14 @@ export const transactionRequestMachine = createMachine( target: 'failed', }, { - actions: ['assignAccount'], + actions: ['assignPreflightData'], target: 'simulatingTransaction', }, ], }, }, simulatingTransaction: { + entry: ['openDialog'], tags: ['loading'], invoke: { src: 'simulateTransaction', @@ -267,45 +244,36 @@ export const transactionRequestMachine = createMachine( }, }, { - delays: { TIMEOUT: 1300 }, actions: { reset: assign(() => ({})), - assignDefaultTips: assign((ctx, ev) => ({ - fees: { - ...ctx.fees, - regularTip: ev.data.regularTip, - fastTip: ev.data.fastTip, - }, - })), - assignGasLimit: assign((ctx, ev) => ({ + assignPreflightData: assign((ctx, ev) => ({ + account: ev.data.account, fees: { ...ctx.fees, - maxGasLimit: ev.data.maxGasLimit, + regularTip: ev.data.estimated.regularTip, + fastTip: ev.data.estimated.fastTip, + maxGasLimit: ev.data.estimated.maxGasLimit, }, })), - assignAccount: assign({ - input: (ctx, ev) => ({ - ...ctx.input, - account: ev.data, - }), - }), assignTxRequestData: assign({ input: (ctx, ev) => { const { transactionRequest, origin, - address, providerUrl, title, favIconUrl, skipCustomFee, + account, + address, + fees, } = ev.input || {}; if (!providerUrl) { throw new Error('providerUrl is required'); } - if (!address) { - throw new Error('address is required'); + if (!account?.address && !address) { + throw new Error('account or address is required'); } if (!transactionRequest) { throw new Error('transaction is required'); @@ -317,11 +285,13 @@ export const transactionRequestMachine = createMachine( return { transactionRequest, origin, + account, address, providerUrl, title, favIconUrl, skipCustomFee, + fees, }; }, fees: (_ctx, ev) => { @@ -385,23 +355,30 @@ export const transactionRequestMachine = createMachine( }), }, services: { - estimateDefaultTips: FetchMachine.create< - never, - EstimateDefaultTipsReturn + prepareInputForSimulateTransaction: FetchMachine.create< + { address?: string; account?: AccountWithBalance }, + { + estimated: PrepareInputForSimulateTransactionReturn['estimated']; + account: AccountWithBalance; + } >({ showError: false, maxAttempts: 1, - async fetch() { - const defaultTips = await TxService.estimateDefaultTips(); - return defaultTips; - }, - }), - estimateGasLimit: FetchMachine.create({ - showError: false, - maxAttempts: 1, - async fetch() { - const gasLimit = await TxService.estimateGasLimit(); - return gasLimit; + async fetch({ input }) { + const [estimated, acc] = await Promise.all([ + TxService.estimateGasLimitAndDefaultTips(), + input?.account || + AccountService.fetchAccount({ + address: input?.address as string, + }).then(async (_account) => { + const network = await NetworkService.getSelectedNetwork(); + return await AccountService.fetchBalance({ + account: _account, + providerUrl: network?.url as string, + }); + }), + ]); + return { estimated, account: acc }; }, }), simulateTransaction: FetchMachine.create< @@ -427,7 +404,7 @@ export const transactionRequestMachine = createMachine( async fetch(params) { const { input } = params; if ( - !input?.address || + (!input?.account && !input?.address) || !input?.transactionRequest || !input?.providerUrl ) { @@ -443,26 +420,6 @@ export const transactionRequestMachine = createMachine( }; }, }), - fetchAccount: FetchMachine.create< - { address: string; providerUrl: string }, - Account - >({ - showError: true, - async fetch({ input }) { - if (!input?.address || !input?.providerUrl) { - throw new Error('Invalid fetchAccount input'); - } - const account = await AccountService.fetchAccount({ - address: input.address, - }); - const accountWithBalances = await AccountService.fetchBalance({ - account, - providerUrl: input.providerUrl, - }); - - return accountWithBalances; - }, - }), }, } ); diff --git a/packages/app/src/systems/DApp/methods.ts b/packages/app/src/systems/DApp/methods.ts index 35e76cdf2d..3cab2aa0c0 100644 --- a/packages/app/src/systems/DApp/methods.ts +++ b/packages/app/src/systems/DApp/methods.ts @@ -2,6 +2,7 @@ import { ExtensionPageConnection } from '@fuel-wallet/connections'; import { transactionRequestify } from 'fuels'; import { IS_CRX } from '~/config'; import { Services, store } from '~/store'; +import { AccountService } from '~/systems/Account/services/account'; import type { MessageInputs, PopUpServiceInputs, @@ -51,6 +52,7 @@ export class RequestMethods extends ExtensionPageConnection { const { origin, address, provider, transaction, title, favIconUrl } = input; const providerUrl = provider.url; const transactionRequest = transactionRequestify(JSON.parse(transaction)); + const state = await store .requestTransaction({ origin, diff --git a/packages/app/src/systems/Network/hooks/useProvider.tsx b/packages/app/src/systems/Network/hooks/useProvider.tsx index f693bf42e1..8334941e34 100644 --- a/packages/app/src/systems/Network/hooks/useProvider.tsx +++ b/packages/app/src/systems/Network/hooks/useProvider.tsx @@ -5,7 +5,8 @@ import { useNetworks } from './useNetworks'; export function useProvider() { const { network } = useNetworks(); - const [provider, setProvider] = useState(undefined); + // When we pass a function to the useState, we guarantee that the function will be called only once. + const [provider, setProvider] = useState(); useEffect(() => { if (network?.url) { diff --git a/packages/app/src/systems/Send/hooks/useSend.tsx b/packages/app/src/systems/Send/hooks/useSend.tsx index 05dfbcf8ba..6a707914ed 100644 --- a/packages/app/src/systems/Send/hooks/useSend.tsx +++ b/packages/app/src/systems/Send/hooks/useSend.tsx @@ -2,21 +2,23 @@ import { yupResolver } from '@hookform/resolvers/yup'; import { useInterpret, useSelector } from '@xstate/react'; import type { BN, BNInput } from 'fuels'; import { Address, type Provider, bn, isB256 } from 'fuels'; -import { useCallback, useEffect, useMemo } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import { useForm, useWatch } from 'react-hook-form'; import { useNavigate } from 'react-router-dom'; import * as yup from 'yup'; -import { useAccounts } from '~/systems/Account'; +import type { AccountsMachineState } from '~/systems/Account'; import { Pages } from '~/systems/Core'; import { useTransactionRequest } from '~/systems/DApp'; import { TxRequestStatus } from '~/systems/DApp/machines/transactionRequestMachine'; import type { TxInputs } from '~/systems/Transaction/services'; +import { Services } from '~/store'; +import { store } from '~/store'; import { AssetsCache } from '~/systems/Asset/cache/AssetsCache'; import { useProvider } from '~/systems/Network/hooks/useProvider'; import { formatGasLimit } from '~/systems/Transaction'; import { sendMachine } from '../machines/sendMachine'; -import type { SendMachineState } from '../machines/sendMachine'; +import type { MachineContext, SendMachineState } from '../machines/sendMachine'; export enum SendStatus { loading = 'loading', @@ -43,6 +45,9 @@ const selectors = { readyToSend(state: SendMachineState) { return state.matches('readyToSend'); }, + account(state: AccountsMachineState) { + return state.context.account; + }, error(state: SendMachineState) { if (state.context.error?.includes('Gas limit')) { return ''; @@ -273,9 +278,40 @@ const DEFAULT_VALUES: SendFormValues = { export function useSend() { const navigate = useNavigate(); const txRequest = useTransactionRequest(); - const { account } = useAccounts(); const provider = useProvider(); + const account = store.useSelector(Services.accounts, selectors.account); + const callTransactionRequest = useRef<(ctx: MachineContext) => void>(); + + callTransactionRequest.current = (ctx: MachineContext) => { + const { + providerUrl, + transactionRequest, + address, + baseFee, + regularTip, + fastTip, + maxGasLimit, + } = ctx; + if (!providerUrl || !transactionRequest || !address) { + throw new Error('Params are required'); + } + + txRequest.handlers.request({ + providerUrl, + transactionRequest, + account, + address, + fees: { + baseFee, + regularTip, + fastTip, + maxGasLimit, + }, + skipCustomFee: true, + }); + }; + const service = useInterpret(() => sendMachine.withConfig({ actions: { @@ -283,31 +319,7 @@ export function useSend() { navigate(Pages.index()); }, callTransactionRequest(ctx) { - const { - providerUrl, - transactionRequest, - address, - baseFee, - regularTip, - fastTip, - maxGasLimit, - } = ctx; - if (!providerUrl || !transactionRequest || !address) { - throw new Error('Params are required'); - } - - txRequest.handlers.request({ - providerUrl, - transactionRequest, - address, - fees: { - baseFee, - regularTip, - fastTip, - maxGasLimit, - }, - skipCustomFee: true, - }); + callTransactionRequest.current?.(ctx); }, }, }) @@ -348,7 +360,10 @@ export function useSend() { const fastTip = useSelector(service, selectors.fastTip); const sendStatusSelector = selectors.status(txRequest.txStatus); const sendStatus = useSelector(service, sendStatusSelector); - const readyToSend = useSelector(service, selectors.readyToSend); + const readyToSend = + useSelector(service, selectors.readyToSend) && + !!account && + !!callTransactionRequest.current; const input = useSelector(service, selectors.input); const balanceAssetSelected = useMemo(() => { diff --git a/packages/app/src/systems/Send/machines/sendMachine.ts b/packages/app/src/systems/Send/machines/sendMachine.ts index 7da036b12b..1933444d03 100644 --- a/packages/app/src/systems/Send/machines/sendMachine.ts +++ b/packages/app/src/systems/Send/machines/sendMachine.ts @@ -28,12 +28,9 @@ export type MachineContext = { error?: string; }; -type EstimateDefaultTipsReturn = { +type EstimateGasLimitAndDefaultTipsReturn = { regularTip: BN; fastTip: BN; -}; - -type EstimateGasLimitReturn = { maxGasLimit: BN; }; @@ -49,11 +46,8 @@ type MachineServices = { createTransactionRequest: { data: CreateTransactionReturn; }; - estimateDefaultTips: { - data: EstimateDefaultTipsReturn; - }; - estimateGasLimit: { - data: EstimateGasLimitReturn; + estimatingGasLimitAndDefaultTips: { + data: EstimateGasLimitAndDefaultTipsReturn; }; }; @@ -82,27 +76,11 @@ export const sendMachine = createMachine( services: {} as MachineServices, }, id: '(machine)', - initial: 'estimatingInitialTips', + initial: 'estimatingGasLimitAndDefaultTips', states: { - estimatingInitialTips: { - invoke: { - src: 'estimateDefaultTips', - onDone: [ - { - cond: FetchMachine.hasError, - target: 'idle', - actions: [assignError()], - }, - { - actions: ['assignDefaultTips'], - target: 'estimatingGasLimit', - }, - ], - }, - }, - estimatingGasLimit: { + estimatingGasLimitAndDefaultTips: { invoke: { - src: 'estimateGasLimit', + src: 'estimatingGasLimitAndDefaultTips', onDone: [ { cond: FetchMachine.hasError, @@ -110,7 +88,7 @@ export const sendMachine = createMachine( actions: [assignError()], }, { - actions: ['assignGasLimit'], + actions: ['assignGasLimitAndDefaultTips'], target: 'idle', }, ], @@ -165,12 +143,9 @@ export const sendMachine = createMachine( }, { actions: { - assignDefaultTips: assign((_ctx, ev) => ({ + assignGasLimitAndDefaultTips: assign((_ctx, ev) => ({ regularTip: ev.data.regularTip, fastTip: ev.data.fastTip, - error: undefined, - })), - assignGasLimit: assign((_ctx, ev) => ({ maxGasLimit: ev.data.maxGasLimit, error: undefined, })), @@ -187,23 +162,15 @@ export const sendMachine = createMachine( })), }, services: { - estimateDefaultTips: FetchMachine.create< + estimatingGasLimitAndDefaultTips: FetchMachine.create< never, - EstimateDefaultTipsReturn + EstimateGasLimitAndDefaultTipsReturn >({ showError: false, maxAttempts: 1, async fetch() { - const defaultTips = await TxService.estimateDefaultTips(); - return defaultTips; - }, - }), - estimateGasLimit: FetchMachine.create({ - showError: false, - maxAttempts: 1, - async fetch() { - const gasLimit = await TxService.estimateGasLimit(); - return gasLimit; + const estimated = await TxService.estimateGasLimitAndDefaultTips(); + return estimated; }, }), createTransactionRequest: FetchMachine.create< diff --git a/packages/app/src/systems/Transaction/pages/TxApprove/TxApprove.stories.tsx b/packages/app/src/systems/Transaction/pages/TxApprove/TxApprove.stories.tsx index a38c1bcec1..d357aa8de6 100644 --- a/packages/app/src/systems/Transaction/pages/TxApprove/TxApprove.stories.tsx +++ b/packages/app/src/systems/Transaction/pages/TxApprove/TxApprove.stories.tsx @@ -21,12 +21,13 @@ export default { const Template: StoryFn = (_args, { loaded }) => { const txRequest = useTransactionRequest(); - const { transactionRequest, network, address } = loaded || {}; + const { transactionRequest, network, account, address } = loaded || {}; // biome-ignore lint/correctness/useExhaustiveDependencies: useEffect(() => { txRequest.handlers.request({ address, + account, transactionRequest, providerUrl: network?.url, }); diff --git a/packages/app/src/systems/Transaction/services/transaction.tsx b/packages/app/src/systems/Transaction/services/transaction.tsx index 1ec72b9562..8bfd3b19ed 100644 --- a/packages/app/src/systems/Transaction/services/transaction.tsx +++ b/packages/app/src/systems/Transaction/services/transaction.tsx @@ -1,5 +1,5 @@ -import type { Account } from '@fuel-wallet/types'; -import type { TransactionRequest, WalletLocked } from 'fuels'; +import type { Account, AccountWithBalance } from '@fuel-wallet/types'; +import type { Provider, TransactionRequest, WalletLocked } from 'fuels'; import { clone } from 'ramda'; import { @@ -49,6 +49,7 @@ export type TxInputs = { origin?: string; title?: string; favIconUrl?: string; + account?: AccountWithBalance; skipCustomFee?: boolean; fees?: { baseFee?: BN; @@ -58,7 +59,8 @@ export type TxInputs = { }; }; send: { - address: string; + address?: string; + account?: Account; transactionRequest: TransactionRequest; providerUrl?: string; }; @@ -152,12 +154,16 @@ export class TxService { } static async send({ + account, address, transactionRequest, providerUrl = '', }: TxInputs['send']) { const provider = await createProvider(providerUrl); - const wallet = new WalletLockedCustom(address, provider); + const wallet = new WalletLockedCustom( + (account?.address?.toString() || address) as string, + provider + ); const txSent = await wallet.sendTransaction(transactionRequest); return txSent; @@ -374,24 +380,14 @@ export class TxService { }; } - static async estimateDefaultTips() { + static async estimateGasLimitAndDefaultTips() { const currentNetwork = await NetworkService.getSelectedNetwork(); const provider = await createProvider(currentNetwork?.url || ''); - - const { regularTip, fastTip } = await getCurrentTips(provider); - + const [{ regularTip, fastTip }, { consensusParameters }] = + await Promise.all([await getCurrentTips(provider), provider.getChain()]); return { regularTip: bn(regularTip), fastTip: bn(fastTip), - }; - } - - static async estimateGasLimit() { - const currentNetwork = await NetworkService.getSelectedNetwork(); - const provider = await createProvider(currentNetwork?.url || ''); - const consensusParameters = provider.getChain().consensusParameters; - - return { maxGasLimit: consensusParameters.txParameters.maxGasPerTx, }; } diff --git a/packages/app/src/systems/Transaction/utils/fee.ts b/packages/app/src/systems/Transaction/utils/fee.ts index fd66015cf5..8759b123d4 100644 --- a/packages/app/src/systems/Transaction/utils/fee.ts +++ b/packages/app/src/systems/Transaction/utils/fee.ts @@ -28,8 +28,9 @@ export async function calculateTotalFee({ export async function getCurrentTips(provider: Provider) { const DEFAULT_REGULAR_TIP = 0; const DEFAULT_FAST_TIP = 1000; - const blockWithTransactions = - await provider.getBlockWithTransactions('latest'); + const blockWithTransactions = await provider + ?.getBlockWithTransactions('latest') + .catch(() => null); if (!blockWithTransactions) { return { regularTip: DEFAULT_REGULAR_TIP, diff --git a/packages/playwright-utils/src/playwright-utils/button.ts b/packages/playwright-utils/src/playwright-utils/button.ts index 80439d22bf..7f4d0dc174 100644 --- a/packages/playwright-utils/src/playwright-utils/button.ts +++ b/packages/playwright-utils/src/playwright-utils/button.ts @@ -21,7 +21,9 @@ export function expectButtonToBeEnabled( return expect .poll(async () => await button.isEnabled(), { timeout: timeout ?? 7000, - intervals: intervals ?? [1000, 2000, 3000, 4000, 5000, 6000, 7000], + intervals: intervals ?? [ + 0, 500, 1000, 2000, 3000, 4000, 5000, 6000, 7000, + ], message: message ?? 'Button is not enabled', }) .toBeTruthy(); diff --git a/packages/playwright-utils/src/playwright-utils/fuelWalletTestHelper.ts b/packages/playwright-utils/src/playwright-utils/fuelWalletTestHelper.ts index 2708c74901..ad7dd9d9af 100644 --- a/packages/playwright-utils/src/playwright-utils/fuelWalletTestHelper.ts +++ b/packages/playwright-utils/src/playwright-utils/fuelWalletTestHelper.ts @@ -46,12 +46,13 @@ export class FuelWalletTestHelper { }) { const { url, chainId } = fuelProvider; const popupNotSignedUpPage = await context.newPage(); + const signupPagePromise = context.waitForEvent('page', { + predicate: (page) => page.url().includes('sign-up'), + }); await popupNotSignedUpPage.goto( `chrome-extension://${fuelExtensionId}/popup.html` ); - const signupPage = await context.waitForEvent('page', { - predicate: (page) => page.url().includes('sign-up'), - }); + const signupPage = await signupPagePromise; expect(signupPage.url()).toContain('sign-up'); await popupNotSignedUpPage.close(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d6ef73dc5..568332b2a3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -35,6 +35,7 @@ overrides: elliptic@<6.6.0: '>=6.6.0' cross-spawn@<7.0.5: '>=7.0.5' nanoid@<3.3.8: 3.3.8 + store2@<2.14.4: '>=2.14.4' importers: @@ -161,13 +162,13 @@ importers: version: 18.3.0 '@vitejs/plugin-react': specifier: 4.2.1 - version: 4.2.1(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 4.2.1(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) typescript: specifier: 5.2.2 version: 5.2.2 vite: - specifier: 6.0.3 - version: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + specifier: 6.0.8 + version: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) packages/app: dependencies: @@ -281,7 +282,7 @@ importers: version: 1.0.0 vite-plugin-markdown: specifier: 2.2.0 - version: 2.2.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 2.2.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) xstate: specifier: 4.38.2 version: 4.38.2 @@ -342,7 +343,7 @@ importers: version: 7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) '@storybook/react-vite': specifier: 7.4.6 - version: 7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) '@storybook/react-webpack5': specifier: 7.4.6 version: 7.4.6(@babel/core@7.24.0)(@swc/core@1.3.92(@swc/helpers@0.5.11))(@swc/helpers@0.5.11)(@types/react-dom@18.3.0)(@types/react@18.3.3)(esbuild@0.18.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@2.19.0)(typescript@5.2.2)(webpack-hot-middleware@2.25.4) @@ -378,7 +379,7 @@ importers: version: 6.1.7 '@vitejs/plugin-react': specifier: 4.1.0 - version: 4.1.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 4.1.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) '@xstate/inspect': specifier: 0.8.0 version: 0.8.0(@types/ws@8.5.12)(ws@8.18.0(bufferutil@4.0.8)(utf-8-validate@5.0.10))(xstate@4.38.2) @@ -410,17 +411,17 @@ importers: specifier: 5.2.2 version: 5.2.2 vite: - specifier: 6.0.3 - version: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + specifier: 6.0.8 + version: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) vite-plugin-clean: specifier: 1.0.0 version: 1.0.0 vite-plugin-static-copy: specifier: 2.2.0 - version: 2.2.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 2.2.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) vite-tsconfig-paths: specifier: 5.1.4 - version: 5.1.4(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + version: 5.1.4(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) whatwg-fetch: specifier: 3.6.20 version: 3.6.20 @@ -2165,6 +2166,12 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.24.2': + resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -2177,6 +2184,12 @@ packages: cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.24.2': + resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -2189,6 +2202,12 @@ packages: cpu: [arm] os: [android] + '@esbuild/android-arm@0.24.2': + resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -2201,6 +2220,12 @@ packages: cpu: [x64] os: [android] + '@esbuild/android-x64@0.24.2': + resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -2213,6 +2238,12 @@ packages: cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.24.2': + resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -2225,6 +2256,12 @@ packages: cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.24.2': + resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -2237,6 +2274,12 @@ packages: cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.24.2': + resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -2249,6 +2292,12 @@ packages: cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.24.2': + resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -2261,6 +2310,12 @@ packages: cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.24.2': + resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -2273,6 +2328,12 @@ packages: cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.24.2': + resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -2285,6 +2346,12 @@ packages: cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.24.2': + resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.14.54': resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==} engines: {node: '>=12'} @@ -2303,6 +2370,12 @@ packages: cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.24.2': + resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -2315,6 +2388,12 @@ packages: cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.24.2': + resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -2327,6 +2406,12 @@ packages: cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.24.2': + resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -2339,6 +2424,12 @@ packages: cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.24.2': + resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -2351,6 +2442,12 @@ packages: cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.24.2': + resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -2363,6 +2460,18 @@ packages: cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.24.2': + resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.24.2': + resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -2375,12 +2484,24 @@ packages: cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.24.2': + resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.24.0': resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.24.2': + resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -2393,6 +2514,12 @@ packages: cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.24.2': + resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.18.20': resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -2405,6 +2532,12 @@ packages: cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.24.2': + resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -2417,6 +2550,12 @@ packages: cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.24.2': + resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -2429,6 +2568,12 @@ packages: cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.24.2': + resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -2441,6 +2586,12 @@ packages: cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.24.2': + resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8118,6 +8269,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.24.2: + resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -12078,8 +12234,8 @@ packages: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} - store2@2.14.2: - resolution: {integrity: sha512-siT1RiqlfQnGqgT/YzXVUNsom9S0H1OX+dpdGN1xkyYATo4I6sep5NmsRD/40s3IIOvlCq6akxkqG82urIZW1w==} + store2@2.14.4: + resolution: {integrity: sha512-srTItn1GOvyvOycgxjAnPA63FZNwy0PTyUBFMHRM+hVFltAeoh0LmNBz9SZqUS9mMqGk8rfyWyXn3GH5ReJ8Zw==} storybook-addon-react-router-v6@2.0.7: resolution: {integrity: sha512-vky9WXG84fQjwx55KKFQdhyUC5AnfsGJSoYx/yaJi2q/oTDcCTkcwpxlcrSKpTpNtVjsFNnaS3cuWXX+Sfc8Vw==} @@ -13205,8 +13361,8 @@ packages: terser: optional: true - vite@6.0.3: - resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} + vite@6.0.8: + resolution: {integrity: sha512-rJmB+6m3Qmo5nssFmm6hbSvaCS+5tH/iuTJYeHEOHMwqu/DPrjjBs1rlecCo4D0qy5xq506hMpkKx6pKaudUxA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -17246,66 +17402,99 @@ snapshots: '@esbuild/aix-ppc64@0.24.0': optional: true + '@esbuild/aix-ppc64@0.24.2': + optional: true + '@esbuild/android-arm64@0.18.20': optional: true '@esbuild/android-arm64@0.24.0': optional: true + '@esbuild/android-arm64@0.24.2': + optional: true + '@esbuild/android-arm@0.18.20': optional: true '@esbuild/android-arm@0.24.0': optional: true + '@esbuild/android-arm@0.24.2': + optional: true + '@esbuild/android-x64@0.18.20': optional: true '@esbuild/android-x64@0.24.0': optional: true + '@esbuild/android-x64@0.24.2': + optional: true + '@esbuild/darwin-arm64@0.18.20': optional: true '@esbuild/darwin-arm64@0.24.0': optional: true + '@esbuild/darwin-arm64@0.24.2': + optional: true + '@esbuild/darwin-x64@0.18.20': optional: true '@esbuild/darwin-x64@0.24.0': optional: true + '@esbuild/darwin-x64@0.24.2': + optional: true + '@esbuild/freebsd-arm64@0.18.20': optional: true '@esbuild/freebsd-arm64@0.24.0': optional: true + '@esbuild/freebsd-arm64@0.24.2': + optional: true + '@esbuild/freebsd-x64@0.18.20': optional: true '@esbuild/freebsd-x64@0.24.0': optional: true + '@esbuild/freebsd-x64@0.24.2': + optional: true + '@esbuild/linux-arm64@0.18.20': optional: true '@esbuild/linux-arm64@0.24.0': optional: true + '@esbuild/linux-arm64@0.24.2': + optional: true + '@esbuild/linux-arm@0.18.20': optional: true '@esbuild/linux-arm@0.24.0': optional: true + '@esbuild/linux-arm@0.24.2': + optional: true + '@esbuild/linux-ia32@0.18.20': optional: true '@esbuild/linux-ia32@0.24.0': optional: true + '@esbuild/linux-ia32@0.24.2': + optional: true + '@esbuild/linux-loong64@0.14.54': optional: true @@ -17315,75 +17504,117 @@ snapshots: '@esbuild/linux-loong64@0.24.0': optional: true + '@esbuild/linux-loong64@0.24.2': + optional: true + '@esbuild/linux-mips64el@0.18.20': optional: true '@esbuild/linux-mips64el@0.24.0': optional: true + '@esbuild/linux-mips64el@0.24.2': + optional: true + '@esbuild/linux-ppc64@0.18.20': optional: true '@esbuild/linux-ppc64@0.24.0': optional: true + '@esbuild/linux-ppc64@0.24.2': + optional: true + '@esbuild/linux-riscv64@0.18.20': optional: true '@esbuild/linux-riscv64@0.24.0': optional: true + '@esbuild/linux-riscv64@0.24.2': + optional: true + '@esbuild/linux-s390x@0.18.20': optional: true '@esbuild/linux-s390x@0.24.0': optional: true + '@esbuild/linux-s390x@0.24.2': + optional: true + '@esbuild/linux-x64@0.18.20': optional: true '@esbuild/linux-x64@0.24.0': optional: true + '@esbuild/linux-x64@0.24.2': + optional: true + + '@esbuild/netbsd-arm64@0.24.2': + optional: true + '@esbuild/netbsd-x64@0.18.20': optional: true '@esbuild/netbsd-x64@0.24.0': optional: true + '@esbuild/netbsd-x64@0.24.2': + optional: true + '@esbuild/openbsd-arm64@0.24.0': optional: true + '@esbuild/openbsd-arm64@0.24.2': + optional: true + '@esbuild/openbsd-x64@0.18.20': optional: true '@esbuild/openbsd-x64@0.24.0': optional: true + '@esbuild/openbsd-x64@0.24.2': + optional: true + '@esbuild/sunos-x64@0.18.20': optional: true '@esbuild/sunos-x64@0.24.0': optional: true + '@esbuild/sunos-x64@0.24.2': + optional: true + '@esbuild/win32-arm64@0.18.20': optional: true '@esbuild/win32-arm64@0.24.0': optional: true + '@esbuild/win32-arm64@0.24.2': + optional: true + '@esbuild/win32-ia32@0.18.20': optional: true '@esbuild/win32-ia32@0.24.0': optional: true + '@esbuild/win32-ia32@0.24.2': + optional: true + '@esbuild/win32-x64@0.18.20': optional: true '@esbuild/win32-x64@0.24.0': optional: true + '@esbuild/win32-x64@0.24.2': + optional: true + '@eslint-community/eslint-utils@4.4.0(eslint@8.51.0)': dependencies: eslint: 8.51.0 @@ -18338,13 +18569,13 @@ snapshots: - ioredis - utf-8-validate - '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.2.2) - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) optionalDependencies: typescript: 5.2.2 @@ -21814,7 +22045,7 @@ snapshots: - encoding - supports-color - '@storybook/builder-vite@7.4.6(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@storybook/builder-vite@7.4.6(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@storybook/channels': 7.4.6 '@storybook/client-logger': 7.4.6 @@ -21835,7 +22066,7 @@ snapshots: remark-external-links: 8.0.0 remark-slug: 6.1.0 rollup: 3.29.5 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) optionalDependencies: typescript: 5.2.2 transitivePeerDependencies: @@ -22184,7 +22415,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) semver: 7.5.4 - store2: 2.14.2 + store2: 2.14.4 telejson: 7.2.0 ts-dedent: 2.2.0 @@ -22271,19 +22502,19 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/react-vite@7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@storybook/react-vite@7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) '@rollup/pluginutils': 5.0.2 - '@storybook/builder-vite': 7.4.6(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + '@storybook/builder-vite': 7.4.6(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) '@storybook/react': 7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.2.2) - '@vitejs/plugin-react': 3.1.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) + '@vitejs/plugin-react': 3.1.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)) ast-types: 0.14.2 magic-string: 0.30.2 react: 18.3.1 react-docgen: 6.0.0-alpha.3 react-dom: 18.3.1(react@18.3.1) - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - '@preact/preset-vite' - encoding @@ -23099,14 +23330,14 @@ snapshots: '@typescript-eslint/types': 6.7.5 eslint-visitor-keys: 3.4.3 - '@vitejs/plugin-react@3.1.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@vitejs/plugin-react@3.1.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@babel/core': 7.24.0 '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.24.0) '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.24.0) magic-string: 0.27.0 react-refresh: 0.14.0 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -23121,25 +23352,25 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.1.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@vitejs/plugin-react@4.1.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@babel/core': 7.24.0 '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.24.0) '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.24.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.2.1(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': + '@vitejs/plugin-react@4.2.1(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1))': dependencies: '@babel/core': 7.24.0 '@babel/plugin-transform-react-jsx-self': 7.23.3(@babel/core@7.24.0) '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.24.0) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - supports-color @@ -26813,6 +27044,34 @@ snapshots: '@esbuild/win32-ia32': 0.24.0 '@esbuild/win32-x64': 0.24.0 + esbuild@0.24.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.2 + '@esbuild/android-arm': 0.24.2 + '@esbuild/android-arm64': 0.24.2 + '@esbuild/android-x64': 0.24.2 + '@esbuild/darwin-arm64': 0.24.2 + '@esbuild/darwin-x64': 0.24.2 + '@esbuild/freebsd-arm64': 0.24.2 + '@esbuild/freebsd-x64': 0.24.2 + '@esbuild/linux-arm': 0.24.2 + '@esbuild/linux-arm64': 0.24.2 + '@esbuild/linux-ia32': 0.24.2 + '@esbuild/linux-loong64': 0.24.2 + '@esbuild/linux-mips64el': 0.24.2 + '@esbuild/linux-ppc64': 0.24.2 + '@esbuild/linux-riscv64': 0.24.2 + '@esbuild/linux-s390x': 0.24.2 + '@esbuild/linux-x64': 0.24.2 + '@esbuild/netbsd-arm64': 0.24.2 + '@esbuild/netbsd-x64': 0.24.2 + '@esbuild/openbsd-arm64': 0.24.2 + '@esbuild/openbsd-x64': 0.24.2 + '@esbuild/sunos-x64': 0.24.2 + '@esbuild/win32-arm64': 0.24.2 + '@esbuild/win32-ia32': 0.24.2 + '@esbuild/win32-x64': 0.24.2 + escalade@3.1.1: {} escalade@3.2.0: {} @@ -32272,7 +32531,7 @@ snapshots: dependencies: internal-slot: 1.0.5 - store2@2.14.2: {} + store2@2.14.4: {} storybook-addon-react-router-v6@2.0.7(@storybook/blocks@7.4.6(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/channels@7.4.6)(@storybook/components@7.4.6(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/core-events@7.4.6)(@storybook/manager-api@7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/preview-api@7.4.6)(@storybook/theming@7.4.6(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1): dependencies: @@ -33365,29 +33624,29 @@ snapshots: - sass - stylus - vite-plugin-markdown@2.2.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): + vite-plugin-markdown@2.2.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): dependencies: domhandler: 4.3.1 front-matter: 4.0.2 htmlparser2: 6.1.0 markdown-it: 12.3.2 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) - vite-plugin-static-copy@2.2.0(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): + vite-plugin-static-copy@2.2.0(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): dependencies: chokidar: 3.6.0 fast-glob: 3.3.2 fs-extra: 11.1.1 picocolors: 1.1.1 - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) - vite-tsconfig-paths@5.1.4(typescript@5.2.2)(vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): + vite-tsconfig-paths@5.1.4(typescript@5.2.2)(vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1)): dependencies: debug: 4.4.0 globrex: 0.1.2 tsconfck: 3.1.4(typescript@5.2.2) optionalDependencies: - vite: 6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) + vite: 6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1) transitivePeerDependencies: - supports-color - typescript @@ -33411,9 +33670,9 @@ snapshots: fsevents: 2.3.3 terser: 5.37.0 - vite@6.0.3(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1): + vite@6.0.8(@types/node@22.10.1)(jiti@2.3.3)(terser@5.37.0)(yaml@2.6.1): dependencies: - esbuild: 0.24.0 + esbuild: 0.24.2 postcss: 8.4.49 rollup: 4.28.1 optionalDependencies: