From bd2844b749357167c5b1e6f947dbca2b841bcf59 Mon Sep 17 00:00:00 2001 From: katspaugh Date: Thu, 9 Nov 2023 17:32:58 +0100 Subject: [PATCH 01/10] Feat: track tx creations and safe views --- .../tx-flow/flows/AddOwner/ReviewOwner.tsx | 2 + .../ChangeThreshold/ReviewChangeThreshold.tsx | 2 + .../tx-flow/flows/ConfirmBatch/index.tsx | 11 +++++- .../NewSpendingLimit/ReviewSpendingLimit.tsx | 3 ++ .../flows/NftTransfer/ReviewNftBatch.tsx | 11 +++++- .../tx-flow/flows/RejectTx/RejectTx.tsx | 8 +++- .../flows/RemoveGuard/ReviewRemoveGuard.tsx | 10 +++-- .../flows/RemoveModule/ReviewRemoveModule.tsx | 10 +++-- .../flows/RemoveOwner/ReviewRemoveOwner.tsx | 2 + .../RemoveSpendingLimit.tsx | 10 +++-- .../flows/SafeAppsTx/ReviewSafeAppsTx.tsx | 7 +++- .../tx-flow/flows/SafeAppsTx/index.tsx | 10 ++++- .../ReviewSignMessageOnChain.tsx | 5 +++ .../flows/TokenTransfer/ReviewTokenTx.tsx | 18 +++++++-- .../flows/UpdateSafe/UpdateSafeReview.tsx | 8 +++- src/hooks/messages/useSafeMsgTracking.ts | 5 +++ src/services/analytics/events/overview.ts | 4 ++ src/services/analytics/events/transactions.ts | 38 +++++++++++++++++++ src/services/analytics/useGtm.ts | 6 +++ .../useSafeWalletProvider.tsx | 23 +++++------ src/services/tx/tx-sender/dispatch.ts | 3 +- 21 files changed, 157 insertions(+), 39 deletions(-) create mode 100644 src/services/analytics/events/transactions.ts diff --git a/src/components/tx-flow/flows/AddOwner/ReviewOwner.tsx b/src/components/tx-flow/flows/AddOwner/ReviewOwner.tsx index d2c18301b3..ba1aa23212 100644 --- a/src/components/tx-flow/flows/AddOwner/ReviewOwner.tsx +++ b/src/components/tx-flow/flows/AddOwner/ReviewOwner.tsx @@ -14,6 +14,7 @@ import PlusIcon from '@/public/images/common/plus.svg' import MinusIcon from '@/public/images/common/minus.svg' import EthHashInfo from '@/components/common/EthHashInfo' import commonCss from '@/components/tx-flow/common/styles.module.css' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' export const ReviewOwner = ({ params }: { params: AddOwnerFlowProps | ReplaceOwnerFlowProps }) => { const dispatch = useAppDispatch() @@ -49,6 +50,7 @@ export const ReviewOwner = ({ params }: { params: AddOwnerFlowProps | ReplaceOwn trackEvent({ ...SETTINGS_EVENTS.SETUP.THRESHOLD, label: safe.threshold }) trackEvent({ ...SETTINGS_EVENTS.SETUP.OWNERS, label: safe.owners.length }) + trackEvent({ ...TX_EVENTS.CREATE, label: params.removedOwner ? TX_TYPES.owner_swap : TX_TYPES.owner_add }) } return ( diff --git a/src/components/tx-flow/flows/ChangeThreshold/ReviewChangeThreshold.tsx b/src/components/tx-flow/flows/ChangeThreshold/ReviewChangeThreshold.tsx index 6c1aa11d61..e9e7068a25 100644 --- a/src/components/tx-flow/flows/ChangeThreshold/ReviewChangeThreshold.tsx +++ b/src/components/tx-flow/flows/ChangeThreshold/ReviewChangeThreshold.tsx @@ -8,6 +8,7 @@ import SignOrExecuteForm from '@/components/tx/SignOrExecuteForm' import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' import { ChangeThresholdFlowFieldNames } from '@/components/tx-flow/flows/ChangeThreshold' import type { ChangeThresholdFlowProps } from '@/components/tx-flow/flows/ChangeThreshold' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' import commonCss from '@/components/tx-flow/common/styles.module.css' @@ -24,6 +25,7 @@ const ReviewChangeThreshold = ({ params }: { params: ChangeThresholdFlowProps }) const onChangeThreshold = () => { trackEvent({ ...SETTINGS_EVENTS.SETUP.OWNERS, label: safe.owners.length }) trackEvent({ ...SETTINGS_EVENTS.SETUP.THRESHOLD, label: newThreshold }) + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.owner_threshold_change }) } return ( diff --git a/src/components/tx-flow/flows/ConfirmBatch/index.tsx b/src/components/tx-flow/flows/ConfirmBatch/index.tsx index 27e53d211f..daf1ae5580 100644 --- a/src/components/tx-flow/flows/ConfirmBatch/index.tsx +++ b/src/components/tx-flow/flows/ConfirmBatch/index.tsx @@ -1,4 +1,4 @@ -import { type ReactElement, useContext, useEffect } from 'react' +import { type ReactElement, useContext, useEffect, useCallback } from 'react' import { type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk' import SignOrExecuteForm from '@/components/tx/SignOrExecuteForm' import { createMultiSendCallOnlyTx } from '@/services/tx/tx-sender' @@ -9,6 +9,8 @@ import TxLayout from '../../common/TxLayout' import BatchIcon from '@/public/images/common/batch.svg' import { useDraftBatch } from '@/hooks/useDraftBatch' import BatchTxList from '@/components/batch/BatchSidebar/BatchTxList' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' +import { trackEvent } from '@/services/analytics' type ConfirmBatchProps = { onSubmit: () => void @@ -32,8 +34,13 @@ const ConfirmBatch = ({ onSubmit }: ConfirmBatchProps): ReactElement => { createMultiSendCallOnlyTx(calls).then(setSafeTx).catch(setSafeTxError) }, [batchTxs, setSafeTx, setSafeTxError]) + const onTxSubmit = useCallback(() => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.batch }) + onSubmit() + }, [onSubmit]) + return ( - + ) diff --git a/src/components/tx-flow/flows/NewSpendingLimit/ReviewSpendingLimit.tsx b/src/components/tx-flow/flows/NewSpendingLimit/ReviewSpendingLimit.tsx index 5ab7d1a2a2..15cb0b27e0 100644 --- a/src/components/tx-flow/flows/NewSpendingLimit/ReviewSpendingLimit.tsx +++ b/src/components/tx-flow/flows/NewSpendingLimit/ReviewSpendingLimit.tsx @@ -17,6 +17,7 @@ import type { SpendingLimitState } from '@/store/spendingLimitsSlice' import type { NewSpendingLimitFlowProps } from '.' import EthHashInfo from '@/components/common/EthHashInfo' import { SafeTxContext } from '../../SafeTxProvider' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' export const ReviewSpendingLimit = ({ params }: { params: NewSpendingLimitFlowProps }) => { const [existingSpendingLimit, setExistingSpendingLimit] = useState() @@ -53,6 +54,8 @@ export const ReviewSpendingLimit = ({ params }: { params: NewSpendingLimitFlowPr ...SETTINGS_EVENTS.SPENDING_LIMIT.RESET_PERIOD, label: resetTime, }) + + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.spending_limit_add }) } const existingAmount = existingSpendingLimit diff --git a/src/components/tx-flow/flows/NftTransfer/ReviewNftBatch.tsx b/src/components/tx-flow/flows/NftTransfer/ReviewNftBatch.tsx index c9024eb02f..baa97927fb 100644 --- a/src/components/tx-flow/flows/NftTransfer/ReviewNftBatch.tsx +++ b/src/components/tx-flow/flows/NftTransfer/ReviewNftBatch.tsx @@ -1,4 +1,4 @@ -import { type ReactElement, useEffect, useContext } from 'react' +import { type ReactElement, useEffect, useContext, useCallback } from 'react' import { Grid, Typography } from '@mui/material' import SendToBlock from '@/components/tx-flow/flows/TokenTransfer/SendToBlock' import { createNftTransferParams } from '@/services/tx/tokenTransferParams' @@ -8,6 +8,8 @@ import { createMultiSendCallOnlyTx, createTx } from '@/services/tx/tx-sender' import SignOrExecuteForm from '@/components/tx/SignOrExecuteForm' import { SafeTxContext } from '../../SafeTxProvider' import { NftItems } from '@/components/tx-flow/flows/NftTransfer/SendNftBatch' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' +import { trackEvent } from '@/services/analytics' type ReviewNftBatchProps = { params: NftTransferParams @@ -38,8 +40,13 @@ const ReviewNftBatch = ({ params, onSubmit, txNonce }: ReviewNftBatchProps): Rea promise.then(setSafeTx).catch(setSafeTxError) }, [safeAddress, params, setSafeTx, setSafeTxError]) + const onTxSubmit = useCallback(() => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.transfer_nft }) + onSubmit() + }, [onSubmit]) + return ( - + diff --git a/src/components/tx-flow/flows/RejectTx/RejectTx.tsx b/src/components/tx-flow/flows/RejectTx/RejectTx.tsx index 91db5ae55f..24b2f66251 100644 --- a/src/components/tx-flow/flows/RejectTx/RejectTx.tsx +++ b/src/components/tx-flow/flows/RejectTx/RejectTx.tsx @@ -4,11 +4,17 @@ import SignOrExecuteForm from '@/components/tx/SignOrExecuteForm' import { createRejectTx } from '@/services/tx/tx-sender' import { useContext, useEffect } from 'react' import { SafeTxContext } from '../../SafeTxProvider' +import { trackEvent } from '@/services/analytics' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' type RejectTxProps = { txNonce: number } +const onSubmit = () => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.rejection }) +} + const RejectTx = ({ txNonce }: RejectTxProps): ReactElement => { const { setSafeTx, setSafeTxError, setNonce } = useContext(SafeTxContext) @@ -19,7 +25,7 @@ const RejectTx = ({ txNonce }: RejectTxProps): ReactElement => { }, [txNonce, setNonce, setSafeTx, setSafeTxError]) return ( - {}} isBatchable={false}> + To reject the transaction, a separate rejection transaction will be created to replace the original one. diff --git a/src/components/tx-flow/flows/RemoveGuard/ReviewRemoveGuard.tsx b/src/components/tx-flow/flows/RemoveGuard/ReviewRemoveGuard.tsx index e2155eb66e..6ac5920984 100644 --- a/src/components/tx-flow/flows/RemoveGuard/ReviewRemoveGuard.tsx +++ b/src/components/tx-flow/flows/RemoveGuard/ReviewRemoveGuard.tsx @@ -7,6 +7,12 @@ import { trackEvent, SETTINGS_EVENTS } from '@/services/analytics' import { createRemoveGuardTx } from '@/services/tx/tx-sender' import { type RemoveGuardFlowProps } from '.' import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' + +const onFormSubmit = () => { + trackEvent(SETTINGS_EVENTS.MODULES.REMOVE_GUARD) + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.guard_remove }) +} export const ReviewRemoveGuard = ({ params }: { params: RemoveGuardFlowProps }) => { const { setSafeTx, safeTxError, setSafeTxError } = useContext(SafeTxContext) @@ -21,10 +27,6 @@ export const ReviewRemoveGuard = ({ params }: { params: RemoveGuardFlowProps }) } }, [safeTxError]) - const onFormSubmit = () => { - trackEvent(SETTINGS_EVENTS.MODULES.REMOVE_GUARD) - } - return ( ({ color: palette.primary.light })}>Transaction guard diff --git a/src/components/tx-flow/flows/RemoveModule/ReviewRemoveModule.tsx b/src/components/tx-flow/flows/RemoveModule/ReviewRemoveModule.tsx index 01a11b223d..d6fb40da21 100644 --- a/src/components/tx-flow/flows/RemoveModule/ReviewRemoveModule.tsx +++ b/src/components/tx-flow/flows/RemoveModule/ReviewRemoveModule.tsx @@ -7,6 +7,12 @@ import { createRemoveModuleTx } from '@/services/tx/tx-sender' import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' import { type RemoveModuleFlowProps } from '.' import EthHashInfo from '@/components/common/EthHashInfo' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' + +const onFormSubmit = () => { + trackEvent(SETTINGS_EVENTS.MODULES.REMOVE_MODULE) + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.module_remove }) +} export const ReviewRemoveModule = ({ params }: { params: RemoveModuleFlowProps }) => { const { setSafeTx, safeTxError, setSafeTxError } = useContext(SafeTxContext) @@ -21,10 +27,6 @@ export const ReviewRemoveModule = ({ params }: { params: RemoveModuleFlowProps } } }, [safeTxError]) - const onFormSubmit = () => { - trackEvent(SETTINGS_EVENTS.MODULES.REMOVE_MODULE) - } - return ( diff --git a/src/components/tx-flow/flows/RemoveOwner/ReviewRemoveOwner.tsx b/src/components/tx-flow/flows/RemoveOwner/ReviewRemoveOwner.tsx index 676a2b1561..59c5498744 100644 --- a/src/components/tx-flow/flows/RemoveOwner/ReviewRemoveOwner.tsx +++ b/src/components/tx-flow/flows/RemoveOwner/ReviewRemoveOwner.tsx @@ -11,6 +11,7 @@ import MinusIcon from '@/public/images/common/minus.svg' import { SafeTxContext } from '../../SafeTxProvider' import type { RemoveOwnerFlowProps } from '.' import EthHashInfo from '@/components/common/EthHashInfo' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' import commonCss from '@/components/tx-flow/common/styles.module.css' @@ -29,6 +30,7 @@ export const ReviewRemoveOwner = ({ params }: { params: RemoveOwnerFlowProps }): const onFormSubmit = () => { trackEvent({ ...SETTINGS_EVENTS.SETUP.THRESHOLD, label: safe.threshold }) trackEvent({ ...SETTINGS_EVENTS.SETUP.OWNERS, label: safe.owners.length }) + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.owner_remove }) } return ( diff --git a/src/components/tx-flow/flows/RemoveSpendingLimit/RemoveSpendingLimit.tsx b/src/components/tx-flow/flows/RemoveSpendingLimit/RemoveSpendingLimit.tsx index df046f6cc6..087cf68705 100644 --- a/src/components/tx-flow/flows/RemoveSpendingLimit/RemoveSpendingLimit.tsx +++ b/src/components/tx-flow/flows/RemoveSpendingLimit/RemoveSpendingLimit.tsx @@ -13,6 +13,12 @@ import SendAmountBlock from '@/components/tx-flow/flows/TokenTransfer/SendAmount import { safeFormatUnits } from '@/utils/formatters' import SpendingLimitLabel from '@/components/common/SpendingLimitLabel' import { createTx } from '@/services/tx/tx-sender' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' + +const onFormSubmit = () => { + trackEvent(SETTINGS_EVENTS.SPENDING_LIMIT.LIMIT_REMOVED) + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.spending_limit_remove }) +} export const RemoveSpendingLimit = ({ params }: { params: SpendingLimitState }) => { const { setSafeTx, setSafeTxError } = useContext(SafeTxContext) @@ -42,10 +48,6 @@ export const RemoveSpendingLimit = ({ params }: { params: SpendingLimitState }) createTx(txParams).then(setSafeTx).catch(setSafeTxError) }, [chainId, params.beneficiary, params.token, setSafeTx, setSafeTxError]) - const onFormSubmit = () => { - trackEvent(SETTINGS_EVENTS.SPENDING_LIMIT.LIMIT_REMOVED) - } - return ( {token && ( diff --git a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx index 4580b6021f..efc96834a3 100644 --- a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx +++ b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx @@ -20,10 +20,12 @@ import { asError } from '@/services/exceptions/utils' type ReviewSafeAppsTxProps = { safeAppsTx: SafeAppsTxParams + onSubmit?: (txId: string, safeTxHash: string) => void } const ReviewSafeAppsTx = ({ safeAppsTx: { txs, requestId, params, appId, app }, + onSubmit, }: ReviewSafeAppsTxProps): ReactElement => { const { safe } = useSafeInfo() const onboard = useOnboard() @@ -54,11 +56,14 @@ const ReviewSafeAppsTx = ({ if (!safeTx || !onboard) return trackSafeAppTxCount(Number(appId)) + let safeTxHash = '' try { - await dispatchSafeAppsTx(safeTx, requestId, onboard, safe.chainId, txId) + safeTxHash = await dispatchSafeAppsTx(safeTx, requestId, onboard, safe.chainId, txId) } catch (error) { setSafeTxError(asError(error)) } + + onSubmit?.(txId, safeTxHash) } const origin = useMemo(() => getTxOrigin(app), [app]) diff --git a/src/components/tx-flow/flows/SafeAppsTx/index.tsx b/src/components/tx-flow/flows/SafeAppsTx/index.tsx index a5f6bdf329..297d13f569 100644 --- a/src/components/tx-flow/flows/SafeAppsTx/index.tsx +++ b/src/components/tx-flow/flows/SafeAppsTx/index.tsx @@ -12,14 +12,20 @@ export type SafeAppsTxParams = { params?: SendTransactionRequestParams } -const SafeAppsTxFlow = ({ data }: { data: SafeAppsTxParams }) => { +const SafeAppsTxFlow = ({ + data, + onSubmit, +}: { + data: SafeAppsTxParams + onSubmit?: (txId: string, safeTxHash: string) => void +}) => { return ( } step={0} > - + ) } diff --git a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx index ab535b7ede..378b296979 100644 --- a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx +++ b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx @@ -25,6 +25,8 @@ import useHighlightHiddenTab from '@/hooks/useHighlightHiddenTab' import { type SafeAppData } from '@safe-global/safe-gateway-typescript-sdk' import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' import { asError } from '@/services/exceptions/utils' +import { trackEvent } from '@/services/analytics' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' export type SignMessageOnChainProps = { app?: SafeAppData @@ -98,6 +100,9 @@ const ReviewSignMessageOnChain = ({ message, method, requestId }: SignMessageOnC const handleSubmit = async () => { if (!safeTx || !onboard) return + + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.message }) + try { await dispatchSafeAppsTx(safeTx, requestId, onboard, safe.chainId) } catch (error) { diff --git a/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx b/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx index 98e2535f31..4b13a65cc3 100644 --- a/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx +++ b/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx @@ -1,7 +1,9 @@ -import { type ReactElement } from 'react' +import { useCallback, type ReactElement } from 'react' import { type TokenTransferParams, TokenTransferType } from '@/components/tx-flow/flows/TokenTransfer/index' import ReviewTokenTransfer from '@/components/tx-flow/flows/TokenTransfer/ReviewTokenTransfer' import ReviewSpendingLimitTx from '@/components/tx-flow/flows/TokenTransfer/ReviewSpendingLimitTx' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' +import { trackEvent } from '@/services/analytics' // TODO: Split this into separate flows const ReviewTokenTx = ({ @@ -15,10 +17,20 @@ const ReviewTokenTx = ({ }): ReactElement => { const isSpendingLimitTx = params.type === TokenTransferType.spendingLimit + const onTxSubmit = useCallback(() => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.transfer_token }) + onSubmit() + }, [onSubmit]) + + const onSpendingLimitTxSubmit = useCallback(() => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.spending_limit_transfer }) + onSubmit() + }, [onSubmit]) + return isSpendingLimitTx ? ( - + ) : ( - + ) } diff --git a/src/components/tx-flow/flows/UpdateSafe/UpdateSafeReview.tsx b/src/components/tx-flow/flows/UpdateSafe/UpdateSafeReview.tsx index 62239c188f..8e3f7e7d7f 100644 --- a/src/components/tx-flow/flows/UpdateSafe/UpdateSafeReview.tsx +++ b/src/components/tx-flow/flows/UpdateSafe/UpdateSafeReview.tsx @@ -9,6 +9,12 @@ import { createUpdateSafeTxs } from '@/services/tx/safeUpdateParams' import { createMultiSendCallOnlyTx } from '@/services/tx/tx-sender' import { SafeTxContext } from '../../SafeTxProvider' import SignOrExecuteForm from '@/components/tx/SignOrExecuteForm' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' +import { trackEvent } from '@/services/analytics' + +const onSubmit = () => { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.safe_update }) +} export const UpdateSafeReview = () => { const { safe, safeLoaded } = useSafeInfo() @@ -25,7 +31,7 @@ export const UpdateSafeReview = () => { }, [chain, safe, safeLoaded, setNonce, setSafeTx, setSafeTxError]) return ( - null}> + Update now to take advantage of new features and the highest security standards available. diff --git a/src/hooks/messages/useSafeMsgTracking.ts b/src/hooks/messages/useSafeMsgTracking.ts index 45b3bf6fae..8e1131ccbf 100644 --- a/src/hooks/messages/useSafeMsgTracking.ts +++ b/src/hooks/messages/useSafeMsgTracking.ts @@ -2,6 +2,7 @@ import { useEffect } from 'react' import { trackEvent, WALLET_EVENTS } from '@/services/analytics' import { SafeMsgEvent, safeMsgSubscribe } from '@/services/safe-messages/safeMsgEvents' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' const safeMsgEvents = { [SafeMsgEvent.PROPOSE]: WALLET_EVENTS.SIGN_MESSAGE, @@ -13,6 +14,10 @@ export const useSafeMsgTracking = (): void => { const unsubFns = Object.entries(safeMsgEvents).map(([safeMsgEvent, analyticsEvent]) => safeMsgSubscribe(safeMsgEvent as SafeMsgEvent, () => { trackEvent(analyticsEvent) + + if (analyticsEvent === WALLET_EVENTS.SIGN_MESSAGE) { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.message }) + } }), ) diff --git a/src/services/analytics/events/overview.ts b/src/services/analytics/events/overview.ts index 369dad15eb..a1a408c469 100644 --- a/src/services/analytics/events/overview.ts +++ b/src/services/analytics/events/overview.ts @@ -96,4 +96,8 @@ export const OVERVIEW_EVENTS = { action: 'Click on SEP5 allocation button', category: OVERVIEW_CATEGORY, }, + SAFE_VIEWED: { + action: 'Safe viewed', + category: OVERVIEW_CATEGORY, + }, } diff --git a/src/services/analytics/events/transactions.ts b/src/services/analytics/events/transactions.ts new file mode 100644 index 0000000000..df6503e367 --- /dev/null +++ b/src/services/analytics/events/transactions.ts @@ -0,0 +1,38 @@ +export enum TX_TYPES { + // Owner txs + owner_add = 'owner_add', + owner_remove = 'owner_remove', + owner_swap = 'owner_swap', + owner_threshold_change = 'owner_threshold_change', + + // Module txs + guard_remove = 'guard_remove', + module_remove = 'module_remove', + spending_limit_remove = 'spending_limit_remove', + spending_limit_add = 'spending_limit_add', + spending_limit_transfer = 'spending_limit_transfer', + + // Safe txs + safe_update = 'safe_update', + + // Transfers + transfer_token = 'transfer_token', + transfer_nft = 'transfer_nft', + + // Other + batch = 'batch', + rejection = 'rejection', + message = 'message', + safeapps = 'safeapps', + walletconnect = 'walletconnect', +} + +const TX_CATEGORY = 'transactions' + +export const TX_EVENTS = { + CREATE: { + action: 'Create transaction', + category: TX_CATEGORY, + // label: TX_TYPES, + }, +} diff --git a/src/services/analytics/useGtm.ts b/src/services/analytics/useGtm.ts index f2fc484de3..6525867c60 100644 --- a/src/services/analytics/useGtm.ts +++ b/src/services/analytics/useGtm.ts @@ -14,6 +14,7 @@ import { gtmSetDeviceType, gtmSetSafeAddress, gtmSetUserProperty, + gtmTrack, } from '@/services/analytics/gtm' import { useAppSelector } from '@/store' import { CookieType, selectCookies } from '@/store/cookiesSlice' @@ -25,6 +26,7 @@ import { useMediaQuery } from '@mui/material' import { AnalyticsUserProperties, DeviceType } from './types' import useSafeAddress from '@/hooks/useSafeAddress' import useWallet from '@/hooks/wallets/useWallet' +import { OVERVIEW_EVENTS } from './events' const useGtm = () => { const chainId = useChainId() @@ -72,6 +74,10 @@ const useGtm = () => { // Set safe address for all GTM events useEffect(() => { gtmSetSafeAddress(safeAddress) + + if (safeAddress) { + gtmTrack(OVERVIEW_EVENTS.SAFE_VIEWED) + } }, [safeAddress]) // Track page views – anonymized by default. diff --git a/src/services/safe-wallet-provider/useSafeWalletProvider.tsx b/src/services/safe-wallet-provider/useSafeWalletProvider.tsx index ae04d26073..8573a958f0 100644 --- a/src/services/safe-wallet-provider/useSafeWalletProvider.tsx +++ b/src/services/safe-wallet-provider/useSafeWalletProvider.tsx @@ -23,6 +23,8 @@ import SignMessageOnChainFlow from '@/components/tx-flow/flows/SignMessageOnChai import { useAppSelector } from '@/store' import { selectOnChainSigning } from '@/store/settingsSlice' import { isOffchainEIP1271Supported } from '@/utils/safe-messages' +import { TX_EVENTS, TX_TYPES } from '../analytics/events/transactions' +import { trackEvent } from '../analytics' export const _useTxFlowApi = (chainId: string, safeAddress: string): WalletSDK | undefined => { const { safe } = useSafeInfo() @@ -131,23 +133,15 @@ export const _useTxFlowApi = (chainId: string, safeAddress: string): WalletSDK | code: RpcErrorCode.USER_REJECTED, message: 'User rejected transaction', }) - unsubscribe() } - const unsubscribeSignaturePrepared = txSubscribe( - TxEvent.SAFE_APPS_REQUEST, - async ({ safeAppRequestId, safeTxHash, txId }) => { - if (safeAppRequestId === id) { - const txHash = txId ? pendingTxs.current[txId] : undefined - resolve({ safeTxHash, txHash }) - unsubscribe() - } - }, - ) - - const unsubscribe = () => { + const onSubmit = (txId: string, safeTxHash: string) => { + const txHash = pendingTxs.current[txId] onClose = () => {} - unsubscribeSignaturePrepared() + + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.walletconnect }) + + resolve({ safeTxHash, txHash }) } setTxFlow( @@ -159,6 +153,7 @@ export const _useTxFlowApi = (chainId: string, safeAddress: string): WalletSDK | txs: transactions, params: params.params, }} + onSubmit={onSubmit} />, onClose, ) diff --git a/src/services/tx/tx-sender/dispatch.ts b/src/services/tx/tx-sender/dispatch.ts index 570aa0e0ea..2013ecc84f 100644 --- a/src/services/tx/tx-sender/dispatch.ts +++ b/src/services/tx/tx-sender/dispatch.ts @@ -312,10 +312,11 @@ export const dispatchSafeAppsTx = async ( onboard: OnboardAPI, chainId: SafeInfo['chainId'], txId?: string, -) => { +): Promise => { const sdk = await getSafeSDKWithSigner(onboard, chainId) const safeTxHash = await sdk.getTransactionHash(safeTx) txDispatch(TxEvent.SAFE_APPS_REQUEST, { safeAppRequestId, safeTxHash, txId }) + return safeTxHash } export const dispatchTxRelay = async ( From 6ee3c154e4c9918802ea806531cb7575f405534e Mon Sep 17 00:00:00 2001 From: katspaugh Date: Thu, 9 Nov 2023 18:18:03 +0100 Subject: [PATCH 02/10] Rm PROPOSE_TX, rename TOGGLE_EXECUTE_TX, fix SIMULATE_TX --- src/components/tx/ExecuteCheckbox/index.tsx | 2 +- src/components/tx/security/tenderly/index.tsx | 22 +++++++++++-------- src/services/analytics/events/modals.ts | 12 ++-------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/components/tx/ExecuteCheckbox/index.tsx b/src/components/tx/ExecuteCheckbox/index.tsx index 43e1ad6720..7ec0bf2a56 100644 --- a/src/components/tx/ExecuteCheckbox/index.tsx +++ b/src/components/tx/ExecuteCheckbox/index.tsx @@ -12,7 +12,7 @@ const ExecuteCheckbox = ({ onChange }: { onChange: (checked: boolean) => void }) const handleChange = (_: ChangeEvent, value: string) => { const checked = value === 'true' - trackEvent({ ...MODALS_EVENTS.EXECUTE_TX, label: checked }) + trackEvent({ ...MODALS_EVENTS.TOGGLE_EXECUTE_TX, label: checked }) dispatch(setTransactionExecution(checked)) onChange(checked) } diff --git a/src/components/tx/security/tenderly/index.tsx b/src/components/tx/security/tenderly/index.tsx index 4f1487205e..243eda41d6 100644 --- a/src/components/tx/security/tenderly/index.tsx +++ b/src/components/tx/security/tenderly/index.tsx @@ -18,6 +18,8 @@ import sharedCss from '@/components/tx/security/shared/styles.module.css' import { TxInfoContext } from '@/components/tx-flow/TxInfoProvider' import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider' import InfoIcon from '@/public/images/notifications/info.svg' +import Track from '@/components/common/Track' +import { MODALS_EVENTS } from '@/services/analytics' export type TxSimulationProps = { transactions?: SimulationTxParams['transactions'] @@ -112,15 +114,17 @@ const TxSimulationBlock = ({ transactions, disabled, gasLimit }: TxSimulationPro ) ) : ( - + + + )} diff --git a/src/services/analytics/events/modals.ts b/src/services/analytics/events/modals.ts index d13418b99c..6d81dd8139 100644 --- a/src/services/analytics/events/modals.ts +++ b/src/services/analytics/events/modals.ts @@ -31,8 +31,8 @@ export const MODALS_EVENTS = { action: 'Estimation', category: MODALS_CATEGORY, }, - EXECUTE_TX: { - action: 'Execute transaction', + TOGGLE_EXECUTE_TX: { + action: 'Toggle execute transaction', category: MODALS_CATEGORY, }, USE_SPENDING_LIMIT: { @@ -44,18 +44,10 @@ export const MODALS_EVENTS = { action: 'Simulate transaction', category: MODALS_CATEGORY, }, - REJECT_TX: { - action: 'Reject transaction', - category: MODALS_CATEGORY, - }, EDIT_APPROVALS: { action: 'Edit approval', category: MODALS_CATEGORY, }, - PROPOSE_TX: { - action: 'Propose transaction', - category: MODALS_CATEGORY, - }, ACCEPT_RISK: { action: 'Accept transaction risk', category: MODALS_CATEGORY, From b04bb15e8263e2bf224e8b2498b5e4050ce7614c Mon Sep 17 00:00:00 2001 From: katspaugh Date: Thu, 9 Nov 2023 18:21:58 +0100 Subject: [PATCH 03/10] Fix tests --- src/services/safe-wallet-provider/useSafeWalletProvider.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/safe-wallet-provider/useSafeWalletProvider.test.tsx b/src/services/safe-wallet-provider/useSafeWalletProvider.test.tsx index 4d4ea0ff51..57bc87b834 100644 --- a/src/services/safe-wallet-provider/useSafeWalletProvider.test.tsx +++ b/src/services/safe-wallet-provider/useSafeWalletProvider.test.tsx @@ -271,6 +271,7 @@ describe('useSafeWalletProvider', () => { ], params: { safeTxGas: 0 }, }, + onSubmit: expect.any(Function), }) expect(resp).toBeInstanceOf(Promise) From 0b8fcb067af72fb46303d649ceabcb1b28e7fe5f Mon Sep 17 00:00:00 2001 From: katspaugh Date: Fri, 10 Nov 2023 11:31:13 +0100 Subject: [PATCH 04/10] Track only typed messages as tx_created --- .../tx-flow/flows/SignMessage/SignMessage.tsx | 19 +++++++++++-------- .../ReviewSignMessageOnChain.tsx | 5 ++++- src/hooks/messages/useSafeMsgTracking.ts | 5 ----- src/services/analytics/events/transactions.ts | 2 +- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx index d331e10b96..dfd2cd79a9 100644 --- a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx +++ b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx @@ -38,6 +38,8 @@ import InfoBox from '@/components/safe-messages/InfoBox' import { DecodedMsg } from '@/components/safe-messages/DecodedMsg' import TxCard from '@/components/tx-flow/common/TxCard' import { dispatchPreparedSignature } from '@/services/safe-messages/safeMsgNotifications' +import { trackEvent } from '@/services/analytics' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' const createSkeletonMessage = (confirmationsRequired: number): SafeMessage => { return { @@ -169,19 +171,14 @@ const SignMessage = ({ message, safeAppId, requestId }: ProposeProps | ConfirmPr const { safe } = useSafeInfo() const isOwner = useIsSafeOwner() const wallet = useWallet() + useHighlightHiddenTab() const { decodedMessage, safeMessageMessage, safeMessageHash } = useDecodedSafeMessage(message, safe) const [safeMessage, setSafeMessage] = useSafeMessage(safeMessageHash) - - useHighlightHiddenTab() - - const decodedMessageAsString = - typeof decodedMessage === 'string' ? decodedMessage : JSON.stringify(decodedMessage, null, 2) - + const isPlainTextMessage = typeof decodedMessage === 'string' + const decodedMessageAsString = isPlainTextMessage ? decodedMessage : JSON.stringify(decodedMessage, null, 2) const hasSigned = !!safeMessage?.confirmations.some(({ owner }) => owner.value === wallet?.address) - const isFullySigned = !!safeMessage?.preparedSignature - const isDisabled = !isOwner || hasSigned const { onSign, submitError } = useSyncSafeMessageSigner( @@ -195,9 +192,15 @@ const SignMessage = ({ message, safeAppId, requestId }: ProposeProps | ConfirmPr const handleSign = async () => { const updatedMessage = await onSign() + if (updatedMessage) { setSafeMessage(updatedMessage) } + + // Track first signature as creation + if (updatedMessage?.confirmations.length === 1) { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.typed_message }) + } } const onContinue = async () => { diff --git a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx index 378b296979..d940608ac5 100644 --- a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx +++ b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx @@ -101,7 +101,10 @@ const ReviewSignMessageOnChain = ({ message, method, requestId }: SignMessageOnC const handleSubmit = async () => { if (!safeTx || !onboard) return - trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.message }) + // Track the creation of a typed message + if (isTypedMessage && safeTx.signatures.size === 1) { + trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.typed_message }) + } try { await dispatchSafeAppsTx(safeTx, requestId, onboard, safe.chainId) diff --git a/src/hooks/messages/useSafeMsgTracking.ts b/src/hooks/messages/useSafeMsgTracking.ts index 8e1131ccbf..45b3bf6fae 100644 --- a/src/hooks/messages/useSafeMsgTracking.ts +++ b/src/hooks/messages/useSafeMsgTracking.ts @@ -2,7 +2,6 @@ import { useEffect } from 'react' import { trackEvent, WALLET_EVENTS } from '@/services/analytics' import { SafeMsgEvent, safeMsgSubscribe } from '@/services/safe-messages/safeMsgEvents' -import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' const safeMsgEvents = { [SafeMsgEvent.PROPOSE]: WALLET_EVENTS.SIGN_MESSAGE, @@ -14,10 +13,6 @@ export const useSafeMsgTracking = (): void => { const unsubFns = Object.entries(safeMsgEvents).map(([safeMsgEvent, analyticsEvent]) => safeMsgSubscribe(safeMsgEvent as SafeMsgEvent, () => { trackEvent(analyticsEvent) - - if (analyticsEvent === WALLET_EVENTS.SIGN_MESSAGE) { - trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.message }) - } }), ) diff --git a/src/services/analytics/events/transactions.ts b/src/services/analytics/events/transactions.ts index df6503e367..09b94763e4 100644 --- a/src/services/analytics/events/transactions.ts +++ b/src/services/analytics/events/transactions.ts @@ -22,7 +22,7 @@ export enum TX_TYPES { // Other batch = 'batch', rejection = 'rejection', - message = 'message', + typed_message = 'typed_message', safeapps = 'safeapps', walletconnect = 'walletconnect', } From e2ecc40e87b30a18f92af58f051b7f1ab1373460 Mon Sep 17 00:00:00 2001 From: katspaugh Date: Tue, 14 Nov 2023 16:41:11 +0100 Subject: [PATCH 05/10] Safe viewed = meta event --- src/services/analytics/events/overview.ts | 1 + src/services/analytics/events/transactions.ts | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/services/analytics/events/overview.ts b/src/services/analytics/events/overview.ts index a1a408c469..9c8dc47202 100644 --- a/src/services/analytics/events/overview.ts +++ b/src/services/analytics/events/overview.ts @@ -97,6 +97,7 @@ export const OVERVIEW_EVENTS = { category: OVERVIEW_CATEGORY, }, SAFE_VIEWED: { + event: EventType.META, action: 'Safe viewed', category: OVERVIEW_CATEGORY, }, diff --git a/src/services/analytics/events/transactions.ts b/src/services/analytics/events/transactions.ts index 09b94763e4..14031a17e1 100644 --- a/src/services/analytics/events/transactions.ts +++ b/src/services/analytics/events/transactions.ts @@ -1,3 +1,5 @@ +import { EventType } from '../types' + export enum TX_TYPES { // Owner txs owner_add = 'owner_add', @@ -31,6 +33,7 @@ const TX_CATEGORY = 'transactions' export const TX_EVENTS = { CREATE: { + event: EventType.META, action: 'Create transaction', category: TX_CATEGORY, // label: TX_TYPES, From 18122e6d65dce81a67ed41004cc06efa971865bf Mon Sep 17 00:00:00 2001 From: katspaugh Date: Mon, 20 Nov 2023 10:21:46 +0100 Subject: [PATCH 06/10] Do not call onSubmit when adding to batch --- src/components/tx/SignOrExecuteForm/ExecuteForm.tsx | 2 +- src/components/tx/SignOrExecuteForm/SignForm.tsx | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx b/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx index 72ae840fc6..8fdbe5a755 100644 --- a/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx +++ b/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx @@ -96,8 +96,8 @@ const ExecuteForm = ({ } // On success - setTxFlow(, undefined, false) onSubmit(executedTxId) + setTxFlow(, undefined, false) } const cannotPropose = !isOwner && !onlyExecute diff --git a/src/components/tx/SignOrExecuteForm/SignForm.tsx b/src/components/tx/SignOrExecuteForm/SignForm.tsx index 410254da8e..f7767d24e6 100644 --- a/src/components/tx/SignOrExecuteForm/SignForm.tsx +++ b/src/components/tx/SignOrExecuteForm/SignForm.tsx @@ -63,9 +63,12 @@ const SignForm = ({ return } - // On success + // On successful sign + if (!isAddingToBatch) { + onSubmit(resultTxId) + } + setTxFlow(undefined) - onSubmit(resultTxId) } const onBatchClick = (e: SyntheticEvent) => { From d97f40e956e068881328498bcbe51f7ab35e2dda Mon Sep 17 00:00:00 2001 From: katspaugh Date: Mon, 20 Nov 2023 10:35:04 +0100 Subject: [PATCH 07/10] Track safe apps tx creation --- .../dashboard/FeaturedApps/FeaturedApps.tsx | 8 ++------ .../tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx | 11 +++++++++++ .../safe-wallet-provider/useSafeWalletProvider.tsx | 5 ----- src/services/walletconnect/utils.ts | 5 +++++ 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/components/dashboard/FeaturedApps/FeaturedApps.tsx b/src/components/dashboard/FeaturedApps/FeaturedApps.tsx index 6f9ebe139c..39b868b2f7 100644 --- a/src/components/dashboard/FeaturedApps/FeaturedApps.tsx +++ b/src/components/dashboard/FeaturedApps/FeaturedApps.tsx @@ -10,11 +10,7 @@ import { SafeAppsTag } from '@/config/constants' import { useRemoteSafeApps } from '@/hooks/safe-apps/useRemoteSafeApps' import SafeAppIconCard from '@/components/safe-apps/SafeAppIconCard' import { WalletConnectContext } from '@/services/walletconnect/WalletConnectContext' - -const isWalletConnectSafeApp = (app: SafeAppData): boolean => { - const WALLET_CONNECT = /wallet-connect/ - return WALLET_CONNECT.test(app.url) -} +import { isWalletConnectSafeApp } from '@/services/walletconnect/utils' const FeaturedAppCard = ({ app }: { app: SafeAppData }) => ( @@ -62,7 +58,7 @@ export const FeaturedApps = ({ stackedLayout }: { stackedLayout: boolean }): Rea > {featuredApps?.map((app) => ( - {isWalletConnectSafeApp(app) ? ( + {isWalletConnectSafeApp(app.url) ? ( diff --git a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx index efc96834a3..f9c8c7b847 100644 --- a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx +++ b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx @@ -17,6 +17,9 @@ import ApprovalEditor from '@/components/tx/ApprovalEditor' import { getInteractionTitle, isTxValid } from '@/components/safe-apps/utils' import ErrorMessage from '@/components/tx/ErrorMessage' import { asError } from '@/services/exceptions/utils' +import { trackEvent } from '@/services/analytics' +import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' +import { isWalletConnectSafeApp } from '@/services/walletconnect/utils' type ReviewSafeAppsTxProps = { safeAppsTx: SafeAppsTxParams @@ -63,6 +66,14 @@ const ReviewSafeAppsTx = ({ setSafeTxError(asError(error)) } + // Track tx creation + if (safeTx.signatures.size === 1) { + trackEvent({ + ...TX_EVENTS.CREATE, + label: isWalletConnectSafeApp(app?.url || '') ? TX_TYPES.walletconnect : TX_TYPES.safeapps, + }) + } + onSubmit?.(txId, safeTxHash) } diff --git a/src/services/safe-wallet-provider/useSafeWalletProvider.tsx b/src/services/safe-wallet-provider/useSafeWalletProvider.tsx index 8573a958f0..289f75a62e 100644 --- a/src/services/safe-wallet-provider/useSafeWalletProvider.tsx +++ b/src/services/safe-wallet-provider/useSafeWalletProvider.tsx @@ -23,8 +23,6 @@ import SignMessageOnChainFlow from '@/components/tx-flow/flows/SignMessageOnChai import { useAppSelector } from '@/store' import { selectOnChainSigning } from '@/store/settingsSlice' import { isOffchainEIP1271Supported } from '@/utils/safe-messages' -import { TX_EVENTS, TX_TYPES } from '../analytics/events/transactions' -import { trackEvent } from '../analytics' export const _useTxFlowApi = (chainId: string, safeAddress: string): WalletSDK | undefined => { const { safe } = useSafeInfo() @@ -138,9 +136,6 @@ export const _useTxFlowApi = (chainId: string, safeAddress: string): WalletSDK | const onSubmit = (txId: string, safeTxHash: string) => { const txHash = pendingTxs.current[txId] onClose = () => {} - - trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.walletconnect }) - resolve({ safeTxHash, txHash }) } diff --git a/src/services/walletconnect/utils.ts b/src/services/walletconnect/utils.ts index 047e1003ad..bd3f903646 100644 --- a/src/services/walletconnect/utils.ts +++ b/src/services/walletconnect/utils.ts @@ -62,3 +62,8 @@ export const getPeerName = (peer: SessionTypes.Struct['peer'] | ProposalTypes.St export const splitError = (message: string): string[] => { return message.split(/: (.+)/).slice(0, 2) } + +export const isWalletConnectSafeApp = (url: string): boolean => { + const WALLET_CONNECT = /wallet-connect/ + return WALLET_CONNECT.test(url) +} From cec8fed00c3692e5c733e426ecc7869919d93712 Mon Sep 17 00:00:00 2001 From: katspaugh <381895+katspaugh@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:29:36 +0100 Subject: [PATCH 08/10] Analytics: track app version in all events (#2831) * Fix: remove deprecated mobile pairing (#2794) * Fix: remove deprecated mobile pairing * Fix accounts[0] and Delete Account * Update onboard package * Update env vars * Fix: add help link in footer (#2822) * Fix: add help link in footer * External link * Fix: double scroll bar in safe apps (#2829) * Feat: track app version in all events * Tests --- .env.example | 3 +- README.md | 63 +- package.json | 2 +- .../common/AppStoreButton/index.tsx | 1 - .../common/ConnectWallet/styles.module.css | 7 - src/components/common/Footer/index.tsx | 14 +- .../PairingDeprecationWarning.tsx | 12 - .../PairingDetails/PairingDescription.tsx | 24 - .../common/PairingDetails/PairingQRCode.tsx | 53 -- .../common/WalletInfo/index.test.tsx | 6 +- src/components/common/WalletInfo/index.tsx | 7 +- .../common/WalletInfo/styles.module.css | 7 + .../safe-apps/AppFrame/styles.module.css | 1 + .../WcSessionList/WcNoSessions.tsx | 4 +- src/config/constants.ts | 1 - src/hooks/wallets/consts.ts | 2 - src/hooks/wallets/useOnboard.ts | 17 - src/hooks/wallets/wallets.ts | 2 - src/pages/_app.tsx | 3 - src/services/analytics/__tests__/gtm.test.ts | 133 ++- src/services/analytics/gtm.ts | 2 + src/services/exceptions/ErrorCodes.ts | 1 - src/services/pairing/QRModal.tsx | 55 -- src/services/pairing/__tests__/utils.test.ts | 103 --- src/services/pairing/connector.ts | 58 -- src/services/pairing/hooks.ts | 142 --- src/services/pairing/icon.ts | 8 - src/services/pairing/module.ts | 257 ------ src/services/pairing/utils.ts | 60 -- src/styles/globals.css | 1 - yarn.lock | 865 ++++++++++-------- 31 files changed, 687 insertions(+), 1227 deletions(-) delete mode 100644 src/components/common/PairingDetails/PairingDeprecationWarning.tsx delete mode 100644 src/components/common/PairingDetails/PairingDescription.tsx delete mode 100644 src/components/common/PairingDetails/PairingQRCode.tsx delete mode 100644 src/services/pairing/QRModal.tsx delete mode 100644 src/services/pairing/__tests__/utils.test.ts delete mode 100644 src/services/pairing/connector.ts delete mode 100644 src/services/pairing/hooks.ts delete mode 100644 src/services/pairing/icon.ts delete mode 100644 src/services/pairing/module.ts delete mode 100644 src/services/pairing/utils.ts diff --git a/.env.example b/.env.example index 4ee43536d7..ab53f2b047 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -## Infura token (required) +## Infura token NEXT_PUBLIC_INFURA_TOKEN= NEXT_PUBLIC_SAFE_APPS_INFURA_TOKEN= @@ -22,7 +22,6 @@ NEXT_PUBLIC_SENTRY_DSN= NEXT_PUBLIC_BEAMER_ID= # Wallet-specific variables -NEXT_PUBLIC_WC_BRIDGE= NEXT_PUBLIC_WC_PROJECT_ID= # E2E tests diff --git a/README.md b/README.md index c2bdf1146f..9ead08c0fe 100644 --- a/README.md +++ b/README.md @@ -17,37 +17,38 @@ Contributions, be it a bug report or a pull request, are very welcome. Please ch Create a `.env` file with environment variables. You can use the `.env.example` file as a reference. -Here's the list of all the required and optional variables: - -| Env variable | | Description -| ------------------------------------------------------ | ------------ | ----------- -| `NEXT_PUBLIC_INFURA_TOKEN` | optional | [Infura](https://docs.infura.io/infura/networks/ethereum/how-to/secure-a-project/project-id) RPC API token -| `NEXT_PUBLIC_SAFE_APPS_INFURA_TOKEN` | optional | Infura token for Safe Apps, falls back to `NEXT_PUBLIC_INFURA_TOKEN` -| `NEXT_PUBLIC_IS_PRODUCTION` | optional | Set to `true` to build a minified production app -| `NEXT_PUBLIC_GATEWAY_URL_PRODUCTION` | optional | The base URL for the [Safe Client Gateway](https://github.com/safe-global/safe-client-gateway) -| `NEXT_PUBLIC_GATEWAY_URL_STAGING` | optional | The base CGW URL on staging -| `NEXT_PUBLIC_SAFE_VERSION` | optional | The latest version of the Safe contract, defaults to 1.3.0 -| `NEXT_PUBLIC_WC_BRIDGE` | optional | [WalletConnect v1](https://docs.walletconnect.com/1.0/bridge-server) bridge URL, falls back to the public WC bridge -| `NEXT_PUBLIC_WC_PROJECT_ID` | optional | [WalletConnect v2](https://docs.walletconnect.com/2.0/cloud/relay) project ID -| `NEXT_PUBLIC_TENDERLY_ORG_NAME` | optional | [Tenderly](https://tenderly.co) org name for Transaction Simulation -| `NEXT_PUBLIC_TENDERLY_PROJECT_NAME` | optional | Tenderly project name -| `NEXT_PUBLIC_TENDERLY_SIMULATE_ENDPOINT_URL` | optional | Tenderly simulation URL -| `NEXT_PUBLIC_BEAMER_ID` | optional | [Beamer](https://www.getbeamer.com) is a news feed for in-app announcements -| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID` | optional | [GTM](https://tagmanager.google.com) project id -| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_DEVELOPMENT_AUTH` | optional | Dev GTM key -| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_LATEST_AUTH` | optional | Preview GTM key -| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_LIVE_AUTH` | optional | Production GTM key -| `NEXT_PUBLIC_SENTRY_DSN` | optional | [Sentry](https://sentry.io) id for tracking runtime errors -| `NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_PRODUCTION` | optional | [Safe Gelato Relay Service](https://github.com/safe-global/safe-gelato-relay-service) URL to allow relaying transactions via Gelato -| `NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING` | optional | Relay URL on staging -| `NEXT_PUBLIC_IS_OFFICIAL_HOST` | optional | Whether it's the official distribution of the app, or a fork; has legal implications. Set to true only if you also update the legal pages like Imprint and Terms of use -| `NEXT_PUBLIC_REDEFINE_API` | optional | Redefine API base URL -| `NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION` | optional | Firebase Cloud Messaging (FCM) `initializeApp` options on production -| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION` | optional | FCM vapid key on production -| `NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING` | optional | FCM `initializeApp` options on staging -| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING` | optional | FCM vapid key on staging - -If you don't provide some of the optional vars, the corresponding features will be disabled in the UI. +Here's the list of all the environment variables: + +| Env variable | Description +| ------------------------------------------------------ | ----------- +| `NEXT_PUBLIC_INFURA_TOKEN` | [Infura](https://docs.infura.io/infura/networks/ethereum/how-to/secure-a-project/project-id) RPC API token +| `NEXT_PUBLIC_SAFE_APPS_INFURA_TOKEN` | Infura token for Safe Apps, falls back to `NEXT_PUBLIC_INFURA_TOKEN` +| `NEXT_PUBLIC_IS_PRODUCTION` | Set to `true` to build a minified production app +| `NEXT_PUBLIC_GATEWAY_URL_PRODUCTION` | The base URL for the [Safe Client Gateway](https://github.com/safe-global/safe-client-gateway) +| `NEXT_PUBLIC_GATEWAY_URL_STAGING` | The base CGW URL on staging +| `NEXT_PUBLIC_SAFE_VERSION` | The latest version of the Safe contract, defaults to 1.3.0 +| `NEXT_PUBLIC_WC_PROJECT_ID` | [WalletConnect v2](https://docs.walletconnect.com/2.0/cloud/relay) project ID +| `NEXT_PUBLIC_TENDERLY_ORG_NAME` | [Tenderly](https://tenderly.co) org name for Transaction Simulation +| `NEXT_PUBLIC_TENDERLY_PROJECT_NAME` | Tenderly project name +| `NEXT_PUBLIC_TENDERLY_SIMULATE_ENDPOINT_URL` | Tenderly simulation URL +| `NEXT_PUBLIC_BEAMER_ID` | [Beamer](https://www.getbeamer.com) is a news feed for in-app announcements +| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_ID` | [GTM](https://tagmanager.google.com) project id +| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_DEVELOPMENT_AUTH` | Dev GTM key +| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_LATEST_AUTH` | Preview GTM key +| `NEXT_PUBLIC_GOOGLE_TAG_MANAGER_LIVE_AUTH` | Production GTM key +| `NEXT_PUBLIC_SENTRY_DSN` | [Sentry](https://sentry.io) id for tracking runtime errors +| `NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_PRODUCTION` | [Safe Gelato Relay Service](https://github.com/safe-global/safe-gelato-relay-service) URL to allow relaying transactions via Gelato +| `NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING` | Relay URL on staging +| `NEXT_PUBLIC_IS_OFFICIAL_HOST` | Whether it's the official distribution of the app, or a fork; has legal implications. Set to true only if you also update the legal pages like Imprint and Terms of use +| `NEXT_PUBLIC_REDEFINE_API` | Redefine API base URL +| `NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION` | Firebase Cloud Messaging (FCM) `initializeApp` options on production +| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION` | FCM vapid key on production +| `NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING` | FCM `initializeApp` options on staging +| `NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING` | FCM vapid key on staging +| `NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION` | Web3Auth and Google credentials (production) +| `NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING` | Web3Auth and Google credentials (staging) + +If you don't provide some of the variables, the corresponding features will be disabled in the UI. ### Running the app locally diff --git a/package.json b/package.json index 90ca35975a..78e36f596c 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "@web3-onboard/keystone": "^2.3.7", "@web3-onboard/ledger": "2.3.2", "@web3-onboard/trezor": "^2.4.2", - "@web3-onboard/walletconnect": "^2.4.7", + "@web3-onboard/walletconnect": "^2.5.0", "@web3auth/mpc-core-kit": "^1.1.3", "blo": "^1.1.1", "bn.js": "^5.2.1", diff --git a/src/components/common/AppStoreButton/index.tsx b/src/components/common/AppStoreButton/index.tsx index 6687afe3d2..65fe9eb30a 100644 --- a/src/components/common/AppStoreButton/index.tsx +++ b/src/components/common/AppStoreButton/index.tsx @@ -6,7 +6,6 @@ import { MOBILE_APP_EVENTS, trackEvent } from '@/services/analytics' // App Store campaigns track the user interaction enum LINKS { - pairing = 'https://apps.apple.com/app/apple-store/id1515759131?pt=119497694&ct=Web%20App%20Connect&mt=8', footer = 'https://apps.apple.com/app/apple-store/id1515759131?pt=119497694&ct=Web%20App%20Footer&mt=8', } diff --git a/src/components/common/ConnectWallet/styles.module.css b/src/components/common/ConnectWallet/styles.module.css index b41bbc8399..71036103a6 100644 --- a/src/components/common/ConnectWallet/styles.module.css +++ b/src/components/common/ConnectWallet/styles.module.css @@ -64,13 +64,6 @@ border-bottom: 1px solid var(--color-border-light); } -.pairingDetails { - display: flex; - flex-direction: column; - align-items: center; - gap: var(--space-2); -} - .loginButton { min-height: 42px; } diff --git a/src/components/common/Footer/index.tsx b/src/components/common/Footer/index.tsx index 545b1f43aa..59d519013a 100644 --- a/src/components/common/Footer/index.tsx +++ b/src/components/common/Footer/index.tsx @@ -1,5 +1,6 @@ import type { ReactElement, ReactNode } from 'react' -import { Typography } from '@mui/material' +import { SvgIcon, Typography } from '@mui/material' +import GitHubIcon from '@mui/icons-material/GitHub' import Link from 'next/link' import { useRouter } from 'next/router' import css from './styles.module.css' @@ -8,7 +9,7 @@ import packageJson from '../../../../package.json' import AppstoreButton from '../AppStoreButton' import ExternalLink from '../ExternalLink' import MUILink from '@mui/material/Link' -import { IS_DEV, IS_OFFICIAL_HOST } from '@/config/constants' +import { HELP_CENTER_URL, IS_DEV, IS_OFFICIAL_HOST } from '@/config/constants' const footerPages = [ AppRoutes.welcome.index, @@ -67,14 +68,19 @@ const Footer = (): ReactElement | null => {
  • Preferences
  • +
  • + + Help + +
  • ) : (
  • {'This is an unofficial distribution of Safe{Wallet}'}
  • )}
  • - - v{packageJson.version} + + v{packageJson.version}
  • diff --git a/src/components/common/PairingDetails/PairingDeprecationWarning.tsx b/src/components/common/PairingDetails/PairingDeprecationWarning.tsx deleted file mode 100644 index dd720461e0..0000000000 --- a/src/components/common/PairingDetails/PairingDeprecationWarning.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { Alert } from '@mui/material' - -const PairingDeprecationWarning = (): React.ReactElement => { - return ( - - The {'Safe{Wallet}'} web-mobile pairing feature will be discontinued from 15th November 2023. Please migrate to a - different signer wallet before this date. - - ) -} - -export default PairingDeprecationWarning diff --git a/src/components/common/PairingDetails/PairingDescription.tsx b/src/components/common/PairingDetails/PairingDescription.tsx deleted file mode 100644 index bdcad66d90..0000000000 --- a/src/components/common/PairingDetails/PairingDescription.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import { Typography } from '@mui/material' -import type { ReactElement } from 'react' - -import AppStoreButton from '@/components/common/AppStoreButton' -import ExternalLink from '../ExternalLink' -import { HelpCenterArticle } from '@/config/constants' - -const PairingDescription = (): ReactElement => { - return ( - <> - - Scan this code in the {'Safe{Wallet}'} mobile app to sign transactions with your mobile device. -
    - - Learn more about this feature. - -
    - - - - ) -} - -export default PairingDescription diff --git a/src/components/common/PairingDetails/PairingQRCode.tsx b/src/components/common/PairingDetails/PairingQRCode.tsx deleted file mode 100644 index a53f5dbce1..0000000000 --- a/src/components/common/PairingDetails/PairingQRCode.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { useEffect, useState } from 'react' -import { IconButton, Box } from '@mui/material' -import RefreshIcon from '@mui/icons-material/Refresh' -import type { ReactElement } from 'react' - -import { getPairingConnector, usePairingConnector, WalletConnectEvents } from '@/services/pairing/connector' -import usePairingUri from '@/services/pairing/hooks' -import useChainId from '@/hooks/useChainId' -import QRCode from '@/components/common/QRCode' - -const QR_CODE_SIZE = 100 - -const PairingQRCode = ({ size = QR_CODE_SIZE }: { size?: number }): ReactElement => { - const chainId = useChainId() - const uri = usePairingUri() - const connector = usePairingConnector() - const [displayRefresh, setDisplayRefresh] = useState(false) - - // Workaround because the disconnect listener in useInitPairing is not picking up the event - useEffect(() => { - connector?.on(WalletConnectEvents.DISCONNECT, () => { - setDisplayRefresh(true) - }) - }, [connector]) - - const handleRefresh = () => { - setDisplayRefresh(false) - getPairingConnector()?.createSession({ chainId: +chainId }) - } - - if (displayRefresh || (connector && !connector.handshakeTopic)) { - return ( - theme.palette.background.main, - }} - > - - - - - ) - } - - return -} - -export default PairingQRCode diff --git a/src/components/common/WalletInfo/index.test.tsx b/src/components/common/WalletInfo/index.test.tsx index e402e7dd4a..a253bbf8bb 100644 --- a/src/components/common/WalletInfo/index.test.tsx +++ b/src/components/common/WalletInfo/index.test.tsx @@ -104,7 +104,7 @@ describe('WalletInfo', () => { />, ) - expect(getByText('Delete Account')).toBeInTheDocument() + expect(getByText('Delete account')).toBeInTheDocument() }) it('should not display a Delete Account on prod', () => { @@ -122,7 +122,7 @@ describe('WalletInfo', () => { />, ) - expect(queryByText('Delete Account')).not.toBeInTheDocument() + expect(queryByText('Delete account')).not.toBeInTheDocument() }) it('should not display a Delete Account if not social login', () => { @@ -140,7 +140,7 @@ describe('WalletInfo', () => { />, ) - expect(queryByText('Delete Account')).not.toBeInTheDocument() + expect(queryByText('Delete account')).not.toBeInTheDocument() }) it('should display an enable mfa button if mfa is not enabled', () => { diff --git a/src/components/common/WalletInfo/index.tsx b/src/components/common/WalletInfo/index.tsx index 1afdf0d573..d3e081d7d1 100644 --- a/src/components/common/WalletInfo/index.tsx +++ b/src/components/common/WalletInfo/index.tsx @@ -59,9 +59,10 @@ export const WalletInfo = ({ const isSocialLogin = isSocialLoginWallet(wallet.label) return ( - <> + + {isSocialLogin ? ( <> @@ -108,10 +109,10 @@ export const WalletInfo = ({ {!IS_PRODUCTION && isSocialLogin && ( )} - + ) } diff --git a/src/components/common/WalletInfo/styles.module.css b/src/components/common/WalletInfo/styles.module.css index a8c3a97308..e12fa9a690 100644 --- a/src/components/common/WalletInfo/styles.module.css +++ b/src/components/common/WalletInfo/styles.module.css @@ -1,3 +1,10 @@ +.container { + width: 100%; + display: flex; + flex-direction: column; + gap: var(--space-2); +} + .accountContainer { width: 100%; margin-bottom: var(--space-1); diff --git a/src/components/safe-apps/AppFrame/styles.module.css b/src/components/safe-apps/AppFrame/styles.module.css index 60ed8e1e43..b78dd5a04f 100644 --- a/src/components/safe-apps/AppFrame/styles.module.css +++ b/src/components/safe-apps/AppFrame/styles.module.css @@ -4,6 +4,7 @@ } .iframe { + display: block; height: 100%; width: 100%; overflow: auto; diff --git a/src/components/walletconnect/WcSessionList/WcNoSessions.tsx b/src/components/walletconnect/WcSessionList/WcNoSessions.tsx index 17d7960b07..e7183678a6 100644 --- a/src/components/walletconnect/WcSessionList/WcNoSessions.tsx +++ b/src/components/walletconnect/WcSessionList/WcNoSessions.tsx @@ -21,9 +21,9 @@ const WcSampleDapps = ({ onUnload }: { onUnload: () => void }) => { return ( {SAMPLE_DAPPS.map((item) => ( - + - {item.name} + {item.name} {item.name} diff --git a/src/config/constants.ts b/src/config/constants.ts index 7edd0dd2e1..760a102c98 100644 --- a/src/config/constants.ts +++ b/src/config/constants.ts @@ -19,7 +19,6 @@ export const SENTRY_DSN = process.env.NEXT_PUBLIC_SENTRY_DSN || '' export const BEAMER_ID = process.env.NEXT_PUBLIC_BEAMER_ID || '' // Wallets -export const WC_BRIDGE = process.env.NEXT_PUBLIC_WC_BRIDGE || 'https://bridge.walletconnect.org' export const WC_PROJECT_ID = process.env.NEXT_PUBLIC_WC_PROJECT_ID || '' export const TREZOR_APP_URL = 'app.safe.global' export const TREZOR_EMAIL = 'support@safe.global' diff --git a/src/hooks/wallets/consts.ts b/src/hooks/wallets/consts.ts index 6bb6a61f93..506fac0513 100644 --- a/src/hooks/wallets/consts.ts +++ b/src/hooks/wallets/consts.ts @@ -3,7 +3,6 @@ export const enum WALLET_KEYS { WALLETCONNECT_V2 = 'WALLETCONNECT_V2', SOCIAL = 'SOCIAL_LOGIN', COINBASE = 'COINBASE', - PAIRING = 'PAIRING', LEDGER = 'LEDGER', TREZOR = 'TREZOR', KEYSTONE = 'KEYSTONE', @@ -14,7 +13,6 @@ export const CGW_NAMES: { [key in WALLET_KEYS]: string | undefined } = { [WALLET_KEYS.INJECTED]: 'detectedwallet', [WALLET_KEYS.WALLETCONNECT_V2]: 'walletConnect_v2', [WALLET_KEYS.COINBASE]: 'coinbase', - [WALLET_KEYS.PAIRING]: 'safeMobile', [WALLET_KEYS.SOCIAL]: 'socialSigner', [WALLET_KEYS.LEDGER]: 'ledger', [WALLET_KEYS.TREZOR]: 'trezor', diff --git a/src/hooks/wallets/useOnboard.ts b/src/hooks/wallets/useOnboard.ts index 4d8f2c1ab9..ef20d4f128 100644 --- a/src/hooks/wallets/useOnboard.ts +++ b/src/hooks/wallets/useOnboard.ts @@ -6,7 +6,6 @@ import useChains, { useCurrentChain } from '@/hooks/useChains' import ExternalStore from '@/services/ExternalStore' import { logError, Errors } from '@/services/exceptions' import { trackEvent, WALLET_EVENTS } from '@/services/analytics' -import { useInitPairing } from '@/services/pairing/hooks' import { useAppSelector } from '@/store' import { type EnvState, selectRpc } from '@/store/settingsSlice' import { E2E_WALLET_NAME } from '@/tests/e2e-wallet' @@ -93,21 +92,11 @@ const isMobile = () => /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) // Detect injected wallet const hasInjectedWallet = () => typeof window !== 'undefined' && !!window?.ethereum -// `connectWallet` is called when connecting/switching wallets and on pairing `connect` event (when prev. session connects) -// This re-entrant lock prevents multiple `connectWallet`/tracking calls that would otherwise occur for pairing module -let isConnecting = false - // Wrapper that tracks/sets the last used wallet export const connectWallet = async ( onboard: OnboardAPI, options?: Parameters[0], ): Promise => { - if (isConnecting) { - return - } - - isConnecting = true - // On mobile, automatically choose WalletConnect if there is no injected wallet if (!options && isMobile() && !hasInjectedWallet()) { options = { @@ -121,13 +110,9 @@ export const connectWallet = async ( wallets = await onboard.connectWallet(options) } catch (e) { logError(Errors._302, e) - - isConnecting = false return } - isConnecting = false - return wallets } @@ -153,8 +138,6 @@ export const useInitOnboard = () => { const onboard = useStore() const customRpc = useAppSelector(selectRpc) - useInitPairing() - useEffect(() => { if (configs.length > 0 && chain) { void initOnboard(configs, chain, customRpc) diff --git a/src/hooks/wallets/wallets.ts b/src/hooks/wallets/wallets.ts index 2de9efdd29..4195f57adf 100644 --- a/src/hooks/wallets/wallets.ts +++ b/src/hooks/wallets/wallets.ts @@ -9,7 +9,6 @@ import ledgerModule from '@web3-onboard/ledger/dist/index' import trezorModule from '@web3-onboard/trezor' import walletConnect from '@web3-onboard/walletconnect' -import pairingModule from '@/services/pairing/module' import e2eWalletModule from '@/tests/e2e-wallet' import { CGW_NAMES, WALLET_KEYS } from './consts' import MpcModule from '@/services/mpc/SocialLoginModule' @@ -42,7 +41,6 @@ const WALLET_MODULES: { [key in WALLET_KEYS]: (chain: ChainInfo) => WalletInit } [WALLET_KEYS.INJECTED]: () => injectedWalletModule(), [WALLET_KEYS.WALLETCONNECT_V2]: (chain) => walletConnectV2(chain), [WALLET_KEYS.COINBASE]: () => coinbaseModule({ darkMode: prefersDarkMode() }), - [WALLET_KEYS.PAIRING]: () => pairingModule(), [WALLET_KEYS.SOCIAL]: (chain) => MpcModule(chain), [WALLET_KEYS.LEDGER]: () => ledgerModule(), [WALLET_KEYS.TREZOR]: () => trezorModule({ appUrl: TREZOR_APP_URL, email: TREZOR_EMAIL }), diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 65dcbf5fe9..04fb7abb8f 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -43,7 +43,6 @@ import { WalletConnectProvider } from '@/services/walletconnect/WalletConnectCon import useABTesting from '@/services/tracking/useAbTesting' import { AbTest } from '@/services/tracking/abTesting' import { useNotificationTracking } from '@/components/settings/PushNotifications/hooks/useNotificationTracking' -import MobilePairingModal from '@/services/pairing/QRModal' const GATEWAY_URL = IS_PRODUCTION || cgwDebugStorage.get() ? GATEWAY_URL_PRODUCTION : GATEWAY_URL_STAGING @@ -126,8 +125,6 @@ const WebCoreApp = ({ - - diff --git a/src/services/analytics/__tests__/gtm.test.ts b/src/services/analytics/__tests__/gtm.test.ts index 33eacac65c..5381ec244c 100644 --- a/src/services/analytics/__tests__/gtm.test.ts +++ b/src/services/analytics/__tests__/gtm.test.ts @@ -1,18 +1,131 @@ -import { normalizeAppName } from '../gtm' +import * as gtm from '../gtm' +import TagManager from '../TagManager' +import { EventType, DeviceType } from '../types' -const FAKE_SAFE_APP_NAME = 'Safe App' -const FAKE_DOMAIN = 'http://domain.crypto' +// Mock dependencies +jest.mock('../TagManager', () => ({ + initialize: jest.fn(), + dataLayer: jest.fn(), + enableCookies: jest.fn(), + disableCookies: jest.fn(), + setUserProperty: jest.fn(), +})) describe('gtm', () => { - describe('normalizeAppName', () => { - it('should return the app name if is not an URL', () => { - expect(normalizeAppName(FAKE_SAFE_APP_NAME)).toBe(FAKE_SAFE_APP_NAME) + // Reset mocks before each test + beforeEach(() => { + jest.clearAllMocks() + }) + + describe('gtmTrack', () => { + it('should send correct data to the dataLayer', () => { + const mockEventData = { + event: EventType.CLICK, + category: 'testCategory', + action: 'testAction', + chainId: '1234', + label: 'testLabel', + } + + gtm.gtmTrack(mockEventData) + + expect(TagManager.dataLayer).toHaveBeenCalledWith( + expect.objectContaining({ + event: mockEventData.event, + eventCategory: mockEventData.category, + eventAction: mockEventData.action, + chainId: mockEventData.chainId, + eventLabel: mockEventData.label, + appVersion: expect.any(String), + deviceType: DeviceType.DESKTOP, + }), + ) + }) + + it('should set the chain ID correctly', () => { + const testChainId = '1234' + gtm.gtmSetChainId(testChainId) + + const mockEventData = { + event: EventType.CLICK, + category: 'testCategory', + action: 'testAction', + label: 'testLabel', + } + + gtm.gtmTrack(mockEventData) + + expect(TagManager.dataLayer).toHaveBeenCalledWith( + expect.objectContaining({ + event: mockEventData.event, + eventCategory: mockEventData.category, + eventAction: mockEventData.action, + chainId: testChainId, + eventLabel: mockEventData.label, + appVersion: expect.any(String), + deviceType: DeviceType.DESKTOP, + }), + ) }) + }) + + describe('gtmTrackSafeApp', () => { + it('should send correct data to the dataLayer for a Safe App event', () => { + Object.defineProperty(window, 'location', { + writable: true, + value: { + pathname: '/apps', + }, + }) + + const mockEventData = { + event: EventType.SAFE_APP, + category: 'testCategory', + action: 'testAction', + label: 'testLabel', + chainId: '1234', + } + + const mockAppName = 'Test App' + const mockSdkEventData = { + method: 'testMethod', + ethMethod: 'testEthMethod', + version: '1.0.0', + } + + gtm.gtmTrackSafeApp(mockEventData, mockAppName, mockSdkEventData) + + expect(TagManager.dataLayer).toHaveBeenCalledWith( + expect.objectContaining({ + appVersion: expect.any(String), + chainId: expect.any(String), + deviceType: DeviceType.DESKTOP, + event: EventType.SAFE_APP, + eventAction: 'testAction', + eventCategory: 'testCategory', + eventLabel: 'testLabel', + safeAddress: '', + safeAppEthMethod: '', + safeAppMethod: '', + safeAppName: 'Test App', + safeAppSDKVersion: '', + }), + ) + }) + + describe('normalizeAppName', () => { + const FAKE_SAFE_APP_NAME = 'Safe App' + const FAKE_DOMAIN = 'http://domain.crypto' + + it('should return the app name if is not an URL', () => { + expect(gtm.normalizeAppName(FAKE_SAFE_APP_NAME)).toBe(FAKE_SAFE_APP_NAME) + }) - it('should strip the querystring or hash when is an URL', () => { - expect(normalizeAppName(FAKE_DOMAIN)).toBe(FAKE_DOMAIN) - expect(normalizeAppName(`${FAKE_DOMAIN}?q1=query1&q2=query2`)).toBe(FAKE_DOMAIN) - expect(normalizeAppName(`${FAKE_DOMAIN}#hash`)).toBe(FAKE_DOMAIN) + it('should strip the querystring or hash when is an URL', () => { + expect(gtm.normalizeAppName(FAKE_DOMAIN)).toBe(FAKE_DOMAIN) + expect(gtm.normalizeAppName(`${FAKE_DOMAIN}?q1=query1&q2=query2`)).toBe(FAKE_DOMAIN) + expect(gtm.normalizeAppName(`${FAKE_DOMAIN}#hash`)).toBe(FAKE_DOMAIN) + }) }) }) }) diff --git a/src/services/analytics/gtm.ts b/src/services/analytics/gtm.ts index 6f13652e7f..2a87cbc003 100644 --- a/src/services/analytics/gtm.ts +++ b/src/services/analytics/gtm.ts @@ -22,6 +22,7 @@ import { SAFE_APPS_SDK_CATEGORY } from './events' import { getAbTest } from '../tracking/abTesting' import type { AbTest } from '../tracking/abTesting' import { AppRoutes } from '@/config/routes' +import packageJson from '../../../package.json' type GTMEnvironment = 'LIVE' | 'LATEST' | 'DEVELOPMENT' type GTMEnvironmentArgs = Required> @@ -42,6 +43,7 @@ const GTM_ENV_AUTH: Record = { } const commonEventParams = { + appVersion: packageJson.version, chainId: '', deviceType: DeviceType.DESKTOP, safeAddress: '', diff --git a/src/services/exceptions/ErrorCodes.ts b/src/services/exceptions/ErrorCodes.ts index 90993a46ef..15c40d3592 100644 --- a/src/services/exceptions/ErrorCodes.ts +++ b/src/services/exceptions/ErrorCodes.ts @@ -15,7 +15,6 @@ enum ErrorCodes { _106 = '106: Failed to get connected wallet', _302 = '302: Error connecting to the wallet', - _303 = '303: Error creating pairing session', _304 = '304: Error enabling MFA', _305 = '305: Error exporting account key', _306 = '306: Error logging in', diff --git a/src/services/pairing/QRModal.tsx b/src/services/pairing/QRModal.tsx deleted file mode 100644 index 47b2e18b14..0000000000 --- a/src/services/pairing/QRModal.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { Dialog, DialogContent, DialogTitle, IconButton } from '@mui/material' -import CloseIcon from '@mui/icons-material/Close' -import PairingQRCode from '@/components/common/PairingDetails/PairingQRCode' -import PairingDescription from '@/components/common/PairingDetails/PairingDescription' -import { PAIRING_MODULE_LABEL } from '@/services/pairing/module' -import PairingDeprecationWarning from '@/components/common/PairingDetails/PairingDeprecationWarning' -import ExternalStore from '@/services/ExternalStore' - -const { useStore: useCloseCallback, setStore: setCloseCallback } = new ExternalStore<() => void>() - -export const open = (cb: () => void) => { - setCloseCallback(() => cb) -} - -export const close = () => { - setCloseCallback(undefined) -} - -const QRModal = () => { - const closeCallback = useCloseCallback() - const open = !!closeCallback - - const handleClose = () => { - closeCallback?.() - setCloseCallback(undefined) - close() - } - - if (!open) return null - - return ( - - - {PAIRING_MODULE_LABEL} - - - - - - - -
    - -
    -
    - ) -} - -export default QRModal diff --git a/src/services/pairing/__tests__/utils.test.ts b/src/services/pairing/__tests__/utils.test.ts deleted file mode 100644 index 7551a55ca8..0000000000 --- a/src/services/pairing/__tests__/utils.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { addDays } from 'date-fns' -// @ts-expect-error - with native WalletConnect v2, the type is no longer present -import type { IWalletConnectSession } from '@walletconnect/types' - -import { formatPairingUri, isPairingSupported, hasValidPairingSession, _isPairingSessionExpired } from '../utils' - -describe('Pairing utils', () => { - describe('formatPairingUri', () => { - it('should return a prefixed URI', () => { - const uri = 'wc:1-2@1?bridge=https://test.com/&key=1234' - - const result = formatPairingUri(uri) - expect(result).toBe('safe-wc:1-2@1?bridge=https://test.com/&key=1234') - }) - - it('should return undefined if no URI exists', () => { - const result = formatPairingUri('') - expect(result).toBeUndefined() - }) - - it("should return undefined if the URI doesn't end with a key", () => { - const uri = 'wc:1-2@1?bridge=https://test.com/&key=' - - const result = formatPairingUri(uri) - expect(result).toBeUndefined() - }) - }) - - describe('isPairingSupported', () => { - it('should return true if the wallet is enabled', () => { - const disabledWallets = ['walletConnect'] - const result = isPairingSupported(disabledWallets) - expect(result).toBe(true) - }) - - it('should return false if the wallet is disabled', () => { - const disabledWallets1: string[] = [] - const result1 = isPairingSupported(disabledWallets1) - expect(result1).toBe(true) - - const disabledWallets2 = ['safeMobile'] - const result2 = isPairingSupported(disabledWallets2) - expect(result2).toBe(false) - }) - }) - - describe('isPairingSessionExpired', () => { - it('should return true if the session is older than 24h', () => { - const session: Pick = { - handshakeId: 1000000000000123, - } - - expect(_isPairingSessionExpired(session as IWalletConnectSession)).toBe(true) - }) - - it('should return false if the session is within the last 24h', () => { - const session: Pick = { - handshakeId: +`${Date.now()}123`, - } - - expect(_isPairingSessionExpired(session as IWalletConnectSession)).toBe(false) - }) - }) - - describe('hasValidPairingSession', () => { - beforeEach(() => { - window.localStorage.clear() - }) - - it('should return false if there is no cached session', () => { - expect(hasValidPairingSession()).toBe(false) - }) - - it('should return true if the cached session date is within the last 24h', () => { - const session: Pick = { - handshakeId: 1000000000000123, - } - - window.localStorage.setItem('SAFE_v2__pairingConnector', JSON.stringify(session)) - - jest.spyOn(Date, 'now').mockImplementation(() => +session.handshakeId.toString().slice(0, -3) + 1) - - expect(hasValidPairingSession()).toBe(true) - }) - - it('should return false and clear the cache if the cached session date is older than 24h', () => { - const session: Pick = { - handshakeId: 1000000000000123, - } - - window.localStorage.setItem('SAFE_v2__pairingConnector', JSON.stringify(session)) - - const sessionTimestamp = session.handshakeId.toString().slice(0, -3) - const expirationDate = addDays(new Date(+sessionTimestamp), 1) - - jest.spyOn(Date, 'now').mockImplementation(() => expirationDate.getTime() + 1) - - expect(hasValidPairingSession()).toBe(false) - - expect(window.localStorage.getItem('SAFE_v2__pairingConnector')).toBeNull() - }) - }) -}) diff --git a/src/services/pairing/connector.ts b/src/services/pairing/connector.ts deleted file mode 100644 index c60436f48a..0000000000 --- a/src/services/pairing/connector.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type WalletConnect from '@walletconnect/client' -import bowser from 'bowser' - -import packageJson from '../../../package.json' -import { IS_PRODUCTION } from '@/config/constants' -import ExternalStore from '@/services/ExternalStore' -import PairingIcon from '@/public/images/safe-logo-green.png' - -export const PAIRING_MODULE_STORAGE_ID = 'pairingConnector' - -export const getClientMeta = () => { - const host = location.origin - - const APP_META = { - name: `Safe{Wallet} web v${packageJson.version}`, - url: host, - icons: [`${host}${PairingIcon.src}`], - } - - if (typeof window === 'undefined') { - return { - description: APP_META.name, - ...APP_META, - } - } - - const parsed = bowser.getParser(window.navigator.userAgent) - const os = parsed.getOS() - const browser = parsed.getBrowser() - - return { - description: `${browser.name} ${browser.version} (${os.name});${APP_META.name}`, - ...APP_META, - } -} - -export const { - getStore: getPairingConnector, - setStore: setPairingConnector, - useStore: usePairingConnector, -} = new ExternalStore() - -export enum WalletConnectEvents { - CONNECT = 'connect', - DISPLAY_URI = 'display_uri', - DISCONNECT = 'disconnect', - CALL_REQUEST = 'call_request', - SESSION_REQUEST = 'session_request', - SESSION_UPDATE = 'session_update', - WC_SESSION_REQUEST = 'wc_sessionRequest', - WC_SESSION_UPDATE = 'wc_sessionUpdate', -} - -if (!IS_PRODUCTION) { - Object.values(WalletConnectEvents).forEach((event) => { - getPairingConnector()?.on(event, (...args) => console.info('[Pairing]', event, ...args)) - }) -} diff --git a/src/services/pairing/hooks.ts b/src/services/pairing/hooks.ts deleted file mode 100644 index 07292eb0f8..0000000000 --- a/src/services/pairing/hooks.ts +++ /dev/null @@ -1,142 +0,0 @@ -import { useState, useEffect, useCallback } from 'react' - -import { useCurrentChain } from '@/hooks/useChains' -import useOnboard, { connectWallet, getConnectedWallet } from '@/hooks/wallets/useOnboard' -import { logError, Errors } from '@/services/exceptions' -import { - getClientMeta, - PAIRING_MODULE_STORAGE_ID, - setPairingConnector, - usePairingConnector, - WalletConnectEvents, -} from '@/services/pairing/connector' -import { PAIRING_MODULE_LABEL } from '@/services/pairing/module' -import { formatPairingUri, isPairingSupported, killPairingSession } from '@/services/pairing/utils' -import WalletConnect from '@walletconnect/client' -import { WC_BRIDGE } from '@/config/constants' -import local from '@/services/local-storage/local' - -/** - * `useInitPairing` is responsible for WC session management, creating a session when: - * - * - no wallet is connected to onboard, deemed "initializing" pairing (disconnecting wallets via the UI) - * - on WC 'disconnect' event (disconnecting via the app) - */ - -// First session will be created by onboard's state subscription, only -// when there is no connected wallet -let hasInitialized = false - -// WC has no flag to determine if a session is currently being created -let isConnecting = false - -export const useInitPairing = () => { - const onboard = useOnboard() - const chain = useCurrentChain() - const connector = usePairingConnector() - - const canConnect = !connector?.connected && !isConnecting - const isSupported = isPairingSupported(chain?.disabledWallets) - - useEffect(() => { - const _pairingConnector = new WalletConnect({ - bridge: WC_BRIDGE, - storageId: local.getPrefixedKey(PAIRING_MODULE_STORAGE_ID), - clientMeta: getClientMeta(), - }) - - setPairingConnector(_pairingConnector) - }, []) - - const createSession = useCallback(() => { - if (!canConnect || !chain || !isSupported || !onboard) { - return - } - - isConnecting = true - connector - ?.createSession({ chainId: +chain.chainId }) - .then(() => { - isConnecting = false - }) - .catch((e) => logError(Errors._303, e)) - }, [canConnect, chain, isSupported, onboard, connector]) - - useEffect(() => { - if (!onboard || !isSupported) { - return - } - - // Upon successful WC connection, connect it to onboard - connector?.on(WalletConnectEvents.CONNECT, () => { - connectWallet(onboard, { - autoSelect: { - label: PAIRING_MODULE_LABEL, - disableModals: true, - }, - }) - }) - - connector?.on(WalletConnectEvents.DISCONNECT, () => { - createSession() - }) - - // Create new session when no wallet is connected to onboard - const subscription = onboard.state.select('wallets').subscribe((wallets) => { - if (!getConnectedWallet(wallets) && !hasInitialized) { - createSession() - hasInitialized = true - } - }) - - return () => { - subscription.unsubscribe() - } - }, [onboard, createSession, isSupported, connector]) - - /** - * It's not possible to update the `chainId` of the current WC session - * We therefore kill the current session when switching chain to trigger - * a new `createSession` above - */ - useEffect(() => { - // We need to wait for chains to have been fetched before killing the session - if (!chain) { - return - } - - const isConnected = +chain.chainId === connector?.chainId - const shouldKillSession = !isSupported || (!isConnected && hasInitialized && canConnect) - - if (!shouldKillSession || !connector) { - return - } - - killPairingSession(connector) - }, [chain, isSupported, canConnect, connector]) -} - -/** - * `usePairingUri` is responsible for returning to pairing URI - * @returns uri - "safe-" prefixed WC connection URI - */ -const usePairingUri = () => { - const connector = usePairingConnector() - const [uri, setUri] = useState(connector ? formatPairingUri(connector.uri) : undefined) - - useEffect(() => { - connector?.on(WalletConnectEvents.DISPLAY_URI, (_, { params }) => { - setUri(formatPairingUri(params[0])) - }) - - // Prevent the `connector` from setting state when not mounted. - // Note: `off` clears _all_ listeners associated with that event - return () => { - connector?.off(WalletConnectEvents.DISPLAY_URI) - } - }, [connector]) - - return uri -} - -export default usePairingUri diff --git a/src/services/pairing/icon.ts b/src/services/pairing/icon.ts deleted file mode 100644 index b7ddc80874..0000000000 --- a/src/services/pairing/icon.ts +++ /dev/null @@ -1,8 +0,0 @@ -const pairingIcon = ` - - - - -` - -export default pairingIcon diff --git a/src/services/pairing/module.ts b/src/services/pairing/module.ts deleted file mode 100644 index add033b65c..0000000000 --- a/src/services/pairing/module.ts +++ /dev/null @@ -1,257 +0,0 @@ -import type { Chain, ProviderAccounts, WalletInit, EIP1193Provider } from '@web3-onboard/common' -// @ts-expect-error - with native WalletConnect v2, the type is no longer present -import type { ITxData } from '@walletconnect/types' - -import { getPairingConnector, PAIRING_MODULE_STORAGE_ID } from '@/services/pairing/connector' -import local from '@/services/local-storage/local' -import { killPairingSession } from '@/services/pairing/utils' -import * as QRModal from '@/services/pairing/QRModal' - -enum ProviderEvents { - ACCOUNTS_CHANGED = 'accountsChanged', - CHAIN_CHANGED = 'chainChanged', - DISCONNECT = 'disconnect', - CONNECT = 'connect', - WC_SESSION_UPDATE = 'session_update', -} - -enum ProviderMethods { - PERSONAL_SIGN = 'personal_sign', - ETH_CHAIN_ID = 'eth_chainId', - ETH_REQUEST_ACCOUNTS = 'eth_requestAccounts', - ETH_SELECT_ACCOUNTS = 'eth_selectAccounts', - ETH_SEND_TRANSACTION = 'eth_sendTransaction', - ETH_SIGN_TRANSACTION = 'eth_signTransaction', - ETH_SIGN = 'eth_sign', - ETH_SIGN_TYPED_DATA = 'eth_signTypedData', - ETH_SIGN_TYPED_DATA_V3 = 'eth_signTypedData_v3', - ETH_SIGN_TYPED_DATA_V4 = 'eth_signTypedData_v4', - ETH_ACCOUNTS = 'eth_accounts', - WALLET_SWITCH_ETHEREUM_CHAIN = 'wallet_switchEthereumChain', -} - -export const PAIRING_MODULE_LABEL = 'Safe{Wallet}' - -// Modified version of: https://github.com/blocknative/web3-onboard/blob/v2-web3-onboard-develop/packages/walletconnect/src/index.ts -const pairingModule = (): WalletInit => { - return () => { - return { - label: PAIRING_MODULE_LABEL, - getIcon: async () => (await import('./icon')).default, - getInterface: async ({ chains, EventEmitter }) => { - const { StaticJsonRpcProvider } = await import('@ethersproject/providers') - - const { ProviderRpcError, ProviderRpcErrorCode } = await import('@web3-onboard/common') - - const { default: WalletConnect } = await import('@walletconnect/client') - - const { Subject, fromEvent } = await import('rxjs') - const { takeUntil, take } = await import('rxjs/operators') - - const emitter = new EventEmitter() - - class EthProvider { - public request: EIP1193Provider['request'] - public connector: InstanceType - public chains: Chain[] - public disconnect: EIP1193Provider['disconnect'] - // @ts-expect-error - 'emit' does not exist on `typeof EventEmitter` - public emit: EventEmitter['emit'] - // @ts-expect-error - 'on' does not exist on `typeof EventEmitter` - public on: EventEmitter['on'] - // @ts-expect-error - 'removeListener' does not exist on `typeof EventEmitter` - public removeListener: EventEmitter['removeListener'] - - private disconnected$: InstanceType - private providers: Record> - - constructor({ connector, chains }: { connector: InstanceType; chains: Chain[] }) { - this.emit = emitter.emit.bind(emitter) - this.on = emitter.on.bind(emitter) - this.removeListener = emitter.removeListener.bind(emitter) - - this.connector = connector - this.chains = chains - this.disconnected$ = new Subject() - this.providers = {} - - // @ts-expect-error - `payload` type (`ISessionStatus`) is not correctly `pipe`ed - fromEvent(this.connector, ProviderEvents.WC_SESSION_UPDATE, (error, payload) => { - if (error) { - throw error - } - - return payload - }) - .pipe(takeUntil(this.disconnected$)) - .subscribe({ - next: ({ params }) => { - const [{ accounts, chainId }] = params - - this.emit(ProviderEvents.ACCOUNTS_CHANGED, accounts) - this.emit(ProviderEvents.CHAIN_CHANGED, `0x${chainId.toString(16)}`) - }, - error: console.warn, - }) - - // @ts-expect-error - `this.connector` does not satisfy the event target type - fromEvent(this.connector, ProviderEvents.DISCONNECT, (error, payload) => { - if (error) { - throw error - } - - return payload - }) - .pipe(takeUntil(this.disconnected$)) - .subscribe({ - next: () => { - this.emit(ProviderEvents.ACCOUNTS_CHANGED, []) - - this.disconnected$.next(true) - - local.removeItem(PAIRING_MODULE_STORAGE_ID) - }, - error: console.warn, - }) - - fromEvent(window, 'unload').subscribe(() => { - this.disconnect?.() - }) - - this.disconnect = () => killPairingSession(this.connector) - - this.request = async ({ method, params }) => { - switch (method) { - case ProviderMethods.ETH_CHAIN_ID: { - return `0x${this.connector.chainId.toString(16)}` - } - - case ProviderMethods.ETH_REQUEST_ACCOUNTS: { - return new Promise((resolve, reject) => { - if (!this.connector.connected) { - this.connector.createSession().then(() => { - QRModal.open(() => - reject( - new ProviderRpcError({ - code: 4001, - message: 'User rejected the request.', - }), - ), - ) - }) - } else { - const { accounts, chainId } = this.connector.session - - this.emit(ProviderEvents.CHAIN_CHANGED, `0x${chainId.toString(16)}`) - - return resolve(accounts) - } - - // @ts-ignore - fromEvent(this.connector, ProviderEvents.CONNECT, (error, payload) => { - if (error) { - throw error - } - - return payload - }) - .pipe(take(1)) - .subscribe({ - next: ({ params }) => { - const [{ accounts, chainId }] = params - - this.emit(ProviderEvents.ACCOUNTS_CHANGED, accounts) - this.emit(ProviderEvents.CHAIN_CHANGED, `0x${chainId.toString(16)}`) - - QRModal.close() - - resolve(accounts) - }, - error: reject, - }) - }) - } - - case ProviderMethods.ETH_SEND_TRANSACTION: { - const txData = params![0] as ITxData - - return this.connector.sendTransaction({ - ...txData, - // Mobile app expects `value` - value: txData.value || '0x0', - }) - } - - case ProviderMethods.ETH_SIGN_TRANSACTION: { - return this.connector.signTransaction(params![0] as ITxData) - } - - // Mobile app only supports `eth_sign` but emits `personal_sign` event - case ProviderMethods.PERSONAL_SIGN: { - const [safeTxHash, sender] = params as [string, string] - return this.connector.signMessage([sender, safeTxHash]) // `eth_sign` - } - - case ProviderMethods.ETH_ACCOUNTS: { - return this.connector.sendCustomRequest({ - id: 1337, - jsonrpc: '2.0', - method, - params, - }) - } - - // Not supported by mobile app - case ProviderMethods.ETH_SIGN: - case ProviderMethods.ETH_SIGN_TYPED_DATA: - case ProviderMethods.ETH_SIGN_TYPED_DATA_V3: - case ProviderMethods.ETH_SIGN_TYPED_DATA_V4: - // Not supported by WC - case ProviderMethods.ETH_SELECT_ACCOUNTS: { - throw new ProviderRpcError({ - code: ProviderRpcErrorCode.UNSUPPORTED_METHOD, - message: `Safe{Wallet} mobile does not support the requested method: ${method}`, - }) - } - - // Switch wallet chain - case ProviderMethods.WALLET_SWITCH_ETHEREUM_CHAIN: { - this.connector.updateSession({ - chainId: parseInt((params as [{ chainId: string }])[0].chainId), - accounts: this.connector.accounts, - }) - return - } - - default: { - const chainId = await this.request({ method: ProviderMethods.ETH_CHAIN_ID }) - - if (!this.providers[chainId]) { - const currentChain = chains.find(({ id }) => id === chainId) - - if (!currentChain) { - throw new ProviderRpcError({ - code: ProviderRpcErrorCode.CHAIN_NOT_ADDED, - message: `The Provider does not have an RPC to request the method: ${method}`, - }) - } - - this.providers[chainId] = new StaticJsonRpcProvider(currentChain.rpcUrl) - } - - return this.providers[chainId].send(method, params!) - } - } - } - } - } - - return { - provider: new EthProvider({ chains, connector: getPairingConnector()! }), - } - }, - } - } -} - -export default pairingModule diff --git a/src/services/pairing/utils.ts b/src/services/pairing/utils.ts deleted file mode 100644 index 4423a2cfa5..0000000000 --- a/src/services/pairing/utils.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { addDays, isAfter } from 'date-fns' -// @ts-expect-error - with native WalletConnect v2, the type is no longer present -import type { IWalletConnectSession } from '@walletconnect/types' -import type WalletConnect from '@walletconnect/client' - -import { CGW_NAMES, WALLET_KEYS } from '@/hooks/wallets/consts' -import local from '@/services/local-storage/local' -import { PAIRING_MODULE_STORAGE_ID } from '@/services/pairing/connector' - -export const formatPairingUri = (wcUri: string) => { - const PAIRING_MODULE_URI_PREFIX = 'safe-' - - // A disconnected session returns URI with an empty `key` - if (!wcUri || !/key=.+/.test(wcUri)) { - return - } - - return `${PAIRING_MODULE_URI_PREFIX}${wcUri}` -} - -export const killPairingSession = (connector: InstanceType) => { - const TEMP_PEER_ID = '_tempPeerId' - - // WalletConnect throws if no `peerId` is set when attempting to `killSession` - // We therefore manually set it in order to `killSession` without throwing - if (!connector.peerId) { - connector.peerId = TEMP_PEER_ID - } - - return connector.killSession() -} - -export const isPairingSupported = (disabledWallets?: string[]) => { - return disabledWallets && !disabledWallets.includes(CGW_NAMES[WALLET_KEYS.PAIRING] as string) -} - -export const _isPairingSessionExpired = (session: IWalletConnectSession): boolean => { - // WC appends 3 digits to the timestamp. NOTE: This may change in WC v2 - const sessionTimestamp = session.handshakeId.toString().slice(0, -3) - // The session is valid for 24h (mobile clears it on their end) - const expirationDate = addDays(new Date(+sessionTimestamp), 1) - - return isAfter(Date.now(), expirationDate) -} - -export const hasValidPairingSession = (): boolean => { - const cachedSession = local.getItem(PAIRING_MODULE_STORAGE_ID) - - if (!cachedSession) { - return false - } - - const isExpired = _isPairingSessionExpired(cachedSession) - - if (isExpired) { - local.removeItem(PAIRING_MODULE_STORAGE_ID) - } - - return !isExpired -} diff --git a/src/styles/globals.css b/src/styles/globals.css index 91c240e053..dc82e39803 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -35,7 +35,6 @@ button { :root { --header-height: 52px; --footer-height: 67px; - --import-export-widget-height: 166px; } input::-webkit-outer-spin-button, diff --git a/yarn.lock b/yarn.lock index 86e2841099..96c67791a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1948,31 +1948,6 @@ dependencies: "@ethersproject/logger" "^5.7.0" -"@ethersproject/providers@5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.0.tgz#bc2876a8fe5e0053ed9828b1f3767ae46e43758b" - integrity sha512-xqMbDnS/FPy+J/9mBLKddzyLLAQFjrVff5g00efqxPzcAwXiR+SiCGVy6eJ5iAIirBOATjx7QLhDNPGV+AEQsw== - dependencies: - "@ethersproject/abstract-provider" "^5.5.0" - "@ethersproject/abstract-signer" "^5.5.0" - "@ethersproject/address" "^5.5.0" - "@ethersproject/basex" "^5.5.0" - "@ethersproject/bignumber" "^5.5.0" - "@ethersproject/bytes" "^5.5.0" - "@ethersproject/constants" "^5.5.0" - "@ethersproject/hash" "^5.5.0" - "@ethersproject/logger" "^5.5.0" - "@ethersproject/networks" "^5.5.0" - "@ethersproject/properties" "^5.5.0" - "@ethersproject/random" "^5.5.0" - "@ethersproject/rlp" "^5.5.0" - "@ethersproject/sha2" "^5.5.0" - "@ethersproject/strings" "^5.5.0" - "@ethersproject/transactions" "^5.5.0" - "@ethersproject/web" "^5.5.0" - bech32 "1.1.4" - ws "7.4.6" - "@ethersproject/providers@5.5.2": version "5.5.2" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.5.2.tgz#131ccf52dc17afd0ab69ed444b8c0e3a27297d99" @@ -2791,6 +2766,11 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@ioredis/commands@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" + integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -3696,6 +3676,98 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.3.tgz#00d7a8cf35a475b160b3f0293a6403c511099364" integrity sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg== +"@parcel/watcher-android-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.3.0.tgz#d82e74bb564ebd4d8a88791d273a3d2bd61e27ab" + integrity sha512-f4o9eA3dgk0XRT3XhB0UWpWpLnKgrh1IwNJKJ7UJek7eTYccQ8LR7XUWFKqw6aEq5KUNlCcGvSzKqSX/vtWVVA== + +"@parcel/watcher-darwin-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz#c9cd03f8f233d512fcfc873d5b4e23f1569a82ad" + integrity sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw== + +"@parcel/watcher-darwin-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.3.0.tgz#83c902994a2a49b9e1ab5050dba24876fdc2c219" + integrity sha512-20oBj8LcEOnLE3mgpy6zuOq8AplPu9NcSSSfyVKgfOhNAc4eF4ob3ldj0xWjGGbOF7Dcy1Tvm6ytvgdjlfUeow== + +"@parcel/watcher-freebsd-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.3.0.tgz#7a0f4593a887e2752b706aff2dae509aef430cf6" + integrity sha512-7LftKlaHunueAEiojhCn+Ef2CTXWsLgTl4hq0pkhkTBFI3ssj2bJXmH2L67mKpiAD5dz66JYk4zS66qzdnIOgw== + +"@parcel/watcher-linux-arm-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.3.0.tgz#3fc90c3ebe67de3648ed2f138068722f9b1d47da" + integrity sha512-1apPw5cD2xBv1XIHPUlq0cO6iAaEUQ3BcY0ysSyD9Kuyw4MoWm1DV+W9mneWI+1g6OeP6dhikiFE6BlU+AToTQ== + +"@parcel/watcher-linux-arm64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.3.0.tgz#f7bbbf2497d85fd11e4c9e9c26ace8f10ea9bcbc" + integrity sha512-mQ0gBSQEiq1k/MMkgcSB0Ic47UORZBmWoAWlMrTW6nbAGoLZP+h7AtUM7H3oDu34TBFFvjy4JCGP43JlylkTQA== + +"@parcel/watcher-linux-arm64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.3.0.tgz#de131a9fcbe1fa0854e9cbf4c55bed3b35bcff43" + integrity sha512-LXZAExpepJew0Gp8ZkJ+xDZaTQjLHv48h0p0Vw2VMFQ8A+RKrAvpFuPVCVwKJCr5SE+zvaG+Etg56qXvTDIedw== + +"@parcel/watcher-linux-x64-glibc@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.3.0.tgz#193dd1c798003cdb5a1e59470ff26300f418a943" + integrity sha512-P7Wo91lKSeSgMTtG7CnBS6WrA5otr1K7shhSjKHNePVmfBHDoAOHYRXgUmhiNfbcGk0uMCHVcdbfxtuiZCHVow== + +"@parcel/watcher-linux-x64-musl@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.3.0.tgz#6dbdb86d96e955ab0fe4a4b60734ec0025a689dd" + integrity sha512-+kiRE1JIq8QdxzwoYY+wzBs9YbJ34guBweTK8nlzLKimn5EQ2b2FSC+tAOpq302BuIMjyuUGvBiUhEcLIGMQ5g== + +"@parcel/watcher-wasm@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-wasm/-/watcher-wasm-2.3.0.tgz#73b66c6fbd2a3326ae86a1ec77eab7139d0dd725" + integrity sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA== + dependencies: + is-glob "^4.0.3" + micromatch "^4.0.5" + napi-wasm "^1.1.0" + +"@parcel/watcher-win32-arm64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.3.0.tgz#59da26a431da946e6c74fa6b0f30b120ea6650b6" + integrity sha512-35gXCnaz1AqIXpG42evcoP2+sNL62gZTMZne3IackM+6QlfMcJLy3DrjuL6Iks7Czpd3j4xRBzez3ADCj1l7Aw== + +"@parcel/watcher-win32-ia32@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.3.0.tgz#3ee6a18b08929cd3b788e8cc9547fd9a540c013a" + integrity sha512-FJS/IBQHhRpZ6PiCjFt1UAcPr0YmCLHRbTc00IBTrelEjlmmgIVLeOx4MSXzx2HFEy5Jo5YdhGpxCuqCyDJ5ow== + +"@parcel/watcher-win32-x64@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz#14e7246289861acc589fd608de39fe5d8b4bb0a7" + integrity sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA== + +"@parcel/watcher@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.3.0.tgz#803517abbc3981a1a1221791d9f59dc0590d50f9" + integrity sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.3.0" + "@parcel/watcher-darwin-arm64" "2.3.0" + "@parcel/watcher-darwin-x64" "2.3.0" + "@parcel/watcher-freebsd-x64" "2.3.0" + "@parcel/watcher-linux-arm-glibc" "2.3.0" + "@parcel/watcher-linux-arm64-glibc" "2.3.0" + "@parcel/watcher-linux-arm64-musl" "2.3.0" + "@parcel/watcher-linux-x64-glibc" "2.3.0" + "@parcel/watcher-linux-x64-musl" "2.3.0" + "@parcel/watcher-win32-arm64" "2.3.0" + "@parcel/watcher-win32-ia32" "2.3.0" + "@parcel/watcher-win32-x64" "2.3.0" + "@polka/url@^1.0.0-next.20": version "1.0.0-next.23" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.23.tgz#498e41218ab3b6a1419c735e5c6ae2c5ed609b6c" @@ -5615,27 +5687,6 @@ events "^3.3.0" isomorphic-unfetch "^3.1.0" -"@walletconnect/browser-utils@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951" - integrity sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A== - dependencies: - "@walletconnect/safe-json" "1.0.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/window-getters" "1.0.0" - "@walletconnect/window-metadata" "1.0.0" - detect-browser "5.2.0" - -"@walletconnect/client@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.8.0.tgz#6f46b5499c7c861c651ff1ebe5da5b66225ca696" - integrity sha512-svyBQ14NHx6Cs2j4TpkQaBI/2AF4+LXz64FojTjMtV4VMMhl81jSO1vNeg+yYhQzvjcGH/GpSwixjyCW0xFBOQ== - dependencies: - "@walletconnect/core" "^1.8.0" - "@walletconnect/iso-crypto" "^1.8.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - "@walletconnect/core@2.10.2", "@walletconnect/core@^2.10.1": version "2.10.2" resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.10.2.tgz#a1bf6e3e87b33f9df795ce0970d8ddd400fdc8a3" @@ -5658,35 +5709,27 @@ lodash.isequal "4.5.0" uint8arrays "^3.1.0" -"@walletconnect/core@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.8.0.tgz#6b2748b90c999d9d6a70e52e26a8d5e8bfeaa81e" - integrity sha512-aFTHvEEbXcZ8XdWBw6rpQDte41Rxwnuk3SgTD8/iKGSRTni50gI9S3YEzMj05jozSiOBxQci4pJDMVhIUMtarw== +"@walletconnect/core@2.10.5": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.10.5.tgz#d61706c6459d9baaef05e83907df8cab82a03251" + integrity sha512-QnGHkA05KzJrtqExPqXm/TsstM1uTDI8tQT0x86/DuR6LdiYEntzSpVjnv7kKK6Mo9UxlXfud431dNRfOW5uJg== dependencies: - "@walletconnect/socket-transport" "^1.8.0" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - -"@walletconnect/crypto@^1.0.2": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@walletconnect/crypto/-/crypto-1.0.3.tgz#7b8dd4d7e2884fe3543c7c07aea425eef5ef9dd4" - integrity sha512-+2jdORD7XQs76I2Odgr3wwrtyuLUXD/kprNVsjWRhhhdO9Mt6WqVzOPu0/t7OHSmgal8k7SoBQzUc5hu/8zL/g== - dependencies: - "@walletconnect/encoding" "^1.0.2" - "@walletconnect/environment" "^1.0.1" - "@walletconnect/randombytes" "^1.0.3" - aes-js "^3.1.2" - hash.js "^1.1.7" - tslib "1.14.1" - -"@walletconnect/encoding@^1.0.1", "@walletconnect/encoding@^1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@walletconnect/encoding/-/encoding-1.0.2.tgz#cb3942ad038d6a6bf01158f66773062dd25724da" - integrity sha512-CrwSBrjqJ7rpGQcTL3kU+Ief+Bcuu9PH6JLOb+wM6NITX1GTxR/MfNwnQfhLKK6xpRAyj2/nM04OOH6wS8Imag== - dependencies: - is-typedarray "1.0.0" - tslib "1.14.1" - typedarray-to-buffer "3.1.5" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-provider" "1.0.13" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/jsonrpc-ws-connection" "1.0.14" + "@walletconnect/keyvaluestorage" "^1.1.1" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/relay-auth" "^1.0.4" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.10.5" + "@walletconnect/utils" "2.10.5" + events "^3.3.0" + lodash.isequal "4.5.0" + uint8arrays "^3.1.0" "@walletconnect/environment@^1.0.1": version "1.0.1" @@ -5695,19 +5738,20 @@ dependencies: tslib "1.14.1" -"@walletconnect/ethereum-provider@^2.10.1": - version "2.10.2" - resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.2.tgz#d5aca538fbcbbf7dd771bceb2430de30f06411de" - integrity sha512-QMYFZ6+rVq2CJLdIPdKK0j1Qm66UA27oQU5V2SrL8EVwl7wFfm0Bq7fnL+qAWeDpn612dNeNErpk/ROa1zWlWg== +"@walletconnect/ethereum-provider@^2.10.2": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/ethereum-provider/-/ethereum-provider-2.10.5.tgz#a14ede16a751f115f8a0d050736155c8654835d5" + integrity sha512-Pihi2M03cRkWEiGetRUiO2A506YTj/Bbbxp+Ct7t5N5SccoeuhrzsEt30pA7I0XAiOnAeKp79OKmXHRhXfRmhg== dependencies: "@walletconnect/jsonrpc-http-connection" "^1.0.7" "@walletconnect/jsonrpc-provider" "^1.0.13" "@walletconnect/jsonrpc-types" "^1.0.3" "@walletconnect/jsonrpc-utils" "^1.0.8" - "@walletconnect/sign-client" "2.10.2" - "@walletconnect/types" "2.10.2" - "@walletconnect/universal-provider" "2.10.2" - "@walletconnect/utils" "2.10.2" + "@walletconnect/modal" "^2.4.3" + "@walletconnect/sign-client" "2.10.5" + "@walletconnect/types" "2.10.5" + "@walletconnect/universal-provider" "2.10.5" + "@walletconnect/utils" "2.10.5" events "^3.3.0" "@walletconnect/events@^1.0.1": @@ -5727,15 +5771,6 @@ "@walletconnect/time" "^1.0.2" tslib "1.14.1" -"@walletconnect/iso-crypto@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.8.0.tgz#44ddf337c4f02837c062dbe33fa7ab36789df451" - integrity sha512-pWy19KCyitpfXb70hA73r9FcvklS+FvO9QUIttp3c2mfW8frxgYeRXfxLRCIQTkaYueRKvdqPjbyhPLam508XQ== - dependencies: - "@walletconnect/crypto" "^1.0.2" - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - "@walletconnect/jsonrpc-http-connection@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-http-connection/-/jsonrpc-http-connection-1.0.7.tgz#a6973569b8854c22da707a759d241e4f5c2d5a98" @@ -5763,7 +5798,7 @@ keyvaluestorage-interface "^1.0.0" tslib "1.14.1" -"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.3", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": +"@walletconnect/jsonrpc-utils@1.0.8", "@walletconnect/jsonrpc-utils@^1.0.6", "@walletconnect/jsonrpc-utils@^1.0.7", "@walletconnect/jsonrpc-utils@^1.0.8": version "1.0.8" resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.8.tgz#82d0cc6a5d6ff0ecc277cb35f71402c91ad48d72" integrity sha512-vdeb03bD8VzJUL6ZtzRYsFMq1eZQcM3EAzT0a3st59dyLfJ0wq+tKMpmGH7HlB7waD858UWgfIcudbPFsbzVdw== @@ -5783,6 +5818,16 @@ tslib "1.14.1" ws "^7.5.1" +"@walletconnect/jsonrpc-ws-connection@1.0.14": + version "1.0.14" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-ws-connection/-/jsonrpc-ws-connection-1.0.14.tgz#eec700e74766c7887de2bd76c91a0206628732aa" + integrity sha512-Jsl6fC55AYcbkNVkwNM6Jo+ufsuCQRqViOQ8ZBPH9pRREHH9welbBiszuTLqEJiQcO/6XfFDl6bzCJIkrEi8XA== + dependencies: + "@walletconnect/jsonrpc-utils" "^1.0.6" + "@walletconnect/safe-json" "^1.0.2" + events "^3.3.0" + ws "^7.5.1" + "@walletconnect/keyvaluestorage@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.0.2.tgz#92f5ca0f54c1a88a093778842ce0c874d86369c8" @@ -5791,6 +5836,15 @@ safe-json-utils "^1.1.1" tslib "1.14.1" +"@walletconnect/keyvaluestorage@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@walletconnect/keyvaluestorage/-/keyvaluestorage-1.1.1.tgz#dd2caddabfbaf80f6b8993a0704d8b83115a1842" + integrity sha512-V7ZQq2+mSxAq7MrRqDxanTzu2RcElfK1PfNYiaVnJgJ7Q7G7hTVwF8voIBx92qsRyGHZihrwNPHuZd1aKkd0rA== + dependencies: + "@walletconnect/safe-json" "^1.0.1" + idb-keyval "^6.2.1" + unstorage "^1.9.0" + "@walletconnect/logger@2.0.1", "@walletconnect/logger@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.0.1.tgz#7f489b96e9a1ff6bf3e58f0fbd6d69718bf844a8" @@ -5799,11 +5853,6 @@ pino "7.11.0" tslib "1.14.1" -"@walletconnect/mobile-registry@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@walletconnect/mobile-registry/-/mobile-registry-1.4.0.tgz#502cf8ab87330841d794819081e748ebdef7aee5" - integrity sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw== - "@walletconnect/modal-core@2.6.2": version "2.6.2" resolved "https://registry.yarnpkg.com/@walletconnect/modal-core/-/modal-core-2.6.2.tgz#d73e45d96668764e0c8668ea07a45bb8b81119e9" @@ -5821,7 +5870,7 @@ motion "10.16.2" qrcode "1.5.3" -"@walletconnect/modal@2.6.2": +"@walletconnect/modal@2.6.2", "@walletconnect/modal@^2.4.3": version "2.6.2" resolved "https://registry.yarnpkg.com/@walletconnect/modal/-/modal-2.6.2.tgz#4b534a836f5039eeb3268b80be7217a94dd12651" integrity sha512-eFopgKi8AjKf/0U4SemvcYw9zlLpx9njVN8sf6DAkowC2Md0gPU/UNEbH1Wwj407pEKnEds98pKWib1NN1ACoA== @@ -5829,28 +5878,6 @@ "@walletconnect/modal-core" "2.6.2" "@walletconnect/modal-ui" "2.6.2" -"@walletconnect/qrcode-modal@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/qrcode-modal/-/qrcode-modal-1.8.0.tgz#ddd6f5c9b7ee52c16adf9aacec2a3eac4994caea" - integrity sha512-BueaFefaAi8mawE45eUtztg3ZFbsAH4DDXh1UNwdUlsvFMjqcYzLUG0xZvDd6z2eOpbgDg2N3bl6gF0KONj1dg== - dependencies: - "@walletconnect/browser-utils" "^1.8.0" - "@walletconnect/mobile-registry" "^1.4.0" - "@walletconnect/types" "^1.8.0" - copy-to-clipboard "^3.3.1" - preact "10.4.1" - qrcode "1.4.4" - -"@walletconnect/randombytes@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@walletconnect/randombytes/-/randombytes-1.0.3.tgz#e795e4918367fd1e6a2215e075e64ab93e23985b" - integrity sha512-35lpzxcHFbTN3ABefC9W+uBpNZl1GC4Wpx0ed30gibfO/y9oLdy1NznbV96HARQKSBV9J9M/rrtIvf6a23jfYw== - dependencies: - "@walletconnect/encoding" "^1.0.2" - "@walletconnect/environment" "^1.0.1" - randombytes "^2.1.0" - tslib "1.14.1" - "@walletconnect/relay-api@^1.0.9": version "1.0.9" resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.9.tgz#f8c2c3993dddaa9f33ed42197fc9bfebd790ecaf" @@ -5871,11 +5898,6 @@ tslib "1.14.1" uint8arrays "^3.0.0" -"@walletconnect/safe-json@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.0.tgz#12eeb11d43795199c045fafde97e3c91646683b2" - integrity sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg== - "@walletconnect/safe-json@^1.0.1", "@walletconnect/safe-json@^1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.2.tgz#7237e5ca48046e4476154e503c6d3c914126fa77" @@ -5898,14 +5920,20 @@ "@walletconnect/utils" "2.10.2" events "^3.3.0" -"@walletconnect/socket-transport@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.8.0.tgz#9a1128a249628a0be11a0979b522fe82b44afa1b" - integrity sha512-5DyIyWrzHXTcVp0Vd93zJ5XMW61iDM6bcWT4p8DTRfFsOtW46JquruMhxOLeCOieM4D73kcr3U7WtyR4JUsGuQ== +"@walletconnect/sign-client@2.10.5": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.10.5.tgz#f97f0fed544179a3303941f3bebd13ede3a736ed" + integrity sha512-HEYsoeGC6fGplQy0NIZSRNHgOwZwQ892UWG1Ahkcasf2R35QaBgnTVQkSCisl1PAAOKXZG7yB1YDoAAZBF+g5Q== dependencies: - "@walletconnect/types" "^1.8.0" - "@walletconnect/utils" "^1.8.0" - ws "7.5.3" + "@walletconnect/core" "2.10.5" + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-utils" "1.0.8" + "@walletconnect/logger" "^2.0.1" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.10.5" + "@walletconnect/utils" "2.10.5" + events "^3.3.0" "@walletconnect/time@^1.0.2": version "1.0.2" @@ -5926,24 +5954,36 @@ "@walletconnect/logger" "^2.0.1" events "^3.3.0" -"@walletconnect/types@^1.8.0", "@walletconnect/types@~1.8.0": +"@walletconnect/types@2.10.5": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.10.5.tgz#bf4e692cf736b6e71423f96a106d7a96089245de" + integrity sha512-N8xaN7/Kob93rKxKDaT6oy6symgIkAwyLqq0/dLJEhXfv7S/gyNvDka4SosjVVTc4oTvE1+OmxNIR8pB1DuwJw== + dependencies: + "@walletconnect/events" "^1.0.1" + "@walletconnect/heartbeat" "1.2.1" + "@walletconnect/jsonrpc-types" "1.0.3" + "@walletconnect/keyvaluestorage" "^1.1.1" + "@walletconnect/logger" "^2.0.1" + events "^3.3.0" + +"@walletconnect/types@~1.8.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195" integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg== -"@walletconnect/universal-provider@2.10.2": - version "2.10.2" - resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.2.tgz#85c8da39f65da8fe33f65f62689e703607b5ddc5" - integrity sha512-wFgI0LbQ3D56sgaUMsgOHCM5m8WLxiC71BGuCKQfApgsbNMVKugYVy2zWHyUyi8sqTQHI+uSaVpDev4UHq9LEw== +"@walletconnect/universal-provider@2.10.5": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.10.5.tgz#b08965a9306a30775796cc0cc384f2dfc9fde512" + integrity sha512-sQOvjrGF6za7+6zv7KI9eQz2gzRbS19j7U1z+JwIWdn4VBJmriaTjVHDz/R1liwKcS4sUiUthDC6WmQvjukjZQ== dependencies: "@walletconnect/jsonrpc-http-connection" "^1.0.7" "@walletconnect/jsonrpc-provider" "1.0.13" "@walletconnect/jsonrpc-types" "^1.0.2" "@walletconnect/jsonrpc-utils" "^1.0.7" "@walletconnect/logger" "^2.0.1" - "@walletconnect/sign-client" "2.10.2" - "@walletconnect/types" "2.10.2" - "@walletconnect/utils" "2.10.2" + "@walletconnect/sign-client" "2.10.5" + "@walletconnect/types" "2.10.5" + "@walletconnect/utils" "2.10.5" events "^3.3.0" "@walletconnect/utils@2.10.2", "@walletconnect/utils@^2.10.1", "@walletconnect/utils@^2.10.2": @@ -5966,18 +6006,25 @@ query-string "7.1.3" uint8arrays "^3.1.0" -"@walletconnect/utils@^1.8.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.8.0.tgz#2591a197c1fa7429941fe428876088fda6632060" - integrity sha512-zExzp8Mj1YiAIBfKNm5u622oNw44WOESzo6hj+Q3apSMIb0Jph9X3GDIdbZmvVZsNPxWDL7uodKgZcCInZv2vA== - dependencies: - "@walletconnect/browser-utils" "^1.8.0" - "@walletconnect/encoding" "^1.0.1" - "@walletconnect/jsonrpc-utils" "^1.0.3" - "@walletconnect/types" "^1.8.0" - bn.js "4.11.8" - js-sha3 "0.8.0" - query-string "6.13.5" +"@walletconnect/utils@2.10.5": + version "2.10.5" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.10.5.tgz#8c8ef90c9e2b59886aae002ab8cbbdb35da1df9a" + integrity sha512-3yeclD9/AlPEIHBqBVzrHUO/KRAEIXVK0ViIQ5oUH+zT3TpdsDGDiW1Z0TsAQ1EiYoiiz8dOQzd80a3eZVwnrg== + dependencies: + "@stablelib/chacha20poly1305" "1.0.1" + "@stablelib/hkdf" "1.0.1" + "@stablelib/random" "^1.0.2" + "@stablelib/sha256" "1.0.1" + "@stablelib/x25519" "^1.0.3" + "@walletconnect/relay-api" "^1.0.9" + "@walletconnect/safe-json" "^1.0.2" + "@walletconnect/time" "^1.0.2" + "@walletconnect/types" "2.10.5" + "@walletconnect/window-getters" "^1.0.1" + "@walletconnect/window-metadata" "^1.0.1" + detect-browser "5.3.0" + query-string "7.1.3" + uint8arrays "^3.1.0" "@walletconnect/web3wallet@^1.9.2": version "1.9.2" @@ -5993,25 +6040,13 @@ "@walletconnect/types" "2.10.2" "@walletconnect/utils" "2.10.2" -"@walletconnect/window-getters@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.0.tgz#1053224f77e725dfd611c83931b5f6c98c32bfc8" - integrity sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA== - -"@walletconnect/window-getters@^1.0.0", "@walletconnect/window-getters@^1.0.1": +"@walletconnect/window-getters@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== dependencies: tslib "1.14.1" -"@walletconnect/window-metadata@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.0.tgz#93b1cc685e6b9b202f29c26be550fde97800c4e5" - integrity sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA== - dependencies: - "@walletconnect/window-getters" "^1.0.0" - "@walletconnect/window-metadata@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.1.tgz#2124f75447b7e989e4e4e1581d55d25bc75f7be5" @@ -6118,16 +6153,13 @@ ethereumjs-util "^7.1.3" hdkey "^2.0.1" -"@web3-onboard/walletconnect@^2.4.7": - version "2.4.7" - resolved "https://registry.yarnpkg.com/@web3-onboard/walletconnect/-/walletconnect-2.4.7.tgz#e7b0c6494b5414fbf6450689941a01cb1eb7898c" - integrity sha512-Fh0tej56icsjTu0t0njoebXa/yZ7KGIQxfaTD31s/LsbUXMiyMFwqvyYQEaD1dvKlPMWLj/4AgRQlYYHTqjLLg== +"@web3-onboard/walletconnect@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@web3-onboard/walletconnect/-/walletconnect-2.5.0.tgz#3370079a1366c196d5d089d754e54bb6f2c04a01" + integrity sha512-cD5OZYPCg1tvG/mevsEnBauhPK/TJQALru7S6fCB4IpML8tcIf3bk0S+0caZdOlqK+UfOT2P/iiQrIh8OKZ01g== dependencies: - "@ethersproject/providers" "5.5.0" - "@walletconnect/client" "^1.8.0" - "@walletconnect/ethereum-provider" "^2.10.1" + "@walletconnect/ethereum-provider" "^2.10.2" "@walletconnect/modal" "2.6.2" - "@walletconnect/qrcode-modal" "^1.8.0" "@web3-onboard/common" "^2.3.3" joi "17.9.1" rxjs "^7.5.2" @@ -6445,16 +6477,16 @@ acorn@^8.0.4, acorn@^8.1.0, acorn@^8.4.1, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8 resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.10.0.tgz#8be5b3907a67221a81ab23c7889c4c5526b62ec5" integrity sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw== +acorn@^8.10.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + aes-js@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== -aes-js@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -6514,17 +6546,12 @@ ansi-escapes@^4.2.1, ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -6543,7 +6570,7 @@ ansi-styles@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== -anymatch@^3.0.3, anymatch@~3.1.2: +anymatch@^3.0.3, anymatch@^3.1.3, anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== @@ -7095,11 +7122,6 @@ bn.js@4.11.6: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" integrity sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA== -bn.js@4.11.8: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - bn.js@^4.11.0, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.12.0: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -7267,30 +7289,12 @@ btoa@^1.2.1: resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-crc32@~0.2.3: version "0.2.13" resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ== - -buffer-from@^1.0.0, buffer-from@^1.1.1: +buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== @@ -7318,7 +7322,7 @@ buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -buffer@^5.0.5, buffer@^5.1.0, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: +buffer@^5.0.5, buffer@^5.1.0, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -7472,7 +7476,7 @@ checkpoint-store@^1.1.0: dependencies: functional-red-black-tree "^1.0.1" -"chokidar@>=3.0.0 <4.0.0": +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -7521,6 +7525,13 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" +citty@^0.1.3, citty@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.4.tgz#91091be06ae4951dffa42fd443de7fe72245f2e0" + integrity sha512-Q3bK1huLxzQrvj7hImJ7Z1vKYJRPQCDnd0EjXfHMidcjecGOMuLrmuQmtWmFkuKLcMThlGh1yCKG8IEc6VeNXQ== + dependencies: + consola "^3.2.3" + cjs-module-lexer@^1.0.0: version "1.2.3" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" @@ -7588,14 +7599,14 @@ client-only@0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== +clipboardy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-3.0.0.tgz#f3876247404d334c9ed01b6f269c11d09a5e3092" + integrity sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg== dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" + arch "^2.2.0" + execa "^5.1.1" + is-wsl "^2.2.0" cliui@^6.0.0: version "6.0.0" @@ -7637,6 +7648,11 @@ clsx@^2.0.0: resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.0.0.tgz#12658f3fd98fafe62075595a5c30e43d18f3d00b" integrity sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q== +cluster-key-slot@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" + integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -7733,6 +7749,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +consola@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.2.3.tgz#0741857aa88cfa0d6fd53f1cff0375136e98502f" + integrity sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ== + content-disposition@0.5.4: version "0.5.4" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" @@ -7764,6 +7785,11 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie-es@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cookie-es/-/cookie-es-1.0.0.tgz#4759684af168dfc54365b2c2dda0a8d7ee1e4865" + integrity sha512-mWYvfOLrfEc996hlKcdABeIiPHUPC6DM2QYZdGGOvhOTbA3tjm2eBwqlJpoFdjC89NI4Qt6h0Pu06Mp+1Pj5OQ== + cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" @@ -7781,13 +7807,6 @@ copy-anything@^2.0.1: dependencies: is-what "^3.14.1" -copy-to-clipboard@^3.3.1: - version "3.3.3" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" - integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== - dependencies: - toggle-selection "^1.0.6" - core-js-compat@^3.31.0, core-js-compat@^3.32.2: version "3.33.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.33.0.tgz#24aa230b228406450b2277b7c8bfebae932df966" @@ -8212,6 +8231,11 @@ define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0, de has-property-descriptors "^1.0.0" object-keys "^1.1.1" +defu@^6.1.2: + version "6.1.3" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.3.tgz#6d7f56bc61668e844f9f593ace66fd67ef1205fd" + integrity sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ== + del@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" @@ -8235,6 +8259,11 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== +denque@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" + integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -8245,21 +8274,26 @@ dequal@^2.0.3: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +destr@^2.0.1, destr@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.2.tgz#8d3c0ee4ec0a76df54bc8b819bca215592a8c218" + integrity sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== -detect-browser@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97" - integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA== - detect-browser@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca" integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w== +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -8461,11 +8495,6 @@ emittery@^0.13.1: resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -9576,7 +9605,7 @@ execa@4.1.0: signal-exit "^3.0.2" strip-final-newline "^2.0.0" -execa@^5.0.0: +execa@^5.0.0, execa@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== @@ -9865,13 +9894,6 @@ find-root@^1.1.0: resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -10098,6 +10120,11 @@ get-package-type@^0.1.0: resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== +get-port-please@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/get-port-please/-/get-port-please-3.1.1.tgz#2556623cddb4801d823c0a6a15eec038abb483be" + integrity sha512-3UBAyM3u4ZBVYDsxOQfJDxEa6XTbpBDrOjp4mf7ExFRt5BKs/QywQQiJsh2B+hxcZLSapWqCRvElUe8DnKcFHA== + get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -10314,6 +10341,20 @@ gzip-size@^6.0.0: dependencies: duplexer "^0.1.2" +h3@^1.8.1, h3@^1.8.2: + version "1.8.2" + resolved "https://registry.yarnpkg.com/h3/-/h3-1.8.2.tgz#69ea8ca0285c1bb268cd08b9a7017e02939f88b7" + integrity sha512-1Ca0orJJlCaiFY68BvzQtP2lKLk46kcLAxVM8JgYbtm2cUg6IY7pjpYgWMwUvDO9QI30N5JAukOKoT8KD3Q0PQ== + dependencies: + cookie-es "^1.0.0" + defu "^6.1.2" + destr "^2.0.1" + iron-webcrypto "^0.10.1" + radix3 "^1.1.0" + ufo "^1.3.0" + uncrypto "^0.1.3" + unenv "^1.7.4" + har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" @@ -10477,6 +10518,11 @@ http-proxy-agent@^5.0.0: agent-base "6" debug "4" +http-shutdown@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/http-shutdown/-/http-shutdown-1.2.2.tgz#41bc78fc767637c4c95179bc492f312c0ae64c5f" + integrity sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw== + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -10682,6 +10728,21 @@ invariant@2, invariant@^2.2.2: dependencies: loose-envify "^1.0.0" +ioredis@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.3.2.tgz#9139f596f62fc9c72d873353ac5395bcf05709f7" + integrity sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA== + dependencies: + "@ioredis/commands" "^1.1.1" + cluster-key-slot "^1.1.0" + debug "^4.3.4" + denque "^2.1.0" + lodash.defaults "^4.2.0" + lodash.isarguments "^3.1.0" + redis-errors "^1.2.0" + redis-parser "^3.0.0" + standard-as-callback "^2.1.0" + ip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" @@ -10692,6 +10753,11 @@ ipaddr.js@1.9.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +iron-webcrypto@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/iron-webcrypto/-/iron-webcrypto-0.10.1.tgz#cab8636a468685533a8521bfd7f06b19b7174809" + integrity sha512-QGOS8MRMnj/UiOa+aMIgfyHcvkhqNUsUxb1XzskENvbo+rEfp6TOwqd1KPuDzXC4OnGHcMSVxDGRoilqB8ViqA== + is-arguments@^1.0.4, is-arguments@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -10769,6 +10835,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -10786,11 +10857,6 @@ is-fn@^1.0.0: resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" integrity sha512-XoFPJQmsAShb3jEQRfzf2rqXavq7fIqF/jOekp308JlThqrODnMpweVSGilKTCXELfLhltGP2AGgbQGVP8F1dg== -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -10958,7 +11024,7 @@ is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.3, is-typed- dependencies: which-typed-array "^1.1.11" -is-typedarray@1.0.0, is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -10993,12 +11059,19 @@ is-what@^3.14.1: resolved "https://registry.yarnpkg.com/is-what/-/is-what-3.14.1.tgz#e1222f46ddda85dead0fd1c9df131760e77755c1" integrity sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA== +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== -isarray@^2.0.1, isarray@^2.0.5: +isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== @@ -11518,6 +11591,11 @@ jest@^29.6.2: import-local "^3.0.2" jest-cli "^29.7.0" +jiti@^1.20.0: + version "1.21.0" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" + integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== + joi@17.9.1: version "17.9.1" resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.1.tgz#74899b9fa3646904afa984a11df648eca66c9018" @@ -11696,6 +11774,11 @@ json5@^2.1.3, json5@^2.2.0, json5@^2.2.2, json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -11928,6 +12011,29 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== +listhen@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/listhen/-/listhen-1.5.5.tgz#58915512af70f770aa3e9fb19367adf479bb58c4" + integrity sha512-LXe8Xlyh3gnxdv4tSjTjscD1vpr/2PRpzq8YIaMJgyKzRG8wdISlWVWnGThJfHnlJ6hmLt2wq1yeeix0TEbuoA== + dependencies: + "@parcel/watcher" "^2.3.0" + "@parcel/watcher-wasm" "2.3.0" + citty "^0.1.4" + clipboardy "^3.0.0" + consola "^3.2.3" + defu "^6.1.2" + get-port-please "^3.1.1" + h3 "^1.8.1" + http-shutdown "^1.2.2" + jiti "^1.20.0" + mlly "^1.4.2" + node-forge "^1.3.1" + pathe "^1.1.1" + std-env "^3.4.3" + ufo "^1.3.0" + untun "^0.1.2" + uqr "^0.1.2" + listr2@^3.8.3: version "3.14.0" resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e" @@ -11972,14 +12078,6 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -12009,6 +12107,11 @@ lodash.defaults@^4.2.0: resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== +lodash.isarguments@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== + lodash.isequal@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -12099,6 +12202,11 @@ lowercase-keys@^3.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== +lru-cache@^10.0.2: + version "10.0.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.0.3.tgz#b40014d7d2d16d94130b87297a04a1f24874ae7c" + integrity sha512-B7gr+F6MkqB3uzINHXNctGieGsRTMwIBgxkp0yq/5BwcuDzD4A8wQpHQW6vDAm1uKSLQghmRdD9sKqf2vJ1cEg== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -12253,7 +12361,7 @@ micro-ftch@^0.3.1: resolved "https://registry.yarnpkg.com/micro-ftch/-/micro-ftch-0.3.1.tgz#6cb83388de4c1f279a034fb0cf96dfc050853c5f" integrity sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg== -micromatch@^4.0.4: +micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== @@ -12278,6 +12386,11 @@ mime@1.6.0, mime@^1.4.1: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -12373,6 +12486,16 @@ mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mlly@^1.2.0, mlly@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.2.tgz#7cf406aa319ff6563d25da6b36610a93f2a8007e" + integrity sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg== + dependencies: + acorn "^8.10.0" + pathe "^1.1.1" + pkg-types "^1.0.3" + ufo "^1.3.0" + mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -12390,7 +12513,7 @@ motion@10.16.2: "@motionone/utils" "^10.15.1" "@motionone/vue" "^10.16.2" -mri@^1.1.0: +mri@^1.1.0, mri@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== @@ -12493,6 +12616,11 @@ nanoid@^4.0.0: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e" integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw== +napi-wasm@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/napi-wasm/-/napi-wasm-1.1.0.tgz#bbe617823765ae9c1bc12ff5942370eae7b2ba4e" + integrity sha512-lHwIAJbmLSjF9VDRm9GoVOy9AGp3aIvkjv+Kvz9h16QR3uSVYH78PNQUnT2U4X53mhlnV2M7wrhibQ3GHicDmg== + natural-compare-lite@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4" @@ -12570,6 +12698,11 @@ node-addon-api@^7.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e" integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA== +node-fetch-native@^1.4.0, node-fetch-native@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.4.1.tgz#5a336e55b4e1b1e72b9927da09fecd2b374c9be5" + integrity sha512-NsXBU0UgBxo2rQLOeWNZqS3fvflWePMECr8CoSWoSTqCqGbVVsvl9vZu1HfQicYN0g5piV9Gh8RTEvo/uP752w== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -12584,6 +12717,11 @@ node-fetch@^2.0.0, node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@^2.6.12, nod dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp-build@^4.2.0, node-gyp-build@^4.2.2, node-gyp-build@^4.3.0, node-gyp-build@^4.5.0: version "4.6.1" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.6.1.tgz#24b6d075e5e391b8d5539d98c7fc5c210cac8a3e" @@ -12736,6 +12874,15 @@ oboe@2.1.5: dependencies: http-https "^1.0.0" +ofetch@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.3.3.tgz#588cb806a28e5c66c2c47dd8994f9059a036d8c0" + integrity sha512-s1ZCMmQWXy4b5K/TW9i/DtiN8Ku+xCiHcjQ6/J/nDdssirrQNOoB165Zu8EqLMA2lln1JUth9a0aW9Ap2ctrUg== + dependencies: + destr "^2.0.1" + node-fetch-native "^1.4.0" + ufo "^1.3.0" + on-exit-leak-free@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-0.2.0.tgz#b39c9e3bf7690d890f4861558b0d7b90a442d209" @@ -12794,7 +12941,7 @@ p-cancelable@^3.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== -p-limit@^2.0.0, p-limit@^2.2.0: +p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -12808,13 +12955,6 @@ p-limit@^3.0.2, p-limit@^3.1.0: dependencies: yocto-queue "^0.1.0" -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - p-locate@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" @@ -12895,11 +13035,6 @@ path-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -12935,6 +13070,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.0, pathe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a" + integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q== + pbkdf2@^3.0.17: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -13040,10 +13180,14 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -pngjs@^3.3.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" - integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w== +pkg-types@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868" + integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.2.0" + pathe "^1.1.0" pngjs@^5.0.0: version "5.0.0" @@ -13106,11 +13250,6 @@ postcss@8.4.31, postcss@^8.0.0, postcss@^8.4.21: picocolors "^1.0.0" source-map-js "^1.0.2" -preact@10.4.1: - version "10.4.1" - resolved "https://registry.yarnpkg.com/preact/-/preact-10.4.1.tgz#9b3ba020547673a231c6cf16f0fbaef0e8863431" - integrity sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q== - preact@^10.5.9: version "10.18.1" resolved "https://registry.yarnpkg.com/preact/-/preact-10.18.1.tgz#3b84bb305f0b05f4ad5784b981d15fcec4e105da" @@ -13301,19 +13440,6 @@ qrcode.react@^3.1.0: resolved "https://registry.yarnpkg.com/qrcode.react/-/qrcode.react-3.1.0.tgz#5c91ddc0340f768316fbdb8fff2765134c2aecd8" integrity sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q== -qrcode@1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.4.4.tgz#f0c43568a7e7510a55efc3b88d9602f71963ea83" - integrity sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q== - dependencies: - buffer "^5.4.3" - buffer-alloc "^1.2.0" - buffer-from "^1.1.1" - dijkstrajs "^1.0.1" - isarray "^2.0.1" - pngjs "^3.3.0" - yargs "^13.2.4" - qrcode@1.5.3: version "1.5.3" resolved "https://registry.yarnpkg.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" @@ -13350,15 +13476,6 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad" integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== -query-string@6.13.5: - version "6.13.5" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.5.tgz#99e95e2fb7021db90a6f373f990c0c814b3812d8" - integrity sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q== - dependencies: - decode-uri-component "^0.2.0" - split-on-first "^1.0.0" - strict-uri-encode "^2.0.0" - query-string@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/query-string/-/query-string-7.1.3.tgz#a1cf90e994abb113a325804a972d98276fe02328" @@ -13398,6 +13515,11 @@ quick-lru@^5.1.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== +radix3@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/radix3/-/radix3-1.1.0.tgz#9745df67a49c522e94a33d0a93cf743f104b6e0d" + integrity sha512-pNsHDxbGORSvuSScqNJ+3Km6QAVqk8CfsCBIEoDgpqLrkD2f3QM4I7d1ozJJ172OmIcoUcerZaNWqtLkRXTV3A== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -13651,6 +13773,18 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +redis-errors@^1.0.0, redis-errors@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" + integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== + +redis-parser@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" + integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== + dependencies: + redis-errors "^1.0.0" + reduce-flatten@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" @@ -14535,11 +14669,21 @@ stack-utils@^2.0.3: dependencies: escape-string-regexp "^2.0.0" +standard-as-callback@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" + integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== + statuses@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +std-env@^3.4.3: + version "3.5.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.5.0.tgz#83010c9e29bd99bf6f605df87c19012d82d63b97" + integrity sha512-JGUEaALvL0Mf6JCfYnJOTcobY+Nc7sG/TemDRBqCA0wEr4DER7zDchaaixTlmOxAjG1uRJmX82EQcxwTQTkqVA== + stop-iteration-iterator@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4" @@ -14588,15 +14732,6 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -14676,13 +14811,6 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -15025,11 +15153,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toggle-selection@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" - integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== - toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" @@ -15306,7 +15429,7 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: +typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== @@ -15384,6 +15507,11 @@ ua-parser-js@^1.0.35: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-1.0.36.tgz#a9ab6b9bd3a8efb90bb0816674b412717b7c428c" integrity sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw== +ufo@^1.3.0, ufo@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" + integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== + uint8arrays@^3.0.0, uint8arrays@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/uint8arrays/-/uint8arrays-3.1.1.tgz#2d8762acce159ccd9936057572dade9459f65ae0" @@ -15406,11 +15534,27 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + undici-types@~5.25.1: version "5.25.3" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== +unenv@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/unenv/-/unenv-1.7.4.tgz#a0e5a78de2c7c3c4563c06ba9763c96c59db3333" + integrity sha512-fjYsXYi30It0YCQYqLOcT6fHfMXsBr2hw9XC7ycf8rTG7Xxpe3ZssiqUnD0khrjiZEmkBXWLwm42yCSCH46fMw== + dependencies: + consola "^3.2.3" + defu "^6.1.2" + mime "^3.0.0" + node-fetch-native "^1.4.0" + pathe "^1.1.1" + unfetch@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.2.0.tgz#7e21b0ef7d363d8d9af0fb929a5555f6ef97a3be" @@ -15471,11 +15615,37 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +unstorage@^1.9.0: + version "1.10.1" + resolved "https://registry.yarnpkg.com/unstorage/-/unstorage-1.10.1.tgz#bf8cc00a406e40a6293e893da9807057d95875b0" + integrity sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw== + dependencies: + anymatch "^3.1.3" + chokidar "^3.5.3" + destr "^2.0.2" + h3 "^1.8.2" + ioredis "^5.3.2" + listhen "^1.5.5" + lru-cache "^10.0.2" + mri "^1.2.0" + node-fetch-native "^1.4.1" + ofetch "^1.3.3" + ufo "^1.3.1" + untildify@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== +untun@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/untun/-/untun-0.1.2.tgz#fa42a62ae24c1c5c6f3209692a2b0e1f573f1353" + integrity sha512-wLAMWvxfqyTiBODA1lg3IXHQtjggYLeTK7RnSfqtOXixWJ3bAa2kK/HHmOOg19upteqO3muLvN6O/icbyQY33Q== + dependencies: + citty "^0.1.3" + consola "^3.2.3" + pathe "^1.1.1" + upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" @@ -15489,6 +15659,11 @@ update-browserslist-db@^1.0.13: escalade "^3.1.1" picocolors "^1.0.0" +uqr@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/uqr/-/uqr-0.1.2.tgz#5c6cd5dcff9581f9bb35b982cb89e2c483a41d7d" + integrity sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA== + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -16467,15 +16642,6 @@ workbox-window@7.0.0: "@types/trusted-types" "^2.0.2" workbox-core "7.0.0" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -16512,11 +16678,6 @@ ws@7.4.6: resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== -ws@7.5.3: - version "7.5.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" - integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== - ws@7.5.9, ws@^7.2.0, ws@^7.3.1, ws@^7.4.5, ws@^7.5.1: version "7.5.9" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" @@ -16640,14 +16801,6 @@ yaml@^1.10.0, yaml@^1.10.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -16661,22 +16814,6 @@ yargs-parser@^21.1.1: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^13.2.4: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - yargs@^15.3.1: version "15.4.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" From a7bf51848abb2dc0c3657de0bafc461bc1c4ce5b Mon Sep 17 00:00:00 2001 From: katspaugh Date: Tue, 21 Nov 2023 19:49:02 +0100 Subject: [PATCH 09/10] Fix safeapps and walletconnect events --- src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx index f9c8c7b847..6b4f57c3f8 100644 --- a/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx +++ b/src/components/tx-flow/flows/SafeAppsTx/ReviewSafeAppsTx.tsx @@ -67,7 +67,7 @@ const ReviewSafeAppsTx = ({ } // Track tx creation - if (safeTx.signatures.size === 1) { + if (safeTx.signatures.size === 0) { trackEvent({ ...TX_EVENTS.CREATE, label: isWalletConnectSafeApp(app?.url || '') ? TX_TYPES.walletconnect : TX_TYPES.safeapps, From cad088c97fe983b5603a3bfc63271c720bbd3fcf Mon Sep 17 00:00:00 2001 From: katspaugh Date: Wed, 22 Nov 2023 08:12:58 +0100 Subject: [PATCH 10/10] Rm spending_limit_transfer --- .../tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx | 8 +------- src/services/analytics/events/transactions.ts | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx b/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx index 4b13a65cc3..bbacba80e8 100644 --- a/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx +++ b/src/components/tx-flow/flows/TokenTransfer/ReviewTokenTx.tsx @@ -5,7 +5,6 @@ import ReviewSpendingLimitTx from '@/components/tx-flow/flows/TokenTransfer/Revi import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions' import { trackEvent } from '@/services/analytics' -// TODO: Split this into separate flows const ReviewTokenTx = ({ params, onSubmit, @@ -22,13 +21,8 @@ const ReviewTokenTx = ({ onSubmit() }, [onSubmit]) - const onSpendingLimitTxSubmit = useCallback(() => { - trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.spending_limit_transfer }) - onSubmit() - }, [onSubmit]) - return isSpendingLimitTx ? ( - + ) : ( ) diff --git a/src/services/analytics/events/transactions.ts b/src/services/analytics/events/transactions.ts index 14031a17e1..7f33f5676c 100644 --- a/src/services/analytics/events/transactions.ts +++ b/src/services/analytics/events/transactions.ts @@ -12,7 +12,6 @@ export enum TX_TYPES { module_remove = 'module_remove', spending_limit_remove = 'spending_limit_remove', spending_limit_add = 'spending_limit_add', - spending_limit_transfer = 'spending_limit_transfer', // Safe txs safe_update = 'safe_update',